authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-05-16 20:49:37+03:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-05-16 20:49:37+03:00
logeda03354dc865fc18b8bc5862eb837fd8a6e979c
treeded5dc0cd2b1badf10b1904333d6a30e418874c1
parentcf34480f2a3a1e52c09fe762dad34c45d5485717
parent081ffe24cf99db6544293aecfbd6834a0daf6680
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #5358 from Vexu/parser

Fix infinite loop with invalid comptime

3 files changed, 18 insertions(+), 0 deletions(-)

lib/std/zig/ast.zig+4
...@@ -165,6 +165,7 @@ pub const Error = union(enum) {...@@ -165,6 +165,7 @@ pub const Error = union(enum) {
165 ExpectedLoopExpr: ExpectedLoopExpr,165 ExpectedLoopExpr: ExpectedLoopExpr,
166 ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,166 ExpectedDerefOrUnwrap: ExpectedDerefOrUnwrap,
167 ExpectedSuffixOp: ExpectedSuffixOp,167 ExpectedSuffixOp: ExpectedSuffixOp,
168 ExpectedBlockOrField: ExpectedBlockOrField,
168 DeclBetweenFields: DeclBetweenFields,169 DeclBetweenFields: DeclBetweenFields,
169 InvalidAnd: InvalidAnd,170 InvalidAnd: InvalidAnd,
170171
...@@ -215,6 +216,7 @@ pub const Error = union(enum) {...@@ -215,6 +216,7 @@ pub const Error = union(enum) {
215 .ExpectedLoopExpr => |*x| return x.render(tokens, stream),216 .ExpectedLoopExpr => |*x| return x.render(tokens, stream),
216 .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),217 .ExpectedDerefOrUnwrap => |*x| return x.render(tokens, stream),
217 .ExpectedSuffixOp => |*x| return x.render(tokens, stream),218 .ExpectedSuffixOp => |*x| return x.render(tokens, stream),
219 .ExpectedBlockOrField => |*x| return x.render(tokens, stream),
218 .DeclBetweenFields => |*x| return x.render(tokens, stream),220 .DeclBetweenFields => |*x| return x.render(tokens, stream),
219 .InvalidAnd => |*x| return x.render(tokens, stream),221 .InvalidAnd => |*x| return x.render(tokens, stream),
220 }222 }
...@@ -267,6 +269,7 @@ pub const Error = union(enum) {...@@ -267,6 +269,7 @@ pub const Error = union(enum) {
267 .ExpectedLoopExpr => |x| return x.token,269 .ExpectedLoopExpr => |x| return x.token,
268 .ExpectedDerefOrUnwrap => |x| return x.token,270 .ExpectedDerefOrUnwrap => |x| return x.token,
269 .ExpectedSuffixOp => |x| return x.token,271 .ExpectedSuffixOp => |x| return x.token,
272 .ExpectedBlockOrField => |x| return x.token,
270 .DeclBetweenFields => |x| return x.token,273 .DeclBetweenFields => |x| return x.token,
271 .InvalidAnd => |x| return x.token,274 .InvalidAnd => |x| return x.token,
272 }275 }
...@@ -306,6 +309,7 @@ pub const Error = union(enum) {...@@ -306,6 +309,7 @@ pub const Error = union(enum) {
306 pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found '{}'");309 pub const ExpectedLoopExpr = SingleTokenError("Expected loop expression, found '{}'");
307 pub const ExpectedDerefOrUnwrap = SingleTokenError("Expected pointer dereference or optional unwrap, found '{}'");310 pub const ExpectedDerefOrUnwrap = SingleTokenError("Expected pointer dereference or optional unwrap, found '{}'");
308 pub const ExpectedSuffixOp = SingleTokenError("Expected pointer dereference, optional unwrap, or field access, found '{}'");311 pub const ExpectedSuffixOp = SingleTokenError("Expected pointer dereference, optional unwrap, or field access, found '{}'");
312 pub const ExpectedBlockOrField = SingleTokenError("Expected block or field, found '{}'");
309313
310 pub const ExpectedParamType = SimpleError("Expected parameter type");314 pub const ExpectedParamType = SimpleError("Expected parameter type");
311 pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub");315 pub const ExpectedPubItem = SimpleError("Expected function or variable declaration after pub");
lib/std/zig/parse.zig+6
...@@ -231,6 +231,12 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree, top...@@ -231,6 +231,12 @@ fn parseContainerMembers(arena: *Allocator, it: *TokenIterator, tree: *Tree, top
231 const next = it.peek().?.id;231 const next = it.peek().?.id;
232 switch (next) {232 switch (next) {
233 .Eof => break,233 .Eof => break,
234 .Keyword_comptime => {
235 _ = nextToken(it);
236 try tree.errors.push(.{
237 .ExpectedBlockOrField = .{ .token = it.index },
238 });
239 },
234 else => {240 else => {
235 const index = it.index;241 const index = it.index;
236 if (next == .RBrace) {242 if (next == .RBrace) {
lib/std/zig/parser_test.zig+8
...@@ -200,6 +200,14 @@ test "recovery: missing semicolon after if, for, while stmt" {...@@ -200,6 +200,14 @@ test "recovery: missing semicolon after if, for, while stmt" {
200 });200 });
201}201}
202202
203test "recovery: invalid comptime" {
204 try testError(
205 \\comptime
206 , &[_]Error{
207 .ExpectedBlockOrField,
208 });
209}
210
203test "zig fmt: top-level fields" {211test "zig fmt: top-level fields" {
204 try testCanonical(212 try testCanonical(
205 \\a: did_you_know,213 \\a: did_you_know,