aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-09-19 13:11:19 +0300
committerVeikka Tuominen <git@vexu.eu>2022-09-19 18:34:53 +0300
commitfb91483e48fe6cfa21edc613f266e27bd6bf9dbf (patch)
tree1503802e5c2ea8f3959806d388c25244208a54fe /src/Sema.zig
parente584558bd8533ce91d1683cdbc6b77d7bb652acf (diff)
downloadzig-fb91483e48fe6cfa21edc613f266e27bd6bf9dbf.tar.gz
zig-fb91483e48fe6cfa21edc613f266e27bd6bf9dbf.zip
Sema: do not use coerceCompatiblePtr for ptrCast
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig61
1 files changed, 51 insertions, 10 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 4b61266558..748b1de78f 100644
--- 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 {