1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright (c) 2019, Joyent, Inc.
14 * Copyright 2025 Oxide Computer Company
15 */
16
17 #include <sys/types.h>
18 #include <complex.h>
19
20 /*
21 * Test various structure and union constructs, including various things that
22 * have caused regressions in the past.
23 */
24
25 /*
26 * Basic, simple struct.
27 */
28 struct foo {
29 int a;
30 float b;
31 const char *c;
32 };
33
34 struct foo foo;
35
36 /*
37 * Self-referential structs
38 */
39 struct node {
40 struct node *prev;
41 struct node *next;
42 };
43
44 typedef struct nlist {
45 size_t size;
46 size_t off;
47 struct node head;
48 } nlist_t;
49
50 nlist_t head;
51
52 /*
53 * Struct that has a forward declaration.
54 */
55 typedef struct forward forward_t;
56 struct forward {
57 void *past;
58 void *present;
59 void *future;
60 };
61
62 const forward_t forward;
63
64 /*
65 * Here, we have a pair of structures that basically round up to different
66 * sizes. As in, the size of the structure is somewhat compiler dependent.
67 */
68 struct round_up {
69 uint8_t triforce;
70 uint32_t link;
71 uint8_t zelda;
72 uint8_t ganon;
73 };
74
75 #pragma pack(1)
76 struct fixed_up {
77 uint8_t triforce;
78 uint32_t link;
79 uint8_t zelda;
80 uint8_t ganon;
81 };
82 #pragma pack()
83
84 struct round_up oot;
85 struct fixed_up botw;
86
87 /*
88 * Various GNU and c99 style arrays
89 */
90 enum material {
91 COPPER,
92 IRON,
93 STEEL,
94 ADAMANTIUM,
95 MYTHRIL,
96 ORIHALCUM
97 };
98
99 struct component {
100 enum material m;
101 uint64_t grade;
102 uint64_t count;
103 const char *locations[4];
104 };
105
106 struct mysterious_barrel {
107 const char *name;
108 size_t capacity;
109 struct component optional[];
110 };
111
112 struct dusk_barrel {
113 const char *name;
114 size_t opacity;
115 struct component optional[0];
116 };
117
118 struct mysterious_barrel sophie;
119 struct dusk_barrel ayesha;
120
121 /*
122 * Various bitfield forms.
123 */
124
125 /*
126 * Variant of the Intel system_desc.
127 */
128 struct stats {
129 uint64_t hp:16;
130 uint64_t mp:16;
131 uint64_t str:8;
132 uint64_t dex:4;
133 uint64_t con:1;
134 uint64_t inte:2;
135 uint64_t wis:1;
136 uint64_t cha:4;
137 uint64_t sanity:1;
138 uint64_t attack:2;
139 uint64_t mattack:1;
140 uint64_t defense:8;
141 uint64_t mdefense:32;
142 uint64_t evasion:8;
143 uint64_t crit:5;
144 uint64_t luck:19;
145 };
146
147 struct stats stats;
148
149 /*
150 * More odd length structures due to bitfields
151 */
152 struct fellowship {
153 uint16_t frodo:1;
154 uint16_t sam:1;
155 uint16_t merry:1;
156 uint16_t pippin:1;
157 uint16_t aragorn:1;
158 uint16_t boromir:1;
159 uint16_t legolas:1;
160 uint16_t gimli:1;
161 uint16_t gandalf:1;
162 };
163
164 struct fellowship ring;
165
166 struct rings {
167 uint32_t elves:3;
168 uint32_t dwarves:7;
169 uint32_t men:9;
170 uint8_t one;
171 uint8_t silmarils[3];
172 };
173
174 struct rings rings;
175
176 /*
177 * Regression, we didn't handle receiving a negative offset from DWARF with
178 * this.
179 */
180 #pragma pack(1)
181 struct csts {
182 unsigned int rdy:7;
183 unsigned int csts:32;
184 };
185
186 struct csts nvme;
187 #pragma pack()
188
189 /*
190 * Onto unions
191 */
192 union jrpg {
193 int ff;
194 double atelier[4];
195 const char *tales;
196 int (*chrono)(void);
197 struct rings xeno;
198 };
199
200 union jrpg games;
201
202 #pragma pack(1)
203 struct android {
204 uint32_t _2b:16;
205 uint32_t _9s:16;
206 };
207
208 union nier {
209 uint32_t automata;
210 struct android android;
211 };
212 #pragma pack()
213
214 union nier nier;
215
216 union kh {
217 int sora:3;
218 char riku:7;
219 double kairi;
220 complex double namine;
221 };
222
223 union kh kh;
224
225 /*
226 * Anonymous union in a struct, GNU extension / C11
227 */
228
229 struct trigger {
230 uint8_t chrono;
231 uint8_t cross;
232 union {
233 void *lavos;
234 int *crono;
235 uint64_t schala[3];
236 };
237 };
238
239 struct trigger ct;
240
241 /*
242 * This is an array/union combo that failed conversion previously. Because it is
243 * static, we need to have a dummy function to make sure that clang doesn't
244 * optimize it away. Hopefully even with optimizations, this'll still be kept
245 * even though it's a constant.
246 */
247 static const union regress {
248 unsigned int i[3];
249 long double e;
250 } regress[9];
251
252 unsigned int
get_regress(void)253 get_regress(void)
254 {
255 return (regress[0].i[2]);
256 }
257
258 /*
259 * Now we have a series of different anonymous unions and structures.
260 */
261 struct anon_basic {
262 int a;
263 union {
264 int b;
265 double c;
266 const char *d;
267 };
268 struct {
269 int e;
270 const char *f;
271 unsigned int g[10];
272 };
273 };
274
275 struct anon_basic anon_basic;
276
277 struct nested {
278 int a;
279 union {
280 int b;
281 struct {
282 int c;
283 int d;
284 int e;
285 union {
286 int g;
287 struct {
288 int h;
289 };
290 };
291 struct {
292 int i;
293 struct {
294 int j;
295 union {
296 int k;
297 struct {
298 int l;
299 int m;
300 };
301 union {
302 int n;
303 struct {
304 int o;
305 int p;
306 };
307 };
308 };
309 };
310 };
311 };
312 };
313 };
314
315 struct nested nested;
316