| author | |
| committer | |
| log | ff0a15bb7a57370091898fde7bd53364c90252df |
| tree | 766164a638464cd172280d39da73437915b0474e |
| parent | 8bf04c3a6955bc66e8d6fbbf00f12a44bb7079d5 |
3 files changed, 23 insertions(+), 0 deletions(-)
lib/std/zig/ast.zig+4| ... | ... | @@ -297,6 +297,9 @@ pub const Tree = struct { |
| 297 | 297 | .unattached_doc_comment => { |
| 298 | 298 | return stream.writeAll("unattached documentation comment"); |
| 299 | 299 | }, |
| 300 | .varargs_nonfinal => { | |
| 301 | return stream.writeAll("function prototype has parameter after varargs"); | |
| 302 | }, | |
| 300 | 303 | |
| 301 | 304 | .expected_token => { |
| 302 | 305 | const found_tag = token_tags[parse_error.token]; |
| ... | ... | @@ -2414,6 +2417,7 @@ pub const Error = struct { |
| 2414 | 2417 | invalid_token, |
| 2415 | 2418 | same_line_doc_comment, |
| 2416 | 2419 | unattached_doc_comment, |
| 2420 | varargs_nonfinal, | |
| 2417 | 2421 | |
| 2418 | 2422 | /// `expected_tag` is populated. |
| 2419 | 2423 | expected_token, |
lib/std/zig/parse.zig+7| ... | ... | @@ -3553,11 +3553,15 @@ const Parser = struct { |
| 3553 | 3553 | _ = try p.expectToken(.l_paren); |
| 3554 | 3554 | const scratch_top = p.scratch.items.len; |
| 3555 | 3555 | defer p.scratch.shrinkRetainingCapacity(scratch_top); |
| 3556 | var varargs: union(enum){ none, seen, nonfinal: TokenIndex } = .none; | |
| 3556 | 3557 | while (true) { |
| 3557 | 3558 | if (p.eatToken(.r_paren)) |_| break; |
| 3559 | if (varargs == .seen) varargs = .{ .nonfinal = p.tok_i }; | |
| 3558 | 3560 | const param = try p.expectParamDecl(); |
| 3559 | 3561 | if (param != 0) { |
| 3560 | 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 | 3566 | switch (p.token_tags[p.nextToken()]) { |
| 3563 | 3567 | .comma => {}, |
| ... | ... | @@ -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 | 3584 | const params = p.scratch.items[scratch_top..]; |
| 3578 | 3585 | return switch (params.len) { |
| 3579 | 3586 | 0 => SmallSpan { .zero_or_one = 0 }, |
lib/std/zig/parser_test.zig+12| ... | ... | @@ -5171,6 +5171,18 @@ test "recovery: missing while rbrace" { |
| 5171 | 5171 | }); |
| 5172 | 5172 | } |
| 5173 | 5173 | |
| 5174 | test "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 | ||
| 5174 | 5186 | const std = @import("std"); |
| 5175 | 5187 | const mem = std.mem; |
| 5176 | 5188 | const print = std.debug.print; |