Author: Raphael Isemann Date: 2026-07-10T15:34:00+01:00 New Revision: c8b02ba5ac7a37c4fa0100431b357da74f1b200f
URL: https://github.com/llvm/llvm-project/commit/c8b02ba5ac7a37c4fa0100431b357da74f1b200f DIFF: https://github.com/llvm/llvm-project/commit/c8b02ba5ac7a37c4fa0100431b357da74f1b200f.diff LOG: [lldb][test] Expand blocks test (#208406) This moves some of the tested logic from the `types/` test that is about to be deleted to the already existing c/blocks test. See also #208402 assisted-by: claude Added: Modified: lldb/test/API/lang/c/blocks/TestBlocks.py lldb/test/API/lang/c/blocks/main.c Removed: ################################################################################ diff --git a/lldb/test/API/lang/c/blocks/TestBlocks.py b/lldb/test/API/lang/c/blocks/TestBlocks.py index 00714d003c10c..f16e35a09adcf 100644 --- a/lldb/test/API/lang/c/blocks/TestBlocks.py +++ b/lldb/test/API/lang/c/blocks/TestBlocks.py @@ -1,5 +1,4 @@ -"""Test that lldb can invoke blocks and access variables inside them""" - +"""Test that lldb can invoke blocks and read variables captured by blocks.""" import lldb from lldbsuite.test.lldbtest import * @@ -9,78 +8,68 @@ @skipIfWasm # no expression evaluation class BlocksTestCase(TestBase): - lines = [] - - def setUp(self): - # Call super's setUp(). - TestBase.setUp(self) - # Find the line numbers to break at. - self.lines.append(line_number("main.c", "// Set breakpoint 0 here.")) - self.lines.append(line_number("main.c", "// Set breakpoint 1 here.")) - self.lines.append(line_number("main.c", "// Set breakpoint 2 here.")) - - def launch_common(self): - self.build() - exe = self.getBuildArtifact("a.out") - self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET) - - self.is_started = False - - # Break inside the foo function which takes a bar_ptr argument. - for line in self.lines: - lldbutil.run_break_set_by_file_and_line( - self, "main.c", line, num_expected_locations=1, loc_exact=True - ) - - self.wait_for_breakpoint() - @skipUnlessDarwin - def test_expr(self): - self.launch_common() - - self.expect("expression a + b", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 7"]) - - self.expect("expression c", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 1"]) + def test(self): + self.build() + src = lldb.SBFileSpec("main.c") + _, process, _, _ = lldbutil.run_to_source_breakpoint( + self, "Set breakpoint 0 here.", src + ) - self.wait_for_breakpoint() + # Inside the 'add' block we can read its arguments and the captured + # variable 'c'. + self.expect_expr("a + b", result_type="int", result_value="7") + self.expect_expr("c", result_type="int", result_value="1") - # This should display correctly. - self.expect( - "expression (int)neg (-12)", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 12"] + # Calling a block from the expression evaluator works. + lldbutil.continue_to_source_breakpoint( + self, process, "Set breakpoint 1 here.", src ) + self.expect_expr("(int)neg(-12)", result_type="int", result_value="12") - self.wait_for_breakpoint() - + # A block taking a struct argument can be called from the evaluator. + lldbutil.continue_to_source_breakpoint( + self, process, "Set breakpoint 2 here.", src + ) self.expect_expr("h(cg)", result_type="int", result_value="42") + # Inside a block we can read captured variables of various types. + lldbutil.continue_to_source_breakpoint( + self, process, "Set breakpoint 3 here.", src + ) + self.expect_var_path("captured_char", type="char", value="'a'") + self.expect_var_path("captured_int", type="int", value="42") + self.expect_var_path("captured_double", type="double", value="3.5") + self.expect_var_path("*captured_ptr", type="int", value="42") + self.expect_var_path("captured_struct.x", type="int", value="10") + self.expect_var_path("captured_struct.y", type="int", value="20") + + # The same captured variables are also reachable from the expression + # evaluator. + self.expect_expr("captured_char", result_type="char", result_value="'a'") + self.expect_expr("captured_int", result_type="int", result_value="42") + self.expect_expr("captured_double", result_type="double", result_value="3.5") + self.expect_expr("*captured_ptr", result_type="int", result_value="42") + self.expect_expr("captured_struct.x", result_type="int", result_value="10") + @skipUnlessDarwin def test_define(self): - self.launch_common() + """Test defining and calling a block from the expression evaluator.""" + self.build() + lldbutil.run_to_source_breakpoint( + self, "Set breakpoint 0 here.", lldb.SBFileSpec("main.c") + ) self.runCmd( "expression int (^$add)(int, int) = ^int(int a, int b) { return a + b; };" ) - self.expect( - "expression $add(2,3)", VARIABLES_DISPLAYED_CORRECTLY, substrs=[" = 5"] - ) + self.expect_expr("$add(2,3)", result_type="int", result_value="5") + # Blocks defined in the expression evaluator cannot capture persistent + # variables. self.runCmd("expression int $a = 3") self.expect( "expression int (^$addA)(int) = ^int(int b) { return $a + b; };", "Proper error is reported on capture", error=True, ) - - def wait_for_breakpoint(self): - if not self.is_started: - self.is_started = True - self.runCmd("process launch", RUN_SUCCEEDED) - else: - self.runCmd("process continue", RUN_SUCCEEDED) - - # The stop reason of the thread should be breakpoint. - self.expect( - "thread list", - STOPPED_DUE_TO_BREAKPOINT, - substrs=["stopped", "stop reason = breakpoint"], - ) diff --git a/lldb/test/API/lang/c/blocks/main.c b/lldb/test/API/lang/c/blocks/main.c index b1b215ec2331b..6b487ddb44d8e 100644 --- a/lldb/test/API/lang/c/blocks/main.c +++ b/lldb/test/API/lang/c/blocks/main.c @@ -1,40 +1,52 @@ -#include <stdio.h> - -struct CG {int x; int y;}; +struct CG { + int x; + int y; +}; int g(int (^callback)(struct CG)) { - struct CG cg = {.x=1,.y=2}; + struct CG cg = {.x = 1, .y = 2}; - int z = callback(cg); // Set breakpoint 2 here. + int z = callback(cg); // Set breakpoint 2 here. - return z; + return z; } -int h(struct CG cg){return 42;} +int h(struct CG cg) { return 42; } + +int main() { + int c = 1; + + int (^add)(int, int) = ^int(int a, int b) { + return a + b + c; // Set breakpoint 0 here. + }; + + int (^neg)(int) = ^int(int a) { + return -a; + }; -int main() -{ - int c = 1; + int sum = add(3, 4); + int negated = neg(-5); // Set breakpoint 1 here. - int (^add)(int, int) = ^int(int a, int b) - { - return a + b + c; // Set breakpoint 0 here. - }; + int (^add_struct)(struct CG) = ^int(struct CG cg) { + return cg.x + cg.y; + }; - int (^neg)(int) = ^int(int a) - { - return -a; - }; + g(add_struct); - printf("%d\n", add(3, 4)); - printf("%d\n", neg(-5)); // Set breakpoint 1 here. + // A block that captures variables of several diff erent types so we can check + // that lldb reads captured variables of each type correctly. + char captured_char = 'a'; + int captured_int = 42; + double captured_double = 3.5; + int *captured_ptr = &captured_int; + struct CG captured_struct = {.x = 10, .y = 20}; - int (^add_struct)(struct CG) = ^int(struct CG cg) - { - return cg.x + cg.y; - }; + int (^types_block)() = ^int() { + return captured_char + captured_int + (int)captured_double + *captured_ptr + + captured_struct.x; // Set breakpoint 3 here. + }; - g(add_struct); + int result = types_block(); - return 0; + return sum + negated + result; } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
