Commit a492a607d5
Changed files (2)
src
test
behavior
src/type.zig
@@ -3789,6 +3789,39 @@ pub const Type = extern union {
}
}
+ /// Returns true if the type's layout is already resolved and it is safe
+ /// to use `abiSize`, `abiAlignment` and `bitSize` on it.
+ pub fn layoutIsResolved(ty: Type) bool {
+ switch (ty.zigTypeTag()) {
+ .Struct => {
+ if (ty.castTag(.@"struct")) |struct_ty| {
+ return struct_ty.data.haveLayout();
+ }
+ return true;
+ },
+ .Union => {
+ if (ty.cast(Payload.Union)) |union_ty| {
+ return union_ty.data.haveLayout();
+ }
+ return true;
+ },
+ .Array => {
+ if (ty.arrayLenIncludingSentinel() == 0) return true;
+ return ty.childType().layoutIsResolved();
+ },
+ .Optional => {
+ var buf: Type.Payload.ElemType = undefined;
+ const payload_ty = ty.optionalChild(&buf);
+ return payload_ty.layoutIsResolved();
+ },
+ .ErrorUnion => {
+ const payload_ty = ty.errorUnionPayload();
+ return payload_ty.layoutIsResolved();
+ },
+ else => return true,
+ }
+ }
+
pub fn isSinglePointer(self: Type) bool {
return switch (self.tag()) {
.single_const_pointer,
@@ -6498,12 +6531,7 @@ pub const Type = extern union {
// pointee type needs to be resolved more, that needs to be done before calling
// this ptr() function.
if (d.@"align" != 0) canonicalize: {
- if (d.pointee_type.castTag(.@"struct")) |struct_ty| {
- if (!struct_ty.data.haveLayout()) break :canonicalize;
- }
- if (d.pointee_type.cast(Payload.Union)) |union_ty| {
- if (!union_ty.data.haveLayout()) break :canonicalize;
- }
+ if (!d.pointee_type.layoutIsResolved()) break :canonicalize;
if (d.@"align" == d.pointee_type.abiAlignment(target)) {
d.@"align" = 0;
}
test/behavior/pointers.zig
@@ -532,3 +532,18 @@ test "pointer alignment and element type include call expression" {
};
try expect(@alignOf(S.P) > 0);
}
+
+test "pointer to array has explicit alignment" {
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+
+ const S = struct {
+ const Base = extern struct { a: u8 };
+ const Base2 = extern struct { a: u8 };
+ fn func(ptr: *[4]Base) *align(1) [4]Base2 {
+ return @alignCast(1, @ptrCast(*[4]Base2, ptr));
+ }
+ };
+ var bases = [_]S.Base{.{ .a = 2 }} ** 4;
+ const casted = S.func(&bases);
+ try expect(casted[0].a == 2);
+}