parse.zig: make parseParamDeclList check for nonfinal varargs

This commit is contained in:
Matthew Borkowski 2021-05-30 02:24:44 -04:00 committed by Veikka Tuominen
parent 8bf04c3a69
commit ff0a15bb7a
3 changed files with 23 additions and 0 deletions

View File

@ -297,6 +297,9 @@ pub const Tree = struct {
.unattached_doc_comment => {
return stream.writeAll("unattached documentation comment");
},
.varargs_nonfinal => {
return stream.writeAll("function prototype has parameter after varargs");
},
.expected_token => {
const found_tag = token_tags[parse_error.token];
@ -2414,6 +2417,7 @@ pub const Error = struct {
invalid_token,
same_line_doc_comment,
unattached_doc_comment,
varargs_nonfinal,
/// `expected_tag` is populated.
expected_token,

View File

@ -3553,11 +3553,15 @@ const Parser = struct {
_ = try p.expectToken(.l_paren);
const scratch_top = p.scratch.items.len;
defer p.scratch.shrinkRetainingCapacity(scratch_top);
var varargs: union(enum){ none, seen, nonfinal: TokenIndex } = .none;
while (true) {
if (p.eatToken(.r_paren)) |_| break;
if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i };
const param = try p.expectParamDecl();
if (param != 0) {
try p.scratch.append(p.gpa, param);
} else if (p.token_tags[p.tok_i - 1] == .ellipsis3) {
if (varargs == .none) varargs = .seen;
}
switch (p.token_tags[p.nextToken()]) {
.comma => {},
@ -3574,6 +3578,9 @@ const Parser = struct {
},
}
}
if (varargs == .nonfinal) {
try p.warnMsg(.{ .tag = .varargs_nonfinal, .token = varargs.nonfinal });
}
const params = p.scratch.items[scratch_top..];
return switch (params.len) {
0 => SmallSpan { .zero_or_one = 0 },

View File

@ -5171,6 +5171,18 @@ test "recovery: missing while rbrace" {
});
}
test "recovery: nonfinal varargs" {
try testError(
\\extern fn f(a: u32, ..., b: u32) void;
\\extern fn g(a: u32, ..., b: anytype) void;
\\extern fn h(a: u32, ..., ...) void;
, &[_]Error{
.varargs_nonfinal,
.varargs_nonfinal,
.varargs_nonfinal,
});
}
const std = @import("std");
const mem = std.mem;
const print = std.debug.print;