From c1e8612624be5d73cb516775958ab89d3dae0ae0 Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Wed, 22 Apr 2020 13:28:47 +1000 Subject: [PATCH] checker/gen: allow vargs to be forwarded. fix/enable variadic test --- cmd/tools/vtest-fixed.v | 1 - vlib/v/checker/checker.v | 9 ++++++++- vlib/v/gen/fn.v | 8 +++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/cmd/tools/vtest-fixed.v b/cmd/tools/vtest-fixed.v index fb2a054569..e0b8501036 100644 --- a/cmd/tools/vtest-fixed.v +++ b/cmd/tools/vtest-fixed.v @@ -18,7 +18,6 @@ const ( 'vlib/regex/regex_test.v', 'vlib/v/tests/enum_bitfield_test.v', 'vlib/v/tests/fixed_array_test.v', - 'vlib/v/tests/fn_variadic_test.v', 'vlib/v/tests/num_lit_call_method_test.v', 'vlib/v/tests/option_test.v', 'vlib/v/tests/pointers_test.v', diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f5ae37c9d4..50868862a6 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -492,7 +492,11 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type { } else { method.args[i + 1].typ } - call_expr.args[i].typ = c.expr(arg.expr) + arg_typ := c.expr(arg.expr) + call_expr.args[i].typ = arg_typ + if method.is_variadic && table.type_is(arg_typ, .variadic) && call_expr.args.len-1 > i { + c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos) + } } // TODO: typ optimize.. this node can get processed more than once if call_expr.expected_arg_types.len == 0 { @@ -616,6 +620,9 @@ pub fn (c mut Checker) call_fn(call_expr mut ast.CallExpr) table.Type { call_expr.args[i].typ = typ typ_sym := c.table.get_type_symbol(typ) arg_typ_sym := c.table.get_type_symbol(arg.typ) + if f.is_variadic && table.type_is(typ, .variadic) && call_expr.args.len-1 > i { + c.error('when forwarding a varg variable, it must be the final argument', call_expr.pos) + } if !c.table.check(typ, arg.typ) { // str method, allow type with str method if fn arg is string if arg_typ_sym.kind == .string && typ_sym.has_method('str') { diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index c399e4070a..0399546745 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -384,9 +384,11 @@ fn (g mut Gen) fn_call(node ast.CallExpr) { fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { is_variadic := expected_types.len > 0 && table.type_is(expected_types[expected_types.len - 1], .variadic) + is_forwarding_varg := args.len > 0 && table.type_is(args[args.len-1].typ, .variadic) + gen_vargs := is_variadic && !is_forwarding_varg mut arg_no := 0 for arg in args { - if is_variadic && arg_no == expected_types.len - 1 { + if gen_vargs && arg_no == expected_types.len - 1 { break } // some c fn definitions dont have args (cfns.v) or are not updated in checker @@ -396,12 +398,12 @@ fn (g mut Gen) call_args(args []ast.CallArg, expected_types []table.Type) { } else { g.expr(arg.expr) } - if arg_no < args.len - 1 || is_variadic { + if arg_no < args.len - 1 || gen_vargs { g.write(', ') } arg_no++ } - if is_variadic { + if is_variadic && !is_forwarding_varg { varg_type := expected_types[expected_types.len - 1] struct_name := 'varg_' + g.typ(varg_type).replace('*', '_ptr') variadic_count := args.len - arg_no