From fad95741db7529bbad873fb330c25d64ac765340 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Jul 2022 15:59:46 -0700 Subject: [PATCH] AstGen: fix loop control flow applying to wrong loop In the case of 'continue' or 'break' inside the 'else' block of a 'while' or 'for' loop. Closes #12109 --- lib/std/net/test.zig | 1 - lib/std/os.zig | 6 +++--- src/AstGen.zig | 8 ++++++++ test/behavior/for.zig | 14 ++++++++++++++ test/behavior/while.zig | 10 ++++++++++ 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index 5d350be7e0..f2946777bd 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -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) { diff --git a/lib/std/os.zig b/lib/std/os.zig index 02ed710dd3..f4653920ae 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -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]; @@ -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; } diff --git a/src/AstGen.zig b/src/AstGen.zig index 7220fe758d..252610aeeb 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -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; @@ -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; diff --git a/test/behavior/for.zig b/test/behavior/for.zig index 5188f02381..da6f0717ae 100644 --- a/test/behavior/for.zig +++ b/test/behavior/for.zig @@ -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; + } +} diff --git a/test/behavior/while.zig b/test/behavior/while.zig index b664e73b89..62d5bf90fa 100644 --- a/test/behavior/while.zig +++ b/test/behavior/while.zig @@ -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; + } +}