llvm-project/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
Ilia Kuklin 80fffd527c
[lldb] Add evaluation modes to DIL (#178747)
Adding more supported operators to DIL breaks tests in `DWIMPrint` and
`lldb-dap`, which shouldn't be simply adjusted for new DIL capabilities.
They act as a check for the boundaries of what subset of expressions
`DWIMPrint` and `lldb-dap` expect to be evaluated when using
`GetValueForVariableExpressionPath` function. With this patch, the
caller can now pick a mode that limits the expressions DIL can evaluate,
which ensures the expected preexisting behavior. More operators can now
be safely added to DIL, which can still be evaluated by DIL when using
`frame var` command or the API call with Full mode selected (or not
specified at all).

DIL will only attempt evaluating expressions that contain operations
allowed by a selected mode:
 - Simple: identifiers, operators: '.'
 - Legacy: identifiers, integers, operators: '.', '->', '*', '&', '[]'
 - Full: everything supported by DIL
2026-02-13 18:34:58 +05:00

118 lines
4.3 KiB
Python

"""
Test DIL array subscript.
"""
import lldb
from lldbsuite.test.lldbtest import *
from lldbsuite.test.decorators import *
from lldbsuite.test import lldbutil
class TestFrameVarDILArraySubscript(TestBase):
NO_DEBUG_INFO_TESTCASE = True
def test_subscript(self):
self.build()
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
)
self.runCmd("settings set target.experimental.use-DIL true")
# Test int[] and int*
self.expect_var_path("int_arr[0]", value="1")
self.expect_var_path("int_ptr[1]", value="2")
self.expect_var_path("int_ptr[enum_one]", value="2")
# Test when base and index are references.
self.expect_var_path("int_arr[0]", value="1")
self.expect_var_path("int_arr[idx_1_ref]", value="2")
self.expect_var_path("int_arr[enum_ref]", value="2")
self.expect_var_path("int_arr_ref[0]", value="1")
self.expect_var_path("int_arr_ref[idx_1_ref]", value="2")
self.expect_var_path("int_arr_ref[enum_ref]", value="2")
# Test when base and index are typedefs.
self.expect_var_path("td_int_arr[0]", value="1")
self.expect_var_path("td_int_arr[td_int_idx_1]", value="2")
self.expect_var_path("td_int_arr[td_td_int_idx_2]", value="3")
self.expect_var_path("td_int_ptr[0]", value="1")
self.expect_var_path("td_int_ptr[td_int_idx_1]", value="2")
self.expect_var_path("td_int_ptr[td_td_int_idx_2]", value="3")
# Both typedefs and refs
self.expect_var_path("td_int_arr_ref[td_int_idx_1_ref]", value="2")
# Test for index out of bounds. 1 beyond the end.
self.expect_var_path("int_arr[3]", type="int")
# Far beyond the end (but not far enough to be off the top of the stack).
self.expect_var_path("int_arr[10]", type="int")
# Test address-of of the subscripted value.
self.expect_var_path("*(&int_arr[1])", value="2")
# Test for negative index.
self.expect_var_path("int_ptr_1[-1]", value="1")
# Test for floating point index
self.expect(
"frame var 'int_arr[1.0]'",
error=True,
substrs=["array subscript is not an integer"],
)
# Test accessing bits in scalar types.
self.expect_var_path("idx_1[0]", value="1")
self.expect_var_path("idx_1[1]", value="0")
self.expect_var_path("1[0]", value="1")
# Bit access not valid for a reference.
self.expect(
"frame var 'idx_1_ref[0]'",
error=True,
substrs=["bitfield range 0:0 is not valid"],
)
# Base should be a "pointer to T" and index should be of an integral type.
self.expect(
"frame var 'int_arr[int_ptr]'",
error=True,
substrs=["array subscript is not an integer"],
)
# Base should not be a pointer to void
self.expect(
"frame var 'p_void[0]'",
error=True,
substrs=["subscript of pointer to incomplete type 'void'"],
)
# Check that subscription is not allowed in simple mode, but allowed in legacy mode
frame = thread.GetFrameAtIndex(0)
simple = frame.GetValueForVariablePath("int_arr[0]", lldb.eDILModeSimple)
legacy = frame.GetValueForVariablePath("int_arr[0]", lldb.eDILModeLegacy)
self.assertFailure(simple.GetError())
self.assertSuccess(legacy.GetError())
def test_subscript_synthetic(self):
self.build()
lldbutil.run_to_source_breakpoint(
self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
)
self.runCmd("settings set target.experimental.use-DIL true")
self.runCmd("script from myArraySynthProvider import *")
self.runCmd("type synth add -l myArraySynthProvider myArray")
# Test synthetic value subscription
self.expect_var_path("vector[1]", value="2")
self.expect(
"frame var 'vector[100]'",
error=True,
substrs=["array index 100 is not valid"],
)
self.expect(
"frame var 'ma_ptr[0]'",
substrs=["(myArray) ma_ptr[0] = ([0] = 7, [1] = 8, [2] = 9, [3] = 10)"],
)