]> granicus.if.org Git - clang/commitdiff
Debug Info (-gmodules): emit full types for non-anchored template specializations
authorAdrian Prantl <aprantl@apple.com>
Wed, 24 Oct 2018 00:06:02 +0000 (00:06 +0000)
committerAdrian Prantl <aprantl@apple.com>
Wed, 24 Oct 2018 00:06:02 +0000 (00:06 +0000)
Before this patch, clang would emit a (module-)forward declaration for
template instantiations that are not anchored by an explicit template
instantiation, but still are guaranteed to be available in an imported
module. Unfortunately detecting the owning module doesn't reliably
work when local submodule visibility is enabled and the template is
inside a cross-module namespace.

This make clang debuggable again with -gmodules and LSV enabled.

rdar://problem/41552377

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@345109 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDebugInfo.cpp
test/Modules/ExtDebugInfo.cpp
test/Modules/Inputs/lsv-debuginfo/A/ADT.h [new file with mode: 0644]
test/Modules/Inputs/lsv-debuginfo/B/B.h [new file with mode: 0644]
test/Modules/Inputs/lsv-debuginfo/C/C.h [new file with mode: 0644]
test/Modules/Inputs/lsv-debuginfo/module.modulemap [new file with mode: 0644]
test/Modules/lsv-debuginfo.cpp [new file with mode: 0755]

index bcd5338ac050f70ecfeec0ebb1970a5e84ae629b..0d42befa5ab40358ebced89527cd0af35e4c9dbd 100644 (file)
@@ -1955,8 +1955,17 @@ static bool isDefinedInClangModule(const RecordDecl *RD) {
   if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) {
     if (!CXXDecl->isCompleteDefinition())
       return false;
+    // Check wether RD is a template.
     auto TemplateKind = CXXDecl->getTemplateSpecializationKind();
     if (TemplateKind != TSK_Undeclared) {
+      // Unfortunately getOwningModule() isn't accurate enough to find the
+      // owning module of a ClassTemplateSpecializationDecl that is inside a
+      // namespace spanning multiple modules.
+      bool Explicit = false;
+      if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(CXXDecl))
+        Explicit = TD->isExplicitInstantiationOrSpecialization();
+      if (!Explicit && CXXDecl->getEnclosingNamespaceContext())
+        return false;
       // This is a template, check the origin of the first member.
       if (CXXDecl->field_begin() == CXXDecl->field_end())
         return TemplateKind == TSK_ExplicitInstantiationDeclaration;
index c57f1f034eb239cf7f34d1345ffe90f48f020d97..592612b9a5db88ea0acb69b47fec8af9b2a3a06d 100644 (file)
@@ -83,11 +83,11 @@ void foo() {
 // CHECK: ![[NS]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]])
 // CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX
 
-// This type is anchored in the module by an explicit template instantiation.
+// This type is not anchored in the module by an explicit template instantiation.
 // CHECK: !DICompositeType(tag: DW_TAG_class_type,
 // CHECK-SAME:             name: "Template<long, DebugCXX::traits<long> >",
 // CHECK-SAME:             scope: ![[NS]],
-// CHECK-SAME:             flags: DIFlagFwdDecl,
+// CHECK-SAME:             elements:
 // CHECK-SAME:             identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE")
 
 // This type is anchored in the module by an explicit template instantiation.
diff --git a/test/Modules/Inputs/lsv-debuginfo/A/ADT.h b/test/Modules/Inputs/lsv-debuginfo/A/ADT.h
new file mode 100644 (file)
index 0000000..f48d4f7
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef ADT
+#define ADT
+
+#ifdef WITH_NAMESPACE
+namespace llvm {
+#endif
+template <unsigned Alignment, unsigned Size>
+struct AlignedCharArray {
+  alignas(Alignment) char buffer[Size];
+};
+
+template <typename T1>
+class AlignerImpl {
+  T1 t1;
+};
+
+template <typename T1>
+union SizerImpl {
+  char arr1[sizeof(T1)];
+};
+
+template <typename T1>
+struct AlignedCharArrayUnion
+    : AlignedCharArray<alignof(AlignerImpl<T1>), sizeof(SizerImpl<T1>)> {};
+
+template <typename T, unsigned N>
+struct SmallVectorStorage {
+  AlignedCharArrayUnion<T> InlineElts[N];
+};
+template <typename T, unsigned N>
+class SmallVector : SmallVectorStorage<T, N> {};
+
+template <typename T>
+struct OptionalStorage {
+  AlignedCharArrayUnion<T> storage;
+};
+template <typename T>
+class Optional {
+  OptionalStorage<T> Storage;
+};
+
+#ifdef WITH_NAMESPACE
+} // namespace llvm
+#endif
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/B/B.h b/test/Modules/Inputs/lsv-debuginfo/B/B.h
new file mode 100644 (file)
index 0000000..c00bc3c
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef B_H
+#define B_H
+#include <A/ADT.h>
+#include <C/C.h>
+
+namespace llvm {
+struct S {
+  unsigned a, b, c, d;
+};
+class C {
+  Optional<S> S;
+};
+}
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/C/C.h b/test/Modules/Inputs/lsv-debuginfo/C/C.h
new file mode 100644 (file)
index 0000000..52c6e4d
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef C_H
+#define C_H
+#include <A/ADT.h>
+
+namespace llvm {
+class D {
+  struct Q {
+    unsigned a, b, c, d;
+  };
+  SmallVector<Q, 4> q;
+};
+} // namespace llvm
+#endif
diff --git a/test/Modules/Inputs/lsv-debuginfo/module.modulemap b/test/Modules/Inputs/lsv-debuginfo/module.modulemap
new file mode 100644 (file)
index 0000000..5bb0449
--- /dev/null
@@ -0,0 +1,9 @@
+module A {
+  umbrella "A" module * { export * }
+}
+module B {
+  umbrella "B" module * { export * }
+}
+module C {
+  umbrella "C" module * { export * }
+}
diff --git a/test/Modules/lsv-debuginfo.cpp b/test/Modules/lsv-debuginfo.cpp
new file mode 100755 (executable)
index 0000000..4a2644f
--- /dev/null
@@ -0,0 +1,39 @@
+// Test C++ -gmodules debug info in the PCMs with local submodule visibility.
+// REQUIRES: asserts
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple    \
+// RUN:   -fmodules-local-submodule-visibility %s \
+// RUN:   -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone \
+// RUN:   -dwarf-version=4 -fmodules -fimplicit-module-maps \
+// RUN:   -fmodules-cache-path="%t" -o %t.ll -I%S/Inputs/lsv-debuginfo \
+// RUN:   -mllvm -debug-only=pchcontainer &>%t-mod.ll
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -triple %itanium_abi_triple    \
+// RUN:   -fmodules-local-submodule-visibility %s \
+// RUN:   -dwarf-ext-refs -fmodule-format=obj -debug-info-kind=standalone \
+// RUN:   -dwarf-version=4 -fmodules -fimplicit-module-maps \
+// RUN:   -fmodules-cache-path="%t" -o %t.ll -I%S/Inputs/lsv-debuginfo \
+// RUN:   -mllvm -debug-only=pchcontainer &>%t-mod.ll \
+// RUN:   -DWITH_NAMESPACE
+// RUN: cat %t-mod.ll | FileCheck %s
+
+// ADT
+// CHECK: @__clang_ast =
+
+// B
+// CHECK: @__clang_ast =
+
+// This type isn't anchored anywhere, expect a full definition.
+// CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4, 16>",
+// CHECK-SAME:             elements:
+
+// C
+// CHECK: @__clang_ast =
+
+// Here, too.
+// CHECK: !DICompositeType({{.*}}, name: "AlignedCharArray<4, 16>",
+// CHECK-SAME:             elements:
+
+#include <B/B.h>