https://github.com/imkiva updated 
https://github.com/llvm/llvm-project/pull/158256

>From 8e00d31ce15eb3255c7bafe924754752dd563fd3 Mon Sep 17 00:00:00 2001
From: imkiva <zeng...@iscas.ac.cn>
Date: Fri, 12 Sep 2025 16:14:23 +0800
Subject: [PATCH 1/6] [LLDB] Fix `GetIndexOfChildMemberWithName` to handle
 anonymous structs in base classes

Fixes #158131

Similar to #138487 but also search for child indexes in the base classes
---
 .../TypeSystem/Clang/TypeSystemClang.cpp        | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 39aacdb58e694..1cf73dab2e724 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6786,6 +6786,23 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
         }
 
         if (cxx_record_decl) {
+          for (const clang::CXXBaseSpecifier &base_spec : 
cxx_record_decl->bases()) {
+            uint32_t base_slot =
+                GetIndexForRecordBase(record_decl, &base_spec, 
omit_empty_base_classes);
+            if (base_slot == UINT32_MAX)
+              continue;
+
+            std::vector<uint32_t> save = child_indexes;
+            child_indexes.push_back(base_slot);
+            CompilerType base_type = GetType(base_spec.getType());
+            if (GetIndexOfChildMemberWithName(base_type.GetOpaqueQualType(),
+                                              name, omit_empty_base_classes,
+                                              child_indexes)) {
+              return child_indexes.size();
+            }
+            child_indexes = std::move(save);
+          }
+
           const clang::RecordDecl *parent_record_decl = cxx_record_decl;
 
           // Didn't find things easily, lets let clang do its thang...

>From 3c8ce49a705f4fd1dfc304e76704a9294beb4158 Mon Sep 17 00:00:00 2001
From: imkiva <zeng...@iscas.ac.cn>
Date: Fri, 12 Sep 2025 17:12:37 +0800
Subject: [PATCH 2/6] [LLDB] Add tests

---
 .../cpp/type_lookup_anon_base_member/Makefile |  3 ++
 .../TestCppTypeLookupAnonBaseMember.py        | 37 +++++++++++++++++++
 .../cpp/type_lookup_anon_base_member/main.cpp | 18 +++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 lldb/test/API/lang/cpp/type_lookup_anon_base_member/Makefile
 create mode 100644 
lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
 create mode 100644 lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp

diff --git a/lldb/test/API/lang/cpp/type_lookup_anon_base_member/Makefile 
b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git 
a/lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
 
b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
new file mode 100644
index 0000000000000..8f38403acfc34
--- /dev/null
+++ 
b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
@@ -0,0 +1,37 @@
+"""
+Test that we properly print anonymous members in a base class.
+"""
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import decorators
+
+
+class TestTypeLookupAnonBaseMember(TestBase):
+    def test_lookup_anon_base_member(self):
+        self.build()
+        (target, process, thread, bp1) = lldbutil.run_to_source_breakpoint(
+            self, "// Set breakpoint here", lldb.SBFileSpec("main.cpp")
+        )
+
+        thread = lldbutil.get_stopped_thread(process, 
lldb.eStopReasonBreakpoint)
+        frame = thread.GetFrameAtIndex(0)
+
+        d = frame.FindVariable("d")
+        self.assertTrue(d.IsValid())
+
+        # b from Base
+        b = d.GetChildMemberWithName("b")
+        self.assertTrue(b.IsValid())
+        self.assertEqual(b.GetValueAsSigned(), 1)
+
+        # x from anonymous struct (inside Base)
+        x = d.GetChildMemberWithName("x")
+        self.assertTrue(x.IsValid())
+        self.assertEqual(x.GetValueAsSigned(), 2)
+
+        # d from Derived
+        a = d.GetChildMemberWithName("a")
+        self.assertTrue(a.IsValid())
+        self.assertEqual(a.GetValueAsSigned(), 3)
diff --git a/lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp 
b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp
new file mode 100644
index 0000000000000..f27cf4ce163f9
--- /dev/null
+++ b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp
@@ -0,0 +1,18 @@
+struct Base {
+  int b;
+  struct {
+    int x;
+  };
+};
+
+struct Derived : public Base {
+  int a;
+};
+
+int main() {
+  Derived d;
+  d.b = 1;
+  d.x = 2;
+  d.a = 3;
+  return 0; // Set breakpoint here
+}

>From cb332933cd6ec6d0bae0ad8a01216a07587e9c1a Mon Sep 17 00:00:00 2001
From: imkiva <zeng...@iscas.ac.cn>
Date: Fri, 12 Sep 2025 17:40:07 +0800
Subject: [PATCH 3/6] [LLDB] Extract `FindInAnonRecordFields` for traversing
 anonymous records, and fix `type_lookup_anon_struct` test

---
 .../TypeSystem/Clang/TypeSystemClang.cpp      | 71 ++++++++++++++++---
 .../TypeSystem/Clang/TypeSystemClang.h        |  5 ++
 2 files changed, 66 insertions(+), 10 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 1cf73dab2e724..43d956a2e7088 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6707,6 +6707,52 @@ uint32_t TypeSystemClang::GetIndexForRecordChild(
   return UINT32_MAX;
 }
 
+bool TypeSystemClang::FindInAnonRecordFields(const clang::RecordDecl *rd,
+                                             std::vector<uint32_t> &path,
+                                             llvm::StringRef name,
+                                             bool omit_empty_base_classes) {
+  uint32_t local_idx = 0;
+
+  // We need the visible base count to compute the child index offset
+  const clang::CXXRecordDecl *crd =
+      llvm::dyn_cast<clang::CXXRecordDecl>(rd);
+  const uint32_t bases =
+      TypeSystemClang::GetNumBaseClasses(crd, omit_empty_base_classes);
+
+  // We only treat anonymous record fields as transparent containers for 
further lookup.
+  for (auto it = rd->field_begin(), ie = rd->field_end();
+       it != ie; ++it, ++local_idx) {
+    llvm::StringRef fname = it->getName();
+    const bool is_anon = it->isAnonymousStructOrUnion() || fname.empty();
+
+    // named field, check for a match
+    if (!is_anon) {
+      if (fname == name) {
+        path.push_back(bases + local_idx);
+        return true;
+      }
+      continue;
+    }
+
+    // anonymous field, look inside only if it is a record type
+    if (!it->getType()->isRecordType())
+      continue;
+
+    const auto *inner_rt = it->getType()->castAs<clang::RecordType>();
+    const clang::RecordDecl *inner_rd = 
inner_rt->getOriginalDecl()->getDefinitionOrSelf();
+    if (!inner_rd)
+      continue;
+
+    // only descend into the "fields" of the anonymous record
+    // (do not traverse its bases here)
+    path.push_back(bases + local_idx);
+    if (FindInAnonRecordFields(inner_rd, path, name, omit_empty_base_classes))
+      return true;
+    path.pop_back();
+  }
+  return false;
+}
+
 // Look for a child member (doesn't include base classes, but it does include
 // their members) in the type hierarchy. Returns an index path into
 // "clang_type" on how to reach the appropriate member.
@@ -6766,16 +6812,21 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
             field_end = record_decl->field_end();
              field != field_end; ++field, ++child_idx) {
           llvm::StringRef field_name = field->getName();
-          if (field_name.empty()) {
-            CompilerType field_type = GetType(field->getType());
-            std::vector<uint32_t> save_indices = child_indexes;
-            child_indexes.push_back(
-                child_idx + TypeSystemClang::GetNumBaseClasses(
-                                cxx_record_decl, omit_empty_base_classes));
-            if (field_type.GetIndexOfChildMemberWithName(
-                    name, omit_empty_base_classes, child_indexes))
-              return child_indexes.size();
-            child_indexes = std::move(save_indices);
+          const bool is_anon =
+              field->isAnonymousStructOrUnion() || field_name.empty();
+          if (is_anon) {
+            if (field->getType()->isRecordType()) {
+              const uint32_t this_slot =
+                  child_idx + TypeSystemClang::GetNumBaseClasses(
+                                  cxx_record_decl, omit_empty_base_classes);
+              std::vector<uint32_t> save_indices = child_indexes;
+              child_indexes.push_back(this_slot);
+              const auto *rt = field->getType()->castAs<clang::RecordType>();
+              const clang::RecordDecl *rd = 
rt->getOriginalDecl()->getDefinitionOrSelf();
+              if (rd && FindInAnonRecordFields(rd, child_indexes, name, 
omit_empty_base_classes))
+                return child_indexes.size();
+              child_indexes = std::move(save_indices);
+            }
           } else if (field_name == name) {
             // We have to add on the number of base classes to this index!
             child_indexes.push_back(
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 709f89590ba3b..62e6d831440b2 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -320,6 +320,11 @@ class TypeSystemClang : public TypeSystem {
                                  const clang::CXXBaseSpecifier *base_spec,
                                  bool omit_empty_base_classes);
 
+  bool FindInAnonRecordFields(const clang::RecordDecl *rd,
+                              std::vector<uint32_t> &path,
+                              llvm::StringRef name,
+                              bool omit_empty_base_classes);
+
   /// Synthesize a clang::Module and return its ID or a default-constructed ID.
   OptionalClangModuleID GetOrCreateClangModule(llvm::StringRef name,
                                                OptionalClangModuleID parent,

>From fcc45162b3cc0f15b9003f2039d3f52c8327f75a Mon Sep 17 00:00:00 2001
From: imkiva <zeng...@iscas.ac.cn>
Date: Fri, 12 Sep 2025 17:47:15 +0800
Subject: [PATCH 4/6] [LLDB] Update tests

---
 .../TestCppTypeLookupAnonBaseMember.py                      | 6 +++---
 .../test/API/lang/cpp/type_lookup_anon_base_member/main.cpp | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git 
a/lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
 
b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
index 8f38403acfc34..dc538885c32dd 100644
--- 
a/lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
+++ 
b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/TestCppTypeLookupAnonBaseMember.py
@@ -32,6 +32,6 @@ def test_lookup_anon_base_member(self):
         self.assertEqual(x.GetValueAsSigned(), 2)
 
         # d from Derived
-        a = d.GetChildMemberWithName("a")
-        self.assertTrue(a.IsValid())
-        self.assertEqual(a.GetValueAsSigned(), 3)
+        dd = d.GetChildMemberWithName("d")
+        self.assertTrue(dd.IsValid())
+        self.assertEqual(dd.GetValueAsSigned(), 3)
diff --git a/lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp 
b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp
index f27cf4ce163f9..a0b71e8a72237 100644
--- a/lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp
+++ b/lldb/test/API/lang/cpp/type_lookup_anon_base_member/main.cpp
@@ -6,13 +6,13 @@ struct Base {
 };
 
 struct Derived : public Base {
-  int a;
+  int d;
 };
 
 int main() {
   Derived d;
   d.b = 1;
   d.x = 2;
-  d.a = 3;
+  d.d = 3;
   return 0; // Set breakpoint here
 }

>From d8652d3e13ed1c3c5e12589b80a7ec7ca4d1266a Mon Sep 17 00:00:00 2001
From: imkiva <zeng...@iscas.ac.cn>
Date: Wed, 17 Sep 2025 13:52:15 +0800
Subject: [PATCH 5/6] [LLDB] format code

---
 .../TypeSystem/Clang/TypeSystemClang.cpp      | 26 +++++++++++--------
 .../TypeSystem/Clang/TypeSystemClang.h        |  3 +--
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 43d956a2e7088..414349a919721 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6714,14 +6714,14 @@ bool TypeSystemClang::FindInAnonRecordFields(const 
clang::RecordDecl *rd,
   uint32_t local_idx = 0;
 
   // We need the visible base count to compute the child index offset
-  const clang::CXXRecordDecl *crd =
-      llvm::dyn_cast<clang::CXXRecordDecl>(rd);
+  const clang::CXXRecordDecl *crd = llvm::dyn_cast<clang::CXXRecordDecl>(rd);
   const uint32_t bases =
       TypeSystemClang::GetNumBaseClasses(crd, omit_empty_base_classes);
 
-  // We only treat anonymous record fields as transparent containers for 
further lookup.
-  for (auto it = rd->field_begin(), ie = rd->field_end();
-       it != ie; ++it, ++local_idx) {
+  // We only treat anonymous record fields as transparent containers for 
further
+  // lookup.
+  for (auto it = rd->field_begin(), ie = rd->field_end(); it != ie;
+       ++it, ++local_idx) {
     llvm::StringRef fname = it->getName();
     const bool is_anon = it->isAnonymousStructOrUnion() || fname.empty();
 
@@ -6739,7 +6739,8 @@ bool TypeSystemClang::FindInAnonRecordFields(const 
clang::RecordDecl *rd,
       continue;
 
     const auto *inner_rt = it->getType()->castAs<clang::RecordType>();
-    const clang::RecordDecl *inner_rd = 
inner_rt->getOriginalDecl()->getDefinitionOrSelf();
+    const clang::RecordDecl *inner_rd =
+        inner_rt->getOriginalDecl()->getDefinitionOrSelf();
     if (!inner_rd)
       continue;
 
@@ -6822,8 +6823,10 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
               std::vector<uint32_t> save_indices = child_indexes;
               child_indexes.push_back(this_slot);
               const auto *rt = field->getType()->castAs<clang::RecordType>();
-              const clang::RecordDecl *rd = 
rt->getOriginalDecl()->getDefinitionOrSelf();
-              if (rd && FindInAnonRecordFields(rd, child_indexes, name, 
omit_empty_base_classes))
+              const clang::RecordDecl *rd =
+                  rt->getOriginalDecl()->getDefinitionOrSelf();
+              if (rd && FindInAnonRecordFields(rd, child_indexes, name,
+                                               omit_empty_base_classes))
                 return child_indexes.size();
               child_indexes = std::move(save_indices);
             }
@@ -6837,9 +6840,10 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
         }
 
         if (cxx_record_decl) {
-          for (const clang::CXXBaseSpecifier &base_spec : 
cxx_record_decl->bases()) {
-            uint32_t base_slot =
-                GetIndexForRecordBase(record_decl, &base_spec, 
omit_empty_base_classes);
+          for (const clang::CXXBaseSpecifier &base_spec :
+               cxx_record_decl->bases()) {
+            uint32_t base_slot = GetIndexForRecordBase(record_decl, &base_spec,
+                                                       
omit_empty_base_classes);
             if (base_slot == UINT32_MAX)
               continue;
 
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 62e6d831440b2..8a6b364269f82 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -321,8 +321,7 @@ class TypeSystemClang : public TypeSystem {
                                  bool omit_empty_base_classes);
 
   bool FindInAnonRecordFields(const clang::RecordDecl *rd,
-                              std::vector<uint32_t> &path,
-                              llvm::StringRef name,
+                              std::vector<uint32_t> &path, llvm::StringRef 
name,
                               bool omit_empty_base_classes);
 
   /// Synthesize a clang::Module and return its ID or a default-constructed ID.

>From f70ada7b258d92ad964529c420cf288b8dc09c5f Mon Sep 17 00:00:00 2001
From: imkiva <zeng...@iscas.ac.cn>
Date: Wed, 17 Sep 2025 14:00:54 +0800
Subject: [PATCH 6/6] [LLDB] removed two `expectedFailure` from tests, as they
 actually passed now

---
 lldb/test/API/lang/cpp/diamond/TestCppDiamond.py                 | 1 -
 .../cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py  | 1 -
 2 files changed, 2 deletions(-)

diff --git a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py 
b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
index 27062c0666a1a..13ab8cc742551 100644
--- a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
+++ b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
@@ -107,7 +107,6 @@ def test(self):
         # Use variable paths to access the members.
         self.expect_var_path("j1.x", type="long", value="1")
 
-    @expectedFailureAll
     @no_debug_info_test
     def test_invalid_member(self):
         self.build()
diff --git 
a/lldb/test/API/lang/cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py
 
b/lldb/test/API/lang/cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py
index a6e419b7fcdfa..cb28e2b31fad1 100644
--- 
a/lldb/test/API/lang/cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py
+++ 
b/lldb/test/API/lang/cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py
@@ -6,7 +6,6 @@
 
 
 class TestCase(TestBase):
-    @unittest.expectedFailure  # The fix for this was reverted due to 
llvm.org/PR52257
     def test(self):
         self.build()
         self.dbg.CreateTarget(self.getBuildArtifact("a.out"))

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

Reply via email to