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