zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit e2509ddbe69a56bb1f4a56b46946b2a706d5aabe (tree)
parent 0e38cc16d51178525e89774ce9151651b6a0e99a
Author: Veikka Tuominen <git@vexu.eu>
Date:   Fri,  2 Dec 2022 20:16:47 +0200

AstGen: add error for invalid string comparisons

These operations are allowed because the string literals are just
pointers but they produce unexpected results. These errors prevent
beginners from shooting themselves in the foot while still allowing
advanced users to circumvent them if they desire to do so.

Closes #8290

Diffstat:
Msrc/AstGen.zig | 13+++++++++++++
Atest/cases/compile_errors/invalid_compare_string.zig | 29+++++++++++++++++++++++++++++
Mtest/cases/compile_errors/switch_on_slice.zig | 2+-
3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/src/AstGen.zig b/src/AstGen.zig @@ -5628,6 +5628,14 @@ fn simpleBinOp( const tree = astgen.tree; const node_datas = tree.nodes.items(.data); + if (op_inst_tag == .cmp_neq or op_inst_tag == .cmp_eq) { + const node_tags = tree.nodes.items(.tag); + const str = if (op_inst_tag == .cmp_eq) "==" else "!="; + if (node_tags[node_datas[node].lhs] == .string_literal or + node_tags[node_datas[node].rhs] == .string_literal) + return astgen.failNode(node, "cannot compare strings with {s}", .{str}); + } + const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node); var line: u32 = undefined; var column: u32 = undefined; @@ -6625,6 +6633,11 @@ fn switchExpr( continue; } + for (case.ast.values) |val| { + if (node_tags[val] == .string_literal) + return astgen.failNode(val, "cannot switch on strings", .{}); + } + if (case.ast.values.len == 1 and node_tags[case.ast.values[0]] != .switch_range) { scalar_cases_len += 1; } else { diff --git a/test/cases/compile_errors/invalid_compare_string.zig b/test/cases/compile_errors/invalid_compare_string.zig @@ -0,0 +1,29 @@ +comptime { + var a = "foo"; + if (a == "foo") unreachable; +} +comptime { + var a = "foo"; + if (a == ("foo")) unreachable; // intentionally allow +} +comptime { + var a = "foo"; + switch (a) { + "foo" => unreachable, + else => {}, + } +} +comptime { + var a = "foo"; + switch (a) { + ("foo") => unreachable, // intentionally allow + else => {}, + } +} + +// error +// backend=stage2 +// target=native +// +// :3:11: error: cannot compare strings with == +// :12:9: error: cannot switch on strings diff --git a/test/cases/compile_errors/switch_on_slice.zig b/test/cases/compile_errors/switch_on_slice.zig @@ -1,7 +1,7 @@ pub export fn entry() void { var a: [:0]const u8 = "foo"; switch (a) { - "--version", "version" => unreachable, + ("--version"), ("version") => unreachable, else => {}, } }