From 5e2ff246c8556f0a96a7882573f8027e075f3d9a Mon Sep 17 00:00:00 2001 From: walking devel <104449470+walkingdevel@users.noreply.github.com> Date: Fri, 3 Mar 2023 07:11:15 +0000 Subject: [PATCH] cgen: pass sum type values automatically by reference too, when functions require that (#17476) --- vlib/v/gen/c/fn.v | 15 ++++++++++- .../c/testdata/sumtype_pass_by_reference.out | 20 ++++++++++++++ .../c/testdata/sumtype_pass_by_reference.vv | 27 +++++++++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 vlib/v/gen/c/testdata/sumtype_pass_by_reference.out create mode 100644 vlib/v/gen/c/testdata/sumtype_pass_by_reference.vv diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 1e7301aca..bbc6b32cc 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2289,6 +2289,7 @@ fn (mut g Gen) keep_alive_call_postgen(node ast.CallExpr, tmp_cnt_save int) { [inline] fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang ast.Language) { arg_typ := g.unwrap_generic(arg.typ) + arg_sym := g.table.sym(arg_typ) exp_is_ptr := expected_type.is_ptr() || expected_type.idx() in ast.pointer_type_idxs arg_is_ptr := arg_typ.is_ptr() || arg_typ.idx() in ast.pointer_type_idxs if expected_type == 0 { @@ -2300,7 +2301,6 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as g.write('&/*mut*/') } else if exp_is_ptr && !arg_is_ptr { if arg.is_mut { - arg_sym := g.table.sym(arg_typ) if exp_sym.kind == .array { if (arg.expr is ast.Ident && (arg.expr as ast.Ident).kind == .variable) || arg.expr is ast.SelectorExpr { @@ -2353,6 +2353,19 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as g.write('ADDR(${g.typ(atype)}/*qq*/, ') } } + } else if arg_sym.kind == .sum_type && exp_sym.kind == .sum_type { + // Automatically passing sum types by reference if the argument expects it, + // not only the argument is mutable. + if arg.expr is ast.SelectorExpr { + g.write('&/*sum*/') + g.expr(arg.expr) + return + } else if arg.expr is ast.CastExpr { + g.write('ADDR(${g.typ(expected_deref_type)}/*sum*/, ') + g.expr_with_cast(arg.expr, arg_typ, expected_type) + g.write(')') + return + } } } } else if arg_typ.has_flag(.shared_f) && !expected_type.has_flag(.shared_f) { diff --git a/vlib/v/gen/c/testdata/sumtype_pass_by_reference.out b/vlib/v/gen/c/testdata/sumtype_pass_by_reference.out new file mode 100644 index 000000000..e84079820 --- /dev/null +++ b/vlib/v/gen/c/testdata/sumtype_pass_by_reference.out @@ -0,0 +1,20 @@ +&Expr(ParExpr{ + expr: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) +}) +&Expr(ParExpr{ + expr: Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value + }) +}) +&Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value +}) +&Expr(InfixExpr{ + left: unknown sum type value + right: unknown sum type value +}) diff --git a/vlib/v/gen/c/testdata/sumtype_pass_by_reference.vv b/vlib/v/gen/c/testdata/sumtype_pass_by_reference.vv new file mode 100644 index 000000000..b4c94dd13 --- /dev/null +++ b/vlib/v/gen/c/testdata/sumtype_pass_by_reference.vv @@ -0,0 +1,27 @@ +module main + +struct ParExpr { + expr Expr +} + +struct InfixExpr { + left Expr + right Expr +} + +type Expr = InfixExpr | ParExpr + +fn print_expr(expr &Expr) { + println(expr) +} + +fn main() { + par := ParExpr{ + expr: InfixExpr{} + } + + print_expr(par) + print_expr(Expr(par)) + print_expr(par.expr) + print_expr(&par.expr) +} -- 2.39.5