From: Adrian Prantl Date: Mon, 25 Apr 2016 20:52:40 +0000 (+0000) Subject: Module Debugging: Fix the condition for determining whether a template X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=15a13f4ca1516737c5e4d1d8d72ba56a6a77005e;p=clang Module Debugging: Fix the condition for determining whether a template instantiation is in a module. This patch fixes the condition for determining whether the debug info for a template instantiation will exist in an imported clang module by: - checking whether the ClassTemplateSpecializationDecl is complete and - checking that the instantiation was in a module by looking at the first field. I also added a negative check to make sure that a typedef to a forward-declared template (with the definition outside of the module) is handled correctly. http://reviews.llvm.org/D19443 rdar://problem/25553724 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@267464 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 70a5f619aa..0050b78f04 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -1514,12 +1514,28 @@ static bool hasExplicitMemberDefinition(CXXRecordDecl::method_iterator I, return false; } +/// Does a type definition exist in an imported clang module? +static bool isDefinedInClangModule(const RecordDecl *RD) { + if (!RD->isFromASTFile()) + return false; + if (!RD->getDefinition()) + return false; + if (!RD->isExternallyVisible() && RD->getName().empty()) + return false; + if (auto *CTSD = dyn_cast(RD)) { + if (!CTSD->isCompleteDefinition()) + return false; + // Make sure the instantiation is actually in a module. + if (CTSD->field_begin() != CTSD->field_end()) + return CTSD->field_begin()->isFromASTFile(); + } + return true; +} + static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind, bool DebugTypeExtRefs, const RecordDecl *RD, const LangOptions &LangOpts) { - // Does the type exist in an imported clang module? - if (DebugTypeExtRefs && RD->isFromASTFile() && RD->getDefinition() && - (RD->isExternallyVisible() || !RD->getName().empty())) + if (DebugTypeExtRefs && isDefinedInClangModule(RD)) return true; if (DebugKind > codegenoptions::LimitedDebugInfo) diff --git a/test/Modules/ExtDebugInfo.cpp b/test/Modules/ExtDebugInfo.cpp index 6489224774..cefb21eba2 100644 --- a/test/Modules/ExtDebugInfo.cpp +++ b/test/Modules/ExtDebugInfo.cpp @@ -2,7 +2,7 @@ // Test that only forward declarations are emitted for types dfined in modules. // Modules: -// RUN: %clang_cc1 -x objective-c++ -std=c++11 -debug-info-kind=limited \ +// RUN: %clang_cc1 -x objective-c++ -std=c++11 -debug-info-kind=standalone \ // RUN: -dwarf-ext-refs -fmodules \ // RUN: -fmodule-format=obj -fimplicit-module-maps -DMODULES \ // RUN: -triple %itanium_abi_triple \ @@ -13,7 +13,7 @@ // RUN: %clang_cc1 -x c++ -std=c++11 -fmodule-format=obj -emit-pch -I%S/Inputs \ // RUN: -triple %itanium_abi_triple \ // RUN: -o %t.pch %S/Inputs/DebugCXX.h -// RUN: %clang_cc1 -std=c++11 -debug-info-kind=limited \ +// RUN: %clang_cc1 -std=c++11 -debug-info-kind=standalone \ // RUN: -dwarf-ext-refs -fmodule-format=obj \ // RUN: -triple %itanium_abi_triple \ // RUN: -include-pch %t.pch %s -emit-llvm -o %t-pch.ll %s @@ -30,7 +30,9 @@ Struct s; DebugCXX::Enum e; DebugCXX::Template implicitTemplate; DebugCXX::Template explicitTemplate; -DebugCXX::FloatInstatiation typedefTemplate; +DebugCXX::FloatInstantiation typedefTemplate; +DebugCXX::B anchoredTemplate; + int Struct::static_member = -1; enum { e3 = -1 @@ -41,6 +43,11 @@ char _anchor = anon_enum + conflicting_uid; TypedefUnion tdu; TypedefEnum tde; TypedefStruct tds; +TypedefTemplate tdt; +Template1 explicitTemplate1; + +template class FwdDeclTemplate { T t; }; +TypedefFwdDeclTemplate tdfdt; InAnonymousNamespace anon; @@ -48,7 +55,8 @@ void foo() { anon.i = GlobalStruct.i = GlobalUnion.i = GlobalEnum; } -// CHECK: ![[STRUCT:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Struct", + +// CHECK: ![[STRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Struct", // CHECK-SAME: scope: ![[NS:[0-9]+]], // CHECK-SAME: flags: DIFlagFwdDecl, // CHECK-SAME: identifier: "_ZTSN8DebugCXX6StructE") @@ -61,25 +69,69 @@ void foo() { // CHECK-SAME: flags: DIFlagFwdDecl, // CHECK-SAME: identifier: "_ZTSN8DebugCXX4EnumE") -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template >", +// This type is 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: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE") +// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE") -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template >", +// This type is 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: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE") + +// This type isn't, however, even with standalone non-module debug info this +// type is a forward declaration. +// CHECK-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "traits", + +// This one isn't. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template >", +// CHECK-SAME: scope: ![[NS]], +// CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE") +// This type is anchored in the module by an explicit template instantiation. +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "traits", +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIfEE") + + +// This type is anchored in the module by an explicit template instantiation. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A", +// CHECK-SAME: scope: ![[NS]], +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") + // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_member", // CHECK-SAME: scope: ![[STRUCT]] // CHECK: !DICompositeType(tag: DW_TAG_union_type, -// CHECK-SAME: flags: DIFlagFwdDecl, identifier: "_ZTS12TypedefUnion") +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTS12TypedefUnion") // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, -// CHECK-SAME: flags: DIFlagFwdDecl, identifier: "_ZTS11TypedefEnum") +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTS11TypedefEnum") // CHECK: !DICompositeType(tag: DW_TAG_structure_type, -// CHECK-SAME: flags: DIFlagFwdDecl, identifier: "_ZTS13TypedefStruct") +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTS13TypedefStruct") + +// This one isn't. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template1", +// CHECK-SAME: templateParams: +// CHECK-SAME: identifier: "_ZTS9Template1IPvE") + +// This type is anchored in the module by an explicit template instantiation. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template1", +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTS9Template1IiE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdDeclTemplate", +// CHECK-SAME: templateParams: +// CHECK-SAME: identifier: "_ZTS15FwdDeclTemplateIiE") // CHECK: !DIGlobalVariable(name: "anon_enum", {{.*}}, type: ![[ANON_ENUM:[0-9]+]] // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, scope: ![[NS]], @@ -94,6 +146,7 @@ void foo() { // CHECK: ![[GLOBAL_STRUCT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, // CHECK-SAME: elements: !{{[0-9]+}}) + // CHECK: !DIGlobalVariable(name: "anon", // CHECK-SAME: type: ![[GLOBAL_ANON:[0-9]+]] // CHECK: ![[GLOBAL_ANON]] = !DICompositeType(tag: DW_TAG_structure_type, diff --git a/test/Modules/Inputs/DebugCXX.h b/test/Modules/Inputs/DebugCXX.h index 2e17a2ecfd..e6c38435ab 100644 --- a/test/Modules/Inputs/DebugCXX.h +++ b/test/Modules/Inputs/DebugCXX.h @@ -24,10 +24,11 @@ namespace DebugCXX { > class Template { T member; }; + // Explicit template instantiation. extern template class Template; extern template struct traits; - typedef class Template FloatInstatiation; + typedef class Template FloatInstantiation; inline void fn() { Template invisible; @@ -48,6 +49,7 @@ namespace DebugCXX { template class A; template class A {}; typedef A B; + // Anchored by a function parameter. void foo(B) {} } @@ -83,3 +85,13 @@ class Derived : Base { Derived *getParent() const override; }; }; + +template +class Template1 { + T t; +}; +typedef Template1 TypedefTemplate; +extern template class Template1; + +template class FwdDeclTemplate; +typedef FwdDeclTemplate TypedefFwdDeclTemplate; diff --git a/test/Modules/ModuleDebugInfo.cpp b/test/Modules/ModuleDebugInfo.cpp index 7b1391fed7..4502373630 100644 --- a/test/Modules/ModuleDebugInfo.cpp +++ b/test/Modules/ModuleDebugInfo.cpp @@ -47,19 +47,39 @@ // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "B", // no mangled name here yet. +// This type is anchored by a function parameter. // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A" +// CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Struct" // CHECK-SAME: identifier: "_ZTSN8DebugCXX6StructE") -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template >" +// This type is anchored by an explicit template instantiation. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template >" +// CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE") -// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "FloatInstatiation" +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "traits" +// CHECK-SAME: flags: DIFlagFwdDecl +// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIiEE") + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "traits" +// CHECK-SAME: templateParams: +// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIfEE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template >" +// CHECK-SAME: templateParams: +// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE") + +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "FloatInstantiation" // no mangled name here yet. -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template >" +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template >" +// CHECK-SAME: flags: DIFlagFwdDecl // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE") // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdVirtual" @@ -87,12 +107,28 @@ // CHECK-SAME: name: "InAnonymousNamespace", // CHECK-SAME: elements: !{{[0-9]+}}) -// CHECK: ![[A:[0-9]+]] = {{.*}}!DICompositeType(tag: DW_TAG_class_type, name: "A", -// CHECK: ![[DERIVED:[0-9]+]] = {{.*}}!DICompositeType(tag: DW_TAG_class_type, name: "Derived", -// CHECK-SAME: identifier: "_ZTS7Derived") +// CHECK: ![[DERIVED:.*]] = {{.*}}!DICompositeType(tag: DW_TAG_class_type, name: "Derived", +// CHECK-SAME: identifier: "_ZTS7Derived") // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "B", scope: ![[DERIVED]], -// CHECK-SAME: elements: ![[B_MBRS:.*]], vtableHolder: ![[A]] +// CHECK-SAME: elements: ![[B_MBRS:.*]], vtableHolder: // CHECK: ![[B_MBRS]] = !{{{.*}}, ![[GET_PARENT:.*]]} // CHECK: ![[GET_PARENT]] = !DISubprogram(name: "getParent" +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefTemplate", +// CHECK-SAME: baseType: ![[BASE:.*]]) +// CHECK: ![[BASE]] = !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template1", +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTS9Template1IPvE") + +// Explicit instatiation. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template1", +// CHECK-SAME: templateParams: +// CHECK-SAME: identifier: "_ZTS9Template1IiE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdDeclTemplate", +// CHECK-SAME: flags: DIFlagFwdDecl +// CHECK-SAME: identifier: "_ZTS15FwdDeclTemplateIiE") + + // CHECK-NEG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "PureForwardDecl"