Skip to content

Commit

Permalink
cgen: fix codegen for nested selectorexpr on unwrapped option (fix #2…
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Jan 8, 2025
1 parent 9fc8352 commit d1d47d6
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
11 changes: 10 additions & 1 deletion vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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))
Expand All @@ -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(')')
}
Expand Down
44 changes: 44 additions & 0 deletions vlib/v/tests/options/option_selector_nested_unwrapped_test.v
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit d1d47d6

Please sign in to comment.