authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-03-16 17:51:31+00:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-17 01:56:36-04:00
log4ec299007a6a183edddfcb0505a9c1501da7ad0c
tree147976e4d469e4e494244bb86111b73aaeb7bd11
parent68c7261e1daf7787dcbf0cd6f9b01e5678d20a93

Sema: allow dereferencing ill-defined pointers to zero-bit types at comptime

It doesn't matter if a pointer to a zero-bit (i.e. OPV) type is undefined or runtime-known; we still know the result of the dereference at comptime. Code may use this, for instance, when allocating zero-bit types: `@as(*void, undefined)` is entirely reasonable to use at runtime, since we know the pointer will never be accessed, thus it should be valid at comptime too.

2 files changed, 13 insertions(+), 0 deletions(-)

src/Sema.zig+5
......@@ -4712,6 +4712,11 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
47124712 .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}),
47134713 }
47144714
4715 if ((try sema.typeHasOnePossibleValue(operand_ty.childType())) != null) {
4716 // No need to validate the actual pointer value, we don't need it!
4717 return;
4718 }
4719
47154720 const elem_ty = operand_ty.elemType2();
47164721 if (try sema.resolveMaybeUndefVal(operand)) |val| {
47174722 if (val.isUndef()) {
test/behavior/comptime_memory.zig+8
......@@ -420,3 +420,11 @@ test "mutate entire slice at comptime" {
420420 buf[1..3].* = x;
421421 }
422422}
423
424test "dereference undefined pointer to zero-bit type" {
425 const p0: *void = undefined;
426 try testing.expectEqual({}, p0.*);
427
428 const p1: *[0]u32 = undefined;
429 try testing.expect(p1.*.len == 0);
430}