Author: adrian Date: Mon Apr 25 15:52:40 2016 New Revision: 267464 URL: http://llvm.org/viewvc/llvm-project?rev=267464&view=rev Log: 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 Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp cfe/trunk/test/Modules/ExtDebugInfo.cpp cfe/trunk/test/Modules/Inputs/DebugCXX.h cfe/trunk/test/Modules/ModuleDebugInfo.cpp Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=267464&r1=267463&r2=267464&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Apr 25 15:52:40 2016 @@ -1514,12 +1514,28 @@ static bool hasExplicitMemberDefinition( 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<ClassTemplateSpecializationDecl>(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) Modified: cfe/trunk/test/Modules/ExtDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.cpp?rev=267464&r1=267463&r2=267464&view=diff ============================================================================== --- cfe/trunk/test/Modules/ExtDebugInfo.cpp (original) +++ cfe/trunk/test/Modules/ExtDebugInfo.cpp Mon Apr 25 15:52:40 2016 @@ -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<long> implicitTemplate; DebugCXX::Template<int> 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_u TypedefUnion tdu; TypedefEnum tde; TypedefStruct tds; +TypedefTemplate tdt; +Template1<int> explicitTemplate1; + +template <class T> 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<int, DebugCXX::traits<int> >", +// This type is 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: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE") +// CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE") -// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template<float, DebugCXX::traits<float> >", +// This type is anchored in the module by an explicit template instantiation. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template<int, DebugCXX::traits<int> >", // 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<int>", + +// This one isn't. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template<float, DebugCXX::traits<float> >", +// 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<float>", +// 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<void>", +// 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<void *>", +// 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<int>", +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTS9Template1IiE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdDeclTemplate<int>", +// 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, Modified: cfe/trunk/test/Modules/Inputs/DebugCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/DebugCXX.h?rev=267464&r1=267463&r2=267464&view=diff ============================================================================== --- cfe/trunk/test/Modules/Inputs/DebugCXX.h (original) +++ cfe/trunk/test/Modules/Inputs/DebugCXX.h Mon Apr 25 15:52:40 2016 @@ -24,10 +24,11 @@ namespace DebugCXX { > class Template { T member; }; + // Explicit template instantiation. extern template class Template<int>; extern template struct traits<float>; - typedef class Template<float> FloatInstatiation; + typedef class Template<float> FloatInstantiation; inline void fn() { Template<long> invisible; @@ -48,6 +49,7 @@ namespace DebugCXX { template <typename...> class A; template <typename T> class A<T> {}; typedef A<void> B; + // Anchored by a function parameter. void foo(B) {} } @@ -83,3 +85,13 @@ class Derived : Base { Derived *getParent() const override; }; }; + +template <class T> +class Template1 { + T t; +}; +typedef Template1<void *> TypedefTemplate; +extern template class Template1<int>; + +template <class T> class FwdDeclTemplate; +typedef FwdDeclTemplate<int> TypedefFwdDeclTemplate; Modified: cfe/trunk/test/Modules/ModuleDebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ModuleDebugInfo.cpp?rev=267464&r1=267463&r2=267464&view=diff ============================================================================== --- cfe/trunk/test/Modules/ModuleDebugInfo.cpp (original) +++ cfe/trunk/test/Modules/ModuleDebugInfo.cpp Mon Apr 25 15:52:40 2016 @@ -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<void>" +// 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<int, DebugCXX::traits<int> >" +// This type is anchored by an explicit template instantiation. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template<int, DebugCXX::traits<int> >" +// 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<int>" +// CHECK-SAME: flags: DIFlagFwdDecl +// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIiEE") + +// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "traits<float>" +// CHECK-SAME: templateParams: +// CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIfEE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template<long, DebugCXX::traits<long> >" +// 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<float, DebugCXX::traits<float> >" +// CHECK: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "Template<float, DebugCXX::traits<float> >" +// 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<void *>", +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTS9Template1IPvE") + +// Explicit instatiation. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template1<int>", +// CHECK-SAME: templateParams: +// CHECK-SAME: identifier: "_ZTS9Template1IiE") + +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdDeclTemplate<int>", +// CHECK-SAME: flags: DIFlagFwdDecl +// CHECK-SAME: identifier: "_ZTS15FwdDeclTemplateIiE") + + // CHECK-NEG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "PureForwardDecl" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits