authorgravatar for greenfork.lists@yandex.comDmitry Matveyev <greenfork.lists@yandex.com> 2021-06-21 00:04:14+06:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-06-20 21:04:14+03:00
log00982f75e92119aac6182ab9876adfb13305d1ed
tree6ee0b5c6964620a1263eb44498bf1905e20915ec
parente4225ca5f76760568c632d1f1c455e9d8759dce1
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

stage2: Remove special double ampersand parsing case (#9114)

* Remove parser error on double ampersand * Add failing test for double ampersand case * Add error when encountering double ampersand in AstGen "Bit and" operator should not make sense when one of its operands is an address. * Check that 2 ampersands are adjacent to each other in source string * Remove cases of unused variables in tests

7 files changed, 41 insertions(+), 29 deletions(-)

doc/docgen.zig+1-1
......@@ -999,7 +999,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: anytype, source_token:
999999 .tilde,
10001000 => try writeEscaped(out, src[token.loc.start..token.loc.end]),
10011001
1002 .invalid, .invalid_ampersands, .invalid_periodasterisks => return parseError(
1002 .invalid, .invalid_periodasterisks => return parseError(
10031003 docgen_tokenizer,
10041004 source_token,
10051005 "syntax error",
lib/std/zig/ast.zig-4
......@@ -280,9 +280,6 @@ pub const Tree = struct {
280280 token_tags[parse_error.token].symbol(),
281281 });
282282 },
283 .invalid_and => {
284 return stream.writeAll("`&&` is invalid; note that `and` is boolean AND");
285 },
286283 .invalid_bit_range => {
287284 return stream.writeAll("bit range not allowed on slices and arrays");
288285 },
......@@ -2412,7 +2409,6 @@ pub const Error = struct {
24122409 extra_const_qualifier,
24132410 extra_volatile_qualifier,
24142411 ptr_mod_on_array_child_type,
2415 invalid_and,
24162412 invalid_bit_range,
24172413 invalid_token,
24182414 same_line_doc_comment,
lib/std/zig/parse.zig-4
......@@ -1333,7 +1333,6 @@ const Parser = struct {
13331333 .keyword_or = .{ .prec = 10, .tag = .bool_or },
13341334
13351335 .keyword_and = .{ .prec = 20, .tag = .bool_and },
1336 .invalid_ampersands = .{ .prec = 20, .tag = .bool_and },
13371336
13381337 .equal_equal = .{ .prec = 30, .tag = .equal_equal, .assoc = Assoc.none },
13391338 .bang_equal = .{ .prec = 30, .tag = .bang_equal, .assoc = Assoc.none },
......@@ -1385,9 +1384,6 @@ const Parser = struct {
13851384 .keyword_catch => {
13861385 _ = try p.parsePayload();
13871386 },
1388 .invalid_ampersands => {
1389 try p.warn(.invalid_and);
1390 },
13911387 else => {},
13921388 }
13931389 const rhs = try p.parseExprPrecedence(info.prec + 1);
lib/std/zig/parser_test.zig-12
......@@ -4930,7 +4930,6 @@ test "recovery: missing comma" {
49304930 , &[_]Error{
49314931 .expected_token,
49324932 .expected_token,
4933 .invalid_and,
49344933 .invalid_token,
49354934 });
49364935}
......@@ -4963,7 +4962,6 @@ test "recovery: missing return type" {
49634962 \\test ""
49644963 , &[_]Error{
49654964 .expected_return_type,
4966 .invalid_and,
49674965 .expected_block,
49684966 });
49694967}
......@@ -4980,7 +4978,6 @@ test "recovery: continue after invalid decl" {
49804978 .expected_token,
49814979 .expected_pub_item,
49824980 .expected_param_list,
4983 .invalid_and,
49844981 });
49854982 try testError(
49864983 \\threadlocal test "" {
......@@ -4989,7 +4986,6 @@ test "recovery: continue after invalid decl" {
49894986 , &[_]Error{
49904987 .expected_var_decl,
49914988 .expected_param_list,
4992 .invalid_and,
49934989 });
49944990}
49954991
......@@ -4998,13 +4994,11 @@ test "recovery: invalid extern/inline" {
49984994 \\inline test "" { a && b; }
49994995 , &[_]Error{
50004996 .expected_fn,
5001 .invalid_and,
50024997 });
50034998 try testError(
50044999 \\extern "" test "" { a && b; }
50055000 , &[_]Error{
50065001 .expected_var_decl_or_fn,
5007 .invalid_and,
50085002 });
50095003}
50105004
......@@ -5016,9 +5010,7 @@ test "recovery: missing semicolon" {
50165010 \\ @foo
50175011 \\}
50185012 , &[_]Error{
5019 .invalid_and,
50205013 .expected_token,
5021 .invalid_and,
50225014 .expected_token,
50235015 .expected_param_list,
50245016 .expected_token,
......@@ -5038,7 +5030,6 @@ test "recovery: invalid container members" {
50385030 .expected_expr,
50395031 .expected_token,
50405032 .expected_container_members,
5041 .invalid_and,
50425033 .expected_token,
50435034 });
50445035}
......@@ -5076,7 +5067,6 @@ test "recovery: invalid global error set access" {
50765067 , &[_]Error{
50775068 .expected_token,
50785069 .expected_token,
5079 .invalid_and,
50805070 });
50815071}
50825072
......@@ -5094,7 +5084,6 @@ test "recovery: invalid asterisk after pointer dereference" {
50945084 \\}
50955085 , &[_]Error{
50965086 .asterisk_after_ptr_deref,
5097 .invalid_and,
50985087 });
50995088}
51005089
......@@ -5110,7 +5099,6 @@ test "recovery: missing semicolon after if, for, while stmt" {
51105099 .expected_semi_or_else,
51115100 .expected_semi_or_else,
51125101 .expected_semi_or_else,
5113 .invalid_and,
51145102 });
51155103}
51165104
lib/std/zig/tokenizer.zig-7
......@@ -76,7 +76,6 @@ pub const Token = struct {
7676
7777 pub const Tag = enum {
7878 invalid,
79 invalid_ampersands,
8079 invalid_periodasterisks,
8180 identifier,
8281 string_literal,
......@@ -210,7 +209,6 @@ pub const Token = struct {
210209 .container_doc_comment,
211210 => null,
212211
213 .invalid_ampersands => "&&",
214212 .invalid_periodasterisks => ".**",
215213 .bang => "!",
216214 .pipe => "|",
......@@ -579,11 +577,6 @@ pub const Tokenizer = struct {
579577 },
580578
581579 .ampersand => switch (c) {
582 '&' => {
583 result.tag = .invalid_ampersands;
584 self.index += 1;
585 break;
586 },
587580 '=' => {
588581 result.tag = .ampersand_equal;
589582 self.index += 1;
src/AstGen.zig+17-1
......@@ -551,7 +551,23 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) InnerEr
551551 .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap),
552552 .div => return simpleBinOp(gz, scope, rl, node, .div),
553553 .mod => return simpleBinOp(gz, scope, rl, node, .mod_rem),
554 .bit_and => return simpleBinOp(gz, scope, rl, node, .bit_and),
554 .bit_and => {
555 const current_ampersand_token = main_tokens[node];
556 if (token_tags[current_ampersand_token + 1] == .ampersand) {
557 const token_starts = tree.tokens.items(.start);
558 const current_token_offset = token_starts[current_ampersand_token];
559 const next_token_offset = token_starts[current_ampersand_token + 1];
560 if (current_token_offset + 1 == next_token_offset) {
561 return astgen.failTok(
562 current_ampersand_token,
563 "`&&` is invalid; note that `and` is boolean AND",
564 .{},
565 );
566 }
567 }
568
569 return simpleBinOp(gz, scope, rl, node, .bit_and);
570 },
555571 .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or),
556572 .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor),
557573
test/stage2/test.zig+23
......@@ -1565,4 +1565,27 @@ pub fn addCases(ctx: *TestContext) !void {
15651565 \\}
15661566 , "HeHelHellHello");
15671567 }
1568
1569 {
1570 var case = ctx.exe("double ampersand", linux_x64);
1571
1572 case.addError(
1573 \\pub const a = if (true && false) 1 else 2;
1574 , &[_][]const u8{":1:24: error: `&&` is invalid; note that `and` is boolean AND"});
1575
1576 case.addError(
1577 \\pub fn main() void {
1578 \\ const a = true;
1579 \\ const b = false;
1580 \\ _ = a & &b;
1581 \\}
1582 , &[_][]const u8{":4:11: error: incompatible types: 'bool' and '*const bool'"});
1583
1584 case.addCompareOutput(
1585 \\pub fn main() void {
1586 \\ const b: u8 = 1;
1587 \\ _ = &&b;
1588 \\}
1589 , "");
1590 }
15681591}