Skip to content

Commit 7dd91ec

Browse files
authored
cgen: fix assigning fn address (fix #24537) (#25158)
1 parent 8bb7f3d commit 7dd91ec

File tree

5 files changed

+32
-6
lines changed

5 files changed

+32
-6
lines changed

vlib/v/gen/c/assign.v

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
289289

290290
for i, mut left in node.left {
291291
mut is_auto_heap := false
292+
mut is_fn_var := false
292293
mut var_type := node.left_types[i]
293294
mut val_type := node.right_types[i]
294295
val := node.right[i]
@@ -432,6 +433,9 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
432433
}
433434
}
434435
is_auto_heap = left.obj.is_auto_heap
436+
if left.obj.typ != 0 && val is ast.PrefixExpr {
437+
is_fn_var = g.table.final_sym(left.obj.typ).kind == .function
438+
}
435439
}
436440
} else if mut left is ast.ComptimeSelector {
437441
if left.typ_key != '' {
@@ -964,14 +968,14 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
964968
} else {
965969
is_option_unwrapped := val is ast.Ident && val.or_expr.kind != .absent
966970
is_option_auto_heap := is_auto_heap && is_option_unwrapped
967-
if is_auto_heap {
971+
if is_auto_heap && !is_fn_var {
968972
if aligned != 0 {
969973
g.write('HEAP_align(${styp}, (')
970974
} else {
971975
g.write('HEAP(${styp}, (')
972976
}
973977
}
974-
if val.is_auto_deref_var() && !is_option_unwrapped {
978+
if !is_fn_var && val.is_auto_deref_var() && !is_option_unwrapped {
975979
g.write('*')
976980
}
977981
if (var_type.has_flag(.option) && val !in [ast.Ident, ast.SelectorExpr])
@@ -997,9 +1001,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
9971001
g.fixed_array_var_init(tmp_var, false, unaliased_right_sym.info.elem_type,
9981002
unaliased_right_sym.info.size)
9991003
} else {
1004+
old_inside_assign_fn_var := g.inside_assign_fn_var
1005+
g.inside_assign_fn_var = val is ast.PrefixExpr && val.op == .amp
1006+
&& is_fn_var
10001007
g.expr(val)
1008+
g.inside_assign_fn_var = old_inside_assign_fn_var
10011009
}
1002-
if is_auto_heap && !is_option_auto_heap {
1010+
if !is_fn_var && is_auto_heap && !is_option_auto_heap {
10031011
if aligned != 0 {
10041012
g.write('), ${aligned})')
10051013
} else {

vlib/v/gen/c/cgen.v

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ mut:
163163
inside_cinit bool
164164
inside_global_decl bool
165165
inside_interface_deref bool
166+
inside_assign_fn_var bool
166167
last_tmp_call_var []string
167168
last_if_option_type ast.Type // stores the expected if type on nested if expr
168169
loop_depth int
@@ -5360,7 +5361,7 @@ fn (mut g Gen) ident(node ast.Ident) {
53605361
if node.obj is ast.Var {
53615362
is_auto_heap = node.obj.is_auto_heap
53625363
&& (!g.is_assign_lhs || g.assign_op != .decl_assign)
5363-
if is_auto_heap {
5364+
if is_auto_heap && !g.inside_assign_fn_var {
53645365
g.write('(*(')
53655366
}
53665367
is_option = is_option || node.obj.orig_type.has_flag(.option)
@@ -5478,7 +5479,7 @@ fn (mut g Gen) ident(node ast.Ident) {
54785479
}
54795480
g.write(')')
54805481
}
5481-
if is_auto_heap {
5482+
if is_auto_heap && !g.inside_assign_fn_var {
54825483
g.write('))')
54835484
}
54845485
return
@@ -5502,7 +5503,7 @@ fn (mut g Gen) ident(node ast.Ident) {
55025503
}
55035504
}
55045505
g.write(g.get_ternary_name(name))
5505-
if is_auto_heap {
5506+
if is_auto_heap && !g.inside_assign_fn_var {
55065507
g.write('))')
55075508
if is_option && node.or_expr.kind != .absent {
55085509
g.write('.data')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
string (*cb2) (void) = &cb1;
2+
string (*cb3) (void) = &cb2;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
true
2+
true
3+
true
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const hello = 'hello world!'
2+
3+
fn main() {
4+
cb1 := fn () string {
5+
return hello
6+
}
7+
cb2 := &cb1
8+
cb3 := &cb2
9+
println(voidptr(cb1) != voidptr(cb2))
10+
println(voidptr(cb2) != voidptr(cb3))
11+
println(voidptr(cb1) != voidptr(cb3))
12+
}

0 commit comments

Comments
 (0)