AstGen: do not allow unlabeled break to exit a labeled switch

`break`ing from something which isn't a loop should always be opt-in.
This was a bug in #21257.
This commit is contained in:
mlugg
2024-09-11 09:01:05 +01:00
committed by Matthew Lugg
parent 0001f91e4e
commit 03c363300f
2 changed files with 19 additions and 2 deletions

View File

@@ -7811,9 +7811,7 @@ fn switchExpr(
const switch_block = try parent_gz.makeBlockInst(switch_tag, node);
if (switch_full.label_token) |label_token| {
block_scope.break_block = switch_block.toOptional();
block_scope.continue_block = switch_block.toOptional();
// `break_result_info` already set above
block_scope.continue_result_info = .{
.rl = if (any_payload_is_ref)
.{ .ref_coerced_ty = raw_operand_ty_ref }
@@ -7825,6 +7823,8 @@ fn switchExpr(
.token = label_token,
.block_inst = switch_block,
};
// `break` can target this via `label.block_inst`
// `break_result_info` already set by `setBreakResultInfo`
}
// We re-use this same scope for all cases, including the special prong, if any.

View File

@@ -985,3 +985,20 @@ test "labeled switch with break" {
comptime assert(comptime_val);
}
test "unlabeled break ignores switch" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO
const result = while (true) {
_ = s: switch (@as(u32, 1)) {
1 => continue :s 123,
else => |x| break x,
};
comptime unreachable; // control flow never breaks from the switch
};
try expect(result == 123);
}