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  */
15 
16 #include <sys/types.h>
17 #include <complex.h>
18 
19 /*
20  * Test various structure and union constructs, including various things that
21  * have caused regressions in the past.
22  */
23 
24 /*
25  * Basic, simple struct.
26  */
27 struct foo {
28 	int a;
29 	float b;
30 	const char *c;
31 };
32 
33 struct foo foo;
34 
35 /*
36  * Self-referential structs
37  */
38 struct node {
39 	struct node *prev;
40 	struct node *next;
41 };
42 
43 typedef struct nlist {
44 	size_t size;
45 	size_t off;
46 	struct node head;
47 } nlist_t;
48 
49 nlist_t head;
50 
51 /*
52  * Struct that has a forward declaration.
53  */
54 typedef struct forward forward_t;
55 struct forward {
56 	void *past;
57 	void *present;
58 	void *future;
59 };
60 
61 const forward_t forward;
62 
63 /*
64  * Here, we have a pair of structures that basically round up to different
65  * sizes. As in, the size of the structure is somewhat compiler dependent.
66  */
67 struct round_up {
68 	uint8_t triforce;
69 	uint32_t link;
70 	uint8_t zelda;
71 	uint8_t ganon;
72 };
73 
74 #pragma pack(1)
75 struct fixed_up {
76 	uint8_t triforce;
77 	uint32_t link;
78 	uint8_t zelda;
79 	uint8_t ganon;
80 };
81 #pragma pack()
82 
83 struct round_up oot;
84 struct fixed_up botw;
85 
86 /*
87  * Various GNU and c99 style arrays
88  */
89 enum material {
90 	COPPER,
91 	IRON,
92 	STEEL,
93 	ADAMANTIUM,
94 	MYTHRIL,
95 	ORIHALCUM
96 };
97 
98 struct component {
99 	enum material m;
100 	uint64_t grade;
101 	uint64_t count;
102 	const char *locations[4];
103 };
104 
105 struct mysterious_barrel {
106 	const char *name;
107 	size_t capacity;
108 	struct component optional[];
109 };
110 
111 struct dusk_barrel {
112 	const char *name;
113 	size_t opacity;
114 	struct component optional[0];
115 };
116 
117 struct mysterious_barrel sophie;
118 struct dusk_barrel ayesha;
119 
120 /*
121  * Various bitfield forms.
122  */
123 
124 /*
125  * Variant of the Intel system_desc.
126  */
127 struct stats {
128 	uint64_t hp:16;
129 	uint64_t mp:16;
130 	uint64_t str:8;
131 	uint64_t dex:4;
132 	uint64_t con:1;
133 	uint64_t inte:2;
134 	uint64_t wis:1;
135 	uint64_t cha:4;
136 	uint64_t sanity:1;
137 	uint64_t attack:2;
138 	uint64_t mattack:1;
139 	uint64_t defense:8;
140 	uint64_t mdefense:32;
141 	uint64_t evasion:8;
142 	uint64_t crit:5;
143 	uint64_t luck:19;
144 };
145 
146 struct stats stats;
147 
148 /*
149  * More odd length structures due to bitfields
150  */
151 struct fellowship {
152 	uint16_t frodo:1;
153 	uint16_t sam:1;
154 	uint16_t merry:1;
155 	uint16_t pippin:1;
156 	uint16_t aragorn:1;
157 	uint16_t boromir:1;
158 	uint16_t legolas:1;
159 	uint16_t gimli:1;
160 	uint16_t gandalf:1;
161 };
162 
163 struct fellowship ring;
164 
165 struct rings {
166 	uint32_t elves:3;
167 	uint32_t dwarves:7;
168 	uint32_t men:9;
169 	uint8_t one;
170 	uint8_t silmarils[3];
171 };
172 
173 struct rings rings;
174 
175 /*
176  * Regression, we didn't handle receiving a negative offset from DWARF with
177  * this.
178  */
179 #pragma pack(1)
180 struct csts {
181 	unsigned int rdy:7;
182 	unsigned int csts:32;
183 };
184 
185 struct csts nvme;
186 #pragma pack()
187 
188 /*
189  * Onto unions
190  */
191 union jrpg {
192 	int ff;
193 	double atelier[4];
194 	const char *tales;
195 	int (*chrono)(void);
196 	struct rings xeno;
197 };
198 
199 union jrpg games;
200 
201 #pragma pack(1)
202 struct android {
203 	uint32_t _2b:16;
204 	uint32_t _9s:16;
205 };
206 
207 union nier {
208 	uint32_t automata;
209 	struct android android;
210 };
211 #pragma pack()
212 
213 union nier nier;
214 
215 union kh {
216 	int sora:3;
217 	char riku:7;
218 	double kairi;
219 	complex double namine;
220 };
221 
222 union kh kh;
223 
224 /*
225  * Anonymous union in a struct, GNU extension / C11
226  */
227 
228 struct trigger {
229 	uint8_t chrono;
230 	uint8_t cross;
231 	union {
232 		void *lavos;
233 		int *crono;
234 		uint64_t schala[3];
235 	};
236 };
237 
238 struct trigger ct;
239 
240 /*
241  * This is an array/union combo that failed conversion previously. Because it is
242  * static, we need to have a dummy function to make sure that clang doesn't
243  * optimize it away. Hopefully even with optimizations, this'll still be kept
244  * even though it's a constant.
245  */
246 static const union regress {
247 	unsigned int i[3];
248 	long double e;
249 } regress[9];
250 
251 unsigned int
get_regress(void)252 get_regress(void)
253 {
254 	return (regress[0].i[2]);
255 }
256