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

>From 8e00d31ce15eb3255c7bafe924754752dd563fd3 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 12 Sep 2025 16:14:23 +0800
Subject: [PATCH 01/11] [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 <[email protected]>
Date: Fri, 12 Sep 2025 17:12:37 +0800
Subject: [PATCH 02/11] [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 <[email protected]>
Date: Fri, 12 Sep 2025 17:40:07 +0800
Subject: [PATCH 03/11] [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 <[email protected]>
Date: Fri, 12 Sep 2025 17:47:15 +0800
Subject: [PATCH 04/11] [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 <[email protected]>
Date: Wed, 17 Sep 2025 13:52:15 +0800
Subject: [PATCH 05/11] [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 <[email protected]>
Date: Wed, 17 Sep 2025 14:00:54 +0800
Subject: [PATCH 06/11] [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"))

>From 1c05ce0a54ec8d630c5589840687211abcb0d307 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 17 Oct 2025 13:29:52 +0800
Subject: [PATCH 07/11] Revert "[LLDB] format code"

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

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 414349a919721..43d956a2e7088 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,8 +6739,7 @@ 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;
 
@@ -6823,10 +6822,8 @@ 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);
             }
@@ -6840,10 +6837,9 @@ 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 8a6b364269f82..62e6d831440b2 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -321,7 +321,8 @@ 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 616f91681617d246c1aec3512d5f6bfcd0a8601e Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 17 Oct 2025 13:29:55 +0800
Subject: [PATCH 08/11] Revert "[LLDB] Extract `FindInAnonRecordFields` for
 traversing anonymous records, and fix `type_lookup_anon_struct` test"

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

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 43d956a2e7088..1cf73dab2e724 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6707,52 +6707,6 @@ 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.
@@ -6812,21 +6766,16 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
             field_end = record_decl->field_end();
              field != field_end; ++field, ++child_idx) {
           llvm::StringRef field_name = field->getName();
-          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);
-            }
+          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);
           } 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 62e6d831440b2..709f89590ba3b 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -320,11 +320,6 @@ 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 6d0f8cc3acce8c01a5029edb40cef4bf0a3b0c15 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 17 Oct 2025 13:29:58 +0800
Subject: [PATCH 09/11] Revert "[LLDB] Fix `GetIndexOfChildMemberWithName` to
 handle anonymous structs in base classes"

This reverts commit 8e00d31ce15eb3255c7bafe924754752dd563fd3.
---
 .../TypeSystem/Clang/TypeSystemClang.cpp        | 17 -----------------
 1 file changed, 17 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 1cf73dab2e724..39aacdb58e694 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6786,23 +6786,6 @@ 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 51d65e32df8c6d64ba32a9a2c4052749b9c8cbca Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 17 Oct 2025 14:58:31 +0800
Subject: [PATCH 10/11] Revert "[LLDB] removed two `expectedFailure` from
 tests, as they actually passed now"

This reverts commit f70ada7b258d92ad964529c420cf288b8dc09c5f.
---
 lldb/test/API/lang/cpp/diamond/TestCppDiamond.py                 | 1 +
 .../cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py 
b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
index 13ab8cc742551..27062c0666a1a 100644
--- a/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
+++ b/lldb/test/API/lang/cpp/diamond/TestCppDiamond.py
@@ -107,6 +107,7 @@ 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 cb28e2b31fad1..a6e419b7fcdfa 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,6 +6,7 @@
 
 
 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"))

>From 0a001b049c158f1a6923d75b14f9a7b141e67175 Mon Sep 17 00:00:00 2001
From: imkiva <[email protected]>
Date: Fri, 17 Oct 2025 15:00:18 +0800
Subject: [PATCH 11/11] [LLDB] check for `IndirectFieldDecl` in
 `GetIndexForRecordChild`

---
 .../TypeSystem/Clang/TypeSystemClang.cpp      | 80 ++++++++++++++++---
 .../TypeSystem/Clang/TypeSystemClang.h        | 17 +++-
 .../TestCppTypeLookupAnonBaseMember.py        |  5 ++
 .../cpp/type_lookup_anon_base_member/main.cpp |  2 +
 4 files changed, 92 insertions(+), 12 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 39aacdb58e694..2784f62cb99db 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -6690,9 +6690,9 @@ uint32_t TypeSystemClang::GetIndexForRecordBase(
   return UINT32_MAX;
 }
 
-uint32_t TypeSystemClang::GetIndexForRecordChild(
+bool TypeSystemClang::GetIndexForRecordChild(
     const clang::RecordDecl *record_decl, clang::NamedDecl *canonical_decl,
-    bool omit_empty_base_classes) {
+    bool omit_empty_base_classes, RecordChildResult &out) {
   uint32_t child_idx = TypeSystemClang::GetNumBaseClasses(
       llvm::dyn_cast<clang::CXXRecordDecl>(record_decl),
       omit_empty_base_classes);
@@ -6700,11 +6700,70 @@ uint32_t TypeSystemClang::GetIndexForRecordChild(
   clang::RecordDecl::field_iterator field, field_end;
   for (field = record_decl->field_begin(), field_end = 
record_decl->field_end();
        field != field_end; ++field, ++child_idx) {
-    if (field->getCanonicalDecl() == canonical_decl)
-      return child_idx;
+    out = RecordChildResult{};
+
+    // If finding an `IndirectFieldDecl x` from `struct { int x; ... };`
+    if (auto *IFD = llvm::dyn_cast<clang::IndirectFieldDecl>(canonical_decl)) {
+      // Only meaningful is the field is an anonymous struct/union.
+      if (!field->isAnonymousStructOrUnion())
+        continue;
+
+      // Find the anonymous aggregate record that is a direct field of
+      // `record_decl`, and the target field inside that aggregate, we need the
+      // latter to compute the correct child index to the anonymous field.
+      const clang::FieldDecl *anon_aggregate = nullptr;
+      const clang::FieldDecl *target_field_in_anon = nullptr;
+
+      for (clang::NamedDecl *ND : IFD->chain()) {
+        if (auto *FD = llvm::dyn_cast<clang::FieldDecl>(ND)) {
+          if (FD->isAnonymousStructOrUnion() &&
+              FD->getDeclContext() == record_decl)
+            anon_aggregate = FD;
+          if (!FD->isAnonymousStructOrUnion())
+            target_field_in_anon = FD;
+        }
+      }
+      if (!anon_aggregate || !target_field_in_anon)
+        continue;
+
+      // If this field is not the anonymous aggregate, skip.
+      if (field->getCanonicalDecl() != anon_aggregate->getCanonicalDecl())
+        continue;
+
+      // the child_idx now points to the anonymous aggregate.
+      out.index = child_idx;
+
+      // Compute inner slot: within the anonymous aggregate's record.
+      auto inner_rd = anon_aggregate->getType()
+                          ->getAsCXXRecordDecl()
+                          ->getDefinitionOrSelf();
+      if (!inner_rd) {
+        out.has_inner = false;
+        return true;
+      }
+
+      uint32_t inner_idx =
+          TypeSystemClang::GetNumBaseClasses(inner_rd, 
omit_empty_base_classes);
+
+      for (auto inner_f = inner_rd->field_begin(),
+                inner_e = inner_rd->field_end();
+           inner_f != inner_e; ++inner_f, ++inner_idx) {
+        if (inner_f->getCanonicalDecl() ==
+            target_field_in_anon->getCanonicalDecl()) {
+          out.has_inner = true;
+          out.inner_index = inner_idx;
+          return true;
+        }
+      }
+
+    } else if (field->getCanonicalDecl() == canonical_decl) {
+      out.index = child_idx;
+      out.has_inner = false;
+      return true;
+    }
   }
 
-  return UINT32_MAX;
+  return false;
 }
 
 // Look for a child member (doesn't include base classes, but it does include
@@ -6825,13 +6884,16 @@ size_t TypeSystemClang::GetIndexOfChildMemberWithName(
               }
               for (clang::DeclContext::lookup_iterator I = path->Decls, E;
                    I != E; ++I) {
-                child_idx = GetIndexForRecordChild(
-                    parent_record_decl, *I, omit_empty_base_classes);
-                if (child_idx == UINT32_MAX) {
+                RecordChildResult result{};
+                bool success = GetIndexForRecordChild(
+                    parent_record_decl, *I, omit_empty_base_classes, result);
+                if (!success) {
                   child_indexes.clear();
                   return 0;
                 } else {
-                  child_indexes.push_back(child_idx);
+                  child_indexes.push_back(result.index);
+                  if (result.has_inner)
+                    child_indexes.push_back(result.inner_index);
                 }
               }
             }
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 709f89590ba3b..156706ac84535 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -98,6 +98,16 @@ class TypePayloadClang {
   /// \}
 };
 
+/// Return result of GetIndexForRecordChild
+struct RecordChildResult {
+  /// child index in `record_decl`
+  uint32_t index = UINT32_MAX;
+  /// true if canonical_decl is an IndirectFieldDecl via an anonymous aggregate
+  bool has_inner = false;
+  /// if has_inner is true, this is the index within the anonymous aggregate
+  uint32_t inner_index = UINT32_MAX;
+};
+
 /// A TypeSystem implementation based on Clang.
 ///
 /// This class uses a single clang::ASTContext as the backend for storing
@@ -312,9 +322,10 @@ class TypeSystemClang : public TypeSystem {
   uint32_t GetNumBaseClasses(const clang::CXXRecordDecl *cxx_record_decl,
                              bool omit_empty_base_classes);
 
-  uint32_t GetIndexForRecordChild(const clang::RecordDecl *record_decl,
-                                  clang::NamedDecl *canonical_decl,
-                                  bool omit_empty_base_classes);
+  bool GetIndexForRecordChild(const clang::RecordDecl *record_decl,
+                              clang::NamedDecl *canonical_decl,
+                              bool omit_empty_base_classes,
+                              RecordChildResult &result);
 
   uint32_t GetIndexForRecordBase(const clang::RecordDecl *record_decl,
                                  const clang::CXXBaseSpecifier *base_spec,
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 dc538885c32dd..d2cf4a71fbc86 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
@@ -31,6 +31,11 @@ def test_lookup_anon_base_member(self):
         self.assertTrue(x.IsValid())
         self.assertEqual(x.GetValueAsSigned(), 2)
 
+        # y from anonymous struct (inside Base)
+        x = d.GetChildMemberWithName("y")
+        self.assertTrue(x.IsValid())
+        self.assertEqual(x.GetValueAsSigned(), 4)
+
         # d from Derived
         dd = d.GetChildMemberWithName("d")
         self.assertTrue(dd.IsValid())
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 a0b71e8a72237..bff34a5895737 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
@@ -2,6 +2,7 @@ struct Base {
   int b;
   struct {
     int x;
+    int y;
   };
 };
 
@@ -14,5 +15,6 @@ int main() {
   d.b = 1;
   d.x = 2;
   d.d = 3;
+  d.y = 4;
   return 0; // Set breakpoint here
 }

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to