[Lldb-commits] [lldb] [lldb] Add SBValue::GetParent (PR #197311)
Dave Lee via lldb-commits
lldb-commits at lists.llvm.org
Mon May 18 17:54:19 PDT 2026
https://github.com/kastiglione updated https://github.com/llvm/llvm-project/pull/197311
>From c2e0494e0153c7c3523c0c80d0577a38b7aa4248 Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Tue, 12 May 2026 14:49:58 -0700
Subject: [PATCH 1/3] [lldb] Add SBValue::GetParent
---
lldb/bindings/interface/SBValueExtensions.i | 1 +
lldb/include/lldb/API/SBValue.h | 2 ++
lldb/source/API/SBValue.cpp | 14 +++++++++
.../python_api/sbvalue_get_parent/Makefile | 2 ++
.../TestSBValueGetParent.py | 30 +++++++++++++++++++
.../python_api/sbvalue_get_parent/main.cpp | 12 ++++++++
6 files changed, 61 insertions(+)
create mode 100644 lldb/test/API/python_api/sbvalue_get_parent/Makefile
create mode 100644 lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
create mode 100644 lldb/test/API/python_api/sbvalue_get_parent/main.cpp
diff --git a/lldb/bindings/interface/SBValueExtensions.i b/lldb/bindings/interface/SBValueExtensions.i
index f0c8797bd5f78..63e61141afec1 100644
--- a/lldb/bindings/interface/SBValueExtensions.i
+++ b/lldb/bindings/interface/SBValueExtensions.i
@@ -86,6 +86,7 @@ STRING_EXTENSION_OUTSIDE(SBValue)
process = property(GetProcess, None, doc='''A read only property that returns the lldb.SBProcess that this value is associated with, the returned value might be invalid and should be tested.''')
thread = property(GetThread, None, doc='''A read only property that returns the lldb.SBThread that this value is associated with, the returned value might be invalid and should be tested.''')
frame = property(GetFrame, None, doc='''A read only property that returns the lldb.SBFrame that this value is associated with, the returned value might be invalid and should be tested.''')
+ parent = property(GetParent, None, doc='''A read only property that returns the lldb.SBValue that is the parent of this value.''')
num_children = property(GetNumChildren, None, doc='''A read only property that returns the number of child lldb.SBValues that this value has.''')
unsigned = property(GetValueAsUnsigned, None, doc='''A read only property that returns the value of this SBValue as an usigned integer.''')
signed = property(GetValueAsSigned, None, doc='''A read only property that returns the value of this SBValue as a signed integer.''')
diff --git a/lldb/include/lldb/API/SBValue.h b/lldb/include/lldb/API/SBValue.h
index d4cc2f05c39e3..23a58897bc110 100644
--- a/lldb/include/lldb/API/SBValue.h
+++ b/lldb/include/lldb/API/SBValue.h
@@ -82,6 +82,8 @@ class LLDB_API SBValue {
const char *GetObjectDescription();
+ lldb::SBValue GetParent();
+
lldb::SBValue GetDynamicValue(lldb::DynamicValueType use_dynamic);
lldb::SBValue GetStaticValue();
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index 4ee8b271c5aad..82792622177c6 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -598,6 +598,20 @@ SBValue::GetChildMemberWithName(const char *name,
return sb_value;
}
+lldb::SBValue SBValue::GetParent() {
+ LLDB_INSTRUMENT_VA(this);
+
+ SBValue sb_value;
+ ValueLocker locker;
+ lldb::ValueObjectSP value_sp(GetSP(locker));
+ if (value_sp) {
+ ValueObject *parent = value_sp->GetParent();
+ if (parent)
+ sb_value.SetSP(parent->GetSP());
+ }
+ return sb_value;
+}
+
lldb::SBValue SBValue::GetDynamicValue(lldb::DynamicValueType use_dynamic) {
LLDB_INSTRUMENT_VA(this, use_dynamic);
diff --git a/lldb/test/API/python_api/sbvalue_get_parent/Makefile b/lldb/test/API/python_api/sbvalue_get_parent/Makefile
new file mode 100644
index 0000000000000..3d0b98f13f3d7
--- /dev/null
+++ b/lldb/test/API/python_api/sbvalue_get_parent/Makefile
@@ -0,0 +1,2 @@
+CXX_SOURCES := main.cpp
+include Makefile.rules
diff --git a/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py b/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
new file mode 100644
index 0000000000000..f40eddaabfbe0
--- /dev/null
+++ b/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
@@ -0,0 +1,30 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test(self):
+ self.build()
+ _, _, thread, _ = lldbutil.run_to_source_breakpoint(
+ self, "break here", lldb.SBFileSpec("main.cpp")
+ )
+ frame = thread.GetFrameAtIndex(0)
+
+ parent = frame.FindVariable("parent")
+ self.assertTrue(parent.IsValid())
+
+ child = parent.GetChildMemberWithName("child")
+ self.assertTrue(child.IsValid())
+
+ # GetParent of child should be the parent struct.
+ child_parent = child.GetParent()
+ self.assertTrue(child_parent.IsValid())
+ self.assertEqual(child_parent.name, "parent")
+ self.assertEqual(child_parent.GetID(), parent.GetID())
+
+ # GetParent of a top-level variable should be invalid.
+ self.assertFalse(parent.GetParent().IsValid())
diff --git a/lldb/test/API/python_api/sbvalue_get_parent/main.cpp b/lldb/test/API/python_api/sbvalue_get_parent/main.cpp
new file mode 100644
index 0000000000000..27318ae58f92c
--- /dev/null
+++ b/lldb/test/API/python_api/sbvalue_get_parent/main.cpp
@@ -0,0 +1,12 @@
+struct Child {
+ int x;
+};
+
+struct Parent {
+ Child child;
+};
+
+int main() {
+ Parent parent = {{1}};
+ return 0; // break here
+}
>From 282815ec169782d8dcdb1dd2003c9304a93ba845 Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Mon, 18 May 2026 17:12:36 -0700
Subject: [PATCH 2/3] Fix GetParent for synthetic children
---
lldb/include/lldb/ValueObject/ValueObject.h | 14 +++++++++++--
.../ValueObject/ValueObjectSynthetic.cpp | 3 +++
.../TestSBValueGetParent.py | 20 +++++++++++++------
.../python_api/sbvalue_get_parent/main.cpp | 3 +++
4 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
index 029563fa77850..68a2682a81a93 100644
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -913,9 +913,15 @@ class ValueObject {
// update itself then use m_parent. The ValueObjectDynamicValue's parent is
// not the correct parent for displaying, they are really siblings, so for
// display it needs to route through to its grandparent.
- virtual ValueObject *GetParent() { return m_parent; }
+ virtual ValueObject *GetParent() {
+ return m_logical_parent ? m_logical_parent : m_parent;
+ }
+
+ virtual const ValueObject *GetParent() const {
+ return m_logical_parent ? m_logical_parent : m_parent;
+ }
- virtual const ValueObject *GetParent() const { return m_parent; }
+ void SetLogicalParent(ValueObject *parent) { m_logical_parent = parent; }
ValueObject *GetNonBaseClassParent();
@@ -1045,6 +1051,10 @@ class ValueObject {
/// The parent value object, or nullptr if this has no parent.
ValueObject *m_parent = nullptr;
+ /// The parent to report from GetParent(), if different from m_parent.
+ /// Used for synthetic children whose logical parent is the synthetic
+ /// ValueObject, not the infrastructure parent.
+ ValueObject *m_logical_parent = nullptr;
/// The root of the hierarchy for this ValueObject (or nullptr if never
/// calculated).
ValueObject *m_root = nullptr;
diff --git a/lldb/source/ValueObject/ValueObjectSynthetic.cpp b/lldb/source/ValueObject/ValueObjectSynthetic.cpp
index bf7cc80537b17..1485dc1827480 100644
--- a/lldb/source/ValueObject/ValueObjectSynthetic.cpp
+++ b/lldb/source/ValueObject/ValueObjectSynthetic.cpp
@@ -286,6 +286,9 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(uint32_t idx,
if (!synth_guy)
return synth_guy;
+ if (synth_guy->IsSyntheticChildrenGenerated())
+ synth_guy->SetLogicalParent(this);
+
{
std::lock_guard<std::mutex> guard(m_child_mutex);
if (synth_guy->IsSyntheticChildrenGenerated())
diff --git a/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py b/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
index f40eddaabfbe0..63086b9546dc2 100644
--- a/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
+++ b/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
@@ -3,6 +3,7 @@
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
+from typing import Union
class TestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@@ -14,17 +15,24 @@ def test(self):
)
frame = thread.GetFrameAtIndex(0)
- parent = frame.FindVariable("parent")
+ self._do_test(frame, "parent", "child")
+ self._do_test(frame, "vec", 0)
+
+ def _do_test(
+ self, frame: lldb.SBFrame, parent_name: str, child_key: Union[str, int]
+ ):
+ parent = frame.FindVariable(parent_name)
self.assertTrue(parent.IsValid())
- child = parent.GetChildMemberWithName("child")
+ if isinstance(child_key, int):
+ child = parent.GetChildAtIndex(child_key)
+ else:
+ assert isinstance(child_key, str)
+ child = parent.GetChildMemberWithName(child_key)
self.assertTrue(child.IsValid())
# GetParent of child should be the parent struct.
child_parent = child.GetParent()
self.assertTrue(child_parent.IsValid())
- self.assertEqual(child_parent.name, "parent")
+ self.assertEqual(child_parent.name, parent_name)
self.assertEqual(child_parent.GetID(), parent.GetID())
-
- # GetParent of a top-level variable should be invalid.
- self.assertFalse(parent.GetParent().IsValid())
diff --git a/lldb/test/API/python_api/sbvalue_get_parent/main.cpp b/lldb/test/API/python_api/sbvalue_get_parent/main.cpp
index 27318ae58f92c..cfb3452a70eb5 100644
--- a/lldb/test/API/python_api/sbvalue_get_parent/main.cpp
+++ b/lldb/test/API/python_api/sbvalue_get_parent/main.cpp
@@ -1,3 +1,5 @@
+#include <vector>
+
struct Child {
int x;
};
@@ -8,5 +10,6 @@ struct Parent {
int main() {
Parent parent = {{1}};
+ std::vector<int> vec = {10, 20, 30};
return 0; // break here
}
>From c7e537dee69e5de236ec41c7016c12bdf49d40ba Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Mon, 18 May 2026 17:53:47 -0700
Subject: [PATCH 3/3] formatting
---
.../API/python_api/sbvalue_get_parent/TestSBValueGetParent.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py b/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
index 63086b9546dc2..50a6b95009208 100644
--- a/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
+++ b/lldb/test/API/python_api/sbvalue_get_parent/TestSBValueGetParent.py
@@ -5,6 +5,7 @@
from typing import Union
+
class TestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
More information about the lldb-commits
mailing list