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 {...@@ -297,6 +297,9 @@ pub const Tree = struct {
297 .unattached_doc_comment => {297 .unattached_doc_comment => {
298 return stream.writeAll("unattached documentation comment");298 return stream.writeAll("unattached documentation comment");
299 },299 },
300 .varargs_nonfinal => {
301 return stream.writeAll("function prototype has parameter after varargs");
302 },
300303
301 .expected_token => {304 .expected_token => {
302 const found_tag = token_tags[parse_error.token];305 const found_tag = token_tags[parse_error.token];
...@@ -2414,6 +2417,7 @@ pub const Error = struct {...@@ -2414,6 +2417,7 @@ pub const Error = struct {
2414 invalid_token,2417 invalid_token,
2415 same_line_doc_comment,2418 same_line_doc_comment,
2416 unattached_doc_comment,2419 unattached_doc_comment,
2420 varargs_nonfinal,
24172421
2418 /// `expected_tag` is populated.2422 /// `expected_tag` is populated.
2419 expected_token,2423 expected_token,
lib/std/zig/parse.zig+7
...@@ -3553,11 +3553,15 @@ const Parser = struct {...@@ -3553,11 +3553,15 @@ const Parser = struct {
3553 _ = try p.expectToken(.l_paren);3553 _ = try p.expectToken(.l_paren);
3554 const scratch_top = p.scratch.items.len;3554 const scratch_top = p.scratch.items.len;
3555 defer p.scratch.shrinkRetainingCapacity(scratch_top);3555 defer p.scratch.shrinkRetainingCapacity(scratch_top);
3556 var varargs: union(enum){ none, seen, nonfinal: TokenIndex } = .none;
3556 while (true) {3557 while (true) {
3557 if (p.eatToken(.r_paren)) |_| break;3558 if (p.eatToken(.r_paren)) |_| break;
3559 if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };
3558 const param = try p.expectParamDecl();3560 const param = try p.expectParamDecl();
3559 if (param != 0) {3561 if (param != 0) {
3560 try p.scratch.append(p.gpa, param);3562 try p.scratch.append(p.gpa, param);
3563 } else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {
3564 if (varargs == .none) varargs = .seen;
3561 }3565 }
3562 switch (p.token_tags[p.nextToken()]) {3566 switch (p.token_tags[p.nextToken()]) {
3563 .comma => {},3567 .comma => {},
...@@ -3574,6 +3578,9 @@ const Parser = struct {...@@ -3574,6 +3578,9 @@ const Parser = struct {
3574 },3578 },
3575 }3579 }
3576 }3580 }
3581 if (varargs == .nonfinal) {
3582 try p.warnMsg(.{ .tag = .varargs_nonfinal, .token = varargs.nonfinal });
3583 }
3577 const params = p.scratch.items[scratch_top..];3584 const params = p.scratch.items[scratch_top..];
3578 return switch (params.len) {3585 return switch (params.len) {
3579 0 => SmallSpan { .zero_or_one = 0 },3586 0 => SmallSpan { .zero_or_one = 0 },
lib/std/zig/parser_test.zig+12
...@@ -5171,6 +5171,18 @@ test "recovery: missing while rbrace" {...@@ -5171,6 +5171,18 @@ test "recovery: missing while rbrace" {
5171 });5171 });
5172}5172}
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
5174const std = @import("std");5186const std = @import("std");
5175const mem = std.mem;5187const mem = std.mem;
5176const print = std.debug.print;5188const print = std.debug.print;