From ca6e3a38ceedf710a08f1bcff519205737761a72 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 7 Jan 2025 05:01:08 -0300 Subject: [PATCH] cgen: fix codegen for selector on shared var with embed (fix #23378) (#23394) --- vlib/v/gen/c/cgen.v | 22 ++++++++++++++----- .../concurrency/selector_shared_var_test.v | 15 +++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/concurrency/selector_shared_var_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 879e81406ab0b1..9e0a564b246a02 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4125,6 +4125,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { g.write(')') } // struct embedding + mut has_embed := false if sym.info in [ast.Struct, ast.Aggregate] { if node.generic_from_embed_types.len > 0 && sym.info is ast.Struct { if sym.info.embeds.len > 0 { @@ -4134,36 +4135,43 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { if arr_val[0] == sym.info.embeds[0] { g.write_selector_expr_embed_name(node, arr_val) is_find = true + has_embed = true break } } } if !is_find { + has_embed = node.from_embed_types.len > 0 g.write_selector_expr_embed_name(node, node.from_embed_types) } } else { + has_embed = node.from_embed_types.len > 0 g.write_selector_expr_embed_name(node, node.from_embed_types) } } else if sym.info is ast.Aggregate { agg_sym := g.table.sym(sym.info.types[g.aggregate_type_idx]) if !g.table.struct_has_field(agg_sym, field_name) { + has_embed = node.from_embed_types.len > 0 g.write_selector_expr_embed_name(node, node.from_embed_types) } } else { + has_embed = node.from_embed_types.len > 0 g.write_selector_expr_embed_name(node, node.from_embed_types) } } alias_to_ptr := sym.info is ast.Alias && sym.info.parent_type.is_ptr() is_dereferenced := node.expr is ast.SelectorExpr && node.expr.expr_type.is_ptr() && !node.expr.typ.is_ptr() && final_sym.kind in [.interface, .sum_type] - if field_is_opt || (((!is_dereferenced && unwrapped_expr_type.is_ptr()) - || sym.kind == .chan || alias_to_ptr) && node.from_embed_types.len == 0) - || (node.expr.is_as_cast() && g.inside_smartcast) { + left_is_ptr := field_is_opt + || (((!is_dereferenced && unwrapped_expr_type.is_ptr()) || sym.kind == .chan + || alias_to_ptr) && node.from_embed_types.len == 0) + || (node.expr.is_as_cast() && g.inside_smartcast) + if !has_embed && left_is_ptr { g.write('->') } else { g.write('.') } - if node.expr_type.has_flag(.shared_f) { + if !has_embed && node.expr_type.has_flag(.shared_f) { g.write('val.') } if node.expr_type == 0 { @@ -4243,14 +4251,18 @@ fn (mut g Gen) gen_closure_fn(expr_styp string, m ast.Fn, name string) { } fn (mut g Gen) write_selector_expr_embed_name(node ast.SelectorExpr, embed_types []ast.Type) { + is_shared := node.expr_type.has_flag(.shared_f) for i, embed in embed_types { embed_sym := g.table.sym(embed) embed_name := embed_sym.embed_name() is_left_ptr := if i == 0 { - node.expr_type.is_ptr() + node.expr_type.is_ptr() && !is_shared } else { embed_types[i - 1].is_ptr() } + if i == 0 && is_shared { + g.write('->val') + } if is_left_ptr { g.write('->') } else { diff --git a/vlib/v/tests/concurrency/selector_shared_var_test.v b/vlib/v/tests/concurrency/selector_shared_var_test.v new file mode 100644 index 00000000000000..b1ee0a73b3856b --- /dev/null +++ b/vlib/v/tests/concurrency/selector_shared_var_test.v @@ -0,0 +1,15 @@ +struct Foo { +mut: + foo string +} + +struct Bar { + Foo +} + +fn test_main() { + shared bar := Bar{} + rlock bar { + assert bar.foo == '' + } +}