From 6181f4f89d022ebf33ed8a449655347eb1b9b6c0 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Tue, 20 May 2025 07:44:58 +0200 Subject: [lldb] Retcon SBValue::GetChildAtIndex(synthetic=true) (#140065) The motivation here is being (un)able to treat pointer values as an array consistently. This works for pointers to simple/scalar values, but for aggregates, we get a very surprising result: - GetChildAtIndex(x, ??, true) returns the `x` child of the zeroth array member (the one you get by dereferencing the pointer/array) for all `x` which are smaller than the number of children of that value. - for other values of `x`, we get `v[x]`, where `v` is treated like a (C) pointer This patch reimagines this interface so that the value of `true` always treats (pointer and array) values as pointers. For `false`, we always dereference pointers, while in the case of arrays, we only return the values as far as the array bounds will allow. This has the potential to break existing code, but I have a suspicion that code was already broken to begin with, which is why I think this would be better than introducing a new API and keeping the old (and surprising) behavior. If our own test coverage is any indication, breakage should be minimal. --- .../sbvalue_synthetic/TestSBValueSynthetic.py | 28 ++++++++++++++++++++++ .../test/API/python_api/sbvalue_synthetic/main.cpp | 9 +++++++ 2 files changed, 37 insertions(+) (limited to 'lldb/test/API/python_api') diff --git a/lldb/test/API/python_api/sbvalue_synthetic/TestSBValueSynthetic.py b/lldb/test/API/python_api/sbvalue_synthetic/TestSBValueSynthetic.py index 2fd1e0ce9c6a..8b36308de63d 100644 --- a/lldb/test/API/python_api/sbvalue_synthetic/TestSBValueSynthetic.py +++ b/lldb/test/API/python_api/sbvalue_synthetic/TestSBValueSynthetic.py @@ -21,3 +21,31 @@ class TestSBValueSynthetic(TestBase): has_formatted = self.frame().FindVariable("has_foo") self.expect(str(formatted), exe=False, substrs=["synth_child"]) self.expect(str(has_formatted), exe=False, substrs=["synth_child"]) + + def test_synth_arr(self): + self.build() + lldbutil.run_to_source_breakpoint( + self, "break here", lldb.SBFileSpec("main.cpp") + ) + point_arr = self.frame().FindVariable("point_arr") + point_ptr = self.frame().FindVariable("point_ptr") + for v in [point_arr, point_ptr]: + for i in range(3): + child = v.GetChildAtIndex(i, lldb.eDynamicDontRunTarget, True) + check = ValueCheck( + name=f"[{i}]", + type="Point", + children=[ + ValueCheck(name="x", value=str(2 * i + 1)), + ValueCheck(name="y", value=str(2 * i + 2)), + ], + ) + check.check_value(self, child, f"{child}, child {i} of {v.GetName()}") + + int_arr = self.frame().FindVariable("int_arr") + int_ptr = self.frame().FindVariable("int_ptr") + for v in [int_arr, int_ptr]: + for i in range(3): + child = v.GetChildAtIndex(i, lldb.eDynamicDontRunTarget, True) + check = ValueCheck(name=f"[{i}]", type="int", value=str(i + 1)) + check.check_value(self, child, f"{child}, child {i} of {v.GetName()}") diff --git a/lldb/test/API/python_api/sbvalue_synthetic/main.cpp b/lldb/test/API/python_api/sbvalue_synthetic/main.cpp index 52c6474d7a1b..d9b65f017a30 100644 --- a/lldb/test/API/python_api/sbvalue_synthetic/main.cpp +++ b/lldb/test/API/python_api/sbvalue_synthetic/main.cpp @@ -6,8 +6,17 @@ struct HasFoo { Foo f; }; +struct Point { + int x; + int y; +}; + int main() { Foo foo; HasFoo has_foo; + Point point_arr[] = {{1, 2}, {3, 4}, {5, 6}}; + int int_arr[] = {1, 2, 3, 4, 5, 6}; + Point *point_ptr = point_arr; + int *int_ptr = int_arr; return 0; // break here } -- cgit v1.2.3