mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 22:35:24 +00:00
Sema: preserve extern struct field alignment
In
extern struct { x: u32, y: u16 }
we actually know that y's alignment is `@alignOf(u32)`, and not just
`@alignOf(u16)`.
closes: #16134
This commit is contained in:
parent
28f515acd7
commit
4620972d08
@ -316,7 +316,7 @@ pub const Ip6Address = extern struct {
|
||||
.addr = undefined,
|
||||
},
|
||||
};
|
||||
var ip_slice = result.sa.addr[0..];
|
||||
var ip_slice: *[16]u8 = result.sa.addr[0..];
|
||||
|
||||
var tail: [16]u8 = undefined;
|
||||
|
||||
@ -431,7 +431,7 @@ pub const Ip6Address = extern struct {
|
||||
.addr = undefined,
|
||||
},
|
||||
};
|
||||
var ip_slice = result.sa.addr[0..];
|
||||
var ip_slice: *[16]u8 = result.sa.addr[0..];
|
||||
|
||||
var tail: [16]u8 = undefined;
|
||||
|
||||
|
||||
10
src/Sema.zig
10
src/Sema.zig
@ -25926,9 +25926,13 @@ fn structFieldPtrByIndex(
|
||||
ptr_ty_data.packed_offset = .{ .host_size = 0, .bit_offset = 0 };
|
||||
}
|
||||
}
|
||||
} else if (struct_obj.layout == .Extern and field_index == 0) {
|
||||
// This is the first field in memory, so can inherit the struct alignment
|
||||
ptr_ty_data.flags.alignment = Alignment.fromByteUnits(parent_align);
|
||||
} else if (struct_obj.layout == .Extern) {
|
||||
// For extern structs, field aligment might be bigger than type's natural alignment. Eg, in
|
||||
// `extern struct { x: u32, y: u16 }` the second field is aligned as u32.
|
||||
const field_offset = struct_ty.structFieldOffset(field_index, mod);
|
||||
ptr_ty_data.flags.alignment = Alignment.fromByteUnits(
|
||||
if (parent_align == 0) 0 else std.math.gcd(field_offset, parent_align),
|
||||
);
|
||||
} else {
|
||||
// Our alignment is capped at the field alignment
|
||||
const field_align = try sema.structFieldAlignment(field, struct_obj.layout);
|
||||
|
||||
@ -1680,9 +1680,9 @@ test "extern struct field pointer has correct alignment" {
|
||||
|
||||
const S = struct {
|
||||
fn doTheTest() !void {
|
||||
var a: extern struct { x: u32, y: u32 } = .{ .x = 1, .y = 2 };
|
||||
var b: extern struct { x: u32, y: u32 } align(1) = .{ .x = 3, .y = 4 };
|
||||
var c: extern struct { x: u32, y: u32 } align(64) = .{ .x = 5, .y = 6 };
|
||||
var a: extern struct { x: u32, y: u16 } = .{ .x = 1, .y = 2 };
|
||||
var b: extern struct { x: u32, y: u16 } align(1) = .{ .x = 3, .y = 4 };
|
||||
var c: extern struct { x: u32, y: u16 } align(64) = .{ .x = 5, .y = 6 };
|
||||
|
||||
const axp = &a.x;
|
||||
const bxp = &b.x;
|
||||
@ -1693,18 +1693,19 @@ test "extern struct field pointer has correct alignment" {
|
||||
|
||||
comptime assert(@TypeOf(axp) == *u32);
|
||||
comptime assert(@TypeOf(bxp) == *align(1) u32);
|
||||
comptime assert(@TypeOf(cxp) == *align(64) u32); // first field, inherits larger alignment
|
||||
comptime assert(@TypeOf(ayp) == *u32);
|
||||
comptime assert(@TypeOf(byp) == *align(1) u32);
|
||||
comptime assert(@TypeOf(cyp) == *u32);
|
||||
comptime assert(@TypeOf(cxp) == *align(64) u32);
|
||||
|
||||
comptime assert(@TypeOf(ayp) == *align(@alignOf(u32)) u16);
|
||||
comptime assert(@TypeOf(byp) == *align(1) u16);
|
||||
comptime assert(@TypeOf(cyp) == *align(@alignOf(u32)) u16);
|
||||
|
||||
try expectEqual(@as(u32, 1), axp.*);
|
||||
try expectEqual(@as(u32, 3), bxp.*);
|
||||
try expectEqual(@as(u32, 5), cxp.*);
|
||||
|
||||
try expectEqual(@as(u32, 2), ayp.*);
|
||||
try expectEqual(@as(u32, 4), byp.*);
|
||||
try expectEqual(@as(u32, 6), cyp.*);
|
||||
try expectEqual(@as(u16, 2), ayp.*);
|
||||
try expectEqual(@as(u16, 4), byp.*);
|
||||
try expectEqual(@as(u16, 6), cyp.*);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user