mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 23:52:31 +00:00
type: correct condition for eliding pointer alignment canonicalization
Closes #14373
This commit is contained in:
parent
d284c00fda
commit
a492a607d5
40
src/type.zig
40
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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user