Revise debug info machinery to digest nested functions and classes.
authorStuart Hastings <stuart@apple.com>
Tue, 6 Apr 2010 17:19:32 +0000 (17:19 +0000)
committerStuart Hastings <stuart@apple.com>
Tue, 6 Apr 2010 17:19:32 +0000 (17:19 +0000)
A certain GDB testsuite case (local.cc) has a function nested inside a
class nested inside another function.  GCC presents the innermost
function to llvm-convert first.  Heretofore, the debug info mistakenly
placed the inner function at module scope.  This patch walks the GCC
context links and instantiates the outer class and function so the
debug info is properly nested.  Radar 7426545.

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

lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.h
test/FrontendC++/2010-02-17-DbgArtificialArg.cpp

index b472d1e5335c29ae155cef1894b62f678436e31c..0af6b3315ae73f5c694a96f8a0a041770cb04eaa 100644 (file)
@@ -800,12 +800,26 @@ void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) {
   } else if (Context.isNameSpace()) {
     DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context.getNode()));
     ContextDIE->addChild(Die);
+  } else if (Context.isSubprogram()) {
+    DIE *ContextDIE = createSubprogramDIE(DISubprogram(Context.getNode()),
+                                          /*MakeDecl=*/false);
+    ContextDIE->addChild(Die);
   } else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode()))
     ContextDIE->addChild(Die);
   else 
     ModuleCU->addDie(Die);
 }
 
+/// isFunctionContext - True if given Context is nested within a function. 
+bool DwarfDebug::isFunctionContext(DIE *context) {
+  if (context == (DIE *)0)
+    return false;
+  if (context->getTag() == dwarf::DW_TAG_subprogram)
+    return true;
+  else
+    return isFunctionContext(context->getParent());
+}
+
 /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
 /// given DIType.
 DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) {
@@ -987,6 +1001,10 @@ void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
     if (DIDescriptor(ContainingType.getNode()).isCompositeType())
       addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, 
                   getOrCreateTypeDIE(DIType(ContainingType.getNode())));
+    else {
+      DIDescriptor Context = CTy.getContext();
+      addToContextOwner(&Buffer, Context);
+    }
     break;
   }
   default:
@@ -1802,19 +1820,15 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
 void DwarfDebug::constructSubprogramDIE(MDNode *N) {
   DISubprogram SP(N);
 
-  // Check for pre-existence.
-  if (ModuleCU->getDIE(N))
-    return;
-
   if (!SP.isDefinition())
     // This is a method declaration which will be handled while constructing
     // class type.
     return;
 
-  DIE *SubprogramDie = createSubprogramDIE(SP);
-
-  // Add to map.
-  ModuleCU->insertDIE(N, SubprogramDie);
+  // Check for pre-existence.
+  DIE *SubprogramDie = ModuleCU->getDIE(N);
+  if (!SubprogramDie)
+    SubprogramDie = createSubprogramDIE(SP);
 
   // Add to context owner.
   addToContextOwner(SubprogramDie, SP.getContext());
index c7baf5f5d38db19740bba535adb1c8918c64841a..6d6d02b4dfa70c47c2a894de27cd74d0f93f2901 100644 (file)
@@ -332,6 +332,9 @@ private:
   /// addToContextOwner - Add Die into the list of its context owner's children.
   void addToContextOwner(DIE *Die, DIDescriptor Context);
 
+  /// isFunctionContext - True if given Context is nested within a function. 
+  bool isFunctionContext(DIE *context);
+
   /// addType - Add a new type attribute to the specified entity.
   void addType(DIE *Entity, DIType Ty);
 
index 2a9f1f156b1c57d96b9b6d5f38600235b2ae7104..ff45412b4414c247b2b1433efccce7c827510334 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %llvmgcc -g -S %s -o - | grep DW_TAG_pointer_type |  grep "i32 524303, metadata .., metadata ..., metadata .., i32 ., i64 .., i64 .., i64 0, i32 64, metadata ..."
+// RUN: %llvmgcc -g -S %s -o - | FileCheck %s
 // Here, second to last argument "i32 64" indicates that artificial type is set.                                               
 // Test to artificial attribute attahed to "this" pointer type.
 // Radar 7655792 and 7655002
@@ -10,5 +10,7 @@ public:
 
 int foo() {
   A a;
+  // Matching "i32 64, metadata !<number>} ; [ DW_TAG_pointer_type ]"
+  // CHECK: i32 64, metadata {{![0-9]+\} ; \[ DW_TAG_pointer_type \]}}
   return a.fn1(1);
 }