diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 0f9d32a00edc81..025721b866c80f 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2740,6 +2740,23 @@ fn (mut g Gen) keep_alive_call_postgen(node ast.CallExpr, tmp_cnt_save int) { } } +// gen_tmp_var_indirections generates tmp var to fit the expected indirection number +fn (mut g Gen) gen_tmp_var_indirections(var_typ ast.Type, var ast.Ident, nindirections int) { + mut last_var := g.expr_string(var) + var_styp := g.styp(var_typ) + line := g.go_before_last_stmt().trim_space() + g.empty_line = true + tmp_var := g.new_tmp_var() + for i in 0 .. nindirections { + ptr := '*'.repeat(i) + tmp_var_v := if i == 0 { tmp_var } else { '${tmp_var}_${i}' } + g.writeln('${var_styp} *${ptr}${tmp_var_v} = &${last_var};') + last_var = tmp_var_v + } + g.write(line) + g.write(last_var) +} + @[inline] fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang ast.Language, is_smartcast bool) { arg_typ := if arg.expr is ast.ComptimeSelector { @@ -2818,6 +2835,12 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as } else if !(!arg.is_mut && arg_sym.kind == .alias && g.table.unaliased_type(arg_typ).is_any_kind_of_pointer()) { g.write('(voidptr)&/*qq*/') + if arg.expr is ast.Ident && arg.expr.kind != .constant + && expected_type.nr_muls() > (arg_typ.nr_muls() + 1) { + // generates temporary vars for fit the expected indirections + g.gen_tmp_var_indirections(arg_typ, arg.expr, expected_type.nr_muls() - arg_typ.nr_muls() - 1) + return + } } } else { mut atype := expected_deref_type diff --git a/vlib/v/tests/fns/diff_indirections_arg_test.v b/vlib/v/tests/fns/diff_indirections_arg_test.v new file mode 100644 index 00000000000000..34ac537cc1beb3 --- /dev/null +++ b/vlib/v/tests/fns/diff_indirections_arg_test.v @@ -0,0 +1,12 @@ +fn takes_ref(x &&&&int) { + unsafe { + ****x = 5 + } +} + +fn test_main() { + y := 4 + takes_ref(y) + println(y) + assert y == 5 +}