diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2025-03-16 03:26:29 +0000 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2025-04-28 01:14:24 +0100 |
| commit | 95932e98e50f3762c3faf5ac3ee7c8f11f09096e (patch) | |
| tree | 3496052f75c6aad4aada9aab8caec4ba5196646e | |
| parent | d4c539664661a93fe193a9559688e7c6c3955e0d (diff) | |
| download | zig-95932e98e50f3762c3faf5ac3ee7c8f11f09096e.tar.gz zig-95932e98e50f3762c3faf5ac3ee7c8f11f09096e.zip | |
Sema: fix alignment of runtime field pointer of underaligned tuple
| -rw-r--r-- | src/Sema.zig | 16 | ||||
| -rw-r--r-- | test/behavior/tuple.zig | 18 |
2 files changed, 30 insertions, 4 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 788f8ba057..2696cbd87c 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -28617,7 +28617,8 @@ fn tupleFieldPtr( const pt = sema.pt; const zcu = pt.zcu; const tuple_ptr_ty = sema.typeOf(tuple_ptr); - const tuple_ty = tuple_ptr_ty.childType(zcu); + const tuple_ptr_info = tuple_ptr_ty.ptrInfo(zcu); + const tuple_ty: Type = .fromInterned(tuple_ptr_info.child); try tuple_ty.resolveFields(pt); const field_count = tuple_ty.structFieldCount(zcu); @@ -28635,9 +28636,16 @@ fn tupleFieldPtr( const ptr_field_ty = try pt.ptrTypeSema(.{ .child = field_ty.toIntern(), .flags = .{ - .is_const = !tuple_ptr_ty.ptrIsMutable(zcu), - .is_volatile = tuple_ptr_ty.isVolatilePtr(zcu), - .address_space = tuple_ptr_ty.ptrAddressSpace(zcu), + .is_const = tuple_ptr_info.flags.is_const, + .is_volatile = tuple_ptr_info.flags.is_volatile, + .address_space = tuple_ptr_info.flags.address_space, + .alignment = a: { + if (tuple_ptr_info.flags.alignment == .none) break :a .none; + // The tuple pointer isn't naturally aligned, so the field pointer might be underaligned. + const tuple_align = tuple_ptr_info.flags.alignment; + const field_align = try field_ty.abiAlignmentSema(pt); + break :a tuple_align.min(field_align); + }, }, }); diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index 492730df61..c9d3fb4b38 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -602,3 +602,21 @@ test "empty union in tuple" { try std.testing.expectEqualStrings("0", info.@"struct".fields[0].name); try std.testing.expect(@typeInfo(info.@"struct".fields[0].type) == .@"union"); } + +test "field pointer of underaligned tuple" { + if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; + const S = struct { + fn doTheTest() !void { + const T = struct { u8, u32 }; + var val: T align(2) = .{ 1, 2 }; + + comptime assert(@TypeOf(&val[0]) == *u8); // `u8` field pointer isn't overaligned + comptime assert(@TypeOf(&val[1]) == *align(2) u32); // `u32` field pointer is correctly underaligned + + try expect(val[0] == 1); + try expect(val[1] == 2); + } + }; + try S.doTheTest(); + try comptime S.doTheTest(); +} |
