blob: 9335a4b7f2b8ff08ba2fced0779240dccf828f80 [file]
"""
Test lldb-dap variables/stackTrace request for optimized code
"""
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import line_number
from lldbsuite.test.tools.lldb_dap import DAPTestCaseBase, ExpectVar
from lldbsuite.test.tools.lldb_dap.types import LaunchArgs
class TestDAP_optimized(DAPTestCaseBase):
def test_stack_frame_name(self):
"""Test optimized frame has special name suffix."""
program = self.getBuildArtifact("a.out")
session = self.build_and_create_session()
source = "main.cpp"
breakpoint_line = line_number(source, "// breakpoint 1")
with session.configure(LaunchArgs(program)) as ctx:
bp_ids = session.resolve_source_breakpoints(source, [breakpoint_line])
stop_event = session.verify_stopped_on_breakpoint(
bp_ids, after=ctx.process_event
)
frames = session.thread_context_from(stop_event).frames()
leaf_frame = frames[0].frame
self.assertTrue(leaf_frame.name.endswith(" [opt]"))
parent_frame = frames[1].frame
self.assertTrue(parent_frame.name.endswith(" [opt]"))
@skipIfAsan # On ASAN builds this test intermittently fails https://github.com/llvm/llvm-project/issues/111061
@skipIfWasm # an optimized out variable keeps a reused local, so reading it succeeds
def test_optimized_variable(self):
"""Test optimized variable value contains error."""
program = self.getBuildArtifact("a.out")
session = self.build_and_create_session()
source = "main.cpp"
breakpoint_line = line_number(source, "// breakpoint 2")
with session.configure(LaunchArgs(program)) as ctx:
bp_ids = session.resolve_source_breakpoints(source, [breakpoint_line])
stop_event = session.verify_stopped_on_breakpoint(
bp_ids, after=ctx.process_event
)
optimized_variable = session.top_frame_from(stop_event).locals["argc"]
value = optimized_variable.value
self.assertTrue(
value.startswith("<error:"), f"expect error for value: '{value}'"
)
self.assertTrue(
("could not evaluate DW_OP_entry_value: no parent function" in value)
or ("variable not available" in value),
f"{value=}",
)
session.continue_to_exit()
@skipIfWindows
@skipIfWasm # a wasm local always lives in a writable slot
def test_constant_variable_is_read_only(self):
"""A variable without writable storage is hinted as read-only."""
program = self.getBuildArtifact("a.out")
session = self.build_and_create_session()
source = "main.cpp"
breakpoint_line = line_number(source, "// breakpoint 3")
with session.configure(LaunchArgs(program)) as ctx:
bp_ids = session.resolve_source_breakpoints(source, [breakpoint_line])
stop_event = session.verify_stopped_on_breakpoint(
bp_ids, after=ctx.process_event
)
# At -O3 `k` is folded into a constant with no storage.
k = session.top_frame_from(stop_event).locals["k"]
session.verify_variable(
k.variable, ExpectVar(type="int", value="42", read_only=True)
)
session.continue_to_exit()