https://github.com/Michael137 updated 
https://github.com/llvm/llvm-project/pull/144998

>From 2c54344a0bf7c7937166820ae0ada92c4e4445cb Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Wed, 29 Jan 2025 12:15:35 +0000
Subject: [PATCH 1/5] [lldb][DWARFASTParserClang] Support constant index
 encoding of DW_AT_object_pointer

Starting with https://github.com/llvm/llvm-project/pull/124790, Clang
emits `DW_AT_object_pointer` encoded as integer constants rather than
DIE references. This patch accounts for this.
---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  |  47 +++--
 .../x86/explicit-member-function-quals.cpp    |  21 +-
 .../DWARF/DWARFASTParserClangTests.cpp        | 196 ++++++++++++++++++
 3 files changed, 244 insertions(+), 20 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index a4cb608edd8b4..1e86629e0f730 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -170,23 +170,46 @@ DWARFASTParserClang::GetObjectParameter(const DWARFDIE 
&subprogram,
   if (!decl_ctx_die.IsStructUnionOrClass())
     return {};
 
-  if (DWARFDIE object_parameter =
-          subprogram.GetAttributeValueAsReferenceDIE(DW_AT_object_pointer))
-    return object_parameter;
+  // The DW_AT_object_pointer may be either encoded as a reference to a DIE,
+  // in which case that's the object parameter we want. Or it can be a constant
+  // index of the parameter.
+  std::optional<size_t> object_pointer_index;
+  DWARFFormValue form_value;
+  if (subprogram.GetDIE()->GetAttributeValue(
+          subprogram.GetCU(), DW_AT_object_pointer, form_value,
+          /*end_attr_offset_ptr=*/nullptr, /*check_elaborating_dies=*/true)) {
+    if (auto ref = form_value.Reference())
+      return ref;
+
+    object_pointer_index = form_value.Unsigned();
+  }
+
+  // Try to find the DW_TAG_formal_parameter via object_pointer_index.
+  DWARFDIE object_pointer;
+  size_t param_index = 0;
+  for (const auto &child : subprogram.children()) {
+    if (child.Tag() != DW_TAG_formal_parameter)
+      continue;
 
-  // If no DW_AT_object_pointer was specified, assume the implicit object
-  // parameter is the first parameter to the function, is called "this" and is
-  // artificial (which is what most compilers would generate).
-  auto children = subprogram.children();
-  auto it = llvm::find_if(children, [](const DWARFDIE &child) {
-    return child.Tag() == DW_TAG_formal_parameter;
-  });
+    if (param_index == object_pointer_index.value_or(0))
+      object_pointer = child;
+
+    ++param_index;
+  }
 
-  if (it == children.end())
+  // No formal parameter found for object pointer index.
+  // Nothing to be done.
+  if (!object_pointer)
     return {};
 
-  DWARFDIE object_pointer = *it;
+  // We found the object pointer encoded via DW_AT_object_pointer.
+  // No need for the remaining heuristics.
+  if (object_pointer_index)
+    return object_pointer;
 
+  // If no DW_AT_object_pointer was specified, assume the implicit object
+  // parameter is the first parameter to the function, is called "this" and is
+  // artificial (which is what most compilers would generate).
   if (!object_pointer.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
     return {};
 
diff --git 
a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp 
b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
index 33001db69f83e..f89f0f4a4f0bf 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
@@ -1,4 +1,9 @@
 // XFAIL: *
+//
+// FIXME: Explicit object parameter is not shown in
+// type lookup output. This is because we don't attach
+// valid source locations to decls in the DWARF AST,
+// so the ParmVarDecl::isExplicitObjectParameter fails.
 
 // Tests that we correctly deduce the CV-quals and storage
 // class of explicit object member functions.
@@ -8,15 +13,15 @@
 //
 // CHECK:      (lldb) type lookup Foo
 // CHECK-NEXT: struct Foo {
-// CHECK-NEXT:      void Method(Foo);
-// CHECK-NEXT:      void cMethod(const Foo &) const;
-// CHECK-NEXT:      void vMethod(volatile Foo &) volatile;
-// CHECK-NEXT:      void cvMethod(const volatile Foo &) const volatile;
+// CHECK-NEXT:      void Method(this Foo);
+// CHECK-NEXT:      void cMethod(this const Foo &) const;
+// CHECK-NEXT:      void vMethod(this volatile Foo &) volatile;
+// CHECK-NEXT:      void cvMethod(this const volatile Foo &) const volatile;
 // CHECK-NEXT: }
 
 struct Foo {
-  void Method(this Foo) {}
-  void cMethod(this Foo const &) {}
-  void vMethod(this Foo volatile &) {}
-  void cvMethod(this Foo const volatile &) {}
+  [[gnu::always_inline]] void Method(this Foo) {}
+  [[gnu::always_inline]] void cMethod(this Foo const &) {}
+  [[gnu::always_inline]] void vMethod(this Foo volatile &) {}
+  [[gnu::always_inline]] void cvMethod(this Foo const volatile &) {}
 } f;
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp 
b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index f18e938dbc4c9..067e41a19e7f5 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1265,3 +1265,199 @@ TEST_F(DWARFASTParserClangTests, 
TestParseSubroutine_ParameterCreation) {
   EXPECT_EQ(func->getParamDecl(1)->getDeclContext(), func);
   EXPECT_EQ(func->getParamDecl(1)->getName(), "namedParam");
 }
+
+TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointerIndex) {
+  // This tests the behaviour of ParsedDWARFTypeAttributes
+  // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
+  // that encodes a constant index (instead of a DIE reference).
+
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_AARCH64
+DWARF:
+  debug_str:
+    - Context
+    - func
+    - this
+    - self
+    - arg
+  debug_abbrev:
+    - ID:              0
+      Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+        - Code:            0x2
+          Tag:             DW_TAG_structure_type
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+        - Code:            0x3
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_declaration
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_object_pointer
+              Form:            DW_FORM_implicit_const
+              Value:           1
+            - Attribute:       DW_AT_external
+              Form:            DW_FORM_flag_present
+        - Code:            0x4
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_declaration
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_object_pointer
+              Form:            DW_FORM_implicit_const
+              Value:           0
+            - Attribute:       DW_AT_external
+              Form:            DW_FORM_flag_present
+
+        - Code:            0x5
+          Tag:             DW_TAG_formal_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+
+        - Code:            0x6
+          Tag:             DW_TAG_formal_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_artificial
+              Form:            DW_FORM_flag_present
+
+  debug_info:
+     - Version:  5
+       UnitType: DW_UT_compile
+       AddrSize: 8
+       Entries:
+
+# DW_TAG_compile_unit
+#   DW_AT_language [DW_FORM_data2]    (DW_LANG_C_plus_plus)
+
+        - AbbrCode: 0x1
+          Values:
+            - Value: 0x04
+
+#   DW_TAG_structure_type
+#     DW_AT_name [DW_FORM_strp] ("Context")
+
+        - AbbrCode: 0x2
+          Values:
+            - Value: 0x0
+
+#     DW_TAG_subprogram
+#       DW_AT_name [DW_FORM_strp] ("func")
+#       DW_AT_object_pointer [DW_FORM_implicit_const] (1)
+        - AbbrCode: 0x3
+          Values:
+            - Value: 0x8
+            - Value: 0x1
+            - Value: 0x1
+            - Value: 0x1
+
+#       DW_TAG_formal_parameter
+#         DW_AT_name [DW_FORM_strp] ("arg")
+        - AbbrCode: 0x5
+          Values:
+          - Value: 0x17
+
+#       DW_TAG_formal_parameter
+#         DW_AT_name [DW_FORM_strp] ("self")
+#         DW_AT_artificial
+        - AbbrCode: 0x6
+          Values:
+          - Value: 0x12
+          - Value: 0x1
+
+        - AbbrCode: 0x0
+        - AbbrCode: 0x0
+
+#     DW_TAG_subprogram
+#       DW_AT_object_pointer [DW_FORM_implicit_const] (0)
+#       DW_AT_name [DW_FORM_strp] ("func")
+        - AbbrCode:        0x4
+          Values:
+            - Value: 0x8
+            - Value: 0x1
+            - Value: 0x1
+            - Value: 0x1
+
+#       DW_TAG_formal_parameter
+#         DW_AT_name [DW_FORM_strp] ("this")
+#         DW_AT_artificial
+        - AbbrCode:        0x6
+          Values:
+            - Value:           0xd
+            - Value:           0x1
+
+#       DW_TAG_formal_parameter
+#         DW_AT_name [DW_FORM_strp] ("arg")
+        - AbbrCode: 0x5
+          Values:
+          - Value: 0x17
+
+        - AbbrCode: 0x0
+        - AbbrCode: 0x0
+...
+)";
+
+  YAMLModuleTester t(yamldata);
+
+  DWARFUnit *unit = t.GetDwarfUnit();
+  ASSERT_NE(unit, nullptr);
+  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
+  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
+  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
+  DWARFDIE cu_die(unit, cu_entry);
+
+  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
+  auto &ast_ctx = *holder->GetAST();
+  DWARFASTParserClangStub ast_parser(ast_ctx);
+
+  auto context_die = cu_die.GetFirstChild();
+  ASSERT_TRUE(context_die.IsValid());
+  ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);
+
+  auto sub1 = context_die.GetFirstChild();
+  ASSERT_TRUE(sub1.IsValid());
+  ASSERT_EQ(sub1.Tag(), DW_TAG_subprogram);
+
+  auto sub2 = sub1.GetSibling();
+  ASSERT_TRUE(sub2.IsValid());
+  ASSERT_EQ(sub2.Tag(), DW_TAG_subprogram);
+
+  // Object parameter is at constant index 1
+  {
+    auto param_die = sub1.GetFirstChild().GetSibling();
+    ASSERT_TRUE(param_die.IsValid());
+
+    EXPECT_EQ(param_die, ast_parser.GetCXXObjectParameter(sub1, context_die));
+  }
+
+  // Object parameter is at constant index 0
+  {
+    auto param_die = sub2.GetFirstChild();
+    ASSERT_TRUE(param_die.IsValid());
+
+    EXPECT_EQ(param_die,
+              ast_parser.GetCXXObjectParameter(param_die, context_die));
+  }
+}

>From ae660d77f9794d92fb42dd333b6ef150502af33d Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Fri, 20 Jun 2025 10:00:00 +0100
Subject: [PATCH 2/5] fixup! revert redundant test changes

---
 .../DWARF/x86/explicit-member-function-quals.cpp          | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git 
a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp 
b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
index f89f0f4a4f0bf..c592122e7a973 100644
--- a/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
+++ b/lldb/test/Shell/SymbolFile/DWARF/x86/explicit-member-function-quals.cpp
@@ -20,8 +20,8 @@
 // CHECK-NEXT: }
 
 struct Foo {
-  [[gnu::always_inline]] void Method(this Foo) {}
-  [[gnu::always_inline]] void cMethod(this Foo const &) {}
-  [[gnu::always_inline]] void vMethod(this Foo volatile &) {}
-  [[gnu::always_inline]] void cvMethod(this Foo const volatile &) {}
+  void Method(this Foo) {}
+  void cMethod(this Foo const &) {}
+  void vMethod(this Foo volatile &) {}
+  void cvMethod(this Foo const volatile &) {}
 } f;

>From 9d459954f6c77edb44fa9d49ca5d6741ad2931ab Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Sun, 22 Jun 2025 12:00:23 +0100
Subject: [PATCH 3/5] fixup! rename GetCXXObjectParameter in test

---
 lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp 
b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 067e41a19e7f5..4b2f036e45252 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1449,7 +1449,7 @@ TEST_F(DWARFASTParserClangTests, 
TestParseDWARFAttributes_ObjectPointerIndex) {
     auto param_die = sub1.GetFirstChild().GetSibling();
     ASSERT_TRUE(param_die.IsValid());
 
-    EXPECT_EQ(param_die, ast_parser.GetCXXObjectParameter(sub1, context_die));
+    EXPECT_EQ(param_die, ast_parser.GetObjectParameter(sub1, context_die));
   }
 
   // Object parameter is at constant index 0
@@ -1457,7 +1457,6 @@ TEST_F(DWARFASTParserClangTests, 
TestParseDWARFAttributes_ObjectPointerIndex) {
     auto param_die = sub2.GetFirstChild();
     ASSERT_TRUE(param_die.IsValid());
 
-    EXPECT_EQ(param_die,
-              ast_parser.GetCXXObjectParameter(param_die, context_die));
+    EXPECT_EQ(param_die, ast_parser.GetObjectParameter(param_die, 
context_die));
   }
 }

>From d0012e21ba3c90deedccf105a4d66b0ddd42fe86 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Sun, 22 Jun 2025 12:02:18 +0100
Subject: [PATCH 4/5] fixup! rename test

---
 lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp 
b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 4b2f036e45252..42001337c6df1 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -1266,8 +1266,8 @@ TEST_F(DWARFASTParserClangTests, 
TestParseSubroutine_ParameterCreation) {
   EXPECT_EQ(func->getParamDecl(1)->getName(), "namedParam");
 }
 
-TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointerIndex) {
-  // This tests the behaviour of ParsedDWARFTypeAttributes
+TEST_F(DWARFASTParserClangTests, TestObjectPointer_IndexEncoding) {
+  // This tests the behaviour of DWARFASTParserClang
   // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
   // that encodes a constant index (instead of a DIE reference).
 

>From 909316c6e2a03edfa914b2ceaf8e8696367a3169 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuc...@gmail.com>
Date: Sun, 22 Jun 2025 11:59:24 +0100
Subject: [PATCH 5/5] fixup! cherry-pick
 https://github.com/llvm/llvm-project/pull/145126

---
 .../SymbolFile/DWARF/DWARFASTParserClang.cpp  |  35 ++--
 .../SymbolFile/DWARF/DWARFASTParserClang.h    |   7 +-
 .../DWARF/DWARFASTParserClangTests.cpp        | 162 +++++++++++++++++-
 3 files changed, 176 insertions(+), 28 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 1e86629e0f730..df92cd6477022 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -167,9 +167,6 @@ DWARFASTParserClang::GetObjectParameter(const DWARFDIE 
&subprogram,
          subprogram.Tag() == DW_TAG_inlined_subroutine ||
          subprogram.Tag() == DW_TAG_subroutine_type);
 
-  if (!decl_ctx_die.IsStructUnionOrClass())
-    return {};
-
   // The DW_AT_object_pointer may be either encoded as a reference to a DIE,
   // in which case that's the object parameter we want. Or it can be a constant
   // index of the parameter.
@@ -210,6 +207,10 @@ DWARFASTParserClang::GetObjectParameter(const DWARFDIE 
&subprogram,
   // If no DW_AT_object_pointer was specified, assume the implicit object
   // parameter is the first parameter to the function, is called "this" and is
   // artificial (which is what most compilers would generate).
+
+  if (!decl_ctx_die.IsStructUnionOrClass())
+    return {};
+
   if (!object_pointer.GetAttributeValueAsUnsigned(DW_AT_artificial, 0))
     return {};
 
@@ -464,15 +465,6 @@ ParsedDWARFTypeAttributes::ParsedDWARFTypeAttributes(const 
DWARFDIE &die) {
       name.SetCString(form_value.AsCString());
       break;
 
-    case DW_AT_object_pointer:
-      // GetAttributes follows DW_AT_specification.
-      // DW_TAG_subprogram definitions and declarations may both
-      // have a DW_AT_object_pointer. Don't overwrite the one
-      // we parsed for the definition with the one from the declaration.
-      if (!object_pointer.IsValid())
-        object_pointer = form_value.Reference();
-      break;
-
     case DW_AT_signature:
       signature = form_value;
       break;
@@ -1135,7 +1127,7 @@ bool DWARFASTParserClang::ParseObjCMethod(
 std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod(
     const DWARFDIE &die, CompilerType clang_type,
     const ParsedDWARFTypeAttributes &attrs, const DWARFDIE &decl_ctx_die,
-    bool is_static, bool &ignore_containing_context) {
+    const DWARFDIE &object_parameter, bool &ignore_containing_context) {
   Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
   SymbolFileDWARF *dwarf = die.GetDWARF();
   assert(dwarf);
@@ -1219,6 +1211,9 @@ std::pair<bool, TypeSP> 
DWARFASTParserClang::ParseCXXMethod(
       TypeSystemClang::GetDeclContextForType(class_opaque_type), die,
       attrs.name.GetCString());
 
+  // In DWARF, a C++ method is static if it has no object parameter child.
+  const bool is_static = !object_parameter.IsValid();
+
   // We have a C++ member function with no children (this pointer!) and clang
   // will get mad if we try and make a function that isn't well formed in the
   // DWARF, so we will just skip it...
@@ -1244,9 +1239,7 @@ std::pair<bool, TypeSP> 
DWARFASTParserClang::ParseCXXMethod(
     ClangASTMetadata metadata;
     metadata.SetUserID(die.GetID());
 
-    char const *object_pointer_name =
-        attrs.object_pointer ? attrs.object_pointer.GetName() : nullptr;
-    if (object_pointer_name) {
+    if (char const *object_pointer_name = object_parameter.GetName()) {
       metadata.SetObjectPtrName(object_pointer_name);
       LLDB_LOGF(log, "Setting object pointer name: %s on method object %p.\n",
                 object_pointer_name, static_cast<void *>(cxx_method_decl));
@@ -1342,11 +1335,9 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
         type_handled =
             ParseObjCMethod(*objc_method, die, clang_type, attrs, is_variadic);
       } else if (is_cxx_method) {
-        // In DWARF, a C++ method is static if it has no object parameter 
child.
-        const bool is_static = !object_parameter.IsValid();
         auto [handled, type_sp] =
-            ParseCXXMethod(die, clang_type, attrs, decl_ctx_die, is_static,
-                           ignore_containing_context);
+            ParseCXXMethod(die, clang_type, attrs, decl_ctx_die,
+                           object_parameter, ignore_containing_context);
         if (type_sp)
           return type_sp;
 
@@ -1441,9 +1432,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die,
           ClangASTMetadata metadata;
           metadata.SetUserID(die.GetID());
 
-          char const *object_pointer_name =
-              attrs.object_pointer ? attrs.object_pointer.GetName() : nullptr;
-          if (object_pointer_name) {
+          if (char const *object_pointer_name = object_parameter.GetName()) {
             metadata.SetObjectPtrName(object_pointer_name);
             LLDB_LOGF(log,
                       "Setting object pointer name: %s on function "
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h 
b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index e57fc503d34c1..da58f4c146226 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -480,7 +480,8 @@ class DWARFASTParserClang : public 
lldb_private::plugin::dwarf::DWARFASTParser {
   /// \param[in] decl_ctx_die The DIE representing the DeclContext of the C++
   ///                         method being parsed.
   ///
-  /// \param[in] is_static Is true iff we're parsing a static method.
+  /// \param[in] object_parameter The DIE of this subprogram's object 
parameter.
+  ///                             May be an invalid DIE for C++ static methods.
   ///
   /// \param[out] ignore_containing_context Will get set to true if the caller
   ///             should treat this C++ method as-if it was not a C++ method.
@@ -495,7 +496,8 @@ class DWARFASTParserClang : public 
lldb_private::plugin::dwarf::DWARFASTParser {
                  lldb_private::CompilerType clang_type,
                  const ParsedDWARFTypeAttributes &attrs,
                  const lldb_private::plugin::dwarf::DWARFDIE &decl_ctx_die,
-                 bool is_static, bool &ignore_containing_context);
+                 const lldb_private::plugin::dwarf::DWARFDIE &object_parameter,
+                 bool &ignore_containing_context);
 
   lldb::TypeSP ParseArrayType(const lldb_private::plugin::dwarf::DWARFDIE &die,
                               const ParsedDWARFTypeAttributes &attrs);
@@ -565,7 +567,6 @@ struct ParsedDWARFTypeAttributes {
   const char *mangled_name = nullptr;
   lldb_private::ConstString name;
   lldb_private::Declaration decl;
-  lldb_private::plugin::dwarf::DWARFDIE object_pointer;
   lldb_private::plugin::dwarf::DWARFFormValue abstract_origin;
   lldb_private::plugin::dwarf::DWARFFormValue containing_type;
   lldb_private::plugin::dwarf::DWARFFormValue signature;
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp 
b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
index 42001337c6df1..d9acf1ced47c2 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFASTParserClangTests.cpp
@@ -742,8 +742,8 @@ TEST_F(DWARFASTParserClangTests, 
TestUniqueDWARFASTTypeMap_CppInsertMapFind) {
   ASSERT_EQ(type_sp, reparsed_type_sp);
 }
 
-TEST_F(DWARFASTParserClangTests, TestParseDWARFAttributes_ObjectPointer) {
-  // This tests the behaviour of ParsedDWARFTypeAttributes
+TEST_F(DWARFASTParserClangTests, TestObjectPointer) {
+  // This tests the behaviour of DWARFASTParserClang
   // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
   // *and* a DW_AT_specification that also has a DW_AT_object_pointer.
   // We don't want the declaration DW_AT_object_pointer to overwrite the
@@ -916,6 +916,164 @@ TEST_F(DWARFASTParserClangTests, 
TestParseDWARFAttributes_ObjectPointer) {
   }
 }
 
+TEST_F(DWARFASTParserClangTests,
+       TestObjectPointer_NoSpecificationOnDefinition) {
+  // This tests the behaviour of DWARFASTParserClang
+  // for DW_TAG_subprogram definitions which have a DW_AT_object_pointer
+  // but no DW_AT_specification that would link back to its declaration.
+  // This is how Objective-C class method definitions are emitted.
+
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_AARCH64
+DWARF:
+  debug_str:
+    - Context
+    - func
+    - this
+  debug_abbrev:
+    - ID:              0
+      Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+        - Code:            0x2
+          Tag:             DW_TAG_structure_type
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+        - Code:            0x3
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_declaration
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_object_pointer
+              Form:            DW_FORM_ref4
+            - Attribute:       DW_AT_artificial
+              Form:            DW_FORM_flag_present
+            - Attribute:       DW_AT_external
+              Form:            DW_FORM_flag_present
+        - Code:            0x4
+          Tag:             DW_TAG_formal_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_artificial
+              Form:            DW_FORM_flag_present
+        - Code:            0x5
+          Tag:             DW_TAG_subprogram
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_object_pointer
+              Form:            DW_FORM_ref4
+        - Code:            0x6
+          Tag:             DW_TAG_formal_parameter
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_artificial
+              Form:            DW_FORM_flag_present
+  debug_info:
+     - Version:         5
+       UnitType:        DW_UT_compile
+       AddrSize:        8
+       Entries:
+
+# DW_TAG_compile_unit
+#   DW_AT_language [DW_FORM_data2]    (DW_LANG_C_plus_plus)
+
+        - AbbrCode:        0x1
+          Values:
+            - Value:           0x04
+
+#   DW_TAG_structure_type
+#     DW_AT_name [DW_FORM_strp] ("Context")
+
+        - AbbrCode:        0x2
+          Values:
+            - Value:           0x0
+
+#     DW_TAG_subprogram
+#       DW_AT_name [DW_FORM_strp] ("func")
+#       DW_AT_object_pointer [DW_FORM_ref4]
+        - AbbrCode:        0x3
+          Values:
+            - Value:           0x8
+            - Value:           0x1
+            - Value:           0x1d
+            - Value:           0x1
+            - Value:           0x1
+
+#       DW_TAG_formal_parameter
+#         DW_AT_artificial
+        - AbbrCode:        0x4
+          Values:
+          - Value: 0x1
+
+        - AbbrCode: 0x0
+        - AbbrCode: 0x0
+
+#     DW_TAG_subprogram
+#       DW_AT_object_pointer [DW_FORM_ref4] ("this")
+        - AbbrCode:        0x5
+          Values:
+            - Value:           0x25
+
+#       DW_TAG_formal_parameter
+#         DW_AT_name [DW_FORM_strp] ("this")
+#         DW_AT_artificial
+        - AbbrCode:        0x6
+          Values:
+            - Value:           0xd
+            - Value:           0x1
+
+        - AbbrCode: 0x0
+        - AbbrCode: 0x0
+...
+)";
+  YAMLModuleTester t(yamldata);
+
+  DWARFUnit *unit = t.GetDwarfUnit();
+  ASSERT_NE(unit, nullptr);
+  const DWARFDebugInfoEntry *cu_entry = unit->DIE().GetDIE();
+  ASSERT_EQ(cu_entry->Tag(), DW_TAG_compile_unit);
+  ASSERT_EQ(unit->GetDWARFLanguageType(), DW_LANG_C_plus_plus);
+  DWARFDIE cu_die(unit, cu_entry);
+
+  auto holder = std::make_unique<clang_utils::TypeSystemClangHolder>("ast");
+  auto &ast_ctx = *holder->GetAST();
+  DWARFASTParserClangStub ast_parser(ast_ctx);
+
+  auto context_die = cu_die.GetFirstChild();
+  ASSERT_TRUE(context_die.IsValid());
+  ASSERT_EQ(context_die.Tag(), DW_TAG_structure_type);
+
+  auto subprogram_definition = context_die.GetSibling();
+  ASSERT_TRUE(subprogram_definition.IsValid());
+  ASSERT_EQ(subprogram_definition.Tag(), DW_TAG_subprogram);
+  ASSERT_FALSE(subprogram_definition.GetAttributeValueAsOptionalUnsigned(
+      DW_AT_external));
+  ASSERT_FALSE(
+      
subprogram_definition.GetAttributeValueAsReferenceDIE(DW_AT_specification)
+          .IsValid());
+
+  auto param_die = subprogram_definition.GetFirstChild();
+  ASSERT_TRUE(param_die.IsValid());
+  EXPECT_EQ(param_die,
+            ast_parser.GetObjectParameter(subprogram_definition, {}));
+}
+
 TEST_F(DWARFASTParserClangTests, TestParseSubroutine_ExplicitObjectParameter) {
   // Tests parsing of a C++ non-static member function with an explicit object
   // parameter that isn't called "this" and is not a pointer (but a 
CV-qualified

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to