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

llvm-svn: 267464
This commit is contained in:
Adrian Prantl 2016-04-25 20:52:40 +00:00
parent cef04a25f6
commit 05fefa4a85
4 changed files with 138 additions and 21 deletions

View File

@ -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<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)

View File

@ -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_uid;
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: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE")
// 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")
// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template<float, DebugCXX::traits<float> >",
// 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: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE")
// 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,

View File

@ -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;

View File

@ -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"