]> granicus.if.org Git - clang/commitdiff
Module debug info: Fix a bug in handling record decls without fields.
authorAdrian Prantl <aprantl@apple.com>
Wed, 17 Aug 2016 18:27:24 +0000 (18:27 +0000)
committerAdrian Prantl <aprantl@apple.com>
Wed, 17 Aug 2016 18:27:24 +0000 (18:27 +0000)
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>

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@278952 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDebugInfo.cpp
test/Modules/ExtDebugInfo.cpp
test/Modules/Inputs/DebugCXX.h
test/Modules/ModuleDebugInfo.cpp

index f56cd0a6bb6c90b07fc64244878063815224d2f0..fa5f53e4599bbd6853b46f5b2d3be691f72b27b2 100644 (file)
@@ -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;
 }
 
index dbf79f4ff148c964fa4c2f45c9a4b16789a3a57d..89a3c3945a2d1b51fe5d88e2e11f7e7b4f33eb95 100644 (file)
@@ -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]],
index 793ad209f8bf2d8c0509396f3520063f6eead8ae..c9cd68f30c4655e356e0b1b0e5e3d10a2101295c 100644 (file)
@@ -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;
index 021283a83e6321c97f859d56e4a44a7e0c8128ef..1bc0613f427e3a95c74a8ed5f69a14414cef562c 100644 (file)
@@ -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")
 
 // 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")
 
 // 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"