diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-11-26 22:40:43 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-11-29 15:47:02 +0200 |
| commit | 34be5784a3f19658d15d1fb24bb07800cdb025c4 (patch) | |
| tree | ab1808cfc8fdadcb682d2d5f490162f7cb15d519 /lib/std | |
| parent | 1829b6eab8dc52ad2961467e23bfb36055cc8583 (diff) | |
| download | zig-34be5784a3f19658d15d1fb24bb07800cdb025c4.tar.gz zig-34be5784a3f19658d15d1fb24bb07800cdb025c4.zip | |
parser: disallow defer and variable declaration as else branch
Closes #13658
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/zig/parse.zig | 28 | ||||
| -rw-r--r-- | lib/std/zig/parser_test.zig | 24 |
2 files changed, 39 insertions, 13 deletions
diff --git a/lib/std/zig/parse.zig b/lib/std/zig/parse.zig index 77ed67b3d2..2ae0221d8a 100644 --- a/lib/std/zig/parse.zig +++ b/lib/std/zig/parse.zig @@ -950,13 +950,15 @@ const Parser = struct { /// / LabeledStatement /// / SwitchExpr /// / AssignExpr SEMICOLON - fn parseStatement(p: *Parser) Error!Node.Index { + fn parseStatement(p: *Parser, allow_defer_var: bool) Error!Node.Index { const comptime_token = p.eatToken(.keyword_comptime); - const var_decl = try p.parseVarDecl(); - if (var_decl != 0) { - try p.expectSemicolon(.expected_semi_after_decl, true); - return var_decl; + if (allow_defer_var) { + const var_decl = try p.parseVarDecl(); + if (var_decl != 0) { + try p.expectSemicolon(.expected_semi_after_decl, true); + return var_decl; + } } if (comptime_token) |token| { @@ -993,7 +995,7 @@ const Parser = struct { }, }); }, - .keyword_defer => return p.addNode(.{ + .keyword_defer => if (allow_defer_var) return p.addNode(.{ .tag = .@"defer", .main_token = p.nextToken(), .data = .{ @@ -1001,7 +1003,7 @@ const Parser = struct { .rhs = try p.expectBlockExprStatement(), }, }), - .keyword_errdefer => return p.addNode(.{ + .keyword_errdefer => if (allow_defer_var) return p.addNode(.{ .tag = .@"errdefer", .main_token = p.nextToken(), .data = .{ @@ -1040,8 +1042,8 @@ const Parser = struct { return null_node; } - fn expectStatement(p: *Parser) !Node.Index { - const statement = try p.parseStatement(); + fn expectStatement(p: *Parser, allow_defer_var: bool) !Node.Index { + const statement = try p.parseStatement(allow_defer_var); if (statement == 0) { return p.fail(.expected_statement); } @@ -1053,7 +1055,7 @@ const Parser = struct { /// statement, returns 0. fn expectStatementRecoverable(p: *Parser) Error!Node.Index { while (true) { - return p.expectStatement() catch |err| switch (err) { + return p.expectStatement(true) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ParseError => { p.findNextStmt(); // Try to skip to the next statement. @@ -1114,7 +1116,7 @@ const Parser = struct { }); }; _ = try p.parsePayload(); - const else_expr = try p.expectStatement(); + const else_expr = try p.expectStatement(false); return p.addNode(.{ .tag = .@"if", .main_token = if_token, @@ -1226,7 +1228,7 @@ const Parser = struct { .lhs = array_expr, .rhs = try p.addExtra(Node.If{ .then_expr = then_expr, - .else_expr = try p.expectStatement(), + .else_expr = try p.expectStatement(false), }), }, }); @@ -1309,7 +1311,7 @@ const Parser = struct { } }; _ = try p.parsePayload(); - const else_expr = try p.expectStatement(); + const else_expr = try p.expectStatement(false); return p.addNode(.{ .tag = .@"while", .main_token = while_token, diff --git a/lib/std/zig/parser_test.zig b/lib/std/zig/parser_test.zig index e554c51f70..d2f7a15994 100644 --- a/lib/std/zig/parser_test.zig +++ b/lib/std/zig/parser_test.zig @@ -4233,6 +4233,30 @@ test "zig fmt: remove newlines surrounding doc comment within container decl" { ); } +test "zig fmt: invalid else branch statement" { + try testError( + \\comptime { + \\ if (true) {} else var a = 0; + \\ if (true) {} else defer {} + \\} + \\comptime { + \\ while (true) {} else var a = 0; + \\ while (true) {} else defer {} + \\} + \\comptime { + \\ for ("") |_| {} else var a = 0; + \\ for ("") |_| {} else defer {} + \\} + , &[_]Error{ + .expected_statement, + .expected_statement, + .expected_statement, + .expected_statement, + .expected_statement, + .expected_statement, + }); +} + test "zig fmt: anytype struct field" { try testError( \\pub const Pointer = struct { |
