From ff0a15bb7a57370091898fde7bd53364c90252df Mon Sep 17 00:00:00 2001 From: Matthew Borkowski Date: Sun, 30 May 2021 02:24:44 -0400 Subject: [PATCH] parse.zig: make `parseParamDeclList` check for nonfinal varargs --- lib/std/zig/ast.zig | 4 ++++ lib/std/zig/parse.zig | 7 +++++++ lib/std/zig/parser_test.zig | 12 ++++++++++++ 3 files changed, 23 insertions(+) diff --git a/lib/std/zig/ast.zig b/lib/std/zig/ast.zig index 6ed8987e54..7c67e03b67 100644 --- a/lib/std/zig/ast.zig +++ b/lib/std/zig/ast.zig @@ -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, diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index b8e624ab27..508809f1de 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -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 }, diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index 9e07810d9c..08e9c283fd 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -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;