authorgravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2019-12-20 20:58:29+01:00
committergravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2020-01-10 22:35:41+01:00
logf81529fab17fe1a7ded4f1aae959159563f09efb
treec1766cd4b46039b3db4f20bb7905a4662f849e7a
parente06a6b9645827fa35cfa388bbea8813206d444ad

stage2 parser: fix segfault on extern block


2 files changed, 26 insertions(+), 1 deletions(-)

lib/std/zig/parse.zig+11-1
...@@ -303,7 +303,17 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -303,7 +303,17 @@ fn parseTopLevelDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
303fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {303fn parseFnProto(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
304 const cc = parseFnCC(arena, it, tree);304 const cc = parseFnCC(arena, it, tree);
305 const fn_token = eatToken(it, .Keyword_fn) orelse {305 const fn_token = eatToken(it, .Keyword_fn) orelse {
306 if (cc == null) return null else return error.ParseError;306 if (cc) |fnCC| {
307 if (fnCC == .Extern) {
308 putBackToken(it, fnCC.Extern); // 'extern' is also used in ContainerDecl
309 } else {
310 try tree.errors.push(AstError{
311 .ExpectedToken = .{ .token = it.index, .expected_id = .Keyword_fn },
312 });
313 return error.ParseError;
314 }
315 }
316 return null;
307 };317 };
308 const name_token = eatToken(it, .Identifier);318 const name_token = eatToken(it, .Identifier);
309 const lparen = try expectToken(it, tree, .LParen);319 const lparen = try expectToken(it, tree, .LParen);
lib/std/zig/parser_test.zig+15
...@@ -2714,6 +2714,13 @@ test "zig fmt: top level doc comments" {...@@ -2714,6 +2714,13 @@ test "zig fmt: top level doc comments" {
2714 );2714 );
2715}2715}
27162716
2717test "zig fmt: extern without container keyword returns error" {
2718 try testError(
2719 \\const container = extern {};
2720 \\
2721 );
2722}
2723
2717const std = @import("std");2724const std = @import("std");
2718const mem = std.mem;2725const mem = std.mem;
2719const warn = std.debug.warn;2726const warn = std.debug.warn;
...@@ -2820,3 +2827,11 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {...@@ -2820,3 +2827,11 @@ fn testTransform(source: []const u8, expected_source: []const u8) !void {
2820fn testCanonical(source: []const u8) !void {2827fn testCanonical(source: []const u8) !void {
2821 return testTransform(source, source);2828 return testTransform(source, source);
2822}2829}
2830
2831fn testError(source: []const u8) !void {
2832 var fixed_allocator = std.heap.FixedBufferAllocator.init(fixed_buffer_mem[0..]);
2833 const tree = try std.zig.parse(&fixed_allocator.allocator, source);
2834 defer tree.deinit();
2835
2836 std.testing.expect(tree.errors.len != 0);
2837}