aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-02 19:09:54 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-02 19:09:54 -0700
commit61a53a587558ff1fe1b0ec98bb424022885edccf (patch)
tree0e0ad82f7998a473104ec6fa07cb051a1b56a7c3 /src
parentac52e005640e9dc7829356f857a82b0bc3894245 (diff)
downloadzig-61a53a587558ff1fe1b0ec98bb424022885edccf.tar.gz
zig-61a53a587558ff1fe1b0ec98bb424022885edccf.zip
AstGen: fix if, orelse, catch, with unreachable bodies
Before, the system to replace a result location pointer with a traditional break instruction did not notice the case when one of the bodies was unreachable. Now, the emitted ZIR code is improved and simplified in this case, resulting in a new passing behavior test.
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 387364cb82..54534b1e5a 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -4891,7 +4891,7 @@ fn orelseCatchExpr(
// We cannot use `block_scope.break_result_loc` because that has the bare
// type, whereas this expression has the optional type. Later we make
// up for this fact by calling rvalue on the else branch.
- const operand = try expr(&block_scope, &block_scope.base, operand_rl, lhs);
+ const operand = try reachableExpr(&block_scope, &block_scope.base, operand_rl, lhs, rhs);
const cond = try block_scope.addUnNode(cond_op, operand, node);
const condbr = try block_scope.addCondBr(.condbr, node);
@@ -4930,8 +4930,10 @@ fn orelseCatchExpr(
break :blk &err_val_scope.base;
};
- block_scope.break_count += 1;
const else_result = try expr(&else_scope, else_sub_scope, block_scope.break_result_loc, rhs);
+ if (!else_scope.endsWithNoReturn()) {
+ block_scope.break_count += 1;
+ }
try checkUsed(parent_gz, &else_scope.base, else_sub_scope);
// We hold off on the break instructions as well as copying the then/else
@@ -5249,8 +5251,10 @@ fn ifExpr(
}
};
- block_scope.break_count += 1;
const then_result = try expr(&then_scope, then_sub_scope, block_scope.break_result_loc, if_full.ast.then_expr);
+ if (!then_scope.endsWithNoReturn()) {
+ block_scope.break_count += 1;
+ }
try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
// We hold off on the break instructions as well as copying the then/else
// instructions into place until we know whether to keep store_to_block_ptr
@@ -5264,7 +5268,6 @@ fn ifExpr(
src: Ast.Node.Index,
result: Zir.Inst.Ref,
} = if (else_node != 0) blk: {
- block_scope.break_count += 1;
const sub_scope = s: {
if (if_full.error_token) |error_token| {
const tag: Zir.Inst.Tag = if (payload_is_ref)
@@ -5291,6 +5294,9 @@ fn ifExpr(
}
};
const e = try expr(&else_scope, sub_scope, block_scope.break_result_loc, else_node);
+ if (!else_scope.endsWithNoReturn()) {
+ block_scope.break_count += 1;
+ }
try checkUsed(parent_gz, &else_scope.base, sub_scope);
break :blk .{
.src = else_node,