Index: lit/SymbolFile/DWARF/find-method-local-struct.cpp =================================================================== --- lit/SymbolFile/DWARF/find-method-local-struct.cpp +++ lit/SymbolFile/DWARF/find-method-local-struct.cpp @@ -1,6 +1,3 @@ -// llvm.org/pr37537 -// XFAIL: * - // RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx // RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \ // RUN: FileCheck %s Index: source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -146,6 +146,14 @@ m_apple_namespaces_up->FindByName(name.GetStringRef(), offsets); } +static bool KeepFunctionDIE(DWARFDIE die, uint32_t name_type_mask) { + bool looking_for_methods = name_type_mask & eFunctionNameTypeMethod; + bool looking_for_functions = name_type_mask & eFunctionNameTypeBase; + if (looking_for_methods && looking_for_functions) + return true; + return looking_for_methods == die.IsMethod(); +} + void AppleDWARFIndex::GetFunctions( ConstString name, DWARFDebugInfo &info, llvm::function_refGetType(); - - if (type) { - CompilerDeclContext decl_ctx = - get_decl_context_containing_uid(type->GetID()); - if (decl_ctx.IsStructUnionOrClass()) { - if (name_type_mask & eFunctionNameTypeBase) { - sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1); - keep_die = false; - } - } else { - if (name_type_mask & eFunctionNameTypeMethod) { - sc_list.RemoveContextAtIndex(sc_list.GetSize() - 1); - keep_die = false; - } - } - } else { - m_module.ReportWarning( - "function at die offset 0x%8.8x had no function type", - die_ref.die_offset); - } - } - } - } - if (keep_die) - resolved_dies.insert(die.GetDIE()); - } + if (resolve_function(die, include_inlines, sc_list)) + resolved_dies.insert(die.GetDIE()); } else ReportInvalidDIEOffset(die_ref.die_offset, name.GetStringRef()); } Index: source/Plugins/SymbolFile/DWARF/DWARFDIE.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -19,7 +19,9 @@ //---------------------------------------------------------------------- // Tests //---------------------------------------------------------------------- - bool IsStructClassOrUnion() const; + bool IsStructUnionOrClass() const; + + bool IsMethod() const; //---------------------------------------------------------------------- // Accessors Index: source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -10,12 +10,12 @@ #include "DWARFDIE.h" #include "DWARFASTParser.h" -#include "DWARFUnit.h" #include "DWARFDIECollection.h" #include "DWARFDebugInfo.h" -#include "DWARFDeclContext.h" - #include "DWARFDebugInfoEntry.h" +#include "DWARFDeclContext.h" +#include "DWARFUnit.h" +#include "llvm/ADT/SmallSet.h" using namespace lldb_private; @@ -209,12 +209,37 @@ return DWARFDIE(); } -bool DWARFDIE::IsStructClassOrUnion() const { +bool DWARFDIE::IsStructUnionOrClass() const { const dw_tag_t tag = Tag(); return tag == DW_TAG_class_type || tag == DW_TAG_structure_type || tag == DW_TAG_union_type; } +bool DWARFDIE::IsMethod() const { + // Prevent infinite recursion by maintaining a list of seen DIEs. Container + // sizes are optimized for the case of following DW_AT_specification and + // DW_AT_abstract_origin just once. + llvm::SmallVector worklist(1, *this); + llvm::SmallSet seen; + + while (!worklist.empty()) { + DWARFDIE die = worklist.back(); + worklist.pop_back(); + if (!seen.insert(die.GetID()).second) + continue; + + DWARFDIE parent = die.GetParent(); + if (parent.IsStructUnionOrClass()) + return true; + + if (DWARFDIE d = die.GetReferencedDIE(DW_AT_specification)) + worklist.push_back(d); + if (DWARFDIE d = die.GetReferencedDIE(DW_AT_abstract_origin)) + worklist.push_back(d); + } + return false; +} + DWARFDIE DWARFDIE::GetContainingDWOModuleDIE() const { if (IsValid()) { Index: source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -288,22 +288,7 @@ } // If we have a mangled name, then the DW_AT_name attribute is // usually the method name without the class or any parameters - const DWARFDebugInfoEntry *parent = die.GetParent(); - bool is_method = false; - if (parent) { - DWARFDIE parent_die(&unit, parent); - if (parent_die.IsStructClassOrUnion()) - is_method = true; - else { - if (specification_die_form.IsValid()) { - DWARFDIE specification_die = - unit.GetSymbolFileDWARF()->DebugInfo()->GetDIE( - DIERef(specification_die_form)); - if (specification_die.GetParent().IsStructClassOrUnion()) - is_method = true; - } - } - } + bool is_method = DWARFDIE(&unit, &die).IsMethod(); if (is_method) set.function_methods.Insert(ConstString(name),