<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Sep 11, 2015 at 10:23 AM, Adrian Prantl via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Author: adrian<br>
Date: Fri Sep 11 12:23:08 2015<br>
New Revision: 247432<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=247432&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=247432&view=rev</a><br>
Log:<br>
Module Debugging: Emit forward declarations for types that are defined in<br>
clang modules, if -dwarf-ext-refs (DebugTypesExtRefs) is specified.<br>
<br>
This reimplements r247369 in about a third of the amount of code.<br>
Thanks to David Blaikie pointing this out in post-commit review!<br>
<br>
Added:<br>
    cfe/trunk/test/Modules/ExtDebugInfo.cpp<br>
    cfe/trunk/test/Modules/ExtDebugInfo.m<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>
    cfe/trunk/lib/CodeGen/CGDebugInfo.h<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=247432&r1=247431&r2=247432&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=247432&r1=247431&r2=247432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Fri Sep 11 12:23:08 2015<br>
@@ -148,7 +148,9 @@ void CGDebugInfo::setLocation(SourceLoca<br>
 }<br>
<br>
 llvm::DIScope *CGDebugInfo::getDeclContextDescriptor(const Decl *D) {<br>
-  return getContextDescriptor(cast<Decl>(D->getDeclContext()), TheCU);<br>
+  llvm::DIScope *Mod = getParentModuleOrNull(D);<br>
+  return getContextDescriptor(cast<Decl>(D->getDeclContext()),<br>
+                              Mod ? Mod : TheCU);<br></blockquote><div><br></div><div>Might've been nice to separate the module-parenting part of the change, smaller patches (easier to revert, review, etc), the usual stuff.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
 }<br>
<br>
 llvm::DIScope *CGDebugInfo::getContextDescriptor(const Decl *Context,<br>
@@ -1448,6 +1450,9 @@ void CGDebugInfo::completeRequiredType(c<br>
     if (CXXDecl->isDynamicClass())<br>
       return;<br>
<br>
+  if (DebugTypeExtRefs && RD->isFromASTFile())<br>
+    return;<br>
+<br>
   QualType Ty = CGM.getContext().getRecordType(RD);<br>
   llvm::DIType *T = getTypeOrNull(Ty);<br>
   if (T && T->isForwardDecl())<br>
@@ -1478,8 +1483,19 @@ static bool hasExplicitMemberDefinition(<br>
 }<br>
<br>
 static bool shouldOmitDefinition(CodeGenOptions::DebugInfoKind DebugKind,<br>
+                                 bool DebugTypeExtRefs,<br>
                                  const RecordDecl *RD,<br>
                                  const LangOptions &LangOpts) {<br>
+  // Does the type exist in an imported clang module?<br>
+  if (DebugTypeExtRefs && RD->isFromASTFile()) {<br>
+    if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))<br>
+      if (CTSD->isExplicitInstantiationOrSpecialization())<br>
+        // We may not assume that this type made it into the module.<br></blockquote><div><br></div><div>I guess you mean "we may assume this type made it into the module"? (the "not" seems erroneous - but perhaps I'm misparsing the sentence?)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+        return true;<br></blockquote><div><br></div><div>Does this case ^ actually do anything? (aren't all these instantiations going to be definitions anyway? so if you removed that code the below would return true anyway, wouldn't it?)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+    if (RD->getDefinition())<br>
+      return true;<br>
+  }<br>
+<br>
   if (DebugKind > CodeGenOptions::LimitedDebugInfo)<br>
     return false;<br>
<br>
@@ -1513,7 +1529,8 @@ static bool shouldOmitDefinition(CodeGen<br>
 llvm::DIType *CGDebugInfo::CreateType(const RecordType *Ty) {<br>
   RecordDecl *RD = Ty->getDecl();<br>
   llvm::DIType *T = cast_or_null<llvm::DIType>(getTypeOrNull(QualType(Ty, 0)));<br>
-  if (T || shouldOmitDefinition(DebugKind, RD, CGM.getLangOpts())) {<br>
+  if (T || shouldOmitDefinition(DebugKind, DebugTypeExtRefs, RD,<br>
+                                CGM.getLangOpts())) {<br>
     if (!T)<br>
       T = getOrCreateRecordFwdDecl(Ty, getDeclContextDescriptor(RD));<br>
     return T;<br>
@@ -1616,6 +1633,12 @@ llvm::DIType *CGDebugInfo::CreateType(co<br>
   if (!ID)<br>
     return nullptr;<br>
<br>
+  // Return a forward declaration if this type was imported from a clang module.<br></blockquote><div><br></div><div>What's this extra code needed for? Isn't this what shouldOmitDefinition already does? It causes calls to getOrCreateRecordFwdDecl and so we should never get into the CreateTypeDefinition function for the type.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+  if (DebugTypeExtRefs && ID->isFromASTFile() && ID->getDefinition())<br>
+    return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,<br>
+                                      ID->getName(),<br>
+                                      getDeclContextDescriptor(ID), Unit, 0);<br>
+<br>
   // Get overall information about the record type for the debug info.<br>
   llvm::DIFile *DefUnit = getOrCreateFile(ID->getLocation());<br>
   unsigned Line = getLineNumber(ID->getLocation());<br>
@@ -1669,9 +1692,9 @@ CGDebugInfo::getOrCreateModuleRef(Extern<br>
       TheCU->getSourceLanguage(), internString(Mod.ModuleName),<br>
       internString(Mod.Path), TheCU->getProducer(), true, StringRef(), 0,<br>
       internString(Mod.ASTFile), llvm::DIBuilder::FullDebug, Mod.Signature);<br>
-  llvm::DIModule *M =<br>
-      DIB.createModule(CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path),<br>
-                       internString(CGM.getHeaderSearchOpts().Sysroot));<br>
+  llvm::DIModule *M = DIB.createModule(<br>
+      CU, Mod.ModuleName, ConfigMacros, internString(Mod.Path),<br>
+      internString(CGM.getHeaderSearchOpts().Sysroot));<br></blockquote><div><br></div><div>This is just reformatting, yes? (stared at it for a while & couldn't spot the difference)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
   DIB.finalize();<br>
   ModRef.reset(M);<br>
   return M;<br>
@@ -1930,6 +1953,7 @@ llvm::DIType *CGDebugInfo::CreateType(co<br>
<br>
 llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {<br>
   const EnumDecl *ED = Ty->getDecl();<br>
+<br>
   uint64_t Size = 0;<br>
   uint64_t Align = 0;<br>
   if (!ED->getTypeForDecl()->isIncompleteType()) {<br>
@@ -1939,9 +1963,12 @@ llvm::DIType *CGDebugInfo::CreateEnumTyp<br>
<br>
   SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);<br>
<br>
+  bool isImportedFromModule =<br>
+      DebugTypeExtRefs && ED->isFromASTFile() && ED->getDefinition();<br>
+<br></blockquote><div><br></div><div>Again, seems like code that shouldn't be here - shouldOmitDefinition returning true should mean that getOrCreateRecordFwdDecl is called and we never reach into the concrete CreateXXX functions.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
   // If this is just a forward declaration, construct an appropriately<br>
   // marked node and just return it.<br>
-  if (!ED->getDefinition()) {<br>
+  if (isImportedFromModule || !ED->getDefinition()) {<br>
     llvm::DIScope *EDContext = getDeclContextDescriptor(ED);<br>
     llvm::DIFile *DefUnit = getOrCreateFile(ED->getLocation());<br>
     unsigned Line = getLineNumber(ED->getLocation());<br>
@@ -2081,9 +2108,8 @@ llvm::DIType *CGDebugInfo::getOrCreateTy<br>
   if (auto *T = getTypeOrNull(Ty))<br>
     return T;<br>
<br>
-  // Otherwise create the type.<br>
   llvm::DIType *Res = CreateTypeNode(Ty, Unit);<br>
-  void *TyPtr = Ty.getAsOpaquePtr();<br>
+  void* TyPtr = Ty.getAsOpaquePtr();<br>
<br>
   // And update the type cache.<br>
   TypeCache[TyPtr].reset(Res);<br>
@@ -2115,6 +2141,19 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCI<br>
   }<br>
 }<br>
<br>
+llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {<br>
+  if (!DebugTypeExtRefs || !D || !D->isFromASTFile())<br></blockquote><div><br></div><div>Is a null Decl valid here? What's that for?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+    return nullptr;<br>
+<br>
+  llvm::DIModule *ModuleRef = nullptr;<br>
+  auto *Reader = CGM.getContext().getExternalSource();<br>
+  auto Idx = D->getOwningModuleID();<br>
+  auto Info = Reader->getSourceDescriptor(Idx);<br>
+  if (Info)<br>
+    ModuleRef = getOrCreateModuleRef(*Info);<br>
+  return ModuleRef;<br>
+}<br>
+<br>
 llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {<br>
   // Handle qualifiers, which recursively handles what they refer to.<br>
   if (Ty.hasLocalQualifiers())<br>
@@ -2325,8 +2364,10 @@ void CGDebugInfo::collectFunctionDeclPro<br>
         dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))<br>
       FDContext = getOrCreateNameSpace(NSDecl);<br>
     else if (const RecordDecl *RDecl =<br>
-             dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))<br>
-      FDContext = getContextDescriptor(RDecl, TheCU);<br>
+             dyn_cast_or_null<RecordDecl>(FD->getDeclContext())) {<br>
+      llvm::DIScope *Mod = getParentModuleOrNull(RDecl);<br>
+      FDContext = getContextDescriptor(RDecl, Mod ? Mod : TheCU);<br>
+    }<br>
     // Collect template parameters.<br>
     TParamsArray = CollectFunctionTemplateParams(FD, Unit);<br>
   }<br>
@@ -2374,7 +2415,9 @@ void CGDebugInfo::collectVarDeclProps(co<br>
   // outside the class by putting it in the global scope.<br>
   if (DC->isRecord())<br>
     DC = CGM.getContext().getTranslationUnitDecl();<br>
-  VDContext = getContextDescriptor(cast<Decl>(DC), TheCU);<br>
+<br>
+ llvm::DIScope *Mod = getParentModuleOrNull(VD);<br>
+ VDContext = getContextDescriptor(cast<Decl>(DC), Mod ? Mod : TheCU);<br></blockquote><div><br>I'm not quite seeing why this (& the other two/three cases) aren't using the <span style="font-family:monospace">getDeclContextDescriptor helper you added? Could you explain it to me?</span></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
 }<br>
<br>
 llvm::DISubprogram *<br>
@@ -3299,7 +3342,8 @@ void CGDebugInfo::EmitGlobalVariable(con<br>
 llvm::DIScope *CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {<br>
   if (!LexicalBlockStack.empty())<br>
     return LexicalBlockStack.back();<br>
-  return getContextDescriptor(D, TheCU);<br>
+  llvm::DIScope *Mod = getParentModuleOrNull(D);<br>
+  return getContextDescriptor(D, Mod ? Mod : TheCU);<br>
 }<br>
<br>
 void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=247432&r1=247431&r2=247432&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=247432&r1=247431&r2=247432&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Fri Sep 11 12:23:08 2015<br>
@@ -397,6 +397,9 @@ private:<br>
   llvm::DIModule *<br>
   getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod);<br>
<br>
+  /// DebugTypeExtRefs: If \p D originated in a clang module, return it.<br>
+  llvm::DIModule *getParentModuleOrNull(const Decl *D);<br>
+<br>
   /// Get the type from the cache or create a new partial type if<br>
   /// necessary.<br>
   llvm::DICompositeType *getOrCreateLimitedType(const RecordType *Ty,<br>
<br>
Added: cfe/trunk/test/Modules/ExtDebugInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.cpp?rev=247432&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.cpp?rev=247432&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/ExtDebugInfo.cpp (added)<br>
+++ cfe/trunk/test/Modules/ExtDebugInfo.cpp Fri Sep 11 12:23:08 2015<br>
@@ -0,0 +1,69 @@<br>
+// RUN: rm -rf %t<br>
+// Test that only forward declarations are emitted for types dfined in modules.<br>
+<br>
+// Modules:<br>
+// RUN: %clang_cc1 -x objective-c++ -std=c++11 -g -dwarf-ext-refs -fmodules \<br>
+// RUN:     -fmodule-format=obj -fimplicit-module-maps -DMODULES \<br>
+// RUN:     -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t-mod.ll<br>
+// RUN: cat %t-mod.ll |  FileCheck %s<br>
+<br>
+// PCH:<br>
+// RUN: %clang_cc1 -x c++ -std=c++11 -fmodule-format=obj -emit-pch -I%S/Inputs \<br>
+// RUN:     -o %t.pch %S/Inputs/DebugCXX.h<br>
+// RUN: %clang_cc1 -std=c++11 -g -dwarf-ext-refs -fmodule-format=obj \<br>
+// RUN:     -include-pch %t.pch %s -emit-llvm -o %t-pch.ll %s<br>
+// RUN: cat %t-pch.ll |  FileCheck %s<br>
+<br>
+#ifdef MODULES<br>
+@import DebugCXX;<br>
+#endif<br>
+<br>
+using DebugCXX::Struct;<br>
+<br>
+Struct s;<br>
+DebugCXX::Enum e;<br>
+DebugCXX::Template<long> implicitTemplate;<br>
+DebugCXX::Template<int> explicitTemplate;<br>
+DebugCXX::FloatInstatiation typedefTemplate;<br>
+int Struct::static_member = -1;<br>
+enum {<br>
+  e3 = -1<br>
+} conflicting_uid = e3;<br>
+auto anon_enum = DebugCXX::e2;<br>
+char _anchor = anon_enum + conflicting_uid;<br>
+<br>
+// CHECK: ![[NS:.*]] = !DINamespace(name: "DebugCXX", scope: ![[MOD:[0-9]+]],<br>
+// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugCXX<br>
+<br>
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Struct",<br>
+// CHECK-SAME:             scope: ![[NS]],<br>
+// CHECK-SAME:             flags: DIFlagFwdDecl,<br>
+// CHECK-SAME:             identifier: "_ZTSN8DebugCXX6StructE")<br>
+<br>
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "Enum",<br>
+// CHECK-SAME:             scope: ![[NS]],<br>
+// CHECK-SAME:             flags: DIFlagFwdDecl,<br>
+// CHECK-SAME:             identifier:  "_ZTSN8DebugCXX4EnumE")<br>
+<br>
+// CHECK: !DICompositeType(tag: DW_TAG_class_type,<br>
+<br>
+// CHECK: !DICompositeType(tag: DW_TAG_class_type,<br>
+// CHECK-SAME:             name: "Template<int, DebugCXX::traits<int> >",<br>
+// CHECK-SAME:             scope: ![[NS]],<br>
+// CHECK-SAME:             flags: DIFlagFwdDecl,<br>
+// CHECK-SAME:             identifier: "_ZTSN8DebugCXX8TemplateIiNS_6traitsIiEEEE")<br>
+<br>
+// CHECK: !DICompositeType(tag: DW_TAG_class_type,<br>
+// CHECK-SAME:             name: "Template<float, DebugCXX::traits<float> >",<br>
+// CHECK-SAME:             scope: ![[NS]],<br>
+// CHECK-SAME:             flags: DIFlagFwdDecl,<br>
+// CHECK-SAME:             identifier: "_ZTSN8DebugCXX8TemplateIfNS_6traitsIfEEEE")<br>
+<br>
+// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_member",<br>
+// CHECK-SAME:           scope: !"_ZTSN8DebugCXX6StructE"<br>
+<br>
+// CHECK: !DIGlobalVariable(name: "anon_enum", {{.*}}, type: ![[ANON_ENUM:[0-9]+]]<br>
+// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, scope: ![[NS]],<br>
+// CHECK-SAME:             line: 16<br>
+<br>
+// CHECK: !DIImportedEntity(tag: DW_TAG_imported_declaration, scope: !0, entity: !"_ZTSN8DebugCXX6StructE", line: 21)<br>
<br>
Added: cfe/trunk/test/Modules/ExtDebugInfo.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.m?rev=247432&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/ExtDebugInfo.m?rev=247432&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/ExtDebugInfo.m (added)<br>
+++ cfe/trunk/test/Modules/ExtDebugInfo.m Fri Sep 11 12:23:08 2015<br>
@@ -0,0 +1,29 @@<br>
+// RUN: rm -rf %t<br>
+// Test that only forward declarations are emitted for types dfined in modules.<br></blockquote><div><br></div><div>Typo "dfined".<br><br>I don't see where/how this test is testing for forward declarations - it doesn't seem to test for any declarations or definitions. (they could be emitted as either, or not emitted at all?)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+// Modules:<br>
+// RUN: %clang_cc1 -x objective-c -g -dwarf-ext-refs -fmodules \<br>
+// RUN:     -fmodule-format=obj -fimplicit-module-maps -DMODULES \<br>
+// RUN:     -fmodules-cache-path=%t %s -I %S/Inputs -I %t -emit-llvm -o %t-mod.ll<br>
+// RUN: cat %t-mod.ll |  FileCheck %s<br>
+<br>
+// PCH:<br>
+// RUN: %clang_cc1 -x objective-c -fmodule-format=obj -emit-pch -I%S/Inputs \<br>
+// RUN:     -o %t.pch %S/Inputs/DebugObjC.h<br>
+// RUN: %clang_cc1 -x objective-c -g -dwarf-ext-refs -fmodule-format=obj \<br>
+// RUN:     -include-pch %t.pch %s -emit-llvm -o %t-pch.ll %s<br>
+// RUN: cat %t-pch.ll |  FileCheck %s<br>
+<br>
+#ifdef MODULES<br>
+@import DebugObjC;<br>
+#endif<br>
+<br>
+int foo(ObjCClass *c) {<br>
+  [c instanceMethodWithInt: 0];<br>
+  return [c property];<br>
+}<br>
+<br>
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type,<br>
+// CHECK-SAME:             scope: ![[MOD:[0-9]+]],<br>
+// CHECK-SAME:             flags: DIFlagFwdDecl)<br>
+// CHECK: ![[MOD]] = !DIModule(scope: null, name: {{.*}}DebugObjC </blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>