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...@@ -839,12 +839,9 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
839 .slice_open => {839 .slice_open => {
840 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);840 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
841841
842 maybeAdvanceSourceCursorToMainToken(gz, node);842 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
843 const line = gz.astgen.source_line - gz.decl_line;
844 const column = gz.astgen.source_column;
845
846 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs);843 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);
848 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{845 const result = try gz.addPlNode(.slice_start, node, Zir.Inst.SliceStart{
849 .lhs = lhs,846 .lhs = lhs,
850 .start = start,847 .start = start,
...@@ -854,14 +851,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -854,14 +851,11 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
854 .slice => {851 .slice => {
855 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);852 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
856853
857 maybeAdvanceSourceCursorToMainToken(gz, node);854 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
858 const line = gz.astgen.source_line - gz.decl_line;
859 const column = gz.astgen.source_column;
860
861 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);855 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.Slice);
862 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);856 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
863 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);857 const end = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end);
864 try emitDbgStmt(gz, line, column);858 try emitDbgStmt(gz, cursor);
865 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{859 const result = try gz.addPlNode(.slice_end, node, Zir.Inst.SliceEnd{
866 .lhs = lhs,860 .lhs = lhs,
867 .start = start,861 .start = start,
...@@ -872,15 +866,12 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -872,15 +866,12 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
872 .slice_sentinel => {866 .slice_sentinel => {
873 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);867 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
874868
875 maybeAdvanceSourceCursorToMainToken(gz, node);869 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
876 const line = gz.astgen.source_line - gz.decl_line;
877 const column = gz.astgen.source_column;
878
879 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);870 const extra = tree.extraData(node_datas[node].rhs, Ast.Node.SliceSentinel);
880 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);871 const start = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.start);
881 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;872 const end = if (extra.end != 0) try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, extra.end) else .none;
882 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);873 const sentinel = try expr(gz, scope, .{ .rl = .none }, extra.sentinel);
883 try emitDbgStmt(gz, line, column);874 try emitDbgStmt(gz, cursor);
884 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{875 const result = try gz.addPlNode(.slice_sentinel, node, Zir.Inst.SliceSentinel{
885 .lhs = lhs,876 .lhs = lhs,
886 .start = start,877 .start = start,
...@@ -914,20 +905,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE...@@ -914,20 +905,16 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE
914 .ref => {905 .ref => {
915 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);906 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
916907
917 maybeAdvanceSourceCursorToMainToken(gz, node);908 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
918 const line = gz.astgen.source_line - gz.decl_line;909 try emitDbgStmt(gz, cursor);
919 const column = gz.astgen.source_column;
920 try emitDbgStmt(gz, line, column);
921910
922 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);911 return gz.addUnNode(.optional_payload_safe_ptr, lhs, node);
923 },912 },
924 else => {913 else => {
925 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);914 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
926915
927 maybeAdvanceSourceCursorToMainToken(gz, node);916 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
928 const line = gz.astgen.source_line - gz.decl_line;917 try emitDbgStmt(gz, cursor);
929 const column = gz.astgen.source_column;
930 try emitDbgStmt(gz, line, column);
931918
932 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);919 return rvalue(gz, ri, try gz.addUnNode(.optional_payload_safe, lhs, node), node);
933 },920 },
...@@ -3330,23 +3317,17 @@ fn assignOp(...@@ -3330,23 +3317,17 @@ fn assignOp(
33303317
3331 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);3318 const lhs_ptr = try lvalExpr(gz, scope, node_datas[infix_node].lhs);
33323319
3333 var line: u32 = undefined;3320 const cursor = switch (op_inst_tag) {
3334 var column: u32 = undefined;3321 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, infix_node),
3335 switch (op_inst_tag) {3322 else => undefined,
3336 .add, .sub, .mul, .div, .mod_rem => {3323 };
3337 maybeAdvanceSourceCursorToMainToken(gz, infix_node);
3338 line = gz.astgen.source_line - gz.decl_line;
3339 column = gz.astgen.source_column;
3340 },
3341 else => {},
3342 }
3343 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);3324 const lhs = try gz.addUnNode(.load, lhs_ptr, infix_node);
3344 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);3325 const lhs_type = try gz.addUnNode(.typeof, lhs, infix_node);
3345 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs);3326 const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = lhs_type } }, node_datas[infix_node].rhs);
33463327
3347 switch (op_inst_tag) {3328 switch (op_inst_tag) {
3348 .add, .sub, .mul, .div, .mod_rem => {3329 .add, .sub, .mul, .div, .mod_rem => {
3349 try emitDbgStmt(gz, line, column);3330 try emitDbgStmt(gz, cursor);
3350 },3331 },
3351 else => {},3332 else => {},
3352 }3333 }
...@@ -5360,8 +5341,7 @@ fn tryExpr(...@@ -5360,8 +5341,7 @@ fn tryExpr(
5360 if (!parent_gz.is_comptime) {5341 if (!parent_gz.is_comptime) {
5361 try emitDbgNode(parent_gz, node);5342 try emitDbgNode(parent_gz, node);
5362 }5343 }
5363 const try_line = astgen.source_line - parent_gz.decl_line;5344 const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
5364 const try_column = astgen.source_column;
53655345
5366 const operand_ri: ResultInfo = switch (ri.rl) {5346 const operand_ri: ResultInfo = switch (ri.rl) {
5367 .ref => .{ .rl = .ref, .ctx = .error_handling_expr },5347 .ref => .{ .rl = .ref, .ctx = .error_handling_expr },
...@@ -5382,7 +5362,7 @@ fn tryExpr(...@@ -5382,7 +5362,7 @@ fn tryExpr(
5382 };5362 };
5383 const err_code = try else_scope.addUnNode(err_tag, operand, node);5363 const err_code = try else_scope.addUnNode(err_tag, operand, node);
5384 try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code });5364 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);
5386 _ = try else_scope.addUnNode(.ret_node, err_code, node);5366 _ = try else_scope.addUnNode(.ret_node, err_code, node);
53875367
5388 try else_scope.setTryBody(try_inst, operand);5368 try else_scope.setTryBody(try_inst, operand);
...@@ -5607,10 +5587,8 @@ fn addFieldAccess(...@@ -5607,10 +5587,8 @@ fn addFieldAccess(
5607 const str_index = try astgen.identAsString(field_ident);5587 const str_index = try astgen.identAsString(field_ident);
5608 const lhs = try expr(gz, scope, lhs_ri, object_node);5588 const lhs = try expr(gz, scope, lhs_ri, object_node);
56095589
5610 maybeAdvanceSourceCursorToMainToken(gz, node);5590 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
5611 const line = gz.astgen.source_line - gz.decl_line;5591 try emitDbgStmt(gz, cursor);
5612 const column = gz.astgen.source_column;
5613 try emitDbgStmt(gz, line, column);
56145592
5615 return gz.addPlNode(tag, node, Zir.Inst.Field{5593 return gz.addPlNode(tag, node, Zir.Inst.Field{
5616 .lhs = lhs,5594 .lhs = lhs,
...@@ -5630,24 +5608,20 @@ fn arrayAccess(...@@ -5630,24 +5608,20 @@ fn arrayAccess(
5630 .ref => {5608 .ref => {
5631 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);5609 const lhs = try expr(gz, scope, .{ .rl = .ref }, node_datas[node].lhs);
56325610
5633 maybeAdvanceSourceCursorToMainToken(gz, node);5611 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
5634 const line = gz.astgen.source_line - gz.decl_line;
5635 const column = gz.astgen.source_column;
56365612
5637 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);5613 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
5640 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });5616 return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
5641 },5617 },
5642 else => {5618 else => {
5643 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);5619 const lhs = try expr(gz, scope, .{ .rl = .none }, node_datas[node].lhs);
56445620
5645 maybeAdvanceSourceCursorToMainToken(gz, node);5621 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
5646 const line = gz.astgen.source_line - gz.decl_line;
5647 const column = gz.astgen.source_column;
56485622
5649 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs);5623 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
5652 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);5626 return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node);
5653 },5627 },
...@@ -5674,21 +5648,15 @@ fn simpleBinOp(...@@ -5674,21 +5648,15 @@ fn simpleBinOp(
5674 }5648 }
56755649
5676 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);5650 const lhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].lhs, node);
5677 var line: u32 = undefined;5651 const cursor = switch (op_inst_tag) {
5678 var column: u32 = undefined;5652 .add, .sub, .mul, .div, .mod_rem => maybeAdvanceSourceCursorToMainToken(gz, node),
5679 switch (op_inst_tag) {5653 else => undefined,
5680 .add, .sub, .mul, .div, .mod_rem => {5654 };
5681 maybeAdvanceSourceCursorToMainToken(gz, node);
5682 line = gz.astgen.source_line - gz.decl_line;
5683 column = gz.astgen.source_column;
5684 },
5685 else => {},
5686 }
5687 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);5655 const rhs = try reachableExpr(gz, scope, .{ .rl = .none }, node_datas[node].rhs, node);
56885656
5689 switch (op_inst_tag) {5657 switch (op_inst_tag) {
5690 .add, .sub, .mul, .div, .mod_rem => {5658 .add, .sub, .mul, .div, .mod_rem => {
5691 try emitDbgStmt(gz, line, column);5659 try emitDbgStmt(gz, cursor);
5692 },5660 },
5693 else => {},5661 else => {},
5694 }5662 }
...@@ -6787,14 +6755,15 @@ fn switchExpr(...@@ -6787,14 +6755,15 @@ fn switchExpr(
6787 }6755 }
67886756
6789 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };6757 const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
6758
6790 astgen.advanceSourceCursorToNode(operand_node);6759 astgen.advanceSourceCursorToNode(operand_node);
6791 const operand_line = astgen.source_line - parent_gz.decl_line;6760 const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
6792 const operand_column = astgen.source_column;6761
6793 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);6762 const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
6794 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;6763 const cond_tag: Zir.Inst.Tag = if (any_payload_is_ref) .switch_cond_ref else .switch_cond;
6795 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);6764 const cond = try parent_gz.addUnNode(cond_tag, raw_operand, operand_node);
6796 // Sema expects a dbg_stmt immediately after switch_cond(_ref)6765 // 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);
6798 // We need the type of the operand to use as the result location for all the prong items.6767 // We need the type of the operand to use as the result location for all the prong items.
6799 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);6768 const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node);
6800 const item_ri: ResultInfo = .{ .rl = .{ .ty = cond_ty_inst } };6769 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...@@ -7154,8 +7123,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
7154 if (!gz.is_comptime) {7123 if (!gz.is_comptime) {
7155 try emitDbgNode(gz, node);7124 try emitDbgNode(gz, node);
7156 }7125 }
7157 const ret_line = astgen.source_line - gz.decl_line;7126 const ret_lc = LineColumn{ astgen.source_line - gz.decl_line, astgen.source_column };
7158 const ret_column = astgen.source_column;
71597127
7160 const defer_outer = &astgen.fn_block.?.base;7128 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...@@ -7179,13 +7147,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
7179 const defer_counts = countDefers(defer_outer, scope);7147 const defer_counts = countDefers(defer_outer, scope);
7180 if (!defer_counts.need_err_code) {7148 if (!defer_counts.need_err_code) {
7181 try genDefers(gz, defer_outer, scope, .both_sans_err);7149 try genDefers(gz, defer_outer, scope, .both_sans_err);
7182 try emitDbgStmt(gz, ret_line, ret_column);7150 try emitDbgStmt(gz, ret_lc);
7183 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);7151 _ = try gz.addStrTok(.ret_err_value, err_name_str_index, ident_token);
7184 return Zir.Inst.Ref.unreachable_value;7152 return Zir.Inst.Ref.unreachable_value;
7185 }7153 }
7186 const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);7154 const err_code = try gz.addStrTok(.ret_err_value_code, err_name_str_index, ident_token);
7187 try genDefers(gz, defer_outer, scope, .{ .both = err_code });7155 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
7188 try emitDbgStmt(gz, ret_line, ret_column);7156 try emitDbgStmt(gz, ret_lc);
7189 _ = try gz.addUnNode(.ret_node, err_code, node);7157 _ = try gz.addUnNode(.ret_node, err_code, node);
7190 return Zir.Inst.Ref.unreachable_value;7158 return Zir.Inst.Ref.unreachable_value;
7191 }7159 }
...@@ -7210,7 +7178,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -7210,7 +7178,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
7210 // As our last action before the return, "pop" the error trace if needed7178 // As our last action before the return, "pop" the error trace if needed
7211 _ = try gz.addRestoreErrRetIndex(.ret, .always);7179 _ = try gz.addRestoreErrRetIndex(.ret, .always);
72127180
7213 try emitDbgStmt(gz, ret_line, ret_column);7181 try emitDbgStmt(gz, ret_lc);
7214 try gz.addRet(ri, operand, node);7182 try gz.addRet(ri, operand, node);
7215 return Zir.Inst.Ref.unreachable_value;7183 return Zir.Inst.Ref.unreachable_value;
7216 },7184 },
...@@ -7218,7 +7186,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -7218,7 +7186,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
7218 // Value is always an error. Emit both error defers and regular defers.7186 // Value is always an error. Emit both error defers and regular defers.
7219 const err_code = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;7187 const err_code = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;
7220 try genDefers(gz, defer_outer, scope, .{ .both = err_code });7188 try genDefers(gz, defer_outer, scope, .{ .both = err_code });
7221 try emitDbgStmt(gz, ret_line, ret_column);7189 try emitDbgStmt(gz, ret_lc);
7222 try gz.addRet(ri, operand, node);7190 try gz.addRet(ri, operand, node);
7223 return Zir.Inst.Ref.unreachable_value;7191 return Zir.Inst.Ref.unreachable_value;
7224 },7192 },
...@@ -7227,7 +7195,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -7227,7 +7195,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
7227 if (!defer_counts.have_err) {7195 if (!defer_counts.have_err) {
7228 // Only regular defers; no branch needed.7196 // Only regular defers; no branch needed.
7229 try genDefers(gz, defer_outer, scope, .normal_only);7197 try genDefers(gz, defer_outer, scope, .normal_only);
7230 try emitDbgStmt(gz, ret_line, ret_column);7198 try emitDbgStmt(gz, ret_lc);
72317199
7232 // As our last action before the return, "pop" the error trace if needed7200 // As our last action before the return, "pop" the error trace if needed
7233 const result = if (ri.rl == .ptr) try gz.addUnNode(.load, ri.rl.ptr.inst, node) else operand;7201 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...@@ -7250,7 +7218,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
7250 // As our last action before the return, "pop" the error trace if needed7218 // As our last action before the return, "pop" the error trace if needed
7251 _ = try then_scope.addRestoreErrRetIndex(.ret, .always);7219 _ = try then_scope.addRestoreErrRetIndex(.ret, .always);
72527220
7253 try emitDbgStmt(&then_scope, ret_line, ret_column);7221 try emitDbgStmt(&then_scope, ret_lc);
7254 try then_scope.addRet(ri, operand, node);7222 try then_scope.addRet(ri, operand, node);
72557223
7256 var else_scope = gz.makeSubBlock(scope);7224 var else_scope = gz.makeSubBlock(scope);
...@@ -7260,7 +7228,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref...@@ -7260,7 +7228,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
7260 .both = try else_scope.addUnNode(.err_union_code, result, node),7228 .both = try else_scope.addUnNode(.err_union_code, result, node),
7261 };7229 };
7262 try genDefers(&else_scope, defer_outer, scope, which_ones);7230 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);
7264 try else_scope.addRet(ri, operand, node);7232 try else_scope.addRet(ri, operand, node);
72657233
7266 try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);7234 try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0);
...@@ -8650,11 +8618,14 @@ fn typeCast(...@@ -8650,11 +8618,14 @@ fn typeCast(
8650 rhs_node: Ast.Node.Index,8618 rhs_node: Ast.Node.Index,
8651 tag: Zir.Inst.Tag,8619 tag: Zir.Inst.Tag,
8652) InnerError!Zir.Inst.Ref {8620) 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);
8655 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8626 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8656 .lhs = try typeExpr(gz, scope, lhs_node),8627 .lhs = result_type,
8657 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),8628 .rhs = operand,
8658 });8629 });
8659 return rvalue(gz, ri, result, node);8630 return rvalue(gz, ri, result, node);
8660}8631}
...@@ -8681,14 +8652,15 @@ fn simpleUnOp(...@@ -8681,14 +8652,15 @@ fn simpleUnOp(
8681 operand_node: Ast.Node.Index,8652 operand_node: Ast.Node.Index,
8682 tag: Zir.Inst.Tag,8653 tag: Zir.Inst.Tag,
8683) InnerError!Zir.Inst.Ref {8654) InnerError!Zir.Inst.Ref {
8684 switch (tag) {8655 const cursor = maybeAdvanceSourceCursorToMainToken(gz, node);
8685 .tag_name, .error_name, .ptr_to_int => try emitDbgNode(gz, node),
8686 else => {},
8687 }
8688 const operand = if (tag == .compile_error)8656 const operand = if (tag == .compile_error)
8689 try comptimeExpr(gz, scope, operand_ri, operand_node)8657 try comptimeExpr(gz, scope, operand_ri, operand_node)
8690 else8658 else
8691 try expr(gz, scope, operand_ri, operand_node);8659 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 }
8692 const result = try gz.addUnNode(tag, operand, node);8664 const result = try gz.addUnNode(tag, operand, node);
8693 return rvalue(gz, ri, result, node);8665 return rvalue(gz, ri, result, node);
8694}8666}
...@@ -8760,12 +8732,12 @@ fn divBuiltin(...@@ -8760,12 +8732,12 @@ fn divBuiltin(
8760 rhs_node: Ast.Node.Index,8732 rhs_node: Ast.Node.Index,
8761 tag: Zir.Inst.Tag,8733 tag: Zir.Inst.Tag,
8762) InnerError!Zir.Inst.Ref {8734) 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{8739 try emitDbgStmt(gz, cursor);
8766 .lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node),8740 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs });
8767 .rhs = try expr(gz, scope, .{ .rl = .none }, rhs_node),
8768 });
8769 return rvalue(gz, ri, result, node);8741 return rvalue(gz, ri, result, node);
8770}8742}
87718743
...@@ -8814,23 +8786,21 @@ fn shiftOp(...@@ -8814,23 +8786,21 @@ fn shiftOp(
8814 rhs_node: Ast.Node.Index,8786 rhs_node: Ast.Node.Index,
8815 tag: Zir.Inst.Tag,8787 tag: Zir.Inst.Tag,
8816) InnerError!Zir.Inst.Ref {8788) InnerError!Zir.Inst.Ref {
8817 var line = gz.astgen.source_line - gz.decl_line;
8818 var column = gz.astgen.source_column;
8819 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);8789 const lhs = try expr(gz, scope, .{ .rl = .none }, lhs_node);
88208790
8821 switch (gz.astgen.tree.nodes.items(.tag)[node]) {8791 const cursor = switch (gz.astgen.tree.nodes.items(.tag)[node]) {
8822 .shl, .shr => {8792 .shl, .shr => maybeAdvanceSourceCursorToMainToken(gz, node),
8823 maybeAdvanceSourceCursorToMainToken(gz, node);8793 else => undefined,
8824 line = gz.astgen.source_line - gz.decl_line;8794 };
8825 column = gz.astgen.source_column;
8826 },
8827 else => {},
8828 }
88298795
8830 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);8796 const log2_int_type = try gz.addUnNode(.typeof_log2_int_type, lhs, lhs_node);
8831 const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type }, .ctx = .shift_op }, rhs_node);8797 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
8834 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{8804 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
8835 .lhs = lhs,8805 .lhs = lhs,
8836 .rhs = rhs,8806 .rhs = rhs,
...@@ -12594,16 +12564,20 @@ fn detectLocalShadowing(...@@ -12594,16 +12564,20 @@ fn detectLocalShadowing(
12594 };12564 };
12595}12565}
1259612566
12567const LineColumn = struct { u32, u32 };
12568
12597/// Advances the source cursor to the main token of `node` if not in comptime scope.12569/// Advances the source cursor to the main token of `node` if not in comptime scope.
12598/// Usually paired with `emitDbgStmt`.12570/// Usually paired with `emitDbgStmt`.
12599fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) void {12571fn maybeAdvanceSourceCursorToMainToken(gz: *GenZir, node: Ast.Node.Index) LineColumn {
12600 if (gz.is_comptime) return;12572 if (gz.is_comptime) return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
1260112573
12602 const tree = gz.astgen.tree;12574 const tree = gz.astgen.tree;
12603 const token_starts = tree.tokens.items(.start);12575 const token_starts = tree.tokens.items(.start);
12604 const main_tokens = tree.nodes.items(.main_token);12576 const main_tokens = tree.nodes.items(.main_token);
12605 const node_start = token_starts[main_tokens[node]];12577 const node_start = token_starts[main_tokens[node]];
12606 gz.astgen.advanceSourceCursor(node_start);12578 gz.astgen.advanceSourceCursor(node_start);
12579
12580 return .{ gz.astgen.source_line - gz.decl_line, gz.astgen.source_column };
12607}12581}
1260812582
12609/// Advances the source cursor to the beginning of `node`.12583/// Advances the source cursor to the beginning of `node`.
...@@ -12807,13 +12781,13 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {...@@ -12807,13 +12781,13 @@ fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 {
12807 return @intCast(u32, count);12781 return @intCast(u32, count);
12808}12782}
1280912783
12810fn emitDbgStmt(gz: *GenZir, line: u32, column: u32) !void {12784fn emitDbgStmt(gz: *GenZir, lc: LineColumn) !void {
12811 if (gz.is_comptime) return;12785 if (gz.is_comptime) return;
1281212786
12813 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{12787 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
12814 .dbg_stmt = .{12788 .dbg_stmt = .{
12815 .line = line,12789 .line = lc[0],
12816 .column = column,12790 .column = lc[1],
12817 },12791 },
12818 } });12792 } });
12819}12793}
src/Sema.zig+3-3
...@@ -19627,7 +19627,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -19627,7 +19627,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
19627 }19627 }
1962819628
19629 try sema.requireRuntimeBlock(block, src, operand_src);19629 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)) {
19631 if (!ptr_ty.isAllowzeroPtr()) {19631 if (!ptr_ty.isAllowzeroPtr()) {
19632 const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);19632 const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
19633 try sema.addSafetyCheck(block, is_non_zero, .cast_to_null);19633 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...@@ -19853,7 +19853,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1985319853
19854 try sema.requireRuntimeBlock(block, src, null);19854 try sema.requireRuntimeBlock(block, src, null);
19855 if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and19855 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))
19857 {19857 {
19858 const ptr_int = try block.addUnOp(.ptrtoint, ptr);19858 const ptr_int = try block.addUnOp(.ptrtoint, ptr);
19859 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);19859 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
...@@ -27742,7 +27742,7 @@ fn coerceCompatiblePtrs(...@@ -27742,7 +27742,7 @@ fn coerceCompatiblePtrs(
27742 try sema.requireRuntimeBlock(block, inst_src, null);27742 try sema.requireRuntimeBlock(block, inst_src, null);
27743 const inst_allows_zero = inst_ty.zigTypeTag() != .Pointer or inst_ty.ptrAllowsZero();27743 const inst_allows_zero = inst_ty.zigTypeTag() != .Pointer or inst_ty.ptrAllowsZero();
27744 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and27744 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))
27746 {27746 {
27747 const actual_ptr = if (inst_ty.isSlice())27747 const actual_ptr = if (inst_ty.isSlice())
27748 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)27748 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" {...@@ -486,10 +486,9 @@ test "Type.Union from regular enum" {
486}486}
487487
488test "Type.Fn" {488test "Type.Fn" {
489 if (true) {489 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
490 // https://github.com/ziglang/zig/issues/12360490 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
491 return error.SkipZigTest;491 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
492 }
493492
494 const some_opaque = opaque {};493 const some_opaque = opaque {};
495 const some_ptr = *some_opaque;494 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