authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-30 02:24:44-04:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-08 20:50:55+03:00
logff0a15bb7a57370091898fde7bd53364c90252df
tree766164a638464cd172280d39da73437915b0474e
parent8bf04c3a6955bc66e8d6fbbf00f12a44bb7079d5

parse.zig: make `parseParamDeclList` check for nonfinal varargs


3 files changed, 23 insertions(+), 0 deletions(-)

lib/std/zig/ast.zig+4
......@@ -297,6 +297,9 @@ pub const Tree = struct {
297297 .unattached_doc_comment => {
298298 return stream.writeAll("unattached documentation comment");
299299 },
300 .varargs_nonfinal => {
301 return stream.writeAll("function prototype has parameter after varargs");
302 },
300303
301304 .expected_token => {
302305 const found_tag = token_tags[parse_error.token];
......@@ -2414,6 +2417,7 @@ pub const Error = struct {
24142417 invalid_token,
24152418 same_line_doc_comment,
24162419 unattached_doc_comment,
2420 varargs_nonfinal,
24172421
24182422 /// `expected_tag` is populated.
24192423 expected_token,
lib/std/zig/parse.zig+7
......@@ -3553,11 +3553,15 @@ const Parser = struct {
35533553 _ = try p.expectToken(.l_paren);
35543554 const scratch_top = p.scratch.items.len;
35553555 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3556 var varargs: union(enum){ none, seen, nonfinal: TokenIndex } = .none;
35563557 while (true) {
35573558 if (p.eatToken(.r_paren)) |_| break;
3559 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };
35583560 const param = try p.expectParamDecl();
35593561 if (param != 0) {
35603562 try p.scratch.append(p.gpa, param);
3563 } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {
3564 if (varargs == .none) varargs = .seen;
35613565 }
35623566 switch (p.token_tags[p.nextToken()]) {
35633567 .comma => {},
......@@ -3574,6 +3578,9 @@ const Parser = struct {
35743578 },
35753579 }
35763580 }
3581 if (varargs == .nonfinal) {
3582 try p.warnMsg(.{ .tag = .varargs_nonfinal, .token = varargs.nonfinal });
3583 }
35773584 const params = p.scratch.items[scratch_top..];
35783585 return switch (params.len) {
35793586 0 => SmallSpan { .zero_or_one = 0 },
lib/std/zig/parser_test.zig+12
......@@ -5171,6 +5171,18 @@ test "recovery: missing while rbrace" {
51715171 });
51725172}
51735173
5174test "recovery: nonfinal varargs" {
5175 try testError(
5176 \\extern fn f(a: u32, ..., b: u32) void;
5177 \\extern fn g(a: u32, ..., b: anytype) void;
5178 \\extern fn h(a: u32, ..., ...) void;
5179 , &[_]Error{
5180 .varargs_nonfinal,
5181 .varargs_nonfinal,
5182 .varargs_nonfinal,
5183 });
5184}
5185
51745186const std = @import("std");
51755187const mem = std.mem;
51765188const print = std.debug.print;