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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
