authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-30 15:09:45-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-30 15:25:58-04:00
log5c3a486639443e2fa62433b95108d956088e73bd
tree0ea16023d32ebd5bdbe908e6a424e62b19d094c2
parent8caed4846018cd185b632bc884c7df81b8dd39dc

AstGen: avoid accessing value from inner scope

While continue expressions can access the capture, so ensure that it is unwrapped in an outer scope.

1 files changed, 37 insertions(+), 33 deletions(-)

src/AstGen.zig+37-33
......@@ -5910,8 +5910,8 @@ fn whileExpr(
59105910 defer loop_scope.unstack();
59115911 defer loop_scope.labeled_breaks.deinit(astgen.gpa);
59125912
5913 var continue_scope = parent_gz.makeSubBlock(&loop_scope.base);
5914 defer continue_scope.unstack();
5913 var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);
5914 defer cond_scope.unstack();
59155915
59165916 const payload_is_ref = if (while_full.payload_token) |payload_token|
59175917 token_tags[payload_token] == .asterisk
......@@ -5925,22 +5925,22 @@ fn whileExpr(
59255925 } = c: {
59265926 if (while_full.error_token) |_| {
59275927 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
5928 const err_union = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr);
5928 const err_union = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);
59295929 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_err_ptr else .is_non_err;
59305930 break :c .{
59315931 .inst = err_union,
5932 .bool_bit = try continue_scope.addUnNode(tag, err_union, while_full.ast.then_expr),
5932 .bool_bit = try cond_scope.addUnNode(tag, err_union, while_full.ast.then_expr),
59335933 };
59345934 } else if (while_full.payload_token) |_| {
59355935 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };
5936 const optional = try expr(&continue_scope, &continue_scope.base, cond_ri, while_full.ast.cond_expr);
5936 const optional = try expr(&cond_scope, &cond_scope.base, cond_ri, while_full.ast.cond_expr);
59375937 const tag: Zir.Inst.Tag = if (payload_is_ref) .is_non_null_ptr else .is_non_null;
59385938 break :c .{
59395939 .inst = optional,
5940 .bool_bit = try continue_scope.addUnNode(tag, optional, while_full.ast.then_expr),
5940 .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.then_expr),
59415941 };
59425942 } else {
5943 const cond = try expr(&continue_scope, &continue_scope.base, bool_ri, while_full.ast.cond_expr);
5943 const cond = try expr(&cond_scope, &cond_scope.base, bool_ri, while_full.ast.cond_expr);
59445944 break :c .{
59455945 .inst = cond,
59465946 .bool_bit = cond,
......@@ -5949,16 +5949,16 @@ fn whileExpr(
59495949 };
59505950
59515951 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
5952 const condbr = try continue_scope.addCondBr(condbr_tag, node);
5952 const condbr = try cond_scope.addCondBr(condbr_tag, node);
59535953 const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block;
59545954 const cond_block = try loop_scope.makeBlockInst(block_tag, node);
5955 try continue_scope.setBlockBody(cond_block);
5956 // continue_scope unstacked now, can add new instructions to loop_scope
5955 try cond_scope.setBlockBody(cond_block);
5956 // cond_scope unstacked now, can add new instructions to loop_scope
59575957 try loop_scope.instructions.append(astgen.gpa, cond_block);
59585958
59595959 // make scope now but don't stack on parent_gz until loop_scope
59605960 // gets unstacked after cont_expr is emitted and added below
5961 var then_scope = parent_gz.makeSubBlock(&continue_scope.base);
5961 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
59625962 then_scope.instructions_top = GenZir.unstacked_top;
59635963 defer then_scope.unstack();
59645964
......@@ -6026,24 +6026,17 @@ fn whileExpr(
60266026 }
60276027 };
60286028
6029 // This code could be improved to avoid emitting the continue expr when there
6030 // are no jumps to it. This happens when the last statement of a while body is noreturn
6031 // and there are no `continue` statements.
6032 // Tracking issue: https://github.com/ziglang/zig/issues/9185
6033 try then_scope.addDbgBlockBegin();
6034 if (dbg_var_name) |some| {
6035 try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
6036 }
6037 if (while_full.ast.cont_expr != 0) {
6038 _ = try unusedResultExpr(&loop_scope, then_sub_scope, while_full.ast.cont_expr);
6039 }
6040 try then_scope.addDbgBlockEnd();
6029 var continue_scope = parent_gz.makeSubBlock(then_sub_scope);
6030 continue_scope.instructions_top = GenZir.unstacked_top;
6031 defer continue_scope.unstack();
6032 const continue_block = try then_scope.makeBlockInst(block_tag, node);
6033
60416034 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
60426035 _ = try loop_scope.addNode(repeat_tag, node);
60436036
60446037 try loop_scope.setBlockBody(loop_block);
60456038 loop_scope.break_block = loop_block;
6046 loop_scope.continue_block = cond_block;
6039 loop_scope.continue_block = continue_block;
60476040 if (while_full.label_token) |label_token| {
60486041 loop_scope.label = @as(?GenZir.Label, GenZir.Label{
60496042 .token = label_token,
......@@ -6054,18 +6047,30 @@ fn whileExpr(
60546047 // done adding instructions to loop_scope, can now stack then_scope
60556048 then_scope.instructions_top = then_scope.instructions.items.len;
60566049
6057 if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst);
60586050 try then_scope.addDbgBlockBegin();
6059 if (dbg_var_name) |some| {
6060 try then_scope.addDbgVar(.dbg_var_val, some, dbg_var_inst);
6051 if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst);
6052 if (dbg_var_name) |name| try then_scope.addDbgVar(.dbg_var_val, name, dbg_var_inst);
6053 try then_scope.instructions.append(astgen.gpa, continue_block);
6054 // This code could be improved to avoid emitting the continue expr when there
6055 // are no jumps to it. This happens when the last statement of a while body is noreturn
6056 // and there are no `continue` statements.
6057 // Tracking issue: https://github.com/ziglang/zig/issues/9185
6058 if (while_full.ast.cont_expr != 0) {
6059 _ = try unusedResultExpr(&then_scope, then_sub_scope, while_full.ast.cont_expr);
60616060 }
6062 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, while_full.ast.then_expr);
6063 _ = try addEnsureResult(&then_scope, then_result, while_full.ast.then_expr);
6061 try then_scope.addDbgBlockEnd();
60646062
6063 continue_scope.instructions_top = continue_scope.instructions.items.len;
6064 _ = try unusedResultExpr(&continue_scope, &continue_scope.base, while_full.ast.then_expr);
60656065 try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
6066 try then_scope.addDbgBlockEnd();
6066 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
6067 if (!continue_scope.endsWithNoReturn()) {
6068 const break_inst = try continue_scope.makeBreak(break_tag, continue_block, .void_value);
6069 try then_scope.instructions.append(astgen.gpa, break_inst);
6070 }
6071 try continue_scope.setBlockBody(continue_block);
60676072
6068 var else_scope = parent_gz.makeSubBlock(&continue_scope.base);
6073 var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
60696074 defer else_scope.unstack();
60706075
60716076 const else_node = while_full.ast.else_expr;
......@@ -6128,7 +6133,6 @@ fn whileExpr(
61286133 try astgen.appendErrorTok(some.token, "unused while loop label", .{});
61296134 }
61306135 }
6131 const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
61326136 const result = try finishThenElseBlock(
61336137 parent_gz,
61346138 ri,
......@@ -6138,7 +6142,7 @@ fn whileExpr(
61386142 &else_scope,
61396143 condbr,
61406144 cond.bool_bit,
6141 then_result,
6145 .void_value,
61426146 else_info.result,
61436147 loop_block,
61446148 cond_block,