Skip to content

Commit c7e00b3

Browse files
authored
cgen: fix codegen for nested selector unwrapping on lhs (fix #24292) (#24293)
1 parent 47d8ff9 commit c7e00b3

2 files changed

Lines changed: 59 additions & 4 deletions

File tree

‎vlib/v/gen/c/cgen.v‎

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ mut:
153153
inside_cast_in_heap int // inside cast to interface type in heap (resolve recursive calls)
154154
inside_cast bool
155155
inside_selector bool
156+
inside_selector_deref bool // indicates if the inside selector was already dereferenced
156157
inside_memset bool
157158
inside_const bool
158159
inside_array_item bool
@@ -4173,17 +4174,24 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
41734174
deref := if g.inside_selector {
41744175
if is_iface_or_sumtype || (field.orig_type.is_ptr() && g.left_is_opt
41754176
&& is_option_unwrap) {
4176-
'*'.repeat(field.smartcasts.last().nr_muls())
4177+
'*'.repeat(typ.nr_muls())
41774178
} else {
4178-
'*'.repeat(field.smartcasts.last().nr_muls() + 1)
4179+
'*'.repeat(typ.nr_muls() + 1)
41794180
}
41804181
} else if sym.kind == .interface && !typ.is_ptr()
41814182
&& field.orig_type.has_flag(.option) {
41824183
''
41834184
} else {
41844185
'*'
41854186
}
4186-
g.write('(${deref}(${g.styp(typ)}*)')
4187+
suffix := if g.inside_selector && field.orig_type.has_flag(.option)
4188+
&& field.orig_type.is_ptr() && g.is_assign_lhs {
4189+
''
4190+
} else {
4191+
'*'
4192+
}
4193+
g.inside_selector_deref = suffix == '' && deref.len > 0
4194+
g.write('(${deref}(${g.styp(typ)}${suffix})')
41874195
}
41884196
if i == 0 || !nested_unwrap {
41894197
g.write('(')
@@ -4289,6 +4297,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
42894297
g.write('((${g.base_type(field_typ)})')
42904298
}
42914299
old_inside_selector := g.inside_selector
4300+
old_inside_selector_deref := g.inside_selector_deref
42924301
g.inside_selector = node.expr is ast.SelectorExpr && node.expr.expr is ast.Ident
42934302
n_ptr := node.expr_type.nr_muls() - 1
42944303
if n_ptr > 0 {
@@ -4298,7 +4307,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
42984307
} else {
42994308
g.expr(node.expr)
43004309
}
4310+
mut opt_ptr_already_deref := g.inside_selector_deref
43014311
g.inside_selector = old_inside_selector
4312+
g.inside_selector_deref = old_inside_selector_deref
43024313
if field_is_opt {
43034314
g.write(')')
43044315
}
@@ -4350,7 +4361,7 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
43504361
|| (((!is_dereferenced && unwrapped_expr_type.is_ptr()) || sym.kind == .chan
43514362
|| alias_to_ptr) && node.from_embed_types.len == 0)
43524363
|| (node.expr.is_as_cast() && g.inside_smartcast)
4353-
if !has_embed && left_is_ptr {
4364+
if !has_embed && left_is_ptr && !(opt_ptr_already_deref && !g.inside_selector) {
43544365
g.write('->')
43554366
} else {
43564367
g.write('.')
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
module main
2+
3+
@[heap]
4+
interface IGameObject {
5+
mut:
6+
name string
7+
parent ?&IGameObject
8+
next ?&IGameObject
9+
child ?&IGameObject
10+
last_child ?&IGameObject
11+
add_child(mut o IGameObject)
12+
}
13+
14+
@[heap]
15+
struct GameObject implements IGameObject {
16+
mut:
17+
name string
18+
parent ?&IGameObject
19+
next ?&IGameObject
20+
child ?&IGameObject
21+
last_child ?&IGameObject
22+
}
23+
24+
fn (mut gameobject GameObject) add_child(mut o IGameObject) {
25+
o.parent = gameobject
26+
if gameobject.last_child != none {
27+
gameobject.last_child.next = o
28+
} else {
29+
gameobject.child = o
30+
}
31+
gameobject.last_child = o
32+
}
33+
34+
fn test_main() {
35+
mut v1 := &GameObject{
36+
name: 'v1'
37+
}
38+
mut v2 := &GameObject{
39+
name: 'v2'
40+
}
41+
v1.add_child(mut v2)
42+
assert v1.child? == IGameObject(v2)
43+
assert v1.last_child? == IGameObject(v2)
44+
}

0 commit comments

Comments
 (0)