From: Adrian Prantl Date: Wed, 24 Oct 2018 00:06:02 +0000 (+0000) Subject: Debug Info (-gmodules): emit full types for non-anchored template specializations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b99555bac49041b910b9f12f4aac658f925bd201;p=clang Debug Info (-gmodules): emit full types for non-anchored template specializations 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 --- diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index bcd5338ac0..0d42befa5a 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1955,8 +1955,17 @@ static bool isDefinedInClangModule(const RecordDecl *RD) { if (auto *CXXDecl = dyn_cast(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(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; diff --git a/test/Modules/ExtDebugInfo.cpp b/test/Modules/ExtDebugInfo.cpp index c57f1f034e..592612b9a5 100644 --- a/test/Modules/ExtDebugInfo.cpp +++ b/test/Modules/ExtDebugInfo.cpp @@ -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 >", // 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 index 0000000000..f48d4f7820 --- /dev/null +++ b/test/Modules/Inputs/lsv-debuginfo/A/ADT.h @@ -0,0 +1,45 @@ +#ifndef ADT +#define ADT + +#ifdef WITH_NAMESPACE +namespace llvm { +#endif +template +struct AlignedCharArray { + alignas(Alignment) char buffer[Size]; +}; + +template +class AlignerImpl { + T1 t1; +}; + +template +union SizerImpl { + char arr1[sizeof(T1)]; +}; + +template +struct AlignedCharArrayUnion + : AlignedCharArray), sizeof(SizerImpl)> {}; + +template +struct SmallVectorStorage { + AlignedCharArrayUnion InlineElts[N]; +}; +template +class SmallVector : SmallVectorStorage {}; + +template +struct OptionalStorage { + AlignedCharArrayUnion storage; +}; +template +class Optional { + OptionalStorage 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 index 0000000000..c00bc3cddb --- /dev/null +++ b/test/Modules/Inputs/lsv-debuginfo/B/B.h @@ -0,0 +1,14 @@ +#ifndef B_H +#define B_H +#include +#include + +namespace llvm { +struct S { + unsigned a, b, c, d; +}; +class C { + Optional 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 index 0000000000..52c6e4dbac --- /dev/null +++ b/test/Modules/Inputs/lsv-debuginfo/C/C.h @@ -0,0 +1,13 @@ +#ifndef C_H +#define C_H +#include + +namespace llvm { +class D { + struct Q { + unsigned a, b, c, d; + }; + SmallVector 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 index 0000000000..5bb044908d --- /dev/null +++ b/test/Modules/Inputs/lsv-debuginfo/module.modulemap @@ -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 index 0000000000..4a2644f6b3 --- /dev/null +++ b/test/Modules/lsv-debuginfo.cpp @@ -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