From d1d47d6b8fd3c443eb9d84c17833f6dfd74bf703 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 8 Jan 2025 15:21:19 -0300 Subject: [PATCH] cgen: fix codegen for nested selectorexpr on unwrapped option (fix #23406) (#23409) --- vlib/v/gen/c/cgen.v | 11 ++++- .../option_selector_nested_unwrapped_test.v | 44 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/options/option_selector_nested_unwrapped_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 9e0a564b246a02..b78c80b32b37e4 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -158,6 +158,7 @@ mut: inside_for_c_stmt bool inside_cast_in_heap int // inside cast to interface type in heap (resolve recursive calls) inside_cast bool + inside_selector bool inside_memset bool inside_const bool inside_array_item bool @@ -4008,7 +4009,12 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { } for i, typ in field.smartcasts { if i == 0 && is_option_unwrap { - g.write('(*(${g.styp(typ)}*)') + deref := if g.inside_selector { + '*'.repeat(field.smartcasts.last().nr_muls() + 1) + } else { + '*' + } + g.write('(${deref}(${g.styp(typ)}*)') } g.write('(') if field_sym.kind == .sum_type && !is_option { @@ -4107,6 +4113,8 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { if field_is_opt { g.write('((${g.base_type(field_typ)})') } + old_inside_selector := g.inside_selector + g.inside_selector = node.expr is ast.SelectorExpr && node.expr.expr is ast.Ident n_ptr := node.expr_type.nr_muls() - 1 if n_ptr > 0 { g.write2('(', '*'.repeat(n_ptr)) @@ -4115,6 +4123,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { } else { g.expr(node.expr) } + g.inside_selector = old_inside_selector if field_is_opt { g.write(')') } diff --git a/vlib/v/tests/options/option_selector_nested_unwrapped_test.v b/vlib/v/tests/options/option_selector_nested_unwrapped_test.v new file mode 100644 index 00000000000000..4dc52238d96710 --- /dev/null +++ b/vlib/v/tests/options/option_selector_nested_unwrapped_test.v @@ -0,0 +1,44 @@ +module main + +interface IGameObject { +mut: + name string + parent ?&IGameObject + children []&IGameObject + add_child(mut o IGameObject) + advance() +} + +@[heap] +struct GameObject implements IGameObject { +mut: + name string + parent ?&IGameObject + children []&IGameObject +} + +fn (mut gameobject GameObject) add_child(mut o IGameObject) { + o.parent = &gameobject + gameobject.children << o +} + +fn (mut gameobject GameObject) advance() { + if gameobject.parent != none { + eprintln('parent: ${gameobject.parent.name} ') + } + for mut child in gameobject.children { + child.advance() + } +} + +fn test_main() { + mut v1 := &GameObject{ + name: 'v1' + } + mut v2 := &GameObject{ + name: 'v2' + } + v1.add_child(mut v2) + v1.advance() + assert true +}