aprantl created this revision. aprantl added a reviewer: doug.gregor. aprantl added a subscriber: cfe-commits. aprantl set the repository for this revision to rL LLVM.
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. Repository: rL LLVM http://reviews.llvm.org/D19443 Files: lib/CodeGen/CGDebugInfo.cpp test/Modules/ExtDebugInfo.cpp test/Modules/Inputs/DebugCXX.h test/Modules/ModuleDebugInfo.cpp
Index: test/Modules/ModuleDebugInfo.cpp =================================================================== --- test/Modules/ModuleDebugInfo.cpp +++ test/Modules/ModuleDebugInfo.cpp @@ -47,15 +47,20 @@ // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Struct" // CHECK-SAME: identifier: "_ZTSN8DebugCXX6StructE") +// 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") +// 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_class_type, // CHECK-SAME: name: "Template<float, DebugCXX::traits<float> >" +// CHECK-SAME: flags: DIFlagFwdDecl // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE") // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "B", @@ -81,7 +86,20 @@ // CHECK: ![[B_MBRS]] = !{{{.*}}, ![[GET_PARENT:.*]]} // CHECK: ![[GET_PARENT]] = !DISubprogram(name: "getParent" -// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "FloatInstatiation" +// CHECK: !DICompositeType(tag: DW_TAG_class_type, 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: !DIDerivedType(tag: DW_TAG_typedef, name: "FloatInstantiation" // no mangled name here yet. // CHECK: !DICompositeType(tag: DW_TAG_union_type, @@ -96,4 +114,8 @@ // CHECK-SAME: name: "InAnonymousNamespace", // CHECK-SAME: elements: !{{[0-9]+}}) +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefTemplate", +// CHECK-SAME: baseType: !"_ZTS9Template1IPvE") + + // CHECK-NEG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "PureForwardDecl" Index: test/Modules/Inputs/DebugCXX.h =================================================================== --- test/Modules/Inputs/DebugCXX.h +++ test/Modules/Inputs/DebugCXX.h @@ -24,10 +24,11 @@ > 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 @@ 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 @@ 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; Index: test/Modules/ExtDebugInfo.cpp =================================================================== --- test/Modules/ExtDebugInfo.cpp +++ test/Modules/ExtDebugInfo.cpp @@ -30,7 +30,9 @@ 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,14 +43,25 @@ TypedefUnion tdu; TypedefEnum tde; TypedefStruct tds; +TypedefTemplate tdt; +Template1<int> explicitTemplate1; + +template <class T> class FwdDeclTemplate { T t; }; +TypedefFwdDeclTemplate tdfdt; InAnonymousNamespace anon; void foo() { anon.i = GlobalStruct.i = GlobalUnion.i = GlobalEnum; } -// CHECK: ![[NS:.*]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]], +// 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:[0-9]+]], +// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") + +// CHECK: ![[NS]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]], // CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Struct", @@ -63,24 +76,43 @@ // CHECK: !DICompositeType(tag: DW_TAG_class_type, +// 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 one isn't. // CHECK: !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "Template<float, DebugCXX::traits<float> >", // CHECK-SAME: scope: ![[NS]], -// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE") // 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") + +// 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: !DIDerivedType(tag: DW_TAG_member, name: "static_member", // CHECK-SAME: scope: !"_ZTSN8DebugCXX6StructE" Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -1519,12 +1519,28 @@ 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)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits