<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>Hey Dave!</div><div><br></div><div>This causes our LTO builders to blow up due to use of too much memory (i.e. out of swap). This has been messing with our builders all weekend so I am going to revert now. Can you work with me on IRC to resolve the issue?</div><div><br></div><div>Michael</div><br><div><div>On Aug 18, 2013, at 10:59 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Author: dblaikie<br>Date: Sun Aug 18 12:59:12 2013<br>New Revision: 188642<br><br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=188642&view=rev">http://llvm.org/viewvc/llvm-project?rev=188642&view=rev</a><br>Log:<br>Revert "Revert "DebugInfo: Omit debug info for dynamic classes in TUs that do not have the vtable for that class""<br><br>This reverts commit r188600.<br><br>r188640/r188639 fixed the root cause of the crash-on-valid that r188600<br>originally introduced. This now appears to bootstrap debug clang<br>successfully to the best of my testing.<br><br>Modified:<br>   cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>   cfe/trunk/lib/CodeGen/CGDebugInfo.h<br>   cfe/trunk/lib/CodeGen/CGVTables.cpp<br>   cfe/trunk/test/CodeGenCXX/debug-info-class.cpp<br><br>Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=188642&r1=188641&r2=188642&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=188642&r1=188641&r2=188642&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Sun Aug 18 12:59:12 2013<br>@@ -644,8 +644,24 @@ llvm::DIDescriptor CGDebugInfo::createCo<br><br>  if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {<br>    if (!RD->isDependentType()) {<br>-      llvm::DIType Ty = getOrCreateLimitedType(<br>-          CGM.getContext().getRecordType(RD)->castAs<RecordType>(), getOrCreateMainFile());<br>+      llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));<br>+      llvm::DICompositeType Ty(getOrCreateLimitedType(<br>+          CGM.getContext().getRecordType(RD)->castAs<RecordType>(),<br>+          getOrCreateMainFile()));<br>+      if (!Ty.getTypeArray().getNumElements()) {<br>+        if (T) {<br>+          llvm::DIArray PrevMem = T.getTypeArray();<br>+          unsigned NumElements = PrevMem.getNumElements();<br>+          if (NumElements == 1 && !PrevMem.getElement(0))<br>+            NumElements = 0;<br>+          SmallVector<llvm::Value *, 16> EltTys;<br>+          EltTys.reserve(NumElements);<br>+          for (unsigned i = 0; i != NumElements; ++i)<br>+            EltTys.push_back(PrevMem.getElement(i));<br>+          llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);<br>+          Ty.setTypeArray(Elements);<br>+        }<br>+      }<br>      return llvm::DIDescriptor(Ty);<br>    }<br>  }<br>@@ -865,7 +881,7 @@ CollectRecordLambdaFields(const CXXRecor<br>  }<br>}<br><br>-/// CollectRecordStaticField - Helper for CollectRecordFields.<br>+/// Helper for CollectRecordFields.<br>llvm::DIDerivedType<br>CGDebugInfo::CreateRecordStaticField(const VarDecl *Var,<br>                                     llvm::DIType RecordTy) {<br>@@ -948,7 +964,7 @@ void CGDebugInfo::CollectRecordFields(co<br>    for (RecordDecl::decl_iterator I = record->decls_begin(),<br>           E = record->decls_end(); I != E; ++I)<br>      if (const VarDecl *V = dyn_cast<VarDecl>(*I))<br>-        elements.push_back(CreateRecordStaticField(V, RecordTy));<br>+        elements.push_back(getOrCreateStaticDataMemberDeclaration(V, RecordTy));<br>      else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {<br>        CollectRecordNormalField(field, layout.getFieldOffset(fieldNo),<br>                                 tunit, elements, RecordTy);<br>@@ -1119,8 +1135,14 @@ CollectCXXMemberFunctions(const CXXRecor<br>    if (D->isImplicit())<br>      continue;<br><br>-    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))<br>-      EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));<br>+    if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {<br>+      llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator MI =<br>+          SPCache.find(Method->getCanonicalDecl());<br>+      if (MI == SPCache.end())<br>+        EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));<br>+      else<br>+        EltTys.push_back(MI->second);<br>+    }<br>  }<br>}<br><br>@@ -1404,10 +1426,18 @@ void CGDebugInfo::completeType(const Rec<br>}<br><br>void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {<br>+  if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))<br>+    if (CXXDecl->isDynamicClass())<br>+      return;<br>+<br>  QualType Ty = CGM.getContext().getRecordType(RD);<br>  llvm::DIType T = getTypeOrNull(Ty);<br>-  if (!T || !T.isForwardDecl())<br>-    return;<br>+  if (T && T.isForwardDecl())<br>+    completeClassData(RD);<br>+}<br>+<br>+void CGDebugInfo::completeClassData(const RecordDecl *RD) {<br>+  QualType Ty = CGM.getContext().getRecordType(RD);<br>  void* TyPtr = Ty.getAsOpaquePtr();<br>  if (CompletedTypeCache.count(TyPtr))<br>    return;<br>@@ -1420,14 +1450,23 @@ void CGDebugInfo::completeRequiredType(c<br>/// CreateType - get structure or union type.<br>llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, bool Declaration) {<br>  RecordDecl *RD = Ty->getDecl();<br>+  const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);<br>  // Limited debug info should only remove struct definitions that can<br>  // safely be replaced by a forward declaration in the source code.<br>-  if (DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration &&<br>-      !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) {<br>+  if ((DebugKind <= CodeGenOptions::LimitedDebugInfo && Declaration &&<br>+       !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||<br>+      (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass())) {<br>    llvm::DIDescriptor FDContext =<br>      getContextDescriptor(cast<Decl>(RD->getDeclContext()));<br>    llvm::DIType RetTy = getOrCreateRecordFwdDecl(RD, FDContext);<br>-    return RetTy;<br>+    // FIXME: This is conservatively correct. If we return a non-forward decl<br>+    // that's not a full definition (such as those created by<br>+    // createContextChain) then getOrCreateType will record is as a complete<br>+    // type and we'll never record all its members. But this means we're<br>+    // emitting full debug info in TUs where GCC successfully emits a partial<br>+    // definition of the type.<br>+    if (RetTy.isForwardDecl())<br>+      return RetTy;<br>  }<br><br>  return CreateTypeDefinition(Ty);<br>@@ -1465,6 +1504,7 @@ llvm::DIType CGDebugInfo::CreateTypeDefi<br><br>  // Convert all the elements.<br>  SmallVector<llvm::Value *, 16> EltTys;<br>+  // what about nested types?<br><br>  // Note: The split of CXXDecl information here is intentional, the<br>  // gdb tests will depend on a certain ordering at printout. The debug<br>@@ -2306,7 +2346,7 @@ llvm::DISubprogram CGDebugInfo::getFunct<br>  llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator<br>    MI = SPCache.find(FD->getCanonicalDecl());<br>  if (MI == SPCache.end()) {<br>-    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) {<br>+    if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {<br>      llvm::DICompositeType T(S);<br>      llvm::DISubprogram SP = CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T);<br>      T.addMember(SP);<br>@@ -3012,19 +3052,35 @@ void CGDebugInfo::EmitDeclareOfBlockLite<br>  DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope));<br>}<br><br>-/// getStaticDataMemberDeclaration - If D is an out-of-class definition of<br>-/// a static data member of a class, find its corresponding in-class<br>-/// declaration.<br>-llvm::DIDerivedType CGDebugInfo::getStaticDataMemberDeclaration(const VarDecl *D) {<br>-  if (D->isStaticDataMember()) {<br>-    llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator<br>-      MI = StaticDataMemberCache.find(D->getCanonicalDecl());<br>-    if (MI != StaticDataMemberCache.end())<br>-      // Verify the info still exists.<br>-      if (llvm::Value *V = MI->second)<br>-        return llvm::DIDerivedType(cast<llvm::MDNode>(V));<br>+/// If D is an out-of-class definition of a static data member of a class, find<br>+/// its corresponding in-class declaration.<br>+llvm::DIDerivedType<br>+CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {<br>+  if (!D->isStaticDataMember())<br>+    return llvm::DIDerivedType();<br>+  llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =<br>+      StaticDataMemberCache.find(D->getCanonicalDecl());<br>+  if (MI != StaticDataMemberCache.end()) {<br>+    assert(MI->second && "Static data member declaration should still exist");<br>+    return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));<br>+  }<br>+  llvm::DICompositeType Ctxt(<br>+      getContextDescriptor(cast<Decl>(D->getDeclContext())));<br>+  llvm::DIDerivedType T = CreateRecordStaticField(D, Ctxt);<br>+  Ctxt.addMember(T);<br>+  return T;<br>+}<br>+<br>+llvm::DIDerivedType<br>+CGDebugInfo::getOrCreateStaticDataMemberDeclaration(const VarDecl *D,<br>+                                            llvm::DICompositeType Ctxt) {<br>+  llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =<br>+      StaticDataMemberCache.find(D->getCanonicalDecl());<br>+  if (MI != StaticDataMemberCache.end()) {<br>+    assert(MI->second && "Static data member declaration should still exist");<br>+    return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));<br>  }<br>-  return llvm::DIDerivedType();<br>+  return CreateRecordStaticField(D, Ctxt);<br>}<br><br>/// EmitGlobalVariable - Emit information about a global variable.<br>@@ -3056,11 +3112,10 @@ void CGDebugInfo::EmitGlobalVariable(llv<br>    LinkageName = StringRef();<br>  llvm::DIDescriptor DContext =<br>    getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));<br>-  llvm::DIGlobalVariable GV =<br>-      DBuilder.createStaticVariable(DContext, DeclName, LinkageName, Unit,<br>-                                    LineNo, getOrCreateType(T, Unit),<br>-                                    Var->hasInternalLinkage(), Var,<br>-                                    getStaticDataMemberDeclaration(D));<br>+  llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(<br>+      DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),<br>+      Var->hasInternalLinkage(), Var,<br>+      getOrCreateStaticDataMemberDeclarationOrNull(D));<br>  DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV)));<br>}<br><br>@@ -3108,7 +3163,7 @@ void CGDebugInfo::EmitGlobalVariable(con<br>    return;<br>  llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(<br>      Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init,<br>-      getStaticDataMemberDeclaration(cast<VarDecl>(VD)));<br>+      getOrCreateStaticDataMemberDeclarationOrNull(cast<VarDecl>(VD)));<br>  DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV)));<br>}<br><br><br>Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=188642&r1=188641&r2=188642&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=188642&r1=188641&r2=188642&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)<br>+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Sun Aug 18 12:59:12 2013<br>@@ -291,7 +291,7 @@ public:<br><br>  void completeType(const RecordDecl *RD);<br>  void completeRequiredType(const RecordDecl *RD);<br>-<br>+  void completeClassData(const RecordDecl *RD);<br><br>private:<br>  /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.<br>@@ -354,10 +354,13 @@ private:<br>  /// declaration for the given method definition.<br>  llvm::DISubprogram getFunctionDeclaration(const Decl *D);<br><br>-  /// getStaticDataMemberDeclaration - Return debug info descriptor to<br>-  /// describe in-class static data member declaration for the given<br>-  /// out-of-class definition.<br>-  llvm::DIDerivedType getStaticDataMemberDeclaration(const VarDecl *D);<br>+  /// Return debug info descriptor to describe in-class static data member<br>+  /// declaration for the given out-of-class definition.<br>+  llvm::DIDerivedType<br>+  getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D);<br>+  llvm::DIDerivedType<br>+  getOrCreateStaticDataMemberDeclaration(const VarDecl *D,<br>+                                         llvm::DICompositeType Ctxt);<br><br>  /// getFunctionName - Get function name for the given FunctionDecl. If the<br>  /// name is constructred on demand (e.g. C++ destructor) then the name<br><br>Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=188642&r1=188641&r2=188642&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=188642&r1=188641&r2=188642&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)<br>+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Sun Aug 18 12:59:12 2013<br>@@ -828,6 +828,9 @@ CodeGenVTables::GenerateClassData(const<br>    VFTContext->getVFPtrOffsets(RD);<br>  }<br><br>+  if (CGDebugInfo *DI = CGM.getModuleDebugInfo())<br>+    DI->completeClassData(RD);<br>+<br>  // First off, check whether we've already emitted the v-table and<br>  // associated stuff.<br>  llvm::GlobalVariable *VTable = GetAddrOfVTable(RD);<br><br>Modified: cfe/trunk/test/CodeGenCXX/debug-info-class.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-class.cpp?rev=188642&r1=188641&r2=188642&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-class.cpp?rev=188642&r1=188641&r2=188642&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CodeGenCXX/debug-info-class.cpp (original)<br>+++ cfe/trunk/test/CodeGenCXX/debug-info-class.cpp Sun Aug 18 12:59:12 2013<br>@@ -13,7 +13,39 @@ public:<br>  virtual ~B();<br>};<br><br>+B::~B() {<br>+}<br>+<br>struct C {<br>+  static int s;<br>+  virtual ~C();<br>+};<br>+<br>+C::~C() {<br>+}<br>+<br>+struct D {<br>+  D();<br>+  virtual ~D();<br>+  void func() {<br>+  }<br>+};<br>+<br>+struct E {<br>+  E();<br>+  virtual ~E();<br>+  virtual void func() {<br>+  }<br>+};<br>+<br>+struct F {<br>+  struct inner {<br>+  };<br>+  static const int i = 2;<br>+  virtual ~F();<br>+};<br>+<br>+struct G {<br>  virtual void func();<br>  struct inner {<br>    int j;<br>@@ -29,10 +61,17 @@ struct A {<br>  }<br>};<br><br>+void f1() {<br>+  D x;<br>+  x.func();<br>+  E y;<br>+  int i = F::i;<br>+  F::inner z;<br>+}<br><br>int main(int argc, char **argv) {<br>  B b;<br>-  C::inner c_i;<br>+  G::inner c_i;<br>  if (argc) {<br>    A a;<br>  }<br>@@ -49,15 +88,34 @@ int main(int argc, char **argv) {<br>// CHECK: DW_TAG_structure_type ] [foo]<br>// CHECK: DW_TAG_class_type ] [bar]<br>// CHECK: DW_TAG_union_type ] [baz]<br>-// CHECK: DW_TAG_structure_type ] [A]<br>-// CHECK: HdrSize<br>// CHECK: DW_TAG_class_type ] [B]<br>// CHECK: metadata !"_vptr$B", {{.*}}, i32 64, metadata !{{.*}}} ; [ DW_TAG_member ]<br>-// CHECK: metadata [[C_INNER_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [inner] {{.*}} [def]<br>+<br>+// CHECK: [[C:![0-9]*]] = {{.*}} metadata [[C_MEM:![0-9]*]], i32 0, metadata [[C]], null} ; [ DW_TAG_structure_type ] [C] {{.*}} [def]<br>+// CHECK: [[C_MEM]] = metadata !{metadata [[C_VPTR:![0-9]*]], metadata [[C_S:![0-9]*]], metadata [[C_DTOR:![0-9]*]]}<br>+// CHECK: [[C_VPTR]] = {{.*}} ; [ DW_TAG_member ] [_vptr$C] {{.*}} [artificial]<br>+// CHECK: [[C_S]] = {{.*}} ; [ DW_TAG_member ] [s] {{.*}} [static] [from int]<br>+// CHECK: [[C_DTOR]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [~C]<br>+<br>+// CHECK: ; [ DW_TAG_structure_type ] [A]<br>+// CHECK: HdrSize<br>+// CHECK: metadata [[D_MEM:![0-9]*]], i32 0, null} ; [ DW_TAG_structure_type ] [D] {{.*}} [decl]<br>+// CHECK: [[D_MEM]] = metadata !{metadata [[D_FUNC:![0-9]*]]}<br>+// CHECK: [[D_FUNC]] = {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [func]<br>+<br>+// CHECK: [[F_I_DEF:![0-9]*]] = {{.*}}, metadata [[F_I:![0-9]*]]} ; [ DW_TAG_variable ] [i]<br>+// CHECK: [[F_I]] = {{.*}} ; [ DW_TAG_member ] [i]<br>+// CHECK: [[F:![0-9]*]] = {{.*}} metadata [[F_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [F] {{.*}} [def]<br>+// CHECK: [[F_MEM]] = metadata !{metadata [[F_I]]}<br>+<br>+// CHECK: null, i32 0, null} ; [ DW_TAG_structure_type ] [E] {{.*}} [decl]<br>+<br>+// CHECK: metadata [[G_INNER_MEM:![0-9]*]], i32 0, null, null} ; [ DW_TAG_structure_type ] [inner] [line 50, {{.*}} [def]<br>// Context chains (in Clang -flimit-debug-info and in GCC generally) contain<br>// definitions without members (& without a vbase 'containing type'):<br>-// CHECK: null, i32 0, null, null} ; [ DW_TAG_structure_type ] [C] {{.*}} [def]<br>-// CHECK: [[C_INNER_MEM]] = metadata !{metadata [[C_INNER_I:![0-9]*]]}<br>-// CHECK: [[C_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int]<br>-// CHECK: ![[EXCEPTLOC]] = metadata !{i32 40,<br>-// CHECK: ![[RETLOC]] = metadata !{i32 39,<br>+// CHECK: null, i32 0, null, null} ; [ DW_TAG_structure_type ] [G] {{.*}} [def]<br>+// CHECK: [[G_INNER_MEM]] = metadata !{metadata [[G_INNER_I:![0-9]*]]}<br>+// CHECK: [[G_INNER_I]] = {{.*}} ; [ DW_TAG_member ] [j] {{.*}} [from int]<br>+<br>+// CHECK: ![[EXCEPTLOC]] = metadata !{i32 79,<br>+// CHECK: ![[RETLOC]] = metadata !{i32 78,<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a></div></blockquote></div><br></body></html>