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