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:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user