Michael137 created this revision. Michael137 added reviewers: aprantl, dblaikie. Herald added a reviewer: shafik. Herald added a project: All. Michael137 added a comment. Michael137 updated this revision to Diff 498020. Michael137 updated this revision to Diff 498899. Michael137 updated this revision to Diff 499150. Michael137 updated this revision to Diff 500432. Michael137 updated this revision to Diff 500434. Michael137 published this revision for review. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
Alternative to https://reviews.llvm.org/D143652 Michael137 added a comment. - Update test dblaikie added a comment. Any chance we can make these work more like member functions (could the ctors include their mangled names, for instance)? Or is it the innate nature of ctors having the various C1 <https://reviews.llvm.org/C1>/C2/etc versions? dblaikie added a comment. In D144182#4132736 <https://reviews.llvm.org/D144182#4132736>, @dblaikie wrote: > Any chance we can make these work more like member functions (could the ctors > include their mangled names, for instance)? Or is it the innate nature of > ctors having the various C1 <https://reviews.llvm.org/C1>/C2/etc versions? Oh, sorry, this is more suitable on the LLVM side... I'll make the comment over there instead. Michael137 added a comment. - Fix test on Linux - Add -glldb flag to test Michael137 added a comment. - Add test case for `C2` constructor Michael137 added a comment. - Update tests Michael137 added a comment. - Update tets This patch adds support for parsing `DW_TAG_LLVM_annotation`s for abi_tag's. This allows us to recreate more accurate ASTs nodes for constructors/destructors, where previously we relied on guessing the correct name mangling to resolve a ctor/dtor call. If a ctor/dtor had an abi_tag we would fail to resolve the symbol because the "guessing algorithm" (see CollectCandidateCPlusPlusNames) doesn't account for them. This is necessary to support calling destructors/constructors of numerous libcxx types, since they recently got abi-tagged. **Testing** - Added API test Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D144182 Files: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.cpp lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp
Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/main.cpp @@ -0,0 +1,40 @@ +#include "lib.h" + +struct Bar { + Wrapper<Foo> getWrapper() { return Wrapper<Foo>(); } + int sinkWrapper(Wrapper<Foo>) { return -1; } +}; + +struct A { + int m_int = -1; + float m_float = -1.0; + [[gnu::abi_tag("Ctor", "Int")]] A(int a) : m_int(a) {} + [[gnu::abi_tag("Ctor", "Float")]] A(float f) : m_float(f) {} + [[gnu::abi_tag("Ctor", "Default")]] A() {} + [[gnu::abi_tag("Dtor", "Default")]] ~A() {} +}; + +struct B : virtual A { + [[gnu::abi_tag("TagB")]] B(); +}; +B::B() : A(47) {} + +struct D : B { + [[gnu::abi_tag("TagD")]] D() : A(4.7f) {} +}; + +struct X : public virtual A {}; + +int main() { + Bar b; + Wrapper<int> w1; + Wrapper<double> w2; + Wrapper<Foo> w3 = getFooWrapper(); + Wrapper<Foo> w4; + B b2; + D d; + A a; + auto *ptr = new X(); + delete ptr; + return b.sinkWrapper(b.getWrapper()); +} Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.h @@ -0,0 +1,15 @@ +#ifndef LIB_H_IN +#define LIB_H_IN + +template <typename T> class Wrapper { +public: + [[gnu::abi_tag("test", "ctor")]] Wrapper(){}; + + [[gnu::abi_tag("test", "dtor")]] ~Wrapper(){}; +}; + +struct Foo {}; + +Wrapper<Foo> getFooWrapper(); + +#endif // _H_IN Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.cpp =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/lib.cpp @@ -0,0 +1,3 @@ +#include "lib.h" + +Wrapper<Foo> getFooWrapper() { return {}; } Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/TestExternalCtorDtorLookup.py @@ -0,0 +1,51 @@ +""" +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.expect_expr('B{}.m_int', result_type='int', result_value='47') + self.expect_expr('D{}.m_int', result_type='int', result_value='-1') + self.filecheck("target module dump ast", __file__) +# CHECK: |-CXXRecordDecl {{.*}} struct B definition +# CHECK: | |-virtual public 'A' +# CHECK: | `-CXXConstructorDecl {{.*}} B 'void ()' +# CHECK: | `-AbiTagAttr {{.*}} TagB +# CHECK: |-CXXRecordDecl {{.*}} struct D definition +# CHECK: | `-CXXConstructorDecl {{.*}} D 'void ()' +# CHECK: | `-AbiTagAttr {{.*}} TagD +# CHECK: |-CXXRecordDecl {{.*}} struct A definition +# CHECK: | |-CXXConstructorDecl {{.*}} A 'void (int)' +# CHECK: | | |-ParmVarDecl {{.*}} 'int' +# CHECK: | | `-AbiTagAttr {{.*}} Ctor Int +# CHECK: | |-CXXConstructorDecl {{.*}} A 'void (float)' +# CHECK: | | |-ParmVarDecl {{.*}} 'float' +# CHECK: | | `-AbiTagAttr {{.*}} Ctor Float +# CHECK: | |-CXXConstructorDecl {{.*}} A 'void ()' +# CHECK: | | `-AbiTagAttr {{.*}} Ctor Default +# CHECK: | `-CXXDestructorDecl {{.*}} ~A 'void ()' +# CHECK: | `-AbiTagAttr {{.*}} Default Dtor + + # Confirm that we can call the C2 constructor for 'struct A' + self.expect('expression --top-level -- class Derived : virtual A {};') + self.expect_expr('Derived{}.m_int', result_type='int', result_value='-1') + + # Confirm that we can call the D2 destructor for 'struct A' + self.expect('expression Derived* $derived_ptr = new Derived()') + self.expect('expression delete $derived_ptr') Index: lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile =================================================================== --- /dev/null +++ lldb/test/API/lang/cpp/external_ctor_dtor_lookup/Makefile @@ -0,0 +1,4 @@ +CXX_SOURCES := main.cpp lib.cpp +CXXFLAGS_EXTRAS := -glldb + +include Makefile.rules Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -162,14 +162,13 @@ const lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); - size_t - ParseChildParameters(clang::DeclContext *containing_decl_ctx, - const DWARFDIE &parent_die, bool skip_artificial, - bool &is_static, bool &is_variadic, - bool &has_template_params, - std::vector<lldb_private::CompilerType> &function_args, - std::vector<clang::ParmVarDecl *> &function_param_decls, - unsigned &type_quals); + size_t ParseChildParameters( + clang::DeclContext *containing_decl_ctx, const DWARFDIE &parent_die, + bool skip_artificial, bool &is_static, bool &is_variadic, + bool &has_template_params, + std::vector<lldb_private::CompilerType> &function_args, + std::vector<clang::ParmVarDecl *> &function_param_decls, + unsigned &type_quals, llvm::SmallVector<llvm::StringRef> &abi_tags); size_t ParseChildEnumerators(lldb_private::CompilerType &compiler_type, bool is_signed, uint32_t enumerator_byte_size, Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -941,12 +941,12 @@ is_static = true; } + llvm::SmallVector<llvm::StringRef> abi_tags; if (die.HasChildren()) { bool skip_artificial = true; ParseChildParameters(containing_decl_ctx, die, skip_artificial, is_static, - is_variadic, has_template_params, - function_param_types, function_param_decls, - type_quals); + is_variadic, has_template_params, function_param_types, + function_param_decls, type_quals, abi_tags); } bool ignore_containing_context = false; @@ -1124,6 +1124,11 @@ is_static, attrs.is_inline, attrs.is_explicit, is_attr_used, attrs.is_artificial); + if (!abi_tags.empty()) + cxx_method_decl->addAttr(clang::AbiTagAttr::CreateImplicit( + m_ast.getASTContext(), abi_tags.data(), + abi_tags.size())); + type_handled = cxx_method_decl != nullptr; // Artificial methods are always handled even when we // don't create a new declaration for them. @@ -2366,11 +2371,13 @@ DWARFDeclContext decl_ctx = SymbolFileDWARF::GetDWARFDeclContext(die); sstr << decl_ctx.GetQualifiedName(); + llvm::SmallVector<llvm::StringRef> abi_tags; clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); ParseChildParameters(containing_decl_ctx, die, true, is_static, is_variadic, has_template_params, param_types, param_decls, - type_quals); + type_quals, abi_tags); + sstr << "("; for (size_t i = 0; i < param_types.size(); i++) { if (i > 0) @@ -3049,7 +3056,7 @@ bool skip_artificial, bool &is_static, bool &is_variadic, bool &has_template_params, std::vector<CompilerType> &function_param_types, std::vector<clang::ParmVarDecl *> &function_param_decls, - unsigned &type_quals) { + unsigned &type_quals, llvm::SmallVector<llvm::StringRef> &abi_tags) { if (!parent_die) return 0; @@ -3159,6 +3166,15 @@ has_template_params = true; break; + case DW_TAG_LLVM_annotation: { + const char *name = die.GetName(); + if (!name || ::strcmp(name, "abi_tag") != 0) + break; + + if (const char *tag = + die.GetAttributeValueAsString(DW_AT_const_value, nullptr)) + abi_tags.push_back(tag); + } break; default: break; }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits