| author | |
| committer | |
| log | 00982f75e92119aac6182ab9876adfb13305d1ed |
| tree | 6ee0b5c6964620a1263eb44498bf1905e20915ec |
| parent | e4225ca5f76760568c632d1f1c455e9d8759dce1 |
| signature |
* 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 tests7 files changed, 41 insertions(+), 29 deletions(-)
doc/docgen.zig+1-1| ... | ... | @@ -999,7 +999,7 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: anytype, source_token: |
| 999 | 999 | .tilde, |
| 1000 | 1000 | => try writeEscaped(out, src[token.loc.start..token.loc.end]), |
| 1001 | 1001 | |
| 1002 | .invalid, .invalid_ampersands, .invalid_periodasterisks => return parseError( | |
| 1002 | .invalid, .invalid_periodasterisks => return parseError( | |
| 1003 | 1003 | docgen_tokenizer, |
| 1004 | 1004 | source_token, |
| 1005 | 1005 | "syntax error", |
lib/std/zig/ast.zig-4| ... | ... | @@ -280,9 +280,6 @@ pub const Tree = struct { |
| 280 | 280 | token_tags[parse_error.token].symbol(), |
| 281 | 281 | }); |
| 282 | 282 | }, |
| 283 | .invalid_and => { | |
| 284 | return stream.writeAll("`&&` is invalid; note that `and` is boolean AND"); | |
| 285 | }, | |
| 286 | 283 | .invalid_bit_range => { |
| 287 | 284 | return stream.writeAll("bit range not allowed on slices and arrays"); |
| 288 | 285 | }, |
| ... | ... | @@ -2412,7 +2409,6 @@ pub const Error = struct { |
| 2412 | 2409 | extra_const_qualifier, |
| 2413 | 2410 | extra_volatile_qualifier, |
| 2414 | 2411 | ptr_mod_on_array_child_type, |
| 2415 | invalid_and, | |
| 2416 | 2412 | invalid_bit_range, |
| 2417 | 2413 | invalid_token, |
| 2418 | 2414 | same_line_doc_comment, |
lib/std/zig/parse.zig-4| ... | ... | @@ -1333,7 +1333,6 @@ const Parser = struct { |
| 1333 | 1333 | .keyword_or = .{ .prec = 10, .tag = .bool_or }, |
| 1334 | 1334 | |
| 1335 | 1335 | .keyword_and = .{ .prec = 20, .tag = .bool_and }, |
| 1336 | .invalid_ampersands = .{ .prec = 20, .tag = .bool_and }, | |
| 1337 | 1336 | |
| 1338 | 1337 | .equal_equal = .{ .prec = 30, .tag = .equal_equal, .assoc = Assoc.none }, |
| 1339 | 1338 | .bang_equal = .{ .prec = 30, .tag = .bang_equal, .assoc = Assoc.none }, |
| ... | ... | @@ -1385,9 +1384,6 @@ const Parser = struct { |
| 1385 | 1384 | .keyword_catch => { |
| 1386 | 1385 | _ = try p.parsePayload(); |
| 1387 | 1386 | }, |
| 1388 | .invalid_ampersands => { | |
| 1389 | try p.warn(.invalid_and); | |
| 1390 | }, | |
| 1391 | 1387 | else => {}, |
| 1392 | 1388 | } |
| 1393 | 1389 | const rhs = try p.parseExprPrecedence(info.prec + 1); |
lib/std/zig/parser_test.zig-12| ... | ... | @@ -4930,7 +4930,6 @@ test "recovery: missing comma" { |
| 4930 | 4930 | , &[_]Error{ |
| 4931 | 4931 | .expected_token, |
| 4932 | 4932 | .expected_token, |
| 4933 | .invalid_and, | |
| 4934 | 4933 | .invalid_token, |
| 4935 | 4934 | }); |
| 4936 | 4935 | } |
| ... | ... | @@ -4963,7 +4962,6 @@ test "recovery: missing return type" { |
| 4963 | 4962 | \\test "" |
| 4964 | 4963 | , &[_]Error{ |
| 4965 | 4964 | .expected_return_type, |
| 4966 | .invalid_and, | |
| 4967 | 4965 | .expected_block, |
| 4968 | 4966 | }); |
| 4969 | 4967 | } |
| ... | ... | @@ -4980,7 +4978,6 @@ test "recovery: continue after invalid decl" { |
| 4980 | 4978 | .expected_token, |
| 4981 | 4979 | .expected_pub_item, |
| 4982 | 4980 | .expected_param_list, |
| 4983 | .invalid_and, | |
| 4984 | 4981 | }); |
| 4985 | 4982 | try testError( |
| 4986 | 4983 | \\threadlocal test "" { |
| ... | ... | @@ -4989,7 +4986,6 @@ test "recovery: continue after invalid decl" { |
| 4989 | 4986 | , &[_]Error{ |
| 4990 | 4987 | .expected_var_decl, |
| 4991 | 4988 | .expected_param_list, |
| 4992 | .invalid_and, | |
| 4993 | 4989 | }); |
| 4994 | 4990 | } |
| 4995 | 4991 | |
| ... | ... | @@ -4998,13 +4994,11 @@ test "recovery: invalid extern/inline" { |
| 4998 | 4994 | \\inline test "" { a && b; } |
| 4999 | 4995 | , &[_]Error{ |
| 5000 | 4996 | .expected_fn, |
| 5001 | .invalid_and, | |
| 5002 | 4997 | }); |
| 5003 | 4998 | try testError( |
| 5004 | 4999 | \\extern "" test "" { a && b; } |
| 5005 | 5000 | , &[_]Error{ |
| 5006 | 5001 | .expected_var_decl_or_fn, |
| 5007 | .invalid_and, | |
| 5008 | 5002 | }); |
| 5009 | 5003 | } |
| 5010 | 5004 | |
| ... | ... | @@ -5016,9 +5010,7 @@ test "recovery: missing semicolon" { |
| 5016 | 5010 | \\ @foo |
| 5017 | 5011 | \\} |
| 5018 | 5012 | , &[_]Error{ |
| 5019 | .invalid_and, | |
| 5020 | 5013 | .expected_token, |
| 5021 | .invalid_and, | |
| 5022 | 5014 | .expected_token, |
| 5023 | 5015 | .expected_param_list, |
| 5024 | 5016 | .expected_token, |
| ... | ... | @@ -5038,7 +5030,6 @@ test "recovery: invalid container members" { |
| 5038 | 5030 | .expected_expr, |
| 5039 | 5031 | .expected_token, |
| 5040 | 5032 | .expected_container_members, |
| 5041 | .invalid_and, | |
| 5042 | 5033 | .expected_token, |
| 5043 | 5034 | }); |
| 5044 | 5035 | } |
| ... | ... | @@ -5076,7 +5067,6 @@ test "recovery: invalid global error set access" { |
| 5076 | 5067 | , &[_]Error{ |
| 5077 | 5068 | .expected_token, |
| 5078 | 5069 | .expected_token, |
| 5079 | .invalid_and, | |
| 5080 | 5070 | }); |
| 5081 | 5071 | } |
| 5082 | 5072 | |
| ... | ... | @@ -5094,7 +5084,6 @@ test "recovery: invalid asterisk after pointer dereference" { |
| 5094 | 5084 | \\} |
| 5095 | 5085 | , &[_]Error{ |
| 5096 | 5086 | .asterisk_after_ptr_deref, |
| 5097 | .invalid_and, | |
| 5098 | 5087 | }); |
| 5099 | 5088 | } |
| 5100 | 5089 | |
| ... | ... | @@ -5110,7 +5099,6 @@ test "recovery: missing semicolon after if, for, while stmt" { |
| 5110 | 5099 | .expected_semi_or_else, |
| 5111 | 5100 | .expected_semi_or_else, |
| 5112 | 5101 | .expected_semi_or_else, |
| 5113 | .invalid_and, | |
| 5114 | 5102 | }); |
| 5115 | 5103 | } |
| 5116 | 5104 |
lib/std/zig/tokenizer.zig-7| ... | ... | @@ -76,7 +76,6 @@ pub const Token = struct { |
| 76 | 76 | |
| 77 | 77 | pub const Tag = enum { |
| 78 | 78 | invalid, |
| 79 | invalid_ampersands, | |
| 80 | 79 | invalid_periodasterisks, |
| 81 | 80 | identifier, |
| 82 | 81 | string_literal, |
| ... | ... | @@ -210,7 +209,6 @@ pub const Token = struct { |
| 210 | 209 | .container_doc_comment, |
| 211 | 210 | => null, |
| 212 | 211 | |
| 213 | .invalid_ampersands => "&&", | |
| 214 | 212 | .invalid_periodasterisks => ".**", |
| 215 | 213 | .bang => "!", |
| 216 | 214 | .pipe => "|", |
| ... | ... | @@ -579,11 +577,6 @@ pub const Tokenizer = struct { |
| 579 | 577 | }, |
| 580 | 578 | |
| 581 | 579 | .ampersand => switch (c) { |
| 582 | '&' => { | |
| 583 | result.tag = .invalid_ampersands; | |
| 584 | self.index += 1; | |
| 585 | break; | |
| 586 | }, | |
| 587 | 580 | '=' => { |
| 588 | 581 | result.tag = .ampersand_equal; |
| 589 | 582 | 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 |
| 551 | 551 | .mul_wrap => return simpleBinOp(gz, scope, rl, node, .mulwrap), |
| 552 | 552 | .div => return simpleBinOp(gz, scope, rl, node, .div), |
| 553 | 553 | .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 | }, | |
| 555 | 571 | .bit_or => return simpleBinOp(gz, scope, rl, node, .bit_or), |
| 556 | 572 | .bit_xor => return simpleBinOp(gz, scope, rl, node, .xor), |
| 557 | 573 |
test/stage2/test.zig+23| ... | ... | @@ -1565,4 +1565,27 @@ pub fn addCases(ctx: *TestContext) !void { |
| 1565 | 1565 | \\} |
| 1566 | 1566 | , "HeHelHellHello"); |
| 1567 | 1567 | } |
| 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 | } | |
| 1568 | 1591 | } |