diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index d81c304356d..e3cf13a5d9a 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -780,12 +780,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) { @@ -967,6 +981,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: @@ -1325,8 +1343,7 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) { // function then gdb prefers the definition at top level and but does not // expect specification DIE in parent function. So avoid creating // specification DIE for a function defined inside a function. - if (SP.isDefinition() && !SP.getContext().isCompileUnit() && - !SP.getContext().isFile() && !SP.getContext().isSubprogram()) { + if (SP.isDefinition() && !isFunctionContext(SPDie->getParent())) { addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); // Add arguments. @@ -1754,19 +1771,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()); diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index ad6b0c2cb7c..fba39a14bbb 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -315,6 +315,9 @@ class DwarfDebug : public DwarfPrinter { /// 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);