Files
clang-p2996/lldb/test/API/python_api/sbvalue_synthetic/TestSBValueSynthetic.py
Pavel Labath 6181f4f89d [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.
2025-05-20 07:44:58 +02:00

52 lines
2.0 KiB
Python

import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestSBValueSynthetic(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def test_str(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.cpp")
)
self.runCmd("command script import formatter.py")
self.runCmd(
"type synthetic add --python-class formatter.FooSyntheticProvider Foo"
)
formatted = self.frame().FindVariable("foo")
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()}")