From 42d5c0b2e7231ebde9992d902ec747e974c57cd7 Mon Sep 17 00:00:00 2001 From: CreeperFace <165158232+dy-tea@users.noreply.github.com> Date: Sun, 28 Sep 2025 19:56:28 +0100 Subject: [PATCH] cgen: fix short-circuiting of boolean expressions, when the right side calls array methods (fix #25398) (#25411) --- vlib/v/gen/c/if.v | 3 +- .../logical_and_short_circuit.must_have | 24 ++++++++++++++ .../c/testdata/logical_and_short_circuit.out | 4 +++ .../c/testdata/logical_and_short_circuit.vv | 31 +++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 vlib/v/gen/c/testdata/logical_and_short_circuit.must_have create mode 100644 vlib/v/gen/c/testdata/logical_and_short_circuit.out create mode 100644 vlib/v/gen/c/testdata/logical_and_short_circuit.vv diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index c5f012934..a7310f89c 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -62,7 +62,8 @@ fn (mut g Gen) need_tmp_var_in_expr(expr ast.Expr) bool { if expr.is_method { left_sym := g.table.sym(expr.receiver_type) if left_sym.kind in [.array, .array_fixed, .map] { - return true + return expr.name !in ['contains', 'exists', 'len', 'cap', 'first', 'last', + 'index', 'get'] } } if expr.or_block.kind != .absent { diff --git a/vlib/v/gen/c/testdata/logical_and_short_circuit.must_have b/vlib/v/gen/c/testdata/logical_and_short_circuit.must_have new file mode 100644 index 000000000..fa4b786ed --- /dev/null +++ b/vlib/v/gen/c/testdata/logical_and_short_circuit.must_have @@ -0,0 +1,24 @@ +VV_LOC void main__main(void) { + Array_int list = builtin__new_array_from_c_array_noscan(3, 3, sizeof(int), _MOV((int[3]){1, 2, 3})); + int index = 3; + if (index < list.len && (*(int*)builtin__array_get(list, index)) == 3) { + builtin__println(_S("Index is within bounds and value is 3")); + } else { + builtin__println(_S("Index is out of bounds or value is not 3")); + } + if (index < list.len && main__print_true((*(int*)builtin__array_get(list, index)))) { + builtin__println(_S("Index is within bounds")); + } else { + builtin__println(_S("Index is out of bounds")); + } + if (index < list.len && Array_int_contains(_const_main__other_list, (*(int*)builtin__array_get(list, index)))) { + builtin__println(_S("Index is within bounds and value is in other_list")); + } else { + builtin__println(_S("Index is out of bounds or value is not in other_list")); + } + if (index < list.len && (Array_int_contains(_const_main__other_list, (*(int*)builtin__array_get(list, index))) || Array_int_contains(_const_main__other_list, (*(int*)builtin__array_get(list, index))))) { + builtin__println(_S("Index is within bounds and value is in other_list")); + } else { + builtin__println(_S("Index is out of bounds or value is not in other_list")); + } +} diff --git a/vlib/v/gen/c/testdata/logical_and_short_circuit.out b/vlib/v/gen/c/testdata/logical_and_short_circuit.out new file mode 100644 index 000000000..974ec3589 --- /dev/null +++ b/vlib/v/gen/c/testdata/logical_and_short_circuit.out @@ -0,0 +1,4 @@ +Index is out of bounds or value is not 3 +Index is out of bounds +Index is out of bounds or value is not in other_list +Index is out of bounds or value is not in other_list diff --git a/vlib/v/gen/c/testdata/logical_and_short_circuit.vv b/vlib/v/gen/c/testdata/logical_and_short_circuit.vv new file mode 100644 index 000000000..8d0127935 --- /dev/null +++ b/vlib/v/gen/c/testdata/logical_and_short_circuit.vv @@ -0,0 +1,31 @@ +fn print_true(i int) bool { + println(i) + return true +} + +const other_list = [3, 4] + +fn main() { + list := [1, 2, 3] + index := 3 + if index < list.len && list[index] == 3 { + println('Index is within bounds and value is 3') + } else { + println('Index is out of bounds or value is not 3') + } + if index < list.len && print_true(list[index]) { + println('Index is within bounds') + } else { + println('Index is out of bounds') + } + if index < list.len && other_list.contains(list[index]) { + println('Index is within bounds and value is in other_list') + } else { + println('Index is out of bounds or value is not in other_list') + } + if index < list.len && (other_list.contains(list[index]) || other_list.contains(list[index])) { + println('Index is within bounds and value is in other_list') + } else { + println('Index is out of bounds or value is not in other_list') + } +} -- 2.39.5