diff --git a/src/Module.zig b/src/Module.zig index e8cea97b8f..8c5a86652d 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -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(); } diff --git a/src/Sema.zig b/src/Sema.zig index 1cc50b77b8..28b75b56a6 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -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); diff --git a/test/behavior/inttoptr.zig b/test/behavior/inttoptr.zig index 29a263b2ce..5a3778b09f 100644 --- a/test/behavior/inttoptr.zig +++ b/test/behavior/inttoptr.zig @@ -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)); +}