| ... | ... | @@ -223,7 +223,7 @@ test "packed union generates correctly aligned type" { |
| 223 | 223 | |
| 224 | 224 | const U = packed union { |
| 225 | 225 | f1: *const fn () error{TestUnexpectedResult}!void, |
| 226 | | f2: u32, |
| 226 | f2: usize, |
| 227 | 227 | }; |
| 228 | 228 | var foo = [_]U{ |
| 229 | 229 | U{ .f1 = doTest }, |
| ... | ... | @@ -356,10 +356,10 @@ test "simple union(enum(u32))" { |
| 356 | 356 | |
| 357 | 357 | const PackedPtrOrInt = packed union { |
| 358 | 358 | ptr: *u8, |
| 359 | | int: u64, |
| 359 | int: usize, |
| 360 | 360 | }; |
| 361 | 361 | test "packed union size" { |
| 362 | | comptime assert(@sizeOf(PackedPtrOrInt) == 8); |
| 362 | comptime assert(@sizeOf(PackedPtrOrInt) == @sizeOf(usize)); |
| 363 | 363 | } |
| 364 | 364 | |
| 365 | 365 | const ZeroBits = union { |
| ... | ... | @@ -1337,7 +1337,7 @@ test "packed union in packed struct" { |
| 1337 | 1337 | |
| 1338 | 1338 | const S = packed struct { |
| 1339 | 1339 | nested: packed union { |
| 1340 | | val: u16, |
| 1340 | val: u32, |
| 1341 | 1341 | foo: u32, |
| 1342 | 1342 | }, |
| 1343 | 1343 | bar: u16, |
| ... | ... | @@ -1415,25 +1415,6 @@ test "union reassignment can use previous value" { |
| 1415 | 1415 | try expect(a.b == 32); |
| 1416 | 1416 | } |
| 1417 | 1417 | |
| 1418 | | test "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 | | |
| 1437 | 1418 | test "reinterpreting enum value inside packed union" { |
| 1438 | 1419 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1439 | 1420 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1632,15 +1613,15 @@ test "memset packed union" { |
| 1632 | 1613 | |
| 1633 | 1614 | const U = packed union { |
| 1634 | 1615 | a: u32, |
| 1635 | | b: u8, |
| 1616 | b: u32, |
| 1636 | 1617 | }; |
| 1637 | 1618 | |
| 1638 | 1619 | const S = struct { |
| 1639 | 1620 | fn doTheTest() !void { |
| 1640 | 1621 | var u: U = undefined; |
| 1641 | | @memset(std.mem.asBytes(&u), 42); |
| 1622 | @memset(@as([]u8, @ptrCast(&u)), 42); |
| 1642 | 1623 | try expectEqual(@as(u32, 0x2a2a2a2a), u.a); |
| 1643 | | try expectEqual(@as(u8, 0x2a), u.b); |
| 1624 | try expectEqual(@as(u32, 0x2a2a2a2a), u.b); |
| 1644 | 1625 | } |
| 1645 | 1626 | }; |
| 1646 | 1627 | |
| ... | ... | @@ -1732,10 +1713,19 @@ test "reinterpret packed union" { |
| 1732 | 1713 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1733 | 1714 | |
| 1734 | 1715 | 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 | }, |
| 1737 | 1724 | baz: u64, |
| 1738 | | qux: u12, |
| 1725 | qux: packed struct(u64) { |
| 1726 | a: u12, |
| 1727 | b: u52, |
| 1728 | }, |
| 1739 | 1729 | }; |
| 1740 | 1730 | |
| 1741 | 1731 | const S = struct { |
| ... | ... | @@ -1745,16 +1735,16 @@ test "reinterpret packed union" { |
| 1745 | 1735 | var u: U = undefined; |
| 1746 | 1736 | @memset(std.mem.asBytes(&u), 0); |
| 1747 | 1737 | u.baz = 0xbbbbbbbb; |
| 1748 | | u.qux = 0xe2a; |
| 1738 | u.qux.a = 0xe2a; |
| 1749 | 1739 | break :blk u; |
| 1750 | 1740 | }; |
| 1751 | 1741 | |
| 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); |
| 1754 | 1744 | |
| 1755 | 1745 | // https://github.com/ziglang/zig/issues/17360 |
| 1756 | 1746 | if (@inComptime()) { |
| 1757 | | try expectEqual(@as(u29, 0x1bbbbe2a), u.bar); |
| 1747 | try expectEqual(@as(u29, 0x1bbbbe2a), u.bar.a); |
| 1758 | 1748 | try expectEqual(@as(u64, 0xbbbbbe2a), u.baz); |
| 1759 | 1749 | } |
| 1760 | 1750 | } |
| ... | ... | @@ -1762,31 +1752,31 @@ test "reinterpret packed union" { |
| 1762 | 1752 | { |
| 1763 | 1753 | // Union initialization |
| 1764 | 1754 | 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); |
| 1769 | 1759 | try expectEqual(@as(u64, 0xe2a), u.baz & 0xfff); |
| 1770 | 1760 | |
| 1771 | 1761 | // Writing to a larger field |
| 1772 | 1762 | 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); |
| 1776 | 1766 | try expectEqual(@as(u64, 0xbbbbbbbb), u.baz); |
| 1777 | 1767 | |
| 1778 | 1768 | // Writing to the same field |
| 1779 | 1769 | 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); |
| 1783 | 1773 | try expectEqual(@as(u64, 0xcccccccc), u.baz); |
| 1784 | 1774 | |
| 1785 | 1775 | // 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); |
| 1790 | 1780 | try expectEqual(@as(u64, 0xccccccdd), u.baz); |
| 1791 | 1781 | } |
| 1792 | 1782 | } |
| ... | ... | @@ -1807,7 +1797,10 @@ test "reinterpret packed union inside packed struct" { |
| 1807 | 1797 | |
| 1808 | 1798 | const U = packed union { |
| 1809 | 1799 | a: u7, |
| 1810 | | b: u1, |
| 1800 | b: packed struct(u7) { |
| 1801 | a: u1, |
| 1802 | b: u6, |
| 1803 | }, |
| 1811 | 1804 | }; |
| 1812 | 1805 | |
| 1813 | 1806 | const V = packed struct { |
| ... | ... | @@ -1818,18 +1811,18 @@ test "reinterpret packed union inside packed struct" { |
| 1818 | 1811 | const S = struct { |
| 1819 | 1812 | fn doTheTest() !void { |
| 1820 | 1813 | 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); |
| 1833 | 1826 | } |
| 1834 | 1827 | }; |
| 1835 | 1828 | |
| ... | ... | @@ -1869,8 +1862,9 @@ test "inner struct initializer uses packed union layout" { |
| 1869 | 1862 | a: packed struct { |
| 1870 | 1863 | x: u32 = @alignOf(U) + 1, |
| 1871 | 1864 | }, |
| 1872 | | b: packed struct { |
| 1865 | b: packed struct(u32) { |
| 1873 | 1866 | y: u16 = @sizeOf(U) + 2, |
| 1867 | padding: u16 = 0, |
| 1874 | 1868 | }, |
| 1875 | 1869 | }; |
| 1876 | 1870 | }; |
| ... | ... | @@ -1898,7 +1892,7 @@ test "extern union initialized via reintepreted struct field initializer" { |
| 1898 | 1892 | }; |
| 1899 | 1893 | |
| 1900 | 1894 | const S = extern struct { |
| 1901 | | u: U = std.mem.bytesAsValue(U, &bytes).*, |
| 1895 | u: U = @as(*align(1) const U, @ptrCast(&bytes)).*, |
| 1902 | 1896 | }; |
| 1903 | 1897 | |
| 1904 | 1898 | const s: S = .{}; |
| ... | ... | @@ -1913,17 +1907,20 @@ test "packed union initialized via reintepreted struct field initializer" { |
| 1913 | 1907 | |
| 1914 | 1908 | const U = packed union { |
| 1915 | 1909 | a: u32, |
| 1916 | | b: u8, |
| 1910 | b: packed struct(u32) { |
| 1911 | a: u8, |
| 1912 | b: u24, |
| 1913 | }, |
| 1917 | 1914 | }; |
| 1918 | 1915 | |
| 1919 | 1916 | const S = packed struct { |
| 1920 | | u: U = std.mem.bytesAsValue(U, &bytes).*, |
| 1917 | u: U = @as(*align(1) const U, @ptrCast(&bytes)).*, |
| 1921 | 1918 | }; |
| 1922 | 1919 | |
| 1923 | 1920 | var s: S = .{}; |
| 1924 | 1921 | _ = &s; |
| 1925 | 1922 | 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); |
| 1927 | 1924 | } |
| 1928 | 1925 | |
| 1929 | 1926 | test "store of comptime reinterpreted memory to extern union" { |
| ... | ... | @@ -1938,7 +1935,7 @@ test "store of comptime reinterpreted memory to extern union" { |
| 1938 | 1935 | |
| 1939 | 1936 | const reinterpreted = comptime b: { |
| 1940 | 1937 | var u: U = undefined; |
| 1941 | | u = std.mem.bytesAsValue(U, &bytes).*; |
| 1938 | u = @as(*align(1) const U, @ptrCast(&bytes)).*; |
| 1942 | 1939 | break :b u; |
| 1943 | 1940 | }; |
| 1944 | 1941 | |
| ... | ... | @@ -1955,19 +1952,22 @@ test "store of comptime reinterpreted memory to packed union" { |
| 1955 | 1952 | |
| 1956 | 1953 | const U = packed union { |
| 1957 | 1954 | a: u32, |
| 1958 | | b: u8, |
| 1955 | b: packed struct(u32) { |
| 1956 | a: u8, |
| 1957 | b: u24, |
| 1958 | }, |
| 1959 | 1959 | }; |
| 1960 | 1960 | |
| 1961 | 1961 | const reinterpreted = comptime b: { |
| 1962 | 1962 | var u: U = undefined; |
| 1963 | | u = std.mem.bytesAsValue(U, &bytes).*; |
| 1963 | u = @as(*align(1) const U, @ptrCast(&bytes)).*; |
| 1964 | 1964 | break :b u; |
| 1965 | 1965 | }; |
| 1966 | 1966 | |
| 1967 | 1967 | var u: U = reinterpreted; |
| 1968 | 1968 | _ = &u; |
| 1969 | 1969 | 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); |
| 1971 | 1971 | } |
| 1972 | 1972 | |
| 1973 | 1973 | test "union field is a pointer to an aligned version of itself" { |