diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 4429b4fcae2a0..8401d648c6704 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -888,6 +888,46 @@ ConvertDWARFCallingConventionToClang(const ParsedDWARFTypeAttributes &attrs) { return clang::CC_C; } +/// Given a DIE with an external definition (and thus no linkage name) +/// find the definitions by lookup into the DWARF name index. +/// We check the DW_AT_specification for each DIE in the index with +/// the same name as the specified 'die' until we find one that references +/// 'die'. Then return that linkage name. If no such DIE is found in the index, +/// returns nullptr. +static char const *FindLinkageName(DWARFDIE die) { + auto *dwarf = die.GetDWARF(); + if (!dwarf) + return nullptr; + + ConstString func_name(die.GetName()); + if (!func_name) + return nullptr; + + SymbolContextList sc_list; + Module::LookupInfo lookup_info(func_name, + FunctionNameType::eFunctionNameTypeMethod | + FunctionNameType::eFunctionNameTypeFull, + LanguageType::eLanguageTypeUnknown); + dwarf->GetObjectFile()->GetModule()->FindFunctions(lookup_info, {}, {}, + sc_list); + + for (auto const &sc : sc_list.SymbolContexts()) { + if (auto *func = sc.function) { + auto func_die = dwarf->GetDIE(func->GetID()); + if (!func_die.IsValid()) + continue; + + auto spec_die = + func_die.GetAttributeValueAsReferenceDIE(DW_AT_specification); + if (spec_die.IsValid() && spec_die == die) { + return func->GetMangled().GetMangledName().AsCString(); + } + } + } + + return nullptr; +} + TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ParsedDWARFTypeAttributes &attrs) { Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); @@ -1116,6 +1156,9 @@ TypeSP DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, if (attrs.accessibility == eAccessNone) attrs.accessibility = eAccessPublic; + if (!attrs.mangled_name && attrs.storage == clang::SC_Extern) + attrs.mangled_name = FindLinkageName(die); + clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile new file mode 100644 index 0000000000000..eba15476332f9 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py new file mode 100644 index 0000000000000..e436252800a79 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py @@ -0,0 +1,31 @@ +""" +Test that we can constructors/destructors +without a linkage name because they are +marked DW_AT_external and the fallback +mangled-name-guesser in LLDB doesn't account +for ABI tags. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ExternalCtorDtorLookupTestCase(TestBase): + + @skipIfWindows + def test(self): + self.build() + lldbutil.run_to_source_breakpoint(self, 'b\.getWrapper\(\)', + lldb.SBFileSpec('main.cpp', False)) + + self.expect_expr('b.sinkWrapper(b.getWrapper())', result_type='int', result_value='-1') + self.filecheck("target module dump ast", __file__) +# CHECK: ClassTemplateSpecializationDecl {{.*}} class Wrapper definition +# CHECK: |-TemplateArgument type 'Foo' +# CHECK: | `-RecordType {{.*}} 'Foo' +# CHECK: | `-CXXRecord {{.*}} 'Foo' +# CHECK: |-CXXConstructorDecl {{.*}} Wrapper 'void ()' +# CHECK-NEXT: | `-AsmLabelAttr {{.*}} Implicit "_ZN7WrapperI3Foo{{.*}}testEv" +# CHECK-NEXT: `-CXXDestructorDecl {{.*}} ~Wrapper 'void ()' +# CHECK-NEXT: `-AsmLabelAttr {{.*}} Implicit "_ZN7WrapperI3Foo{{.*}}testEv" diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h new file mode 100644 index 0000000000000..9664068b6e141 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h @@ -0,0 +1,12 @@ +#ifndef LIB_H_IN +#define LIB_H_IN + +template class Wrapper { +public: + [[gnu::abi_tag("test")]] Wrapper(){}; + + [[gnu::abi_tag("test")]] ~Wrapper(){}; +}; + +#endif // _H_IN + diff --git a/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp new file mode 100644 index 0000000000000..3904646c05db3 --- /dev/null +++ b/lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp @@ -0,0 +1,14 @@ +#include "lib.h" + +struct Foo {}; + +struct Bar { + Wrapper getWrapper() { return Wrapper(); } + int sinkWrapper(Wrapper) { return -1; } +}; + +int main() { + Bar b; + return b.sinkWrapper(b.getWrapper()); +} +