Skip to content

Commit 24e9f68

Browse files
authored
cgen: fix fn_var_signature() support nr_muls (fix #26049) (#26075)
1 parent 2024b48 commit 24e9f68

9 files changed

Lines changed: 48 additions & 21 deletions

File tree

‎vlib/v/gen/c/array.v‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ fn (mut g Gen) array_init_with_fields(node ast.ArrayInit, elem_type Type, is_amp
471471

472472
fn (mut g Gen) declare_closure_fn(mut expr ast.AnonFn, var_name string) {
473473
decl_var := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ),
474-
var_name)
474+
var_name, 0)
475475
g.write('${decl_var} = ')
476476
g.gen_anon_fn(mut expr)
477477
g.writeln(';')
@@ -553,7 +553,7 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
553553
if var_sym.info is ast.FnType {
554554
ret_elem_styp = 'voidptr'
555555
closure_var_decl = g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ),
556-
tmp_map_expr_result_name)
556+
tmp_map_expr_result_name, 0)
557557
}
558558
}
559559
}

‎vlib/v/gen/c/assign.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
507507
// if it's a decl assign (`:=`) or a blank assignment `_ =`/`_ :=` then generate `void (*ident) (args) =`
508508
if (is_decl || blank_assign) && left is ast.Ident {
509509
sig := g.fn_var_signature(val.decl.return_type, val.decl.params.map(it.typ),
510-
ident.name)
510+
ident.name, 0)
511511
g.write(sig + ' = ')
512512
} else {
513513
g.is_assign_lhs = true

‎vlib/v/gen/c/auto_eq_methods.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ fn (mut g Gen) gen_map_equality_fn(left_type ast.Type) string {
548548
if kind == .function {
549549
info := value.sym.info as ast.FnType
550550
sig := g.fn_var_signature(info.func.return_type, info.func.params.map(it.typ),
551-
'v')
551+
'v', 0)
552552
fn_builder.writeln('\t\t${sig} = *(voidptr*)builtin__map_get(${a}, k, &(voidptr[]){ 0 });')
553553
} else {
554554
fn_builder.writeln('\t\t${ptr_value_styp} v = *(${ptr_value_styp}*)builtin__map_get(${a}, k, &(${ptr_value_styp}[]){ ${initializer} });')

‎vlib/v/gen/c/consts_and_globals.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ fn (mut g Gen) const_decl_init_later(mod string, name string, cname string, expr
350350
if expr_sym.kind == .function {
351351
// allow for: `const xyz = abc`, where `abc` is `fn abc() {}`
352352
func := (expr_sym.info as ast.FnType).func
353-
def = g.fn_var_signature(func.return_type, func.params.map(it.typ), cname)
353+
def = g.fn_var_signature(func.return_type, func.params.map(it.typ), cname, 0)
354354
}
355355
init_str := init.str().trim_right('\n')
356356
g.global_const_defs[util.no_dots(name)] = GlobalConstDef{

‎vlib/v/gen/c/fn.v‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
309309

310310
if call_fn.is_fn_var {
311311
sig := g.fn_var_signature(call_fn.func.return_type, call_fn.func.params.map(it.typ),
312-
call_fn.name)
312+
call_fn.name, 0)
313313
g.write(sig)
314314
g.definitions.write_string(sig)
315315
} else {
@@ -741,8 +741,8 @@ fn (mut g Gen) gen_anon_fn_decl(mut node ast.AnonFn) {
741741
for var in node.inherited_vars {
742742
var_sym := g.table.sym(var.typ)
743743
if var_sym.info is ast.FnType {
744-
sig := g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ),
745-
c_name(var.name))
744+
mut sig := g.fn_var_signature(var_sym.info.func.return_type, var_sym.info.func.params.map(it.typ),
745+
c_name(var.name), var.typ.nr_muls())
746746
g.definitions.writeln('\t' + sig + ';')
747747
} else {
748748
styp := g.styp(var.typ)
@@ -881,7 +881,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
881881
if node.left.inherited_vars.len > 0 {
882882
tmp_anon_fn_var = g.new_tmp_var()
883883
fn_type := g.fn_var_signature(node.left.decl.return_type, node.left.decl.params.map(it.typ),
884-
tmp_anon_fn_var)
884+
tmp_anon_fn_var, 0)
885885
line := g.go_before_last_stmt().trim_space()
886886
g.empty_line = true
887887
g.write('${fn_type} = ')
@@ -914,7 +914,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
914914
tmp_res := g.new_tmp_var()
915915
fn_sym := g.table.sym(left_typ).info as ast.FnType
916916
fn_type := g.fn_var_signature(fn_sym.func.return_type, fn_sym.func.params.map(it.typ),
917-
tmp_res)
917+
tmp_res, 0)
918918

919919
old_is_fn_index_call := g.is_fn_index_call
920920
g.is_fn_index_call = true

‎vlib/v/gen/c/match.v‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) {
103103
if !node.return_type.has_option_or_result() && ret_final_sym.kind == .function {
104104
if ret_final_sym.info is ast.FnType {
105105
def := g.fn_var_signature(ret_final_sym.info.func.return_type, ret_final_sym.info.func.params.map(it.typ),
106-
tmp_var)
106+
tmp_var, 0)
107107
func_decl = '${def} = &${g.styp(node.return_type)};'
108108
}
109109
}

‎vlib/v/gen/c/spawn_and_go.v‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
5151
} else if mut expr.left is ast.AnonFn {
5252
if expr.left.inherited_vars.len > 0 {
5353
fn_var := g.fn_var_signature(expr.left.decl.return_type, expr.left.decl.params.map(it.typ),
54-
tmp_fn)
54+
tmp_fn, 0)
5555
g.write('\t${fn_var} = ')
5656
g.gen_anon_fn(mut expr.left)
5757
g.writeln(';')
@@ -65,7 +65,8 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
6565
if expr.is_fn_var {
6666
fn_sym := g.table.sym(expr.fn_var_type)
6767
func := (fn_sym.info as ast.FnType).func
68-
fn_var := g.fn_var_signature(func.return_type, func.params.map(it.typ), tmp_fn)
68+
fn_var := g.fn_var_signature(func.return_type, func.params.map(it.typ), tmp_fn,
69+
0)
6970
g.write('\t${fn_var} = ')
7071
g.expr(expr.left)
7172
g.writeln(';')
@@ -185,10 +186,10 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
185186
fn_sym := g.table.sym(node.call_expr.fn_var_type)
186187
info := fn_sym.info as ast.FnType
187188
fn_var = g.fn_var_signature(info.func.return_type, info.func.params.map(it.typ),
188-
'fn')
189+
'fn', 0)
189190
} else if node.call_expr.left is ast.AnonFn {
190191
f := node.call_expr.left.decl
191-
fn_var = g.fn_var_signature(f.return_type, f.params.map(it.typ), 'fn')
192+
fn_var = g.fn_var_signature(f.return_type, f.params.map(it.typ), 'fn', 0)
192193
} else {
193194
if node.call_expr.is_method {
194195
rec_sym := g.table.sym(g.unwrap_generic(node.call_expr.receiver_type))
@@ -199,7 +200,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
199200
mut arg_types := f.params.map(it.typ)
200201
arg_types = arg_types.map(muttable.convert_generic_type(it, f.generic_names,
201202
node.call_expr.concrete_types) or { it })
202-
fn_var = g.fn_var_signature(return_type, arg_types, 'fn')
203+
fn_var = g.fn_var_signature(return_type, arg_types, 'fn', 0)
203204
}
204205
} else {
205206
if f := g.table.find_fn(node.call_expr.name) {
@@ -222,7 +223,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
222223
}
223224
}
224225
}
225-
fn_var = g.fn_var_signature(return_type, arg_types, 'fn')
226+
fn_var = g.fn_var_signature(return_type, arg_types, 'fn', 0)
226227
}
227228
}
228229
}
@@ -238,7 +239,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
238239
arg_sym := g.table.sym(arg.typ)
239240
if arg_sym.info is ast.FnType {
240241
sig := g.fn_var_signature(arg_sym.info.func.return_type, arg_sym.info.func.params.map(it.typ),
241-
'arg${i + 1}')
242+
'arg${i + 1}', arg.typ.nr_muls())
242243
g.type_definitions.writeln('\t' + sig + ';')
243244
} else {
244245
styp := g.styp(arg.typ)

‎vlib/v/gen/c/utils.v‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,15 @@ fn (mut g Gen) unwrap(typ ast.Type) Type {
8484
}
8585

8686
// generate function variable definition, e.g. `void (*var_name) (int, string)`
87-
fn (mut g Gen) fn_var_signature(return_type ast.Type, arg_types []ast.Type, var_name string) string {
87+
fn (mut g Gen) fn_var_signature(return_type ast.Type, arg_types []ast.Type, var_name string, nr_muls int) string {
8888
ret_styp := g.styp(return_type)
89-
mut sig := '${ret_styp} (*${c_name(var_name)}) ('
89+
mut sig := '${ret_styp} (${'*'.repeat(nr_muls + 1)}${c_name(var_name)}) ('
9090
for j, arg_typ in arg_types {
9191
arg_sym := g.table.sym(arg_typ)
9292
if arg_sym.info is ast.FnType {
9393
func := arg_sym.info.func
94-
arg_sig := g.fn_var_signature(func.return_type, func.params.map(it.typ), '')
94+
arg_sig := g.fn_var_signature(func.return_type, func.params.map(it.typ), '',
95+
arg_typ.nr_muls())
9596
sig += arg_sig
9697
} else {
9798
arg_styp := g.styp(arg_typ)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
module main
2+
3+
fn f_a() int {
4+
println('a')
5+
return 1
6+
}
7+
8+
fn test_closure_with_fn_ref_var() {
9+
f := f_a
10+
ref := &f
11+
println('ref=0x${ptr_str(ref)}')
12+
13+
handler := fn [ref] () int { // ref_fn is captured as a direct function pointer (*fn) instead of a pointer to a function (**fn)
14+
println('in closure: ref=0x${ptr_str(ref)}')
15+
deref_fn := *ref
16+
println('in closure: deref=0x${ptr_str(deref_fn)}')
17+
return deref_fn()
18+
}
19+
20+
f()
21+
deref := *ref
22+
println('deref=0x${ptr_str(deref)}')
23+
assert deref() == 1
24+
assert handler() == 1
25+
}

0 commit comments

Comments
 (0)