authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-19 13:11:19+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-19 18:34:53+03:00
logfb91483e48fe6cfa21edc613f266e27bd6bf9dbf
tree1503802e5c2ea8f3959806d388c25244208a54fe
parente584558bd8533ce91d1683cdbc6b77d7bb652acf

Sema: do not use coerceCompatiblePtr for ptrCast


5 files changed, 75 insertions(+), 34 deletions(-)

src/Sema.zig+51-10
...@@ -17772,6 +17772,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat...@@ -17772,6 +17772,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1777217772
17773fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {17773fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
17774 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;17774 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
17775 const src = inst_data.src();
17775 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };17776 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
17776 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };17777 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
17777 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;17778 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
...@@ -17783,6 +17784,15 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -17783,6 +17784,15 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17783 try sema.checkPtrType(block, dest_ty_src, dest_ty);17784 try sema.checkPtrType(block, dest_ty_src, dest_ty);
17784 try sema.checkPtrOperand(block, operand_src, operand_ty);17785 try sema.checkPtrOperand(block, operand_src, operand_ty);
1778517786
17787 const operand_info = operand_ty.ptrInfo().data;
17788 const dest_info = dest_ty.ptrInfo().data;
17789 if (!operand_info.mutable and dest_info.mutable) {
17790 return sema.fail(block, src, "cast discards const qualifier", .{});
17791 }
17792 if (operand_info.@"volatile" and !dest_info.@"volatile") {
17793 return sema.fail(block, src, "cast discards volatile qualifier", .{});
17794 }
17795
17786 const dest_is_slice = dest_ty.isSlice();17796 const dest_is_slice = dest_ty.isSlice();
17787 const operand_is_slice = operand_ty.isSlice();17797 const operand_is_slice = operand_ty.isSlice();
17788 if (dest_is_slice and !operand_is_slice) {17798 if (dest_is_slice and !operand_is_slice) {
...@@ -17793,15 +17803,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -17793,15 +17803,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17793 else17803 else
17794 operand;17804 operand;
1779517805
17796 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| {
17797 if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) {
17798 return sema.failWithUseOfUndef(block, operand_src);
17799 }
17800 if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) {
17801 return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)});
17802 }
17803 }
17804
17805 const dest_elem_ty = dest_ty.elemType2();17806 const dest_elem_ty = dest_ty.elemType2();
17806 try sema.resolveTypeLayout(block, dest_ty_src, dest_elem_ty);17807 try sema.resolveTypeLayout(block, dest_ty_src, dest_elem_ty);
17807 const dest_align = dest_ty.ptrAlignment(target);17808 const dest_align = dest_ty.ptrAlignment(target);
...@@ -17835,7 +17836,47 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -17835,7 +17836,47 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
17835 }17836 }
17836 }17837 }
1783717838
17838 return sema.coerceCompatiblePtrs(block, aligned_dest_ty, ptr, operand_src);17839 if (dest_align > operand_align) {
17840 const msg = msg: {
17841 const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{});
17842 errdefer msg.destroy(sema.gpa);
17843
17844 try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{
17845 operand_ty.fmt(sema.mod), operand_align,
17846 });
17847 try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{
17848 dest_ty.fmt(sema.mod), dest_align,
17849 });
17850 break :msg msg;
17851 };
17852 return sema.failWithOwnedErrorMsg(msg);
17853 }
17854
17855 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| {
17856 if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) {
17857 return sema.failWithUseOfUndef(block, operand_src);
17858 }
17859 if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) {
17860 return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)});
17861 }
17862 return sema.addConstant(aligned_dest_ty, operand_val);
17863 }
17864
17865 try sema.requireRuntimeBlock(block, src, null);
17866 if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and
17867 try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2()))
17868 {
17869 const ptr_int = try block.addUnOp(.ptrtoint, ptr);
17870 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
17871 const ok = if (operand_is_slice) ok: {
17872 const len = try sema.analyzeSliceLen(block, operand_src, operand);
17873 const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);
17874 break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero);
17875 } else is_non_zero;
17876 try sema.addSafetyCheck(block, ok, .cast_to_null);
17877 }
17878
17879 return block.addBitCast(aligned_dest_ty, ptr);
17839}17880}
1784017881
17841fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {17882fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
test/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig created+13
...@@ -0,0 +1,13 @@
1export fn entry() u32 {
2 var bytes: [4]u8 = [_]u8{0x01, 0x02, 0x03, 0x04};
3 const ptr = @ptrCast(*u32, &bytes[0]);
4 return ptr.*;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :3:17: error: cast increases pointer alignment
12// :3:32: note: '*u8' has alignment '1'
13// :3:26: note: '*u32' has alignment '4'
test/cases/compile_errors/ptrCast_discards_const_qualifier.zig created+11
...@@ -0,0 +1,11 @@
1export fn entry() void {
2 const x: i32 = 1234;
3 const y = @ptrCast(*i32, &x);
4 _ = y;
5}
6
7// error
8// backend=stage2
9// target=native
10//
11// :3:15: error: cast discards const qualifier
test/cases/compile_errors/stage1/obj/increase_pointer_alignment_in_ptrCast.zig deleted-13
...@@ -1,13 +0,0 @@
1export fn entry() u32 {
2 var bytes: [4]u8 = [_]u8{0x01, 0x02, 0x03, 0x04};
3 const ptr = @ptrCast(*u32, &bytes[0]);
4 return ptr.*;
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:3:17: error: cast increases pointer alignment
12// tmp.zig:3:38: note: '*u8' has alignment 1
13// tmp.zig:3:26: note: '*u32' has alignment 4
test/cases/compile_errors/stage1/obj/ptrCast_discards_const_qualifier.zig deleted-11
...@@ -1,11 +0,0 @@
1export fn entry() void {
2 const x: i32 = 1234;
3 const y = @ptrCast(*i32, &x);
4 _ = y;
5}
6
7// error
8// backend=stage1
9// target=native
10//
11// tmp.zig:3:15: error: cast discards const qualifier