Sema: fix @intToPtr of zero value to optional pointer

Calling into coercion logic here is a little opaque, and more to the
point wholly unnecessary. Instead, the (very short) logic is now
implemented directly in Sema.

Resolves: #16033
This commit is contained in:
mlugg
2023-06-14 18:10:47 +01:00
committed by Andrew Kelley
parent ce88c43a4e
commit 11d0dfb882
3 changed files with 31 additions and 8 deletions

View File

@@ -6817,17 +6817,12 @@ pub fn errorSetFromUnsortedNames(
return new_ty.toType();
}
/// Supports optionals in addition to pointers.
/// Supports only pointers, not pointer-like optionals.
pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
return mod.getCoerced(try mod.intValue_u64(Type.usize, x), ty);
}
/// Supports only pointers. See `ptrIntValue` for pointer-like optional support.
pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
assert(ty.zigTypeTag(mod) == .Pointer);
const i = try intern(mod, .{ .ptr = .{
.ty = ty.toIntern(),
.addr = .{ .int = try mod.intValue_u64(Type.usize, x) },
.addr = .{ .int = (try mod.intValue_u64(Type.usize, x)).toIntern() },
} });
return i.toValue();
}

View File

@@ -20846,7 +20846,15 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0)
return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)});
return sema.addConstant(ptr_ty, try mod.ptrIntValue(ptr_ty, addr));
const ptr_val = switch (ptr_ty.zigTypeTag(mod)) {
.Optional => (try mod.intern(.{ .opt = .{
.ty = ptr_ty.toIntern(),
.val = if (addr == 0) .none else (try mod.ptrIntValue(ptr_ty.childType(mod), addr)).toIntern(),
} })).toValue(),
.Pointer => try mod.ptrIntValue(ptr_ty, addr),
else => unreachable,
};
return sema.addConstant(ptr_ty, ptr_val);
}
try sema.requireRuntimeBlock(block, src, operand_src);

View File

@@ -1,4 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
const expectEqual = std.testing.expectEqual;
test "casting integer address to function pointer" {
addressToFunction();
@@ -26,3 +28,21 @@ fn forceCompilerAnalyzeBranchHardCodedPtrDereference(x: bool) void {
return;
}
}
test "@intToPtr creates null pointer" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
const ptr = @intToPtr(?*u32, 0);
try expectEqual(@as(?*u32, null), ptr);
}
test "@intToPtr creates allowzero zero pointer" {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
const ptr = @intToPtr(*allowzero u32, 0);
try expectEqual(@as(usize, 0), @ptrToInt(ptr));
}