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

Reply via email to