expr_sizeof.c revision 1.13 1 1.13 rillig /* $NetBSD: expr_sizeof.c,v 1.13 2023/07/09 11:18:55 rillig Exp $ */
2 1.1 rillig # 3 "expr_sizeof.c"
3 1.1 rillig
4 1.1 rillig /*
5 1.1 rillig * C99 6.5.3.4 "The sizeof operator"
6 1.1 rillig * C11 6.5.3.4 "The sizeof operator"
7 1.1 rillig */
8 1.1 rillig
9 1.5 rillig /* lint1-extra-flags: -X 351 */
10 1.5 rillig
11 1.1 rillig /*
12 1.1 rillig * A sizeof expression can either take a type name or an expression.
13 1.1 rillig */
14 1.11 rillig
15 1.1 rillig void sink(unsigned long);
16 1.1 rillig
17 1.1 rillig struct {
18 1.1 rillig int member;
19 1.1 rillig } s, *ps;
20 1.1 rillig
21 1.1 rillig /*
22 1.1 rillig * In a sizeof expression taking a type name, the type name must be enclosed
23 1.1 rillig * in parentheses.
24 1.1 rillig */
25 1.1 rillig /* expect+1: error: negative array dimension (-4) [20] */
26 1.1 rillig typedef int sizeof_int[-(int)sizeof(int)];
27 1.1 rillig
28 1.1 rillig /*
29 1.1 rillig * In a sizeof expression taking an expression, the expression may or may not
30 1.1 rillig * be enclosed in parentheses, like any other expression.
31 1.1 rillig */
32 1.1 rillig /* expect+1: error: negative array dimension (-4) [20] */
33 1.1 rillig typedef int sizeof_paren_zero[-(int)sizeof(0)];
34 1.1 rillig /* expect+1: error: negative array dimension (-4) [20] */
35 1.1 rillig typedef int sizeof_zero[-(int)sizeof 0];
36 1.1 rillig
37 1.1 rillig /*
38 1.1 rillig * Even though 's' is not a constant expression, 'sizeof s' is.
39 1.1 rillig */
40 1.1 rillig /* expect+1: error: negative array dimension (-4) [20] */
41 1.1 rillig typedef int sizeof_global_var[-(int)sizeof s];
42 1.1 rillig /* expect+1: error: negative array dimension (-4) [20] */
43 1.1 rillig typedef int sizeof_paren_global_var[-(int)sizeof(s)];
44 1.1 rillig
45 1.1 rillig /*
46 1.1 rillig * Even though 'sizeof(s)' may look like a function call expression, the
47 1.1 rillig * parentheses around 's' are ordinary parentheses and do not influence the
48 1.2 rillig * precedence.
49 1.2 rillig *
50 1.2 rillig * Therefore, the '.' following the '(s)' takes precedence over the 'sizeof'.
51 1.2 rillig * Same for the '->' following the '(ps)'. Same for the '[0]' following the
52 1.2 rillig * '(arr)'.
53 1.1 rillig */
54 1.1 rillig /* expect+1: error: negative array dimension (-4) [20] */
55 1.1 rillig typedef int sizeof_paren_global_struct_member[-(int)sizeof(s).member];
56 1.1 rillig /* expect+1: error: negative array dimension (-4) [20] */
57 1.1 rillig typedef int sizeof_paren_global_ptr_struct_member[-(int)sizeof(ps)->member];
58 1.2 rillig int arr[] = { 1, 2, 3 };
59 1.2 rillig /* expect+1: error: negative array dimension (-3) [20] */
60 1.2 rillig typedef int arr_count[-(int)sizeof(arr) / (int)sizeof(arr)[0]];
61 1.2 rillig
62 1.2 rillig /* FIXME: 'n' is actually used, for the variable length array. */
63 1.13 rillig /* expect+2: warning: parameter 'n' unused in function 'variable_length_array' [231] */
64 1.2 rillig void
65 1.2 rillig variable_length_array(int n)
66 1.2 rillig {
67 1.2 rillig int local_arr[n + 5];
68 1.3 rillig
69 1.3 rillig /*
70 1.3 rillig * Since the array length is not constant, it cannot be used in a
71 1.4 rillig * typedef. Code like this is already rejected by the compiler. For
72 1.3 rillig * simplicity, lint assumes that the array has length 1.
73 1.3 rillig */
74 1.2 rillig /* expect+1: error: negative array dimension (-4) [20] */
75 1.2 rillig typedef int sizeof_local_arr[-(int)sizeof(local_arr)];
76 1.2 rillig }
77 1.6 rillig
78 1.7 rillig void
79 1.7 rillig bit_fields(void)
80 1.7 rillig {
81 1.7 rillig struct {
82 1.7 rillig _Bool flag0:1;
83 1.7 rillig _Bool flag1:1;
84 1.7 rillig _Bool flag2:1;
85 1.7 rillig } flags;
86 1.7 rillig /* expect+1: error: negative array dimension (-1) [20] */
87 1.7 rillig typedef int sizeof_flags[-(int)sizeof(flags)];
88 1.7 rillig
89 1.7 rillig struct {
90 1.7 rillig struct {
91 1.7 rillig _Bool flag0:1;
92 1.7 rillig _Bool flag1:1;
93 1.7 rillig _Bool flag2:1;
94 1.7 rillig };
95 1.7 rillig } anonymous_flags;
96 1.10 rillig /* expect+1: error: negative array dimension (-1) [20] */
97 1.7 rillig typedef int sizeof_anonymous_flags[-(int)sizeof(anonymous_flags)];
98 1.7 rillig
99 1.7 rillig struct {
100 1.7 rillig unsigned int bits0:16;
101 1.7 rillig unsigned int bits1:16;
102 1.7 rillig } same_storage_unit;
103 1.7 rillig /* expect+1: error: negative array dimension (-4) [20] */
104 1.7 rillig typedef int sizeof_same_storage_unit[-(int)sizeof(same_storage_unit)];
105 1.7 rillig
106 1.7 rillig // Detect whether a bit-field can span multiple storage units.
107 1.7 rillig // If so, the size is 12, if not, the size is 16.
108 1.7 rillig struct {
109 1.7 rillig unsigned int bits0:24;
110 1.7 rillig unsigned int bits1:24;
111 1.7 rillig unsigned int bits2:24;
112 1.7 rillig unsigned int bits3:24;
113 1.7 rillig } cross_storage_unit;
114 1.7 rillig /* expect+1: error: negative array dimension (-16) [20] */
115 1.7 rillig typedef int sizeof_cross_storage_unit[-(int)sizeof(cross_storage_unit)];
116 1.8 rillig
117 1.8 rillig /*
118 1.8 rillig * The bit-fields in a struct may be merged into the same storage
119 1.8 rillig * units, even if their types differ. GCC 10, Clang 15 and lint all
120 1.9 rillig * agree in packing the first group of bit-fields and the char into
121 1.9 rillig * 4 bytes, even though their underlying types differ. The second
122 1.9 rillig * group of bit-fields gets its own storage unit.
123 1.8 rillig */
124 1.8 rillig struct mixed {
125 1.8 rillig _Bool flag0:1;
126 1.8 rillig signed int signed0:1;
127 1.8 rillig unsigned int unsigned0:1;
128 1.9 rillig char ch[3];
129 1.8 rillig _Bool flag1:1;
130 1.8 rillig signed int signed1:1;
131 1.8 rillig unsigned int unsigned1:1;
132 1.8 rillig } mixed;
133 1.9 rillig /* expect+1: error: negative array dimension (-8) [20] */
134 1.8 rillig typedef int sizeof_mixed[-(int)sizeof(mixed)];
135 1.8 rillig /* FIXME: Implement build_offsetof correctly. */
136 1.9 rillig /* expect+3: error: negative array dimension (-8) [20] */
137 1.8 rillig typedef int offsetof_mixed_ch[
138 1.8 rillig -(int)__builtin_offsetof(struct mixed, ch)
139 1.8 rillig ];
140 1.7 rillig }
141 1.7 rillig
142 1.6 rillig /*
143 1.6 rillig * Ensure that anonymous structs and unions are handled correctly. They were
144 1.6 rillig * added in C11, and lint did not properly support them until 2023.
145 1.6 rillig */
146 1.6 rillig void
147 1.6 rillig anonymous_struct_and_union(void)
148 1.6 rillig {
149 1.6 rillig struct {
150 1.6 rillig union {
151 1.6 rillig unsigned char uc16[16];
152 1.6 rillig unsigned char uc32[32];
153 1.6 rillig };
154 1.6 rillig } su_16_32;
155 1.12 rillig /* expect+1: error: negative array dimension (-32) [20] */
156 1.6 rillig typedef int sizeof_su_16_32[-(int)sizeof(su_16_32)];
157 1.6 rillig
158 1.6 rillig union {
159 1.6 rillig struct {
160 1.6 rillig unsigned char uc16[16];
161 1.6 rillig unsigned char uc32[32];
162 1.6 rillig };
163 1.6 rillig } us_16_32;
164 1.6 rillig /* expect+1: error: negative array dimension (-48) [20] */
165 1.6 rillig typedef int sizeof_us_16_32[-(int)sizeof(us_16_32)];
166 1.6 rillig }
167 1.11 rillig
168 1.11 rillig
169 1.11 rillig void
170 1.11 rillig sizeof_errors(void)
171 1.11 rillig {
172 1.11 rillig /* expect+1: error: cannot take size/alignment of void [146] */
173 1.11 rillig typedef int sizeof_void[-(int)sizeof(void)];
174 1.11 rillig
175 1.11 rillig /*
176 1.11 rillig * A 'void array' gets replaced with an 'int array' before
177 1.11 rillig * type_size_in_bits gets to see it, thus the 256 * 4 = 1024.
178 1.11 rillig */
179 1.11 rillig /* expect+2: error: illegal use of 'void' [18] */
180 1.11 rillig /* expect+1: error: negative array dimension (-1024) [20] */
181 1.11 rillig typedef int sizeof_void_array[-(int)sizeof(void[256])];
182 1.11 rillig
183 1.11 rillig /* expect+1: warning: enum 'incomplete_enum' never defined [235] */
184 1.11 rillig enum incomplete_enum;
185 1.11 rillig /* expect+2: warning: cannot take size/alignment of incomplete type [143] */
186 1.11 rillig /* expect+1: error: negative array dimension (-4) [20] */
187 1.11 rillig typedef int sizeof_incomplete_enum[-(int)sizeof(enum incomplete_enum)];
188 1.11 rillig }
189 1.11 rillig
190 1.11 rillig
191 1.11 rillig /*
192 1.11 rillig * Due to the 'double' member, the alignment of this struct is 8, so the size
193 1.11 rillig * has to be 24 (or at least divisible by 8), otherwise the 'double' member
194 1.11 rillig * would not get the correct alignment in an array of this struct.
195 1.11 rillig */
196 1.11 rillig struct s24 {
197 1.11 rillig char c0;
198 1.11 rillig double d8;
199 1.11 rillig char c16;
200 1.11 rillig };
201 1.11 rillig /* expect+1: error: negative array dimension (-24) [20] */
202 1.11 rillig typedef int sizeof_s24[-(int)sizeof(struct s24)];
203