Skip to content

Commit

Permalink
AstGen: fix loop control flow applying to wrong loop
Browse files Browse the repository at this point in the history
In the case of 'continue' or 'break' inside the 'else' block of a
'while' or 'for' loop.

Closes #12109
  • Loading branch information
andrewrk committed Jul 13, 2022
1 parent 1fee9ea commit fad9574
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 4 deletions.
1 change: 0 additions & 1 deletion lib/std/net/test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ test "parse and render UNIX addresses" {
}

test "resolve DNS" {
if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
if (builtin.os.tag == .wasi) return error.SkipZigTest;

if (builtin.os.tag == .windows) {
Expand Down
6 changes: 3 additions & 3 deletions lib/std/os.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6476,7 +6476,7 @@ pub fn dn_expand(
p = msg.ptr + j;
} else if (p[0] != 0) {
if (dest != exp_dn.ptr) {
dest.* = '.';
dest[0] = '.';
dest += 1;
}
var j = p[0];
Expand All @@ -6486,12 +6486,12 @@ pub fn dn_expand(
}
while (j != 0) {
j -= 1;
dest.* = p[0];
dest[0] = p[0];
dest += 1;
p += 1;
}
} else {
dest.* = 0;
dest[0] = 0;
if (len == std.math.maxInt(usize)) len = @ptrToInt(p) + 1 - @ptrToInt(comp_dn.ptr);
return len;
}
Expand Down
8 changes: 8 additions & 0 deletions src/AstGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5795,6 +5795,10 @@ fn whileExpr(
break :s &else_scope.base;
}
};
// Remove the continue block and break block so that `continue` and `break`
// control flow apply to outer loops; not this one.
loop_scope.continue_block = 0;
loop_scope.break_block = 0;
const e = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node);
if (!else_scope.endsWithNoReturn()) {
loop_scope.break_count += 1;
Expand Down Expand Up @@ -5994,6 +5998,10 @@ fn forExpr(
result: Zir.Inst.Ref,
} = if (else_node != 0) blk: {
const sub_scope = &else_scope.base;
// Remove the continue block and break block so that `continue` and `break`
// control flow apply to outer loops; not this one.
loop_scope.continue_block = 0;
loop_scope.break_block = 0;
const else_result = try expr(&else_scope, sub_scope, loop_scope.break_result_loc, else_node);
if (!else_scope.endsWithNoReturn()) {
loop_scope.break_count += 1;
Expand Down
14 changes: 14 additions & 0 deletions test/behavior/for.zig
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,17 @@ test "for on slice with allowzero ptr" {
try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
comptime try S.doTheTest(&[_]u8{ 1, 2, 3, 4 });
}

test "else continue outer for" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

var i: usize = 6;
var buf: [5]u8 = undefined;
while (true) {
i -= 1;
for (buf[i..5]) |_| {
return;
} else continue;
}
}
10 changes: 10 additions & 0 deletions test/behavior/while.zig
Original file line number Diff line number Diff line change
Expand Up @@ -334,3 +334,13 @@ test "continue inline while loop" {
}
comptime assert(i == 5);
}

test "else continue outer while" {
var i: usize = 0;
while (true) {
i += 1;
while (i > 5) {
return;
} else continue;
}
}

0 comments on commit fad9574

Please sign in to comment.