Skip to content

Commit a492a60

Browse files
committed
type: correct condition for eliding pointer alignment canonicalization
Closes #14373
1 parent d284c00 commit a492a60

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed

src/type.zig

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3789,6 +3789,39 @@ pub const Type = extern union {
37893789
}
37903790
}
37913791

3792+
/// Returns true if the type's layout is already resolved and it is safe
3793+
/// to use `abiSize`, `abiAlignment` and `bitSize` on it.
3794+
pub fn layoutIsResolved(ty: Type) bool {
3795+
switch (ty.zigTypeTag()) {
3796+
.Struct => {
3797+
if (ty.castTag(.@"struct")) |struct_ty| {
3798+
return struct_ty.data.haveLayout();
3799+
}
3800+
return true;
3801+
},
3802+
.Union => {
3803+
if (ty.cast(Payload.Union)) |union_ty| {
3804+
return union_ty.data.haveLayout();
3805+
}
3806+
return true;
3807+
},
3808+
.Array => {
3809+
if (ty.arrayLenIncludingSentinel() == 0) return true;
3810+
return ty.childType().layoutIsResolved();
3811+
},
3812+
.Optional => {
3813+
var buf: Type.Payload.ElemType = undefined;
3814+
const payload_ty = ty.optionalChild(&buf);
3815+
return payload_ty.layoutIsResolved();
3816+
},
3817+
.ErrorUnion => {
3818+
const payload_ty = ty.errorUnionPayload();
3819+
return payload_ty.layoutIsResolved();
3820+
},
3821+
else => return true,
3822+
}
3823+
}
3824+
37923825
pub fn isSinglePointer(self: Type) bool {
37933826
return switch (self.tag()) {
37943827
.single_const_pointer,
@@ -6498,12 +6531,7 @@ pub const Type = extern union {
64986531
// pointee type needs to be resolved more, that needs to be done before calling
64996532
// this ptr() function.
65006533
if (d.@"align" != 0) canonicalize: {
6501-
if (d.pointee_type.castTag(.@"struct")) |struct_ty| {
6502-
if (!struct_ty.data.haveLayout()) break :canonicalize;
6503-
}
6504-
if (d.pointee_type.cast(Payload.Union)) |union_ty| {
6505-
if (!union_ty.data.haveLayout()) break :canonicalize;
6506-
}
6534+
if (!d.pointee_type.layoutIsResolved()) break :canonicalize;
65076535
if (d.@"align" == d.pointee_type.abiAlignment(target)) {
65086536
d.@"align" = 0;
65096537
}

test/behavior/pointers.zig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -532,3 +532,18 @@ test "pointer alignment and element type include call expression" {
532532
};
533533
try expect(@alignOf(S.P) > 0);
534534
}
535+
536+
test "pointer to array has explicit alignment" {
537+
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
538+
539+
const S = struct {
540+
const Base = extern struct { a: u8 };
541+
const Base2 = extern struct { a: u8 };
542+
fn func(ptr: *[4]Base) *align(1) [4]Base2 {
543+
return @alignCast(1, @ptrCast(*[4]Base2, ptr));
544+
}
545+
};
546+
var bases = [_]S.Base{.{ .a = 2 }} ** 4;
547+
const casted = S.func(&bases);
548+
try expect(casted[0].a == 2);
549+
}

0 commit comments

Comments
 (0)