authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-05 19:33:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-09-05 19:44:54-07:00
logb9a63433b71e8b07691da158a136d17e1f04c49b
treec85e546ff3d708bbdb290abeffbe8ec440d3e2b5
parent52c6d7a9290d7d6017208e23c6fbac1b8cfeecb8

behavior tests: update for new requirement

packed union fields must all have matching bit sizes

6 files changed, 117 insertions(+), 93 deletions(-)

test/behavior/cast_int.zig+14-8
......@@ -225,20 +225,26 @@ test "load non byte-sized value in union" {
225225 // using ptrCast not to depend on unitialised memory state
226226
227227 var union0: packed union {
228 p: Piece,
228 p: packed struct(u8) {
229 a: Piece,
230 b: u4,
231 },
229232 int: u8,
230233 } = .{ .int = 0 };
231234 union0.int = 0b11111011;
232 try expect(union0.p.type == .PAWN);
233 try expect(union0.p.color == .BLACK);
235 try expect(union0.p.a.type == .PAWN);
236 try expect(union0.p.a.color == .BLACK);
234237
235238 var union1: union {
236 p: Piece,
239 p: packed struct(u8) {
240 a: Piece,
241 b: u4,
242 },
237243 int: u8,
238 } = .{ .p = .{ .color = .WHITE, .type = .KING } };
239 @as(*u8, @ptrCast(&union1.p)).* = 0b11111011;
240 try expect(union1.p.type == .PAWN);
241 try expect(union1.p.color == .BLACK);
244 } = .{ .p = .{ .a = .{ .color = .WHITE, .type = .KING }, .b = 0 } };
245 @as(*u8, @ptrCast(&union1.p.a)).* = 0b11111011;
246 try expect(union1.p.a.type == .PAWN);
247 try expect(union1.p.a.color == .BLACK);
242248
243249 var pieces: [3]Piece = undefined;
244250 @as(*u8, @ptrCast(&pieces[1])).* = 0b11111011;
test/behavior/export_keyword.zig+5-2
......@@ -19,7 +19,10 @@ const PackedStruct = packed struct {
1919 b: u8,
2020};
2121const PackedUnion = packed union {
22 a: u8,
22 a: packed struct(u32) {
23 a: u8,
24 b: u24 = 0,
25 },
2326 b: u32,
2427};
2528
......@@ -29,7 +32,7 @@ test "packed struct, enum, union parameters in extern function" {
2932 testPackedStuff(&(PackedStruct{
3033 .a = 1,
3134 .b = 2,
32 }), &(PackedUnion{ .a = 1 }));
35 }), &(PackedUnion{ .a = .{ .a = 1 } }));
3336}
3437
3538export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
test/behavior/field_parent_ptr.zig+12-6
......@@ -1758,27 +1758,33 @@ test "@fieldParentPtr packed union" {
17581758 if (builtin.target.cpu.arch.endian() == .big) return error.SkipZigTest; // TODO
17591759
17601760 const C = packed union {
1761 a: bool,
1761 a: packed struct(u32) {
1762 a: bool,
1763 b: u31 = 0,
1764 },
17621765 b: f32,
1763 c: packed struct { x: u8 },
1766 c: packed struct(u32) {
1767 x: u8,
1768 b: u24 = 0,
1769 },
17641770 d: i32,
17651771 };
17661772
17671773 {
1768 const c: C = .{ .a = false };
1774 const c: C = .{ .a = .{ .a = false } };
17691775 const pcf = &c.a;
17701776 const pc: *const C = @alignCast(@fieldParentPtr("a", pcf));
17711777 try expect(pc == &c);
17721778 }
17731779 {
1774 const c: C = .{ .a = false };
1780 const c: C = .{ .a = .{ .a = false } };
17751781 const pcf = &c.a;
17761782 var pc: *const C = undefined;
17771783 pc = @alignCast(@fieldParentPtr("a", pcf));
17781784 try expect(pc == &c);
17791785 }
17801786 {
1781 const c: C = .{ .a = false };
1787 const c: C = .{ .a = .{ .a = false } };
17821788 var pcf: @TypeOf(&c.a) = undefined;
17831789 pcf = &c.a;
17841790 var pc: *const C = undefined;
......@@ -1787,7 +1793,7 @@ test "@fieldParentPtr packed union" {
17871793 }
17881794 {
17891795 var c: C = undefined;
1790 c = .{ .a = false };
1796 c = .{ .a = .{ .a = false } };
17911797 var pcf: @TypeOf(&c.a) = undefined;
17921798 pcf = &c.a;
17931799 var pc: *C = undefined;
test/behavior/packed-struct.zig+7-1
......@@ -1223,7 +1223,13 @@ test "load flag from packed struct in union" {
12231223test "bitcasting a packed struct at comptime and using the result" {
12241224 comptime {
12251225 const Struct = packed struct {
1226 x: packed union { a: u63, b: i32 },
1226 x: packed union {
1227 a: u63,
1228 b: packed struct(u63) {
1229 a: i32,
1230 b: u31 = 0,
1231 },
1232 },
12271233 y: u1,
12281234
12291235 pub fn bitcast(fd: u64) @This() {
test/behavior/packed-union.zig+10-7
......@@ -59,14 +59,17 @@ test "flags in packed union at offset" {
5959
6060fn testFlagsInPackedUnionAtOffset() !void {
6161 const FlagBits = packed union {
62 base_flags: packed union {
63 flags: packed struct(u4) {
64 enable_1: bool = true,
65 enable_2: bool = false,
66 enable_3: bool = false,
67 enable_4: bool = false,
62 base_flags: packed struct(u12) {
63 a: packed union {
64 flags: packed struct(u4) {
65 enable_1: bool = true,
66 enable_2: bool = false,
67 enable_3: bool = false,
68 enable_4: bool = false,
69 },
70 bits: u4,
6871 },
69 bits: u4,
72 pad: u8 = 0,
7073 },
7174 adv_flags: packed struct(u12) {
7275 pad: u8 = 0,
test/behavior/union.zig+69-69
......@@ -223,7 +223,7 @@ test "packed union generates correctly aligned type" {
223223
224224 const U = packed union {
225225 f1: *const fn () error{TestUnexpectedResult}!void,
226 f2: u32,
226 f2: usize,
227227 };
228228 var foo = [_]U{
229229 U{ .f1 = doTest },
......@@ -356,10 +356,10 @@ test "simple union(enum(u32))" {
356356
357357const PackedPtrOrInt = packed union {
358358 ptr: *u8,
359 int: u64,
359 int: usize,
360360};
361361test "packed union size" {
362 comptime assert(@sizeOf(PackedPtrOrInt) == 8);
362 comptime assert(@sizeOf(PackedPtrOrInt) == @sizeOf(usize));
363363}
364364
365365const ZeroBits = union {
......@@ -1337,7 +1337,7 @@ test "packed union in packed struct" {
13371337
13381338 const S = packed struct {
13391339 nested: packed union {
1340 val: u16,
1340 val: u32,
13411341 foo: u32,
13421342 },
13431343 bar: u16,
......@@ -1415,25 +1415,6 @@ test "union reassignment can use previous value" {
14151415 try expect(a.b == 32);
14161416}
14171417
1418test "packed union with zero-bit field" {
1419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1421 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1422
1423 const S = packed struct {
1424 nested: packed union {
1425 zero: void,
1426 sized: u32,
1427 },
1428 bar: u32,
1429
1430 fn doTest(self: @This()) !void {
1431 try expect(self.bar == 42);
1432 }
1433 };
1434 try S.doTest(.{ .nested = .{ .zero = {} }, .bar = 42 });
1435}
1436
14371418test "reinterpreting enum value inside packed union" {
14381419 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
14391420 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
......@@ -1632,15 +1613,15 @@ test "memset packed union" {
16321613
16331614 const U = packed union {
16341615 a: u32,
1635 b: u8,
1616 b: u32,
16361617 };
16371618
16381619 const S = struct {
16391620 fn doTheTest() !void {
16401621 var u: U = undefined;
1641 @memset(std.mem.asBytes(&u), 42);
1622 @memset(@as([]u8, @ptrCast(&u)), 42);
16421623 try expectEqual(@as(u32, 0x2a2a2a2a), u.a);
1643 try expectEqual(@as(u8, 0x2a), u.b);
1624 try expectEqual(@as(u32, 0x2a2a2a2a), u.b);
16441625 }
16451626 };
16461627
......@@ -1732,10 +1713,19 @@ test "reinterpret packed union" {
17321713 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
17331714
17341715 const U = packed union {
1735 foo: u8,
1736 bar: u29,
1716 foo: packed struct(u64) {
1717 a: u8,
1718 b: u56,
1719 },
1720 bar: packed struct(u64) {
1721 a: u29,
1722 b: u35,
1723 },
17371724 baz: u64,
1738 qux: u12,
1725 qux: packed struct(u64) {
1726 a: u12,
1727 b: u52,
1728 },
17391729 };
17401730
17411731 const S = struct {
......@@ -1745,16 +1735,16 @@ test "reinterpret packed union" {
17451735 var u: U = undefined;
17461736 @memset(std.mem.asBytes(&u), 0);
17471737 u.baz = 0xbbbbbbbb;
1748 u.qux = 0xe2a;
1738 u.qux.a = 0xe2a;
17491739 break :blk u;
17501740 };
17511741
1752 try expectEqual(@as(u8, 0x2a), u.foo);
1753 try expectEqual(@as(u12, 0xe2a), u.qux);
1742 try expectEqual(@as(u8, 0x2a), u.foo.a);
1743 try expectEqual(@as(u12, 0xe2a), u.qux.a);
17541744
17551745 // https://github.com/ziglang/zig/issues/17360
17561746 if (@inComptime()) {
1757 try expectEqual(@as(u29, 0x1bbbbe2a), u.bar);
1747 try expectEqual(@as(u29, 0x1bbbbe2a), u.bar.a);
17581748 try expectEqual(@as(u64, 0xbbbbbe2a), u.baz);
17591749 }
17601750 }
......@@ -1762,31 +1752,31 @@ test "reinterpret packed union" {
17621752 {
17631753 // Union initialization
17641754 var u: U = .{ .baz = 0 }; // ensure all bits are defined
1765 u.qux = 0xe2a;
1766 try expectEqual(@as(u8, 0x2a), u.foo);
1767 try expectEqual(@as(u12, 0xe2a), u.qux);
1768 try expectEqual(@as(u29, 0xe2a), u.bar & 0xfff);
1755 u.qux.a = 0xe2a;
1756 try expectEqual(@as(u8, 0x2a), u.foo.a);
1757 try expectEqual(@as(u12, 0xe2a), u.qux.a);
1758 try expectEqual(@as(u29, 0xe2a), u.bar.a & 0xfff);
17691759 try expectEqual(@as(u64, 0xe2a), u.baz & 0xfff);
17701760
17711761 // Writing to a larger field
17721762 u.baz = 0xbbbbbbbb;
1773 try expectEqual(@as(u8, 0xbb), u.foo);
1774 try expectEqual(@as(u12, 0xbbb), u.qux);
1775 try expectEqual(@as(u29, 0x1bbbbbbb), u.bar);
1763 try expectEqual(@as(u8, 0xbb), u.foo.a);
1764 try expectEqual(@as(u12, 0xbbb), u.qux.a);
1765 try expectEqual(@as(u29, 0x1bbbbbbb), u.bar.a);
17761766 try expectEqual(@as(u64, 0xbbbbbbbb), u.baz);
17771767
17781768 // Writing to the same field
17791769 u.baz = 0xcccccccc;
1780 try expectEqual(@as(u8, 0xcc), u.foo);
1781 try expectEqual(@as(u12, 0xccc), u.qux);
1782 try expectEqual(@as(u29, 0x0ccccccc), u.bar);
1770 try expectEqual(@as(u8, 0xcc), u.foo.a);
1771 try expectEqual(@as(u12, 0xccc), u.qux.a);
1772 try expectEqual(@as(u29, 0x0ccccccc), u.bar.a);
17831773 try expectEqual(@as(u64, 0xcccccccc), u.baz);
17841774
17851775 // Writing to a smaller field
1786 u.foo = 0xdd;
1787 try expectEqual(@as(u8, 0xdd), u.foo);
1788 try expectEqual(@as(u12, 0xcdd), u.qux);
1789 try expectEqual(@as(u29, 0x0cccccdd), u.bar);
1776 u.foo.a = 0xdd;
1777 try expectEqual(@as(u8, 0xdd), u.foo.a);
1778 try expectEqual(@as(u12, 0xcdd), u.qux.a);
1779 try expectEqual(@as(u29, 0x0cccccdd), u.bar.a);
17901780 try expectEqual(@as(u64, 0xccccccdd), u.baz);
17911781 }
17921782 }
......@@ -1807,7 +1797,10 @@ test "reinterpret packed union inside packed struct" {
18071797
18081798 const U = packed union {
18091799 a: u7,
1810 b: u1,
1800 b: packed struct(u7) {
1801 a: u1,
1802 b: u6,
1803 },
18111804 };
18121805
18131806 const V = packed struct {
......@@ -1818,18 +1811,18 @@ test "reinterpret packed union inside packed struct" {
18181811 const S = struct {
18191812 fn doTheTest() !void {
18201813 var v: V = undefined;
1821 @memset(std.mem.asBytes(&v), 0x55);
1822 try expectEqual(@as(u7, 0x55), v.lo.a);
1823 try expectEqual(@as(u1, 1), v.lo.b);
1824 try expectEqual(@as(u7, 0x2a), v.hi.a);
1825 try expectEqual(@as(u1, 0), v.hi.b);
1826
1827 v.lo.b = 0;
1828 try expectEqual(@as(u7, 0x54), v.lo.a);
1829 try expectEqual(@as(u1, 0), v.lo.b);
1830 v.hi.b = 1;
1831 try expectEqual(@as(u7, 0x2b), v.hi.a);
1832 try expectEqual(@as(u1, 1), v.hi.b);
1814 @memset(@as([]u8, @ptrCast(&v)), 0x55);
1815 try expect(@as(u7, 0x55) == v.lo.a);
1816 try expect(@as(u1, 1) == v.lo.b.a);
1817 try expect(@as(u7, 0x2a) == v.hi.a);
1818 try expect(@as(u1, 0) == v.hi.b.a);
1819
1820 v.lo.b.a = 0;
1821 try expect(@as(u7, 0x54) == v.lo.a);
1822 try expect(@as(u1, 0) == v.lo.b.a);
1823 v.hi.b.a = 1;
1824 try expect(@as(u7, 0x2b) == v.hi.a);
1825 try expect(@as(u1, 1) == v.hi.b.a);
18331826 }
18341827 };
18351828
......@@ -1869,8 +1862,9 @@ test "inner struct initializer uses packed union layout" {
18691862 a: packed struct {
18701863 x: u32 = @alignOf(U) + 1,
18711864 },
1872 b: packed struct {
1865 b: packed struct(u32) {
18731866 y: u16 = @sizeOf(U) + 2,
1867 padding: u16 = 0,
18741868 },
18751869 };
18761870 };
......@@ -1898,7 +1892,7 @@ test "extern union initialized via reintepreted struct field initializer" {
18981892 };
18991893
19001894 const S = extern struct {
1901 u: U = std.mem.bytesAsValue(U, &bytes).*,
1895 u: U = @as(*align(1) const U, @ptrCast(&bytes)).*,
19021896 };
19031897
19041898 const s: S = .{};
......@@ -1913,17 +1907,20 @@ test "packed union initialized via reintepreted struct field initializer" {
19131907
19141908 const U = packed union {
19151909 a: u32,
1916 b: u8,
1910 b: packed struct(u32) {
1911 a: u8,
1912 b: u24,
1913 },
19171914 };
19181915
19191916 const S = packed struct {
1920 u: U = std.mem.bytesAsValue(U, &bytes).*,
1917 u: U = @as(*align(1) const U, @ptrCast(&bytes)).*,
19211918 };
19221919
19231920 var s: S = .{};
19241921 _ = &s;
19251922 try expect(s.u.a == littleToNativeEndian(u32, 0xddccbbaa));
1926 try expect(s.u.b == if (endian == .little) 0xaa else 0xdd);
1923 try expect(s.u.b.a == if (endian == .little) 0xaa else 0xdd);
19271924}
19281925
19291926test "store of comptime reinterpreted memory to extern union" {
......@@ -1938,7 +1935,7 @@ test "store of comptime reinterpreted memory to extern union" {
19381935
19391936 const reinterpreted = comptime b: {
19401937 var u: U = undefined;
1941 u = std.mem.bytesAsValue(U, &bytes).*;
1938 u = @as(*align(1) const U, @ptrCast(&bytes)).*;
19421939 break :b u;
19431940 };
19441941
......@@ -1955,19 +1952,22 @@ test "store of comptime reinterpreted memory to packed union" {
19551952
19561953 const U = packed union {
19571954 a: u32,
1958 b: u8,
1955 b: packed struct(u32) {
1956 a: u8,
1957 b: u24,
1958 },
19591959 };
19601960
19611961 const reinterpreted = comptime b: {
19621962 var u: U = undefined;
1963 u = std.mem.bytesAsValue(U, &bytes).*;
1963 u = @as(*align(1) const U, @ptrCast(&bytes)).*;
19641964 break :b u;
19651965 };
19661966
19671967 var u: U = reinterpreted;
19681968 _ = &u;
19691969 try expect(u.a == littleToNativeEndian(u32, 0xddccbbaa));
1970 try expect(u.b == if (endian == .little) 0xaa else 0xdd);
1970 try expect(u.b.a == if (endian == .little) 0xaa else 0xdd);
19711971}
19721972
19731973test "union field is a pointer to an aligned version of itself" {