Commit 95932e98e5

mlugg <mlugg@mlugg.co.uk>
2025-03-16 04:26:29
Sema: fix alignment of runtime field pointer of underaligned tuple
1 parent d4c5396
Changed files (2)
src
test
behavior
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);
+            },
         },
     });
 
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();
+}