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

Reply via email to