master
1const std = @import("std");
2const builtin = @import("builtin");
3const assert = std.debug.assert;
4const expectEqual = std.testing.expectEqual;
5
6test "flags in packed union" {
7 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
9 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
10 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
11 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
12
13 try testFlagsInPackedUnion();
14 try comptime testFlagsInPackedUnion();
15}
16
17fn testFlagsInPackedUnion() !void {
18 const FlagBits = packed struct(u8) {
19 enable_1: bool = false,
20 enable_2: bool = false,
21 enable_3: bool = false,
22 enable_4: bool = false,
23 other_flags: packed union {
24 flags: packed struct(u4) {
25 enable_1: bool = true,
26 enable_2: bool = false,
27 enable_3: bool = false,
28 enable_4: bool = false,
29 },
30 bits: u4,
31 } = .{ .flags = .{} },
32 };
33 var test_bits: FlagBits = .{};
34
35 try expectEqual(false, test_bits.enable_1);
36 try expectEqual(true, test_bits.other_flags.flags.enable_1);
37
38 test_bits.enable_1 = true;
39
40 try expectEqual(true, test_bits.enable_1);
41 try expectEqual(true, test_bits.other_flags.flags.enable_1);
42
43 test_bits.other_flags.flags.enable_1 = false;
44
45 try expectEqual(true, test_bits.enable_1);
46 try expectEqual(false, test_bits.other_flags.flags.enable_1);
47}
48
49test "flags in packed union at offset" {
50 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
51 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
52 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
53 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
54 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO
55
56 try testFlagsInPackedUnionAtOffset();
57 try comptime testFlagsInPackedUnionAtOffset();
58}
59
60fn testFlagsInPackedUnionAtOffset() !void {
61 const FlagBits = packed union {
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,
71 },
72 pad: u8 = 0,
73 },
74 adv_flags: packed struct(u12) {
75 pad: u8 = 0,
76 adv: packed union {
77 flags: packed struct(u4) {
78 enable_1: bool = true,
79 enable_2: bool = false,
80 enable_3: bool = false,
81 enable_4: bool = false,
82 },
83 bits: u4,
84 },
85 },
86 };
87 var test_bits: FlagBits = .{ .adv_flags = .{ .adv = .{ .flags = .{} } } };
88
89 try expectEqual(@as(u8, 0), test_bits.adv_flags.pad);
90 try expectEqual(true, test_bits.adv_flags.adv.flags.enable_1);
91 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_2);
92
93 test_bits.adv_flags.adv.flags.enable_1 = false;
94 test_bits.adv_flags.adv.flags.enable_2 = true;
95 try expectEqual(@as(u8, 0), test_bits.adv_flags.pad);
96 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_1);
97 try expectEqual(true, test_bits.adv_flags.adv.flags.enable_2);
98
99 test_bits.adv_flags.adv.bits = 12;
100 try expectEqual(@as(u8, 0), test_bits.adv_flags.pad);
101 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_1);
102 try expectEqual(false, test_bits.adv_flags.adv.flags.enable_2);
103}
104
105// Originally reported at https://github.com/ziglang/zig/issues/16581
106test "packed union in packed struct" {
107 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
108 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
109 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
110
111 try testPackedUnionInPackedStruct();
112 try comptime testPackedUnionInPackedStruct();
113}
114
115fn testPackedUnionInPackedStruct() !void {
116 const ReadRequest = packed struct { key: i32 };
117 const RequestType = enum(u1) {
118 read,
119 insert,
120 };
121 const RequestUnion = packed union {
122 read: ReadRequest,
123 };
124
125 const Request = packed struct {
126 active_type: RequestType,
127 request: RequestUnion,
128 const Self = @This();
129
130 fn init(read: ReadRequest) Self {
131 return .{
132 .active_type = .read,
133 .request = RequestUnion{ .read = read },
134 };
135 }
136 };
137
138 try std.testing.expectEqual(RequestType.read, Request.init(.{ .key = 3 }).active_type);
139}
140
141test "packed union initialized with a runtime value" {
142 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
143 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
144 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
145 if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest;
146 if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
147
148 const Fields = packed struct {
149 timestamp: u50,
150 random_bits: u13,
151 };
152 const ID = packed union {
153 value: u63,
154 fields: Fields,
155
156 fn getValue() i64 {
157 return 1341;
158 }
159 };
160
161 const timestamp: i64 = ID.getValue();
162 const id = ID{ .fields = Fields{
163 .timestamp = @as(u50, @intCast(timestamp)),
164 .random_bits = 420,
165 } };
166 try std.testing.expect((ID{ .value = id.value }).fields.timestamp == timestamp);
167}
168
169test "assigning to non-active field at comptime" {
170 comptime {
171 const FlagBits = packed union {
172 flags: packed struct {},
173 bits: packed struct {},
174 };
175
176 var test_bits: FlagBits = .{ .flags = .{} };
177 test_bits.bits = .{};
178 }
179}
180
181test "comptime packed union of pointers" {
182 const U = packed union {
183 a: *const u32,
184 b: *const [1]u32,
185 };
186
187 const x: u32 = 123;
188 const u: U = .{ .a = &x };
189
190 comptime assert(u.b[0] == 123);
191}