checker/gen: allow vargs to be forwarded. fix/enable variadic test

pull/4550/head
joe-conigliaro 2020-04-22 13:28:47 +10:00
parent b288ecb795
commit c1e8612624
3 changed files with 13 additions and 5 deletions

View File

@ -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',

View File

@ -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') {

View File

@ -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