authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-28 17:11:03+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-10-29 14:55:43+03:00
log5321afcf9c633c5dc0da5148981dfdbd61606f1a
tree267b0231ddfa4cb31d0c43328c86387865593d43
parentd7314555f2bc413494d58bbafa2d607b88922afb

stage2: make switch on corrupt value panic point to switch condition

Closes #13295

2 files changed, 14 insertions(+), 3 deletions(-)

src/AstGen.zig+5
...@@ -6496,9 +6496,14 @@ fn switchExpr(...@@ -6496,9 +6496,14 @@ fn switchExpr(
6496 }6496 }
64976497
6498 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };6498 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
6499 astgen.advanceSourceCursorToNode(operand_node);
6500 const operand_line = astgen.source_line - parent_gz.decl_line;
6501 const operand_column = astgen.source_column;
6499 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);6502 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
6500 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;6503 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;
6501 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);6504 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);
6505 // Sema expects a dbg_stmt immediately after switch_cond(_ref)
6506 try emitDbgStmt(parent_gz, operand_line, operand_column);
6502 // We need the type of the operand to use as the result location for all the prong items.6507 // We need the type of the operand to use as the result location for all the prong items.
6503 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);6508 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
6504 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };6509 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };
src/Sema.zig+9-3
...@@ -9663,6 +9663,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9663,6 +9663,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9663 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);9663 const extra = sema.code.extraData(Zir.Inst.SwitchBlock, inst_data.payload_index);
96649664
9665 const operand = try sema.resolveInst(extra.data.operand);9665 const operand = try sema.resolveInst(extra.data.operand);
9666 // AstGen guarantees that the instruction immediately following
9667 // switch_cond(_ref) is a dbg_stmt
9668 const cond_dbg_node_index = Zir.refToIndex(extra.data.operand).? + 1;
96669669
9667 var header_extra_index: usize = extra.end;9670 var header_extra_index: usize = extra.end;
96689671
...@@ -10359,6 +10362,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10359,6 +10362,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10359 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and10362 if (backend_supports_is_named_enum and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
10360 (!operand_ty.isNonexhaustiveEnum() or union_originally))10363 (!operand_ty.isNonexhaustiveEnum() or union_originally))
10361 {10364 {
10365 try sema.zirDbgStmt(block, cond_dbg_node_index);
10362 const ok = try block.addUnOp(.is_named_enum_value, operand);10366 const ok = try block.addUnOp(.is_named_enum_value, operand);
10363 try sema.addSafetyCheck(block, ok, .corrupt_switch);10367 try sema.addSafetyCheck(block, ok, .corrupt_switch);
10364 }10368 }
...@@ -10828,6 +10832,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10828,6 +10832,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10828 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and10832 if (backend_supports_is_named_enum and special.body.len != 0 and block.wantSafety() and
10829 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))10833 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))
10830 {10834 {
10835 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
10831 const ok = try case_block.addUnOp(.is_named_enum_value, operand);10836 const ok = try case_block.addUnOp(.is_named_enum_value, operand);
10832 try sema.addSafetyCheck(&case_block, ok, .corrupt_switch);10837 try sema.addSafetyCheck(&case_block, ok, .corrupt_switch);
10833 }10838 }
...@@ -10851,6 +10856,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -10851,6 +10856,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
10851 // We still need a terminator in this block, but we have proven10856 // We still need a terminator in this block, but we have proven
10852 // that it is unreachable.10857 // that it is unreachable.
10853 if (case_block.wantSafety()) {10858 if (case_block.wantSafety()) {
10859 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
10854 _ = try sema.safetyPanic(&case_block, src, .corrupt_switch);10860 _ = try sema.safetyPanic(&case_block, src, .corrupt_switch);
10855 } else {10861 } else {
10856 _ = try case_block.addNoOp(.unreach);10862 _ = try case_block.addNoOp(.unreach);
...@@ -23931,7 +23937,7 @@ fn coerceExtra(...@@ -23931,7 +23937,7 @@ fn coerceExtra(
23931 inst_ty.isPtrAtRuntime())23937 inst_ty.isPtrAtRuntime())
23932 anyopaque_check: {23938 anyopaque_check: {
23933 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;23939 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
23934 const elem_ty = inst_ty.elemType2(); 23940 const elem_ty = inst_ty.elemType2();
23935 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {23941 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
23936 in_memory_result = .{ .double_ptr_to_anyopaque = .{23942 in_memory_result = .{ .double_ptr_to_anyopaque = .{
23937 .actual = inst_ty,23943 .actual = inst_ty,
...@@ -23941,7 +23947,7 @@ fn coerceExtra(...@@ -23941,7 +23947,7 @@ fn coerceExtra(
23941 }23947 }
23942 // Let the logic below handle wrapping the optional now that23948 // Let the logic below handle wrapping the optional now that
23943 // it has been checked to correctly coerce.23949 // it has been checked to correctly coerce.
23944 if (!inst_ty.isPtrLikeOptional()) break: anyopaque_check;23950 if (!inst_ty.isPtrLikeOptional()) break :anyopaque_check;
23945 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);23951 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
23946 }23952 }
2394723953
...@@ -24066,7 +24072,7 @@ fn coerceExtra(...@@ -24066,7 +24072,7 @@ fn coerceExtra(
24066 // but don't do it if the source type is a double pointer24072 // but don't do it if the source type is a double pointer
24067 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) {24073 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) {
24068 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;24074 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
24069 const elem_ty = inst_ty.elemType2(); 24075 const elem_ty = inst_ty.elemType2();
24070 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {24076 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
24071 in_memory_result = .{ .double_ptr_to_anyopaque = .{24077 in_memory_result = .{ .double_ptr_to_anyopaque = .{
24072 .actual = inst_ty,24078 .actual = inst_ty,