compiler: fix panic when dealing with variadic functions

pull/4002/head
Marko Zitkovic 2020-03-12 18:21:02 +01:00 committed by GitHub
parent 0df6eaa927
commit 26b9987880
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 50 additions and 2 deletions

View File

@ -1308,6 +1308,8 @@ fn (p mut Parser) fn_call_args(f mut Fn, generic_param_types []string) {
p.check(.comma) p.check(.comma)
p.fspace() p.fspace()
p.gen(',') p.gen(',')
} else if p.tok != .comma {
p.gen(',')
} }
} }
} }
@ -1499,9 +1501,17 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string,[]string) {
p.error_with_token_index('variadic arg index out of range: $va.index/${values.len-1}, vargs are 0 indexed', va.tok_idx) p.error_with_token_index('variadic arg index out of range: $va.index/${values.len-1}, vargs are 0 indexed', va.tok_idx)
} }
} }
if !f.is_method && f.args.len > 1 {
if types.len == 0 {
return last_arg.typ,[]string
}
insert_comma_after_arg := if f.is_method { 2 } else { 1 }
if f.args.len > insert_comma_after_arg {
p.cgen.gen(',') p.cgen.gen(',')
} }
return types[0],values return types[0],values
} }
@ -1509,8 +1519,13 @@ fn (p mut Parser) fn_gen_caller_vargs(f &Fn, varg_type string, values []string)
is_varg := varg_type.starts_with('varg_') is_varg := varg_type.starts_with('varg_')
if is_varg { if is_varg {
// forwarding varg // forwarding varg
if values.len == 0 {
vargs_struct := p.register_vargs_stuct(varg_type, 1)
p.cgen.gen('&($vargs_struct){.len=0}')
} else {
p.cgen.gen('${values[0]}') p.cgen.gen('${values[0]}')
} }
}
else { else {
vargs_struct := p.register_vargs_stuct(varg_type, values.len) vargs_struct := p.register_vargs_stuct(varg_type, values.len)
p.cgen.gen('&($vargs_struct){.len=$values.len,.args={' + values.join(',') + '}}') p.cgen.gen('&($vargs_struct){.len=$values.len,.args={' + values.join(',') + '}}')

View File

@ -41,3 +41,36 @@ fn variadic_forward_b(a ...string) string {
fn test_fn_variadic_forward() { fn test_fn_variadic_forward() {
assert variadic_forward_a('a', 'b', 'c') == 'abc' assert variadic_forward_a('a', 'b', 'c') == 'abc'
} }
fn variadic_test_no_args(name string, groups ...VaTestGroup) {
assert groups.len == 0
}
fn test_fn_variadic_no_args() {
variadic_test_no_args('marko')
}
struct VaTestStruct {
}
fn (a VaTestStruct) variadic_method(name string, groups ...VaTestGroup) {
assert groups.len == 2
assert groups[0].name == 'users'
assert groups[1].name == 'admins'
}
fn (a VaTestStruct) variadic_method_no_args(name string, groups ...VaTestGroup) {
assert groups.len == 0
}
fn test_fn_variadic_method() {
a := VaTestStruct{}
group1 := VaTestGroup{name: 'users'}
group2 := VaTestGroup{name: 'admins'}
a.variadic_method('marko', group1, group2)
}
fn test_fn_variadic_method_no_args() {
a := VaTestStruct{}
a.variadic_method_no_args('marko')
}