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
118 lines
4.3 KiB
Python
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)"],
|
|
)
|