diff --git a/compiler/fn.v b/compiler/fn.v index e958c09b45..929b323ff0 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -747,7 +747,7 @@ fn (p mut Parser) fn_args(f mut Fn) { t := p.get_type() vargs_struct := '_V_FnVargs_$f.name' // register varg struct, incase function is never called - p.fn_define_vargs_stuct(f, t, []string) + p.fn_register_vargs_stuct(f, t, []string) p.cgen.typedefs << 'typedef struct $vargs_struct $vargs_struct;\n' typ = '...$t' } else { @@ -1029,7 +1029,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn { return f // TODO is return f right? } -fn (p mut Parser) fn_define_vargs_stuct(f &Fn, typ string, values []string) { +fn (p mut Parser) fn_register_vargs_stuct(f &Fn, typ string, values []string) { vargs_struct := '_V_FnVargs_$f.name' varg_type := Type{ cat: TypeCategory.struct_, @@ -1038,24 +1038,17 @@ fn (p mut Parser) fn_define_vargs_stuct(f &Fn, typ string, values []string) { } if values.len > 0 { p.table.rewrite_type(varg_type) - p.cgen.gen(',&($vargs_struct){.len=$values.len,.args={'+values.join(',')+'}}') } else { p.table.register_type2(varg_type) } p.table.add_field(vargs_struct, 'len', 'int', false, '', .public) p.table.add_field(vargs_struct, 'args[$values.len]', typ, false, '', .public) - for va in p.table.varg_access { - if va.fn_name != f.name { continue } - if va.index >= values.len { - p.error_with_token_index('error accessing variadic arg, index `$va.index` out of range.', va.tok_idx) - } - } } fn (p mut Parser) fn_gen_caller_vargs(f mut Fn) { last_arg := f.args.last() varg_def_type := last_arg.typ.right(3) - mut varg_values := []string + mut values := []string for p.tok != .rpar { if p.tok == .comma { p.check(.comma) @@ -1067,9 +1060,19 @@ fn (p mut Parser) fn_gen_caller_vargs(f mut Fn) { ref_deref := if last_arg.typ.ends_with('*') && !varg_type.ends_with('*') { '&' } else if !last_arg.typ.ends_with('*') && varg_type.ends_with('*') { '*' } else { '' } - varg_values << '$ref_deref$varg_value' + values << '$ref_deref$varg_value' } - p.fn_define_vargs_stuct(f, varg_def_type, varg_values) + for va in p.table.varg_access { + if va.fn_name != f.name { continue } + if va.index >= values.len { + 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.args.len > 1 { + p.cgen.gen(',') + } + p.cgen.gen('&(_V_FnVargs_$f.name){.len=$values.len,.args={'+values.join(',')+'}}') + p.fn_register_vargs_stuct(f, varg_def_type, values) } // "fn (int, string) int" diff --git a/compiler/parser.v b/compiler/parser.v index 60523203a3..ed55be8518 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -2106,6 +2106,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { is_ptr := typ == 'byte*' || typ == 'byteptr' || typ.contains('*') is_indexer := p.tok == .lsbr mut close_bracket := false + index_error_tok_pos := p.token_idx if is_indexer { is_fixed_arr := typ[0] == `[` if !is_str && !is_arr && !is_map && !is_ptr && !is_fixed_arr && !is_variadic_arg { @@ -2202,7 +2203,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { p.cgen.resetln(l.left(fn_ph)) p.table.varg_access << VargAccess{ fn_name: p.cur_fn.name, - tok_idx: p.token_idx, + tok_idx: index_error_tok_pos, index: index_val.int() } p.cgen.set_placeholder(fn_ph, '${v.name}->args[$index_val]')