authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-24 16:23:03-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-04-24 16:23:03-07:00
loga2fe81a63992aa8d0d9b56dfbb6ffe525fdc907a
tree92e1179cff284e603aac60b3d68c6c9ada946474
parentbba90b8863102d75578d521cebdf4c2443451f59
parentf1e43d1f4fde4f7b6909c660ec210f9b14cacb4d
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #15421 from Vexu/fixes

Runtime safety improvements

4 files changed, 103 insertions(+), 107 deletions(-)

src/AstGen.zig+74-100
......@@ -839,12 +839,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
839839 .slice_open => {
840840 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
841841
842 maybeAdvanceSourceCursorToMainToken(gz, node);
843 const line = gz.astgen.source_line - gz.decl_line;
844 const column = gz.astgen.source_column;
845
842 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
846843 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);
847 try emitDbgStmt(gz, line, column);
844 try emitDbgStmt(gz, cursor);
848845 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{
849846 .lhs = lhs,
850847 .start = start,
......@@ -854,14 +851,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
854851 .slice => {
855852 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
856853
857 maybeAdvanceSourceCursorToMainToken(gz, node);
858 const line = gz.astgen.source_line - gz.decl_line;
859 const column = gz.astgen.source_column;
860
854 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
861855 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
862856 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
863857 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);
864 try emitDbgStmt(gz, line, column);
858 try emitDbgStmt(gz, cursor);
865859 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{
866860 .lhs = lhs,
867861 .start = start,
......@@ -872,15 +866,12 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
872866 .slice_sentinel => {
873867 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
874868
875 maybeAdvanceSourceCursorToMainToken(gz, node);
876 const line = gz.astgen.source_line - gz.decl_line;
877 const column = gz.astgen.source_column;
878
869 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
879870 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
880871 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
881872 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;
882873 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);
883 try emitDbgStmt(gz, line, column);
874 try emitDbgStmt(gz, cursor);
884875 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{
885876 .lhs = lhs,
886877 .start = start,
......@@ -914,20 +905,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
914905 .ref => {
915906 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
916907
917 maybeAdvanceSourceCursorToMainToken(gz, node);
918 const line = gz.astgen.source_line - gz.decl_line;
919 const column = gz.astgen.source_column;
920 try emitDbgStmt(gz, line, column);
908 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
909 try emitDbgStmt(gz, cursor);
921910
922911 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
923912 },
924913 else => {
925914 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
926915
927 maybeAdvanceSourceCursorToMainToken(gz, node);
928 const line = gz.astgen.source_line - gz.decl_line;
929 const column = gz.astgen.source_column;
930 try emitDbgStmt(gz, line, column);
916 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
917 try emitDbgStmt(gz, cursor);
931918
932919 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);
933920 },
......@@ -3330,23 +3317,17 @@ fn assignOp(
33303317
33313318 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
33323319
3333 var line: u32 = undefined;
3334 var column: u32 = undefined;
3335 switch (op_inst_tag) {
3336 .add, .sub, .mul, .div, .mod_rem => {
3337 maybeAdvanceSourceCursorToMainToken(gz, infix_node);
3338 line = gz.astgen.source_line - gz.decl_line;
3339 column = gz.astgen.source_column;
3340 },
3341 else => {},
3342 }
3320 const cursor = switch (op_inst_tag) {
3321 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),
3322 else => undefined,
3323 };
33433324 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
33443325 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);
33453326 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs);
33463327
33473328 switch (op_inst_tag) {
33483329 .add, .sub, .mul, .div, .mod_rem => {
3349 try emitDbgStmt(gz, line, column);
3330 try emitDbgStmt(gz, cursor);
33503331 },
33513332 else => {},
33523333 }
......@@ -5360,8 +5341,7 @@ fn tryExpr(
53605341 if (!parent_gz.is_comptime) {
53615342 try emitDbgNode(parent_gz, node);
53625343 }
5363 const try_line = astgen.source_line - parent_gz.decl_line;
5364 const try_column = astgen.source_column;
5344 const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
53655345
53665346 const operand_ri: ResultInfo = switch (ri.rl) {
53675347 .ref => .{ .rl = .ref, .ctx = .error_handling_expr },
......@@ -5382,7 +5362,7 @@ fn tryExpr(
53825362 };
53835363 const err_code = try else_scope.addUnNode(err_tag, operand, node);
53845364 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });
5385 try emitDbgStmt(&else_scope, try_line, try_column);
5365 try emitDbgStmt(&else_scope, try_lc);
53865366 _ = try else_scope.addUnNode(.ret_node, err_code, node);
53875367
53885368 try else_scope.setTryBody(try_inst, operand);
......@@ -5607,10 +5587,8 @@ fn addFieldAccess(
56075587 const str_index = try astgen.identAsString(field_ident);
56085588 const lhs = try expr(gz, scope, lhs_ri, object_node);
56095589
5610 maybeAdvanceSourceCursorToMainToken(gz, node);
5611 const line = gz.astgen.source_line - gz.decl_line;
5612 const column = gz.astgen.source_column;
5613 try emitDbgStmt(gz, line, column);
5590 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
5591 try emitDbgStmt(gz, cursor);
56145592
56155593 return gz.addPlNode(tag, node, Zir.Inst.Field{
56165594 .lhs = lhs,
......@@ -5630,24 +5608,20 @@ fn arrayAccess(
56305608 .ref => {
56315609 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
56325610
5633 maybeAdvanceSourceCursorToMainToken(gz, node);
5634 const line = gz.astgen.source_line - gz.decl_line;
5635 const column = gz.astgen.source_column;
5611 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
56365612
56375613 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);
5638 try emitDbgStmt(gz, line, column);
5614 try emitDbgStmt(gz, cursor);
56395615
56405616 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
56415617 },
56425618 else => {
56435619 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
56445620
5645 maybeAdvanceSourceCursorToMainToken(gz, node);
5646 const line = gz.astgen.source_line - gz.decl_line;
5647 const column = gz.astgen.source_column;
5621 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
56485622
56495623 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);
5650 try emitDbgStmt(gz, line, column);
5624 try emitDbgStmt(gz, cursor);
56515625
56525626 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
56535627 },
......@@ -5674,21 +5648,15 @@ fn simpleBinOp(
56745648 }
56755649
56765650 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
5677 var line: u32 = undefined;
5678 var column: u32 = undefined;
5679 switch (op_inst_tag) {
5680 .add, .sub, .mul, .div, .mod_rem => {
5681 maybeAdvanceSourceCursorToMainToken(gz, node);
5682 line = gz.astgen.source_line - gz.decl_line;
5683 column = gz.astgen.source_column;
5684 },
5685 else => {},
5686 }
5651 const cursor = switch (op_inst_tag) {
5652 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),
5653 else => undefined,
5654 };
56875655 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);
56885656
56895657 switch (op_inst_tag) {
56905658 .add, .sub, .mul, .div, .mod_rem => {
5691 try emitDbgStmt(gz, line, column);
5659 try emitDbgStmt(gz, cursor);
56925660 },
56935661 else => {},
56945662 }
......@@ -6787,14 +6755,15 @@ fn switchExpr(
67876755 }
67886756
67896757 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
6758
67906759 astgen.advanceSourceCursorToNode(operand_node);
6791 const operand_line = astgen.source_line - parent_gz.decl_line;
6792 const operand_column = astgen.source_column;
6760 const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
6761
67936762 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
67946763 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;
67956764 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);
67966765 // Sema expects a dbg_stmt immediately after switch_cond(_ref)
6797 try emitDbgStmt(parent_gz, operand_line, operand_column);
6766 try emitDbgStmt(parent_gz, operand_lc);
67986767 // We need the type of the operand to use as the result location for all the prong items.
67996768 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
68006769 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };
......@@ -7154,8 +7123,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
71547123 if (!gz.is_comptime) {
71557124 try emitDbgNode(gz, node);
71567125 }
7157 const ret_line = astgen.source_line - gz.decl_line;
7158 const ret_column = astgen.source_column;
7126 const ret_lc = LineColumn{ astgen.source_line - gz.decl_line, astgen.source_column };
71597127
71607128 const defer_outer = &astgen.fn_block.?.base;
71617129
......@@ -7179,13 +7147,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
71797147 const defer_counts = countDefers(defer_outer, scope);
71807148 if (!defer_counts.need_err_code) {
71817149 try genDefers(gz, defer_outer, scope, .both_sans_err);
7182 try emitDbgStmt(gz, ret_line, ret_column);
7150 try emitDbgStmt(gz, ret_lc);
71837151 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
71847152 return Zir.Inst.Ref.unreachable_value;
71857153 }
71867154 const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
71877155 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
7188 try emitDbgStmt(gz, ret_line, ret_column);
7156 try emitDbgStmt(gz, ret_lc);
71897157 _ = try gz.addUnNode(.ret_node, err_code, node);
71907158 return Zir.Inst.Ref.unreachable_value;
71917159 }
......@@ -7210,7 +7178,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
72107178 // As our last action before the return, "pop" the error trace if needed
72117179 _ = try gz.addRestoreErrRetIndex(.ret, .always);
72127180
7213 try emitDbgStmt(gz, ret_line, ret_column);
7181 try emitDbgStmt(gz, ret_lc);
72147182 try gz.addRet(ri, operand, node);
72157183 return Zir.Inst.Ref.unreachable_value;
72167184 },
......@@ -7218,7 +7186,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
72187186 // Value is always an error. Emit both error defers and regular defers.
72197187 const err_code = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
72207188 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
7221 try emitDbgStmt(gz, ret_line, ret_column);
7189 try emitDbgStmt(gz, ret_lc);
72227190 try gz.addRet(ri, operand, node);
72237191 return Zir.Inst.Ref.unreachable_value;
72247192 },
......@@ -7227,7 +7195,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
72277195 if (!defer_counts.have_err) {
72287196 // Only regular defers; no branch needed.
72297197 try genDefers(gz, defer_outer, scope, .normal_only);
7230 try emitDbgStmt(gz, ret_line, ret_column);
7198 try emitDbgStmt(gz, ret_lc);
72317199
72327200 // As our last action before the return, "pop" the error trace if needed
72337201 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
......@@ -7250,7 +7218,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
72507218 // As our last action before the return, "pop" the error trace if needed
72517219 _ = try then_scope.addRestoreErrRetIndex(.ret, .always);
72527220
7253 try emitDbgStmt(&then_scope, ret_line, ret_column);
7221 try emitDbgStmt(&then_scope, ret_lc);
72547222 try then_scope.addRet(ri, operand, node);
72557223
72567224 var else_scope = gz.makeSubBlock(scope);
......@@ -7260,7 +7228,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
72607228 .both = try else_scope.addUnNode(.err_union_code, result, node),
72617229 };
72627230 try genDefers(&else_scope, defer_outer, scope, which_ones);
7263 try emitDbgStmt(&else_scope, ret_line, ret_column);
7231 try emitDbgStmt(&else_scope, ret_lc);
72647232 try else_scope.addRet(ri, operand, node);
72657233
72667234 try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);
......@@ -8650,11 +8618,14 @@ fn typeCast(
86508618 rhs_node: Ast.Node.Index,
86518619 tag: Zir.Inst.Tag,
86528620) InnerError!Zir.Inst.Ref {
8653 try emitDbgNode(gz, node);
8621 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
8622 const result_type = try typeExpr(gz, scope, lhs_node);
8623 const operand = try expr(gz, scope, .{ .rl = .none }, rhs_node);
86548624
8625 try emitDbgStmt(gz, cursor);
86558626 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8656 .lhs = try typeExpr(gz, scope, lhs_node),
8657 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
8627 .lhs = result_type,
8628 .rhs = operand,
86588629 });
86598630 return rvalue(gz, ri, result, node);
86608631}
......@@ -8681,14 +8652,15 @@ fn simpleUnOp(
86818652 operand_node: Ast.Node.Index,
86828653 tag: Zir.Inst.Tag,
86838654) InnerError!Zir.Inst.Ref {
8684 switch (tag) {
8685 .tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node),
8686 else => {},
8687 }
8655 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
86888656 const operand = if (tag == .compile_error)
86898657 try comptimeExpr(gz, scope, operand_ri, operand_node)
86908658 else
86918659 try expr(gz, scope, operand_ri, operand_node);
8660 switch (tag) {
8661 .tag_name, .error_name, .ptr_to_int => try emitDbgStmt(gz, cursor),
8662 else => {},
8663 }
86928664 const result = try gz.addUnNode(tag, operand, node);
86938665 return rvalue(gz, ri, result, node);
86948666}
......@@ -8760,12 +8732,12 @@ fn divBuiltin(
87608732 rhs_node: Ast.Node.Index,
87618733 tag: Zir.Inst.Tag,
87628734) InnerError!Zir.Inst.Ref {
8763 try emitDbgNode(gz, node);
8735 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
8736 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
8737 const rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node);
87648738
8765 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8766 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),
8767 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
8768 });
8739 try emitDbgStmt(gz, cursor);
8740 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
87698741 return rvalue(gz, ri, result, node);
87708742}
87718743
......@@ -8814,23 +8786,21 @@ fn shiftOp(
88148786 rhs_node: Ast.Node.Index,
88158787 tag: Zir.Inst.Tag,
88168788) InnerError!Zir.Inst.Ref {
8817 var line = gz.astgen.source_line - gz.decl_line;
8818 var column = gz.astgen.source_column;
88198789 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
88208790
8821 switch (gz.astgen.tree.nodes.items(.tag)[node]) {
8822 .shl, .shr => {
8823 maybeAdvanceSourceCursorToMainToken(gz, node);
8824 line = gz.astgen.source_line - gz.decl_line;
8825 column = gz.astgen.source_column;
8826 },
8827 else => {},
8828 }
8791 const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) {
8792 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),
8793 else => undefined,
8794 };
88298795
88308796 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
88318797 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);
88328798
8833 try emitDbgStmt(gz, line, column);
8799 switch (gz.astgen.tree.nodes.items(.tag)[node]) {
8800 .shl, .shr => try emitDbgStmt(gz, cursor),
8801 else => undefined,
8802 }
8803
88348804 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
88358805 .lhs = lhs,
88368806 .rhs = rhs,
......@@ -12594,16 +12564,20 @@ fn detectLocalShadowing(
1259412564 };
1259512565}
1259612566
12567const LineColumn = struct { u32, u32 };
12568
1259712569/// Advances the source cursor to the main token of `node` if not in comptime scope.
1259812570/// Usually paired with `emitDbgStmt`.
12599fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) void {
12600 if (gz.is_comptime) return;
12571fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineColumn {
12572 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
1260112573
1260212574 const tree = gz.astgen.tree;
1260312575 const token_starts = tree.tokens.items(.start);
1260412576 const main_tokens = tree.nodes.items(.main_token);
1260512577 const node_start = token_starts[main_tokens[node]];
1260612578 gz.astgen.advanceSourceCursor(node_start);
12579
12580 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
1260712581}
1260812582
1260912583/// Advances the source cursor to the beginning of `node`.
......@@ -12807,13 +12781,13 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
1280712781 return @intCast(u32, count);
1280812782}
1280912783
12810fn emitDbgStmt(gz: *GenZir, line: u32, column: u32) !void {
12784fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
1281112785 if (gz.is_comptime) return;
1281212786
1281312787 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
1281412788 .dbg_stmt = .{
12815 .line = line,
12816 .column = column,
12789 .line = lc[0],
12790 .column = lc[1],
1281712791 },
1281812792 } });
1281912793}
src/Sema.zig+3-3
......@@ -19627,7 +19627,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1962719627 }
1962819628
1962919629 try sema.requireRuntimeBlock(block, src, operand_src);
19630 if (block.wantSafety() and try sema.typeHasRuntimeBits(elem_ty)) {
19630 if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag() == .Fn)) {
1963119631 if (!ptr_ty.isAllowzeroPtr()) {
1963219632 const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
1963319633 try sema.addSafetyCheck(block, is_non_zero, .cast_to_null);
......@@ -19853,7 +19853,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1985319853
1985419854 try sema.requireRuntimeBlock(block, src, null);
1985519855 if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and
19856 try sema.typeHasRuntimeBits(dest_ty.elemType2()))
19856 (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn))
1985719857 {
1985819858 const ptr_int = try block.addUnOp(.ptrtoint, ptr);
1985919859 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
......@@ -27742,7 +27742,7 @@ fn coerceCompatiblePtrs(
2774227742 try sema.requireRuntimeBlock(block, inst_src, null);
2774327743 const inst_allows_zero = inst_ty.zigTypeTag() != .Pointer or inst_ty.ptrAllowsZero();
2774427744 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and
27745 try sema.typeHasRuntimeBits(dest_ty.elemType2()))
27745 (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn))
2774627746 {
2774727747 const actual_ptr = if (inst_ty.isSlice())
2774827748 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
test/behavior/type.zig+3-4
......@@ -486,10 +486,9 @@ test "Type.Union from regular enum" {
486486}
487487
488488test "Type.Fn" {
489 if (true) {
490 // https://github.com/ziglang/zig/issues/12360
491 return error.SkipZigTest;
492 }
489 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
490 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
491 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
493492
494493 const some_opaque = opaque {};
495494 const some_ptr = *some_opaque;
test/cases/safety/pointer casting to null function pointer.zig created+23
......@@ -0,0 +1,23 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "cast causes pointer to be null")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11fn getNullPtr() ?*const anyopaque {
12 return null;
13}
14pub fn main() !void {
15 const null_ptr: ?*const anyopaque = getNullPtr();
16 const required_ptr: *align(1) const fn() void = @ptrCast(*align(1) const fn() void, null_ptr);
17 _ = required_ptr;
18 return error.TestFailed;
19}
20
21// run
22// backend=llvm
23// target=native