aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Schmidt <john.schmidt.h@gmail.com>2023-02-28 11:27:56 +0100
committerAndrew Kelley <andrew@ziglang.org>2023-03-01 02:51:59 -0500
commite41bc640c6c4277385236d3dd90b4db566550509 (patch)
treec3ae2d90492cac331e3546a9ffc5115faf078333
parent98508a12cfae15a895d3e829539f907e9d88d0b6 (diff)
downloadzig-e41bc640c6c4277385236d3dd90b4db566550509.tar.gz
zig-e41bc640c6c4277385236d3dd90b4db566550509.zip
astgen: do not discard result location in for/while loops
If we use the discard result location any break with a value will be ignored and not checked for usage. Closes https://github.com/ziglang/zig/issues/14684.
-rw-r--r--src/AstGen.zig4
-rw-r--r--test/cases/compile_errors/for_loop_break_value_ignored.zig15
-rw-r--r--test/cases/compile_errors/while_loop_break_value_ignored.zig26
3 files changed, 43 insertions, 2 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index de259521bc..41a8ccadb2 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2342,10 +2342,10 @@ fn blockExprStmts(gz: *GenZir, parent_scope: *Scope, statements: []const Ast.Nod
.while_simple,
.while_cont,
- .@"while", => _ = try whileExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.fullWhile(inner_node).?, true),
+ .@"while", => _ = try whileExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullWhile(inner_node).?, true),
.for_simple,
- .@"for", => _ = try forExpr(gz, scope, .{ .rl = .discard }, inner_node, tree.fullFor(inner_node).?, true),
+ .@"for", => _ = try forExpr(gz, scope, .{ .rl = .none }, inner_node, tree.fullFor(inner_node).?, true),
else => noreturn_src_node = try unusedResultExpr(gz, scope, inner_node),
// zig fmt: on
diff --git a/test/cases/compile_errors/for_loop_break_value_ignored.zig b/test/cases/compile_errors/for_loop_break_value_ignored.zig
new file mode 100644
index 0000000000..a1119ec651
--- /dev/null
+++ b/test/cases/compile_errors/for_loop_break_value_ignored.zig
@@ -0,0 +1,15 @@
+fn returns() usize {
+ return 2;
+}
+
+export fn f1() void {
+ for ("hello") |_| {
+ break returns();
+ }
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :6:5: error: incompatible types: 'usize' and 'void'
diff --git a/test/cases/compile_errors/while_loop_break_value_ignored.zig b/test/cases/compile_errors/while_loop_break_value_ignored.zig
new file mode 100644
index 0000000000..2d14693fe5
--- /dev/null
+++ b/test/cases/compile_errors/while_loop_break_value_ignored.zig
@@ -0,0 +1,26 @@
+fn returns() usize {
+ return 2;
+}
+
+export fn f1() void {
+ var a: bool = true;
+ while (a) {
+ break returns();
+ }
+}
+
+export fn f2() void {
+ var x: bool = true;
+ outer: while (x) {
+ while (x) {
+ break :outer returns();
+ }
+ }
+}
+
+// error
+// backend=stage2
+// target=native
+//
+// :7:5: error: incompatible types: 'usize' and 'void'
+// :14:12: error: incompatible types: 'usize' and 'void'