diff options
author | Adrian Prantl <aprantl@apple.com> | 2016-08-17 18:27:24 +0000 |
---|---|---|
committer | Adrian Prantl <aprantl@apple.com> | 2016-08-17 18:27:24 +0000 |
commit | 26cb1d266081d85d6fe410b1f7fa741ba2a37dda (patch) | |
tree | 1c95a689ae900318e13e25e6530cdae751483e53 | |
parent | b35be69ff5092d914419609820d0eb0d7c442b99 (diff) | |
download | bcm5719-llvm-26cb1d266081d85d6fe410b1f7fa741ba2a37dda.tar.gz bcm5719-llvm-26cb1d266081d85d6fe410b1f7fa741ba2a37dda.zip |
Module debug info: Fix a bug in handling record decls without fields.
The previous condition would erroneously mark all CXXRecordDecls
that didn't have any fields as being defined in a clang module.
This patch fixes the condition to only apply to explicit template
instantiations.
<rdar://problem/27771823>
llvm-svn: 278952
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 13 | ||||
-rw-r--r-- | clang/test/Modules/ExtDebugInfo.cpp | 25 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/DebugCXX.h | 6 | ||||
-rw-r--r-- | clang/test/Modules/ModuleDebugInfo.cpp | 10 |
4 files changed, 47 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index f56cd0a6bb6..fa5f53e4599 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -1656,12 +1656,15 @@ static bool isDefinedInClangModule(const RecordDecl *RD) { return false; if (auto *CXXDecl = dyn_cast<CXXRecordDecl>(RD)) { assert(CXXDecl->isCompleteDefinition() && "incomplete record definition"); - if (CXXDecl->getTemplateSpecializationKind() != TSK_Undeclared) - // Make sure the instantiation is actually in a module. - if (CXXDecl->field_begin() != CXXDecl->field_end()) - return CXXDecl->field_begin()->isFromASTFile(); + auto TemplateKind = CXXDecl->getTemplateSpecializationKind(); + if (TemplateKind != TSK_Undeclared) { + // This is a template, check the origin of the first member. + if (CXXDecl->field_begin() == CXXDecl->field_end()) + return TemplateKind == TSK_ExplicitInstantiationDeclaration; + if (!CXXDecl->field_begin()->isFromASTFile()) + return false; + } } - return true; } diff --git a/clang/test/Modules/ExtDebugInfo.cpp b/clang/test/Modules/ExtDebugInfo.cpp index dbf79f4ff14..89a3c3945a2 100644 --- a/clang/test/Modules/ExtDebugInfo.cpp +++ b/clang/test/Modules/ExtDebugInfo.cpp @@ -63,6 +63,10 @@ struct Specialized<int>::Member definedLocally2; template <class T> struct FwdDeclTemplateMember<T>::Member { T t; }; TypedefFwdDeclTemplateMember tdfdtm; +SpecializedBase definedLocally3; +extern template class WithSpecializedBase<int>; +WithSpecializedBase<int> definedLocally4; + void foo() { anon.i = GlobalStruct.i = GlobalUnion.i = GlobalEnum; } @@ -103,6 +107,7 @@ void foo() { // CHECK: !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "Template<float, DebugCXX::traits<float> >", // CHECK-SAME: scope: ![[NS]], +// CHECK-SAME: elements: // CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE") @@ -112,10 +117,11 @@ void foo() { // CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIfEE") -// This type is anchored in the module by an explicit template instantiation. +// This type is anchored in the module via a function argument, +// but we don't know this (yet). // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A<void>", // CHECK-SAME: scope: ![[NS]], -// CHECK-SAME: flags: DIFlagFwdDecl, +// CHECK-SAME: elements: // CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_member", @@ -133,6 +139,7 @@ void foo() { // This one isn't. // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "Template1<void *>", +// CHECK-SAME: elements: // CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTS9Template1IPvE") @@ -142,6 +149,7 @@ void foo() { // CHECK-SAME: identifier: "_ZTS9Template1IiE") // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "FwdDeclTemplate<int>", +// CHECK-SAME: elements: // CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTS15FwdDeclTemplateIiE") @@ -160,6 +168,19 @@ void foo() { // CHECK-SAME: elements: // CHECK-SAME: identifier: "_ZTSN21FwdDeclTemplateMemberIiE6MemberE") +// This type is defined locally and forward-declared in the module. +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "SpecializedBase", +// CHECK-SAME: baseType: ![[SPECIALIZEDBASE:.*]]) +// CHECK: ![[SPECIALIZEDBASE]] = +// CHECK-SAME: !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "WithSpecializedBase<float>", +// CHECK-SAME: elements: +// CHECK-SAME: identifier: "_ZTS19WithSpecializedBaseIfE") + +// This type is explicitly specialized locally. +// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "WithSpecializedBase<int>", +// CHECK-SAME: elements: +// CHECK-SAME: identifier: "_ZTS19WithSpecializedBaseIiE") // CHECK: !DIGlobalVariable(name: "anon_enum", {{.*}}, type: ![[ANON_ENUM:[0-9]+]] // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, scope: ![[NS]], diff --git a/clang/test/Modules/Inputs/DebugCXX.h b/clang/test/Modules/Inputs/DebugCXX.h index 793ad209f8b..c9cd68f30c4 100644 --- a/clang/test/Modules/Inputs/DebugCXX.h +++ b/clang/test/Modules/Inputs/DebugCXX.h @@ -105,3 +105,9 @@ template <> struct Specialized<int> { template <class T> struct FwdDeclTemplateMember { struct Member; }; typedef FwdDeclTemplateMember<int>::Member TypedefFwdDeclTemplateMember; + +// Base class specialized on the class itself. +template <typename Derived> class BaseTemplate {}; +template <typename T> +class WithSpecializedBase : public BaseTemplate<WithSpecializedBase<T>> {}; +typedef WithSpecializedBase<float> SpecializedBase; diff --git a/clang/test/Modules/ModuleDebugInfo.cpp b/clang/test/Modules/ModuleDebugInfo.cpp index 021283a83e6..1bc0613f427 100644 --- a/clang/test/Modules/ModuleDebugInfo.cpp +++ b/clang/test/Modules/ModuleDebugInfo.cpp @@ -49,6 +49,7 @@ // This type is anchored by a function parameter. // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "A<void>" +// CHECK-SAME: elements: // CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX1AIJvEEE") @@ -58,6 +59,7 @@ // 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: elements: // CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE") @@ -66,11 +68,13 @@ // CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIiEE") // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "traits<float>" +// CHECK-SAME: elements: // CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX6traitsIfEE") // CHECK: !DICompositeType(tag: DW_TAG_class_type, // CHECK-SAME: name: "Template<long, DebugCXX::traits<long> >" +// CHECK-SAME: elements: // CHECK-SAME: templateParams: // CHECK-SAME: identifier: "_ZTSN8DebugCXX8TemplateIlNS_6traitsIlEEEE") @@ -135,4 +139,10 @@ // CHECK-SAME: flags: DIFlagFwdDecl // CHECK-SAME: identifier: "_ZTSN21FwdDeclTemplateMemberIiE6MemberE") +// CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "SpecializedBase", +// CHECK-SAME: baseType: ![[SPECIALIZEDBASE:.*]]) +// CHECK: ![[SPECIALIZEDBASE]] = !DICompositeType(tag: DW_TAG_class_type, +// CHECK-SAME: name: "WithSpecializedBase<float>", +// CHECK-SAME: flags: DIFlagFwdDecl, + // CHECK-NEG-NOT: !DICompositeType(tag: DW_TAG_structure_type, name: "PureForwardDecl" |