diff --git a/src/Sema/comptime_ptr_access.zig b/src/Sema/comptime_ptr_access.zig index ceddb9457d..2e21c31f2b 100644 --- a/src/Sema/comptime_ptr_access.zig +++ b/src/Sema/comptime_ptr_access.zig @@ -65,6 +65,15 @@ pub fn storeComptimePtr( const zcu = pt.zcu; const ptr_info = ptr.typeOf(zcu).ptrInfo(zcu); assert(store_val.typeOf(zcu).toIntern() == ptr_info.child); + + { + const store_ty: Type = .fromInterned(ptr_info.child); + if (!try store_ty.comptimeOnlySema(pt) and !try store_ty.hasRuntimeBitsIgnoreComptimeSema(pt)) { + // zero-bit store; nothing to do + return .success; + } + } + // TODO: host size for vectors is terrible const host_bits = switch (ptr_info.flags.vector_index) { .none => ptr_info.packed_offset.host_size * 8, diff --git a/src/Type.zig b/src/Type.zig index 3208cf522d..321730067d 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -1740,10 +1740,7 @@ pub fn bitSizeInner( const len = array_type.lenIncludingSentinel(); if (len == 0) return 0; const elem_ty = Type.fromInterned(array_type.child); - const elem_size = @max( - (try elem_ty.abiAlignmentInner(strat_lazy, zcu, tid)).scalar.toByteUnits() orelse 0, - (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar, - ); + const elem_size = (try elem_ty.abiSizeInner(strat_lazy, zcu, tid)).scalar; if (elem_size == 0) return 0; const elem_bit_size = try elem_ty.bitSizeInner(strat, zcu, tid); return (len - 1) * 8 * elem_size + elem_bit_size; diff --git a/test/behavior/comptime_memory.zig b/test/behavior/comptime_memory.zig index baca3da72d..64b494b23e 100644 --- a/test/behavior/comptime_memory.zig +++ b/test/behavior/comptime_memory.zig @@ -515,3 +515,66 @@ fn fieldPtrTest() u32 { test "pointer in aggregate field can mutate comptime state" { try comptime std.testing.expect(fieldPtrTest() == 2); } + +test "comptime store of extern struct with void field" { + comptime { + var x: extern struct { a: u8, b: void } = undefined; + x = .{ .a = 123, .b = {} }; + std.debug.assert(x.a == 123); + } +} + +test "comptime store of extern struct with void field into array" { + comptime { + var x: [3]extern struct { a: u8, b: void } = undefined; + x[1] = .{ .a = 123, .b = {} }; + std.debug.assert(x[1].a == 123); + } +} + +test "comptime store of packed struct with void field" { + comptime { + var x: packed struct { a: u8, b: void } = undefined; + x = .{ .a = 123, .b = {} }; + std.debug.assert(x.a == 123); + } +} + +test "comptime store of packed struct with void field into array" { + comptime { + var x: [3]packed struct { a: u8, b: void } = undefined; + x[1] = .{ .a = 123, .b = {} }; + std.debug.assert(x[1].a == 123); + } +} + +test "comptime store of reinterpreted zero-bit type" { + const S = struct { + fn doTheTest(comptime T: type) void { + comptime var buf: T = undefined; + const ptr: *void = @ptrCast(&buf); + ptr.* = {}; + } + }; + S.doTheTest(void); + S.doTheTest(u0); + S.doTheTest([0]u8); + S.doTheTest([1]u0); + S.doTheTest([5]u0); + S.doTheTest([5]void); + S.doTheTest(packed struct(u0) {}); +} + +test "comptime store to extern struct reinterpreted as byte array" { + const T = extern struct { + x: u32, + y: f32, + z: [2]void, + }; + comptime var val: T = undefined; + + const bytes: *[@sizeOf(T)]u8 = @ptrCast(&val); + @memset(bytes, 0); + + comptime std.debug.assert(val.x == 0); +}