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(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) Index: test/Modules/ExtDebugInfo.cpp =================================================================== --- test/Modules/ExtDebugInfo.cpp +++ test/Modules/ExtDebugInfo.cpp @@ -30,7 +30,9 @@ 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 @@ TypedefUnion tdu; TypedefEnum tde; TypedefStruct tds; +TypedefTemplate tdt; +Template1 explicitTemplate1; + +template class FwdDeclTemplate { T t; }; +TypedefFwdDeclTemplate tdfdt; InAnonymousNamespace anon; @@ -48,7 +55,13 @@ 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", +// 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 >", // 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 >", // 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", +// 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: !DIDerivedType(tag: DW_TAG_member, name: "static_member", // CHECK-SAME: scope: !"_ZTSN8DebugCXX6StructE" 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; extern template struct traits; - typedef class Template FloatInstatiation; + typedef class Template FloatInstantiation; inline void fn() { Template invisible; @@ -48,6 +49,7 @@ template class A; template class A {}; typedef A B; + // Anchored by a function parameter. void foo(B) {} } @@ -83,3 +85,13 @@ Derived *getParent() const override; }; }; + +template +class Template1 { + T t; +}; +typedef Template1 TypedefTemplate; +extern template class Template1; + +template class FwdDeclTemplate; +typedef FwdDeclTemplate TypedefFwdDeclTemplate; 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 >" +// 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" +// CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") // CHECK: !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "Template >" +// 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", +// 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: !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"