From bed28d1e8bbe063d3d985c273fe35c8e83a070d3 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 11 Jan 2025 06:44:33 -0300 Subject: [PATCH] cgen: fix shared array slice (fix #23426) (#23427) --- vlib/v/checker/assign.v | 5 +++- vlib/v/checker/checker.v | 3 +++ vlib/v/gen/c/cgen.v | 4 ++- vlib/v/gen/c/index.v | 22 ++++++++++++--- .../concurrency/shared_array_slice_test.v | 27 +++++++++++++++++++ 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 vlib/v/tests/concurrency/shared_array_slice_test.v diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 68bc08c951..2c451d5330 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -378,7 +378,10 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { left_type = left_type.set_nr_muls(1) } } else if left_type.has_flag(.shared_f) { - left_type = left_type.clear_flag(.shared_f).deref() + left_type = left_type.clear_flag(.shared_f) + if left_type.is_ptr() { + left_type = left_type.deref() + } } if ident_var_info.share == .atomic_t { left_type = left_type.set_flag(.atomic_f) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 37d75f54a7..96d5cb9184 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -5463,6 +5463,9 @@ fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string) if c.fail_if_unreadable(expr.left, expr.left_type, what) { return true } + if typ.has_flag(.shared_f) && expr.left is ast.SelectorExpr { + return false + } } ast.InfixExpr { pos = expr.left.pos().extend(expr.pos) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index eb40fcbbff..db1cff0e8d 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2928,7 +2928,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ g.write('&') } g.expr(expr) - g.write('->val') + if expr !is ast.IndexExpr { + g.write('->val') + } return } if got_is_ptr && !expected_is_ptr && neither_void && exp_sym.kind != .placeholder diff --git a/vlib/v/gen/c/index.v b/vlib/v/gen/c/index.v index 7bf063901f..eea326994e 100644 --- a/vlib/v/gen/c/index.v +++ b/vlib/v/gen/c/index.v @@ -64,10 +64,12 @@ fn (mut g Gen) index_expr(node ast.IndexExpr) { } fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) { - sym := g.table.final_sym(g.unwrap_generic(node.left_type)) + unwrapped_left_type := g.unwrap_generic(node.left_type) + sym := g.table.final_sym(unwrapped_left_type) mut tmp_opt := '' mut cur_line := '' mut gen_or := node.or_expr.kind != .absent || node.is_option + left_is_shared := unwrapped_left_type.has_flag(.shared_f) if sym.kind == .string { if node.is_gated { g.write('string_substr_ni(') @@ -92,10 +94,16 @@ fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) { } else { g.write('array_slice(') } + if left_is_shared { + g.write('(') + } if node.left_type.is_ptr() { g.write('*') } g.expr(node.left) + if left_is_shared { + g.write(').val') + } } else if sym.info is ast.ArrayFixed { // Convert a fixed array to V array when doing `fixed_arr[start..end]` noscan := g.check_noscan(sym.info.elem_type) @@ -107,6 +115,9 @@ fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) { g.write('new_array_from_c_array${noscan}(') ctype := g.styp(sym.info.elem_type) g.write('${sym.info.size}, ${sym.info.size}, sizeof(${ctype}), ') + if left_is_shared { + g.write('(') + } if node.left_type.is_ptr() { g.write('*') } @@ -118,11 +129,14 @@ fn (mut g Gen) index_range_expr(node ast.IndexExpr, range ast.RangeExpr) { g.write('${styp} ${var} = ') g.expr(node.left) g.writeln(';') - g.write2(line, ' ${var})') + g.write2(line, ' ${var}') } else { g.expr(node.left) - g.write(')') } + if left_is_shared { + g.write(').val') + } + g.write(')') } else { g.expr(node.left) } @@ -192,7 +206,7 @@ fn (mut g Gen) index_of_array(node ast.IndexExpr, sym ast.TypeSymbol) { } if left_is_shared { - if left_is_ptr { + if node.index !is ast.RangeExpr && left_is_ptr { g.write('->val') } else { g.write('.val') diff --git a/vlib/v/tests/concurrency/shared_array_slice_test.v b/vlib/v/tests/concurrency/shared_array_slice_test.v new file mode 100644 index 0000000000..c94992a66c --- /dev/null +++ b/vlib/v/tests/concurrency/shared_array_slice_test.v @@ -0,0 +1,27 @@ +struct Foo { +pub mut: + buf shared []u8 = []u8{len: 20, init: 6} + buf2 shared [20]u8 +} + +fn test_main() { + mut foo := Foo{ + buf2: [20]u8{init: 5} + } + rlock foo.buf { + if foo.buf.len > 0 { + x := 10 + println('first ${x} bytes: ' + foo.buf[..x].str()) + sliced := foo.buf[..x] + assert sliced == [u8(6), 6, 6, 6, 6, 6, 6, 6, 6, 6] + } else { + println('no data') + assert false + } + } + rlock foo.buf2 { + x := 4 + println('first ${x} bytes: ' + foo.buf2[..x].str()) + assert foo.buf2[..x] == [u8(5), 5, 5, 5] + } +}