zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit fb91483e48fe6cfa21edc613f266e27bd6bf9dbf (tree)
parent e584558bd8533ce91d1683cdbc6b77d7bb652acf
Author: Veikka Tuominen <git@vexu.eu>
Date:   Mon, 19 Sep 2022 13:11:19 +0300

Sema: do not use coerceCompatiblePtr for ptrCast

Diffstat:
Msrc/Sema.zig | 61+++++++++++++++++++++++++++++++++++++++++++++++++++----------
Atest/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig | 13+++++++++++++
Atest/cases/compile_errors/ptrCast_discards_const_qualifier.zig | 11+++++++++++
Dtest/cases/compile_errors/stage1/obj/increase_pointer_alignment_in_ptrCast.zig | 13-------------
Dtest/cases/compile_errors/stage1/obj/ptrCast_discards_const_qualifier.zig | 11-----------
5 files changed, 75 insertions(+), 34 deletions(-)

diff --git a/src/Sema.zig b/src/Sema.zig @@ -17772,6 +17772,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; + const src = inst_data.src(); const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; 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 try sema.checkPtrType(block, dest_ty_src, dest_ty); try sema.checkPtrOperand(block, operand_src, operand_ty); + const operand_info = operand_ty.ptrInfo().data; + const dest_info = dest_ty.ptrInfo().data; + if (!operand_info.mutable and dest_info.mutable) { + return sema.fail(block, src, "cast discards const qualifier", .{}); + } + if (operand_info.@"volatile" and !dest_info.@"volatile") { + return sema.fail(block, src, "cast discards volatile qualifier", .{}); + } + const dest_is_slice = dest_ty.isSlice(); const operand_is_slice = operand_ty.isSlice(); if (dest_is_slice and !operand_is_slice) { @@ -17793,15 +17803,6 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air else operand; - if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { - if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) { - return sema.failWithUseOfUndef(block, operand_src); - } - if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { - return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)}); - } - } - const dest_elem_ty = dest_ty.elemType2(); try sema.resolveTypeLayout(block, dest_ty_src, dest_elem_ty); const dest_align = dest_ty.ptrAlignment(target); @@ -17835,7 +17836,47 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } } - return sema.coerceCompatiblePtrs(block, aligned_dest_ty, ptr, operand_src); + if (dest_align > operand_align) { + const msg = msg: { + const msg = try sema.errMsg(block, src, "cast increases pointer alignment", .{}); + errdefer msg.destroy(sema.gpa); + + try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{ + operand_ty.fmt(sema.mod), operand_align, + }); + try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{ + dest_ty.fmt(sema.mod), dest_align, + }); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(msg); + } + + if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |operand_val| { + if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) { + return sema.failWithUseOfUndef(block, operand_src); + } + if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) { + return sema.fail(block, operand_src, "null pointer casted to type {}", .{dest_ty.fmt(sema.mod)}); + } + return sema.addConstant(aligned_dest_ty, operand_val); + } + + try sema.requireRuntimeBlock(block, src, null); + if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and + try sema.typeHasRuntimeBits(block, sema.src, dest_ty.elemType2())) + { + const ptr_int = try block.addUnOp(.ptrtoint, ptr); + const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); + const ok = if (operand_is_slice) ok: { + const len = try sema.analyzeSliceLen(block, operand_src, operand); + const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); + break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero); + } else is_non_zero; + try sema.addSafetyCheck(block, ok, .cast_to_null); + } + + return block.addBitCast(aligned_dest_ty, ptr); } fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { diff --git a/test/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig b/test/cases/compile_errors/increase_pointer_alignment_in_ptrCast.zig @@ -0,0 +1,13 @@ +export fn entry() u32 { + var bytes: [4]u8 = [_]u8{0x01, 0x02, 0x03, 0x04}; + const ptr = @ptrCast(*u32, &bytes[0]); + return ptr.*; +} + +// error +// backend=stage2 +// target=native +// +// :3:17: error: cast increases pointer alignment +// :3:32: note: '*u8' has alignment '1' +// :3:26: note: '*u32' has alignment '4' diff --git a/test/cases/compile_errors/ptrCast_discards_const_qualifier.zig b/test/cases/compile_errors/ptrCast_discards_const_qualifier.zig @@ -0,0 +1,11 @@ +export fn entry() void { + const x: i32 = 1234; + const y = @ptrCast(*i32, &x); + _ = y; +} + +// error +// backend=stage2 +// target=native +// +// :3:15: error: cast discards const qualifier diff --git a/test/cases/compile_errors/stage1/obj/increase_pointer_alignment_in_ptrCast.zig b/test/cases/compile_errors/stage1/obj/increase_pointer_alignment_in_ptrCast.zig @@ -1,13 +0,0 @@ -export fn entry() u32 { - var bytes: [4]u8 = [_]u8{0x01, 0x02, 0x03, 0x04}; - const ptr = @ptrCast(*u32, &bytes[0]); - return ptr.*; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:3:17: error: cast increases pointer alignment -// tmp.zig:3:38: note: '*u8' has alignment 1 -// tmp.zig:3:26: note: '*u32' has alignment 4 diff --git a/test/cases/compile_errors/stage1/obj/ptrCast_discards_const_qualifier.zig b/test/cases/compile_errors/stage1/obj/ptrCast_discards_const_qualifier.zig @@ -1,11 +0,0 @@ -export fn entry() void { - const x: i32 = 1234; - const y = @ptrCast(*i32, &x); - _ = y; -} - -// error -// backend=stage1 -// target=native -// -// tmp.zig:3:15: error: cast discards const qualifier