expr_sizeof.c revision 1.17 1 /* $NetBSD: expr_sizeof.c,v 1.17 2024/05/03 15:32:37 rillig Exp $ */
2 # 3 "expr_sizeof.c"
3
4 /*
5 * C99 6.5.3.4 "The sizeof operator"
6 * C11 6.5.3.4 "The sizeof operator"
7 */
8
9 /* lint1-extra-flags: -X 351 */
10 // TODO: Remove the lp64 restriction when sequence_of_structs has been fixed.
11 /* lint1-only-if: lp64 */
12
13 /*
14 * A sizeof expression can either take a type name or an expression.
15 */
16
17 void sink(unsigned long);
18
19 struct {
20 int member;
21 } s, *ps;
22
23 /*
24 * In a sizeof expression taking a type name, the type name must be enclosed
25 * in parentheses.
26 */
27 /* expect+1: error: negative array dimension (-4) [20] */
28 typedef int sizeof_int[-(int)sizeof(int)];
29
30 /*
31 * In a sizeof expression taking an expression, the expression may or may not
32 * be enclosed in parentheses, like any other expression.
33 */
34 /* expect+1: error: negative array dimension (-4) [20] */
35 typedef int sizeof_paren_zero[-(int)sizeof(0)];
36 /* expect+1: error: negative array dimension (-4) [20] */
37 typedef int sizeof_zero[-(int)sizeof 0];
38
39 /*
40 * Even though 's' is not a constant expression, 'sizeof s' is.
41 */
42 /* expect+1: error: negative array dimension (-4) [20] */
43 typedef int sizeof_global_var[-(int)sizeof s];
44 /* expect+1: error: negative array dimension (-4) [20] */
45 typedef int sizeof_paren_global_var[-(int)sizeof(s)];
46
47 /*
48 * Even though 'sizeof(s)' may look like a function call expression, the
49 * parentheses around 's' are ordinary parentheses and do not influence the
50 * precedence.
51 *
52 * Therefore, the '.' following the '(s)' takes precedence over the 'sizeof'.
53 * Same for the '->' following the '(ps)'. Same for the '[0]' following the
54 * '(arr)'.
55 */
56 /* expect+1: error: negative array dimension (-4) [20] */
57 typedef int sizeof_paren_global_struct_member[-(int)sizeof(s).member];
58 /* expect+1: error: negative array dimension (-4) [20] */
59 typedef int sizeof_paren_global_ptr_struct_member[-(int)sizeof(ps)->member];
60 int arr[] = { 1, 2, 3 };
61 /* expect+1: error: negative array dimension (-3) [20] */
62 typedef int arr_count[-(int)sizeof(arr) / (int)sizeof(arr)[0]];
63
64 /* FIXME: 'n' is actually used, for the variable length array. */
65 /* expect+2: warning: parameter 'n' unused in function 'variable_length_array' [231] */
66 void
67 variable_length_array(int n)
68 {
69 int local_arr[n + 5];
70
71 /*
72 * Since the array length is not constant, it cannot be used in a
73 * typedef. Code like this is already rejected by the compiler. For
74 * simplicity, lint assumes that the array has length 1.
75 */
76 /* expect+1: error: negative array dimension (-4) [20] */
77 typedef int sizeof_local_arr[-(int)sizeof(local_arr)];
78 }
79
80 void
81 bit_fields(void)
82 {
83 struct {
84 _Bool flag0:1;
85 _Bool flag1:1;
86 _Bool flag2:1;
87 } flags;
88 /* expect+1: error: negative array dimension (-1) [20] */
89 typedef int sizeof_flags[-(int)sizeof(flags)];
90
91 struct {
92 struct {
93 _Bool flag0:1;
94 _Bool flag1:1;
95 _Bool flag2:1;
96 };
97 } anonymous_flags;
98 /* expect+1: error: negative array dimension (-1) [20] */
99 typedef int sizeof_anonymous_flags[-(int)sizeof(anonymous_flags)];
100
101 struct {
102 unsigned int bits0:16;
103 unsigned int bits1:16;
104 } same_storage_unit;
105 /* expect+1: error: negative array dimension (-4) [20] */
106 typedef int sizeof_same_storage_unit[-(int)sizeof(same_storage_unit)];
107
108 // Detect whether a bit-field can span multiple storage units.
109 // If so, the size is 12, if not, the size is 16.
110 struct {
111 unsigned int bits0:24;
112 unsigned int bits1:24;
113 unsigned int bits2:24;
114 unsigned int bits3:24;
115 } cross_storage_unit;
116 /* expect+1: error: negative array dimension (-16) [20] */
117 typedef int sizeof_cross_storage_unit[-(int)sizeof(cross_storage_unit)];
118
119 /*
120 * The bit-fields in a struct may be merged into the same storage
121 * units, even if their types differ. GCC 10, Clang 15 and lint all
122 * agree in packing the first group of bit-fields and the char into
123 * 4 bytes, even though their underlying types differ. The second
124 * group of bit-fields gets its own storage unit.
125 */
126 struct mixed {
127 _Bool flag0:1;
128 signed int signed0:1;
129 unsigned int unsigned0:1;
130 char ch[3];
131 _Bool flag1:1;
132 signed int signed1:1;
133 unsigned int unsigned1:1;
134 } mixed;
135 /* expect+1: error: negative array dimension (-8) [20] */
136 typedef int sizeof_mixed[-(int)sizeof(mixed)];
137 /* expect+3: error: negative array dimension (-1) [20] */
138 typedef int offsetof_mixed_ch[
139 -(int)__builtin_offsetof(struct mixed, ch)
140 ];
141 }
142
143 /*
144 * Ensure that anonymous structs and unions are handled correctly. They were
145 * added in C11, and lint did not properly support them until 2023.
146 */
147 void
148 anonymous_struct_and_union(void)
149 {
150 struct {
151 union {
152 unsigned char uc16[16];
153 unsigned char uc32[32];
154 };
155 } su_16_32;
156 /* expect+1: error: negative array dimension (-32) [20] */
157 typedef int sizeof_su_16_32[-(int)sizeof(su_16_32)];
158
159 union {
160 struct {
161 unsigned char uc16[16];
162 unsigned char uc32[32];
163 };
164 } us_16_32;
165 /* expect+1: error: negative array dimension (-48) [20] */
166 typedef int sizeof_us_16_32[-(int)sizeof(us_16_32)];
167 }
168
169
170 void
171 sizeof_errors(void)
172 {
173 /* expect+1: error: cannot take size/alignment of void [146] */
174 typedef int sizeof_void[-(int)sizeof(void)];
175
176 /*
177 * A 'void array' gets replaced with an 'int array' before
178 * type_size_in_bits gets to see it, thus the 256 * 4 = 1024.
179 */
180 /* expect+2: error: illegal use of 'void' [18] */
181 /* expect+1: error: negative array dimension (-1024) [20] */
182 typedef int sizeof_void_array[-(int)sizeof(void[256])];
183
184 /* expect+1: warning: enum 'incomplete_enum' never defined [235] */
185 enum incomplete_enum;
186 /* expect+2: warning: cannot take size/alignment of incomplete type [143] */
187 /* expect+1: error: negative array dimension (-4) [20] */
188 typedef int sizeof_incomplete_enum[-(int)sizeof(enum incomplete_enum)];
189 }
190
191
192 /*
193 * Due to the 'double' member, the alignment of this struct is 8, so the size
194 * has to be 24 (or at least divisible by 8), otherwise the 'double' member
195 * would not get the correct alignment in an array of this struct.
196 */
197 struct s24 {
198 char c0;
199 double d8;
200 char c16;
201 };
202 /* expect+1: error: negative array dimension (-24) [20] */
203 typedef int sizeof_s24[-(int)sizeof(struct s24)];
204
205 void
206 sizeof_array_parameter(short arr[12345])
207 {
208 // The size of an array parameter is the size of the decayed pointer.
209 // Subtracting 'sizeof(void *)' makes the test platform-independent.
210 typedef int sizeof_arr[-(int)(sizeof arr - sizeof(void *))];
211
212 // The 2 comes from 'sizeof(short)', as the type 'array[size] of elem'
213 // decays into the type 'pointer to elem', not 'pointer to array[size]
214 // of elem'.
215 /* expect+1: error: negative array dimension (-2) [20] */
216 typedef int sizeof_arr_elem[-(int)(sizeof *arr)];
217 }
218
219
220 void
221 sequence_of_structs(void)
222 {
223 typedef unsigned char uint8_t;
224 typedef short unsigned int uint16_t;
225 typedef unsigned int uint32_t;
226 typedef long unsigned int uint64_t;
227
228 union fp_addr {
229 uint64_t fa_64;
230 struct {
231 uint32_t fa_off;
232 uint16_t fa_seg;
233 uint16_t fa_opcode;
234 } fa_32;
235 } __packed _Alignas(4);
236
237 struct fpacc87 {
238 uint64_t f87_mantissa;
239 uint16_t f87_exp_sign;
240 } __packed _Alignas(2);
241
242 // FIXME: This otherwise unused struct declaration influences the
243 // offsets checked below. Without this struct, sizeof(struct save87)
244 // is calculated correctly as 108 below.
245 struct fpaccfx {
246 struct fpacc87 r _Alignas(16);
247 };
248
249 struct save87 {
250 uint16_t s87_cw _Alignas(4);
251 uint16_t s87_sw _Alignas(4);
252 uint16_t s87_tw _Alignas(4);
253 union fp_addr s87_ip;
254 union fp_addr s87_dp;
255 struct fpacc87 s87_ac[8];
256 };
257
258 /* expect+1: error: negative array dimension (-20) [20] */
259 typedef int o1[-(int)((unsigned long)(&(((struct save87 *)0)->s87_dp)))];
260 // FIXME: must be 28.
261 /* expect+1: error: negative array dimension (-32) [20] */
262 typedef int o2[-(int)((unsigned long)(&(((struct save87 *)0)->s87_ac)))];
263 // FIXME: must be 108.
264 /* expect+1: error: negative array dimension (-112) [20] */
265 typedef int reveal[-(int)sizeof(struct save87)];
266 }
267