diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp')
| -rw-r--r-- | source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 65 |
1 files changed, 64 insertions, 1 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index e2902d5ef787..1d8b759d2fa8 100644 --- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -3682,7 +3682,7 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) { break; case DW_TAG_lexical_block: - decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die); + decl_ctx = GetDeclContextForBlock(die); try_parsing_type = false; break; @@ -3704,6 +3704,69 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) { return nullptr; } +static bool IsSubroutine(const DWARFDIE &die) { + switch (die.Tag()) { + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: + return true; + default: + return false; + } +} + +static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) { + for (DWARFDIE candidate = die; candidate; candidate = candidate.GetParent()) { + if (IsSubroutine(candidate)) { + if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) { + return candidate; + } else { + return DWARFDIE(); + } + } + } + assert(!"Shouldn't call GetContainingFunctionWithAbstractOrigin on something " + "not in a function"); + return DWARFDIE(); +} + +static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) { + for (DWARFDIE candidate = context.GetFirstChild(); candidate.IsValid(); + candidate = candidate.GetSibling()) { + if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) { + return candidate; + } + } + return DWARFDIE(); +} + +static DWARFDIE FindFirstChildWithAbstractOrigin(const DWARFDIE &block, + const DWARFDIE &function) { + assert(IsSubroutine(function)); + for (DWARFDIE context = block; context != function.GetParent(); + context = context.GetParent()) { + assert(!IsSubroutine(context) || context == function); + if (DWARFDIE child = FindAnyChildWithAbstractOrigin(context)) { + return child; + } + } + return DWARFDIE(); +} + +clang::DeclContext * +DWARFASTParserClang::GetDeclContextForBlock(const DWARFDIE &die) { + assert(die.Tag() == DW_TAG_lexical_block); + DWARFDIE containing_function_with_abstract_origin = + GetContainingFunctionWithAbstractOrigin(die); + if (!containing_function_with_abstract_origin) { + return (clang::DeclContext *)ResolveBlockDIE(die); + } + DWARFDIE child = FindFirstChildWithAbstractOrigin( + die, containing_function_with_abstract_origin); + CompilerDeclContext decl_context = + GetDeclContextContainingUIDFromDWARF(child); + return (clang::DeclContext *)decl_context.GetOpaqueDeclContext(); +} + clang::BlockDecl *DWARFASTParserClang::ResolveBlockDIE(const DWARFDIE &die) { if (die && die.Tag() == DW_TAG_lexical_block) { clang::BlockDecl *decl = |
