decl.c revision 1.35 1 /* $NetBSD: decl.c,v 1.35 2025/04/12 15:49:49 rillig Exp $ */
2 # 3 "decl.c"
3
4 /*
5 * Tests for declarations, especially the distinction between the
6 * declaration-specifiers and the declarators.
7 */
8
9 /* lint1-extra-flags: -X 191,351 */
10
11 /*
12 * Even though 'const' comes after 'char' and is therefore quite close to the
13 * first identifier, it applies to both identifiers.
14 */
15 void
16 specifier_qualifier(void)
17 {
18 char const a = 1, b = 2;
19
20 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */
21 a = 1;
22 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */
23 b = 2;
24 }
25
26 /*
27 * Since 'const' comes before 'char', there is no ambiguity whether the
28 * 'const' applies to all variables or just to the first.
29 */
30 void
31 qualifier_specifier(void)
32 {
33 const char a = 1, b = 2;
34
35 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */
36 a = 3;
37 /* expect+1: warning: left operand of '=' must be modifiable lvalue [115] */
38 b = 5;
39 }
40
41 void
42 declarator_with_prefix_qualifier(void)
43 {
44 /* expect+1: error: syntax error 'const' [249] */
45 char a = 1, const b = 2;
46
47 a = 1;
48 /* expect+1: error: 'b' undefined [99] */
49 b = 2;
50 }
51
52 void
53 declarator_with_postfix_qualifier(void)
54 {
55 /* expect+1: error: syntax error 'const' [249] */
56 char a = 1, b const = 2;
57
58 a = 1;
59 b = 2;
60 }
61
62 void sink(double *);
63
64 void
65 declarators(void)
66 {
67 char *pc = 0, c = 0, **ppc = 0;
68
69 /* expect+1: warning: converting 'pointer to char' to incompatible 'pointer to double' for argument 1 [153] */
70 sink(pc);
71 /* expect+1: warning: invalid combination of pointer 'pointer to double' and integer 'char', arg #1 [154] */
72 sink(c);
73 /* expect+1: warning: converting 'pointer to pointer to char' to incompatible 'pointer to double' for argument 1 [153] */
74 sink(ppc);
75 }
76
77 _Bool
78 enum_error_handling(void)
79 {
80 enum {
81 /* expect+1: error: syntax error '"' [249] */
82 "error 1"
83 : /* still the same error */
84 , /* back on track */
85 A,
86 B
87 } x = A;
88
89 return x == B;
90 }
91
92 /*
93 * An __attribute__ at the beginning of a declaration may become ambiguous
94 * since a GCC fallthrough statement starts with __attribute__ as well.
95 */
96 void
97 unused_local_variable(void)
98 {
99 __attribute__((unused)) _Bool unused_var;
100
101 __attribute__((unused))
102 __attribute__((unused)) _Bool unused_twice;
103 }
104
105 int
106 declaration_without_type_specifier(void)
107 {
108 const i = 3;
109 /* expect-1: error: old-style declaration; add 'int' [1] */
110 return i;
111 }
112
113
114 /* expect+2: warning: static function 'unused' unused [236] */
115 static void
116 unused(void)
117 {
118 }
119
120 /*
121 * The attribute 'used' does not influence static functions, it only
122 * applies to function parameters.
123 */
124 /* LINTED */
125 static void
126 unused_linted(void)
127 {
128 }
129
130 /* covers 'type_qualifier_list: type_qualifier_list type_qualifier' */
131 int *const volatile cover_type_qualifier_list;
132
133 _Bool bool;
134 char plain_char;
135 signed char signed_char;
136 unsigned char unsigned_char;
137 short signed_short;
138 unsigned short unsigned_short;
139 int signed_int;
140 unsigned int unsigned_int;
141 long signed_long;
142 unsigned long unsigned_long;
143 struct {
144 int member;
145 } unnamed_struct;
146
147 /*
148 * Before decl.c 1.201 from 2021-07-15, lint crashed with an internal error
149 * in dcs_end_type (named end_type back then).
150 */
151 unsigned long sizes =
152 sizeof(const typeof(bool)) +
153 sizeof(const typeof(plain_char)) +
154 sizeof(const typeof(signed_char)) +
155 sizeof(const typeof(unsigned_char)) +
156 sizeof(const typeof(signed_short)) +
157 sizeof(const typeof(unsigned_short)) +
158 sizeof(const typeof(signed_int)) +
159 sizeof(const typeof(unsigned_int)) +
160 sizeof(const typeof(signed_long)) +
161 sizeof(const typeof(unsigned_long)) +
162 sizeof(const typeof(unnamed_struct));
163
164 /* expect+2: error: old-style declaration; add 'int' [1] */
165 /* expect+1: error: syntax error 'int' [249] */
166 thread int thread_int;
167 __thread int thread_int;
168 /* expect+2: error: old-style declaration; add 'int' [1] */
169 /* expect+1: error: syntax error 'int' [249] */
170 __thread__ int thread_int;
171
172 static
173 /* expect+1: warning: static function 'cover_func_declarator' unused [236] */
174 cover_func_declarator(void)
175 /* expect+1: error: old-style declaration; add 'int' [1] */
176 {
177 }
178
179 /*
180 * Before decl.c 1.268 from 2022-04-03, lint ran into an assertion failure for
181 * "elsz > 0" in 'length'.
182 */
183 /* expect+2: error: syntax error 'goto' [249] */
184 /* expect+1: warning: empty array declaration for 'void_array_error' [190] */
185 void void_array_error[] goto;
186
187 const volatile int
188 /* expect+1: warning: duplicate 'const' [10] */
189 *const volatile const
190 /* expect+1: warning: duplicate 'volatile' [10] */
191 *volatile const volatile
192 *duplicate_ptr;
193
194
195 /*
196 * Since tree.c 1.573 from 2023-07-15 and before decl.c 1.370 from 2023-07-31,
197 * lint crashed due to a failed assertion in find_member. The assertion states
198 * that every member of a struct or union must link back to its containing
199 * type, which had not been the case for unnamed bit-fields.
200 */
201 struct bit_and_data {
202 unsigned int :0;
203 unsigned int bit:1;
204 unsigned int :0;
205
206 void *data;
207 };
208
209 static inline void *
210 bit_and_data(struct bit_and_data *node)
211 {
212 return node->data;
213 }
214
215
216 // See cgram.y, rule 'notype_member_declarator'.
217 void
218 symbol_type_in_unnamed_bit_field_member(void)
219 {
220 enum {
221 bits = 4,
222 };
223
224 struct s {
225 // Since there is no name in the declarator, the next symbol
226 // after the ':' must not be interpreted as a member name, but
227 // instead as a variable, type or function (SK_VCFT).
228 unsigned int :bits;
229 int named_member;
230 };
231 }
232
233 // Symbols that are defined in the parameter list of a function definition can
234 // be accessed in the body of the function, even if they are nested.
235 int
236 get_x(struct point3d { struct point3d_number { int v; } x, y, z; } arg)
237 {
238 /* expect-1: warning: dubious tag declaration 'struct point3d' [85] */
239 /* expect-2: warning: dubious tag declaration 'struct point3d_number' [85] */
240 static struct point3d local;
241 static struct point3d_number z;
242 return arg.x.v + local.x.v + z.v;
243 }
244
245 // Expressions of the form '(size_t)&null_ptr->member' are used by several
246 // C implementations to implement the offsetof macro.
247 void
248 offsetof_on_array_member(void)
249 {
250 typedef struct {
251 int padding, plain, arr[2];
252 } s1;
253
254 // Bit-fields must have a constant number of bits.
255 struct s2 {
256 unsigned int off_plain:(unsigned long)&((s1 *)0)->plain;
257 unsigned int off_arr:(unsigned long)&((s1 *)0)->arr;
258 unsigned int off_arr_0:(unsigned long)&((s1 *)0)->arr[0];
259 unsigned int off_arr_3:(unsigned long)&((s1 *)0)->arr[3];
260 };
261
262 // Arrays may be variable-width, but the diagnostic reveals the size.
263 /* expect+1: error: negative array dimension (-4) [20] */
264 typedef int off_plain[-(int)(unsigned long)&((s1 *)0)->plain];
265 /* expect+1: error: negative array dimension (-8) [20] */
266 typedef int off_arr[-(int)(unsigned long)&((s1 *)0)->arr];
267 /* expect+1: error: negative array dimension (-8) [20] */
268 typedef int off_arr_0[-(int)(unsigned long)&((s1 *)0)->arr[0]];
269 /* expect+1: error: negative array dimension (-20) [20] */
270 typedef int off_arr_3[-(int)(unsigned long)&((s1 *)0)->arr[3]];
271 }
272
273 /* PR bin/39639: writing "long double" gave "long int" */
274 int
275 long_double_vs_long_int(long double *a, long int *b)
276 {
277 /* expect+1: warning: invalid combination of 'pointer to long double' and 'pointer to long', op '==' [124] */
278 return a == b;
279 }
280
281 struct zero_sized_array {
282 int member[0];
283 };
284
285 void
286 type_name_as_member_name(void)
287 {
288 typedef char h[10];
289
290 typedef struct {
291 int i;
292 char *c;
293 } fh;
294
295 struct foo {
296 fh h;
297 struct {
298 int x;
299 int y;
300 } fl;
301 };
302 }
303
304
305 // When query 16 is not enabled, don't produce a 'previous declaration' message
306 // without a preceding main diagnostic.
307 static void static_function(void) __attribute__((__used__));
308
309 // The definition is without 'static'.
310 void
311 static_function(void)
312 {
313 }
314
315
316 typedef void (*fprint_function)(int, const char *, ...);
317 typedef fprint_function (*change_logger)
318 (fprint_function, fprint_function, fprint_function, fprint_function);
319
320 // Provoke a long type name to test reallocation in type_name.
321 /* expect+1: error: redeclaration of 'static_function' with type 'function(pointer to function(pointer to function(int, pointer to const char, ...) returning void, pointer to function(int, pointer to const char, ...) returning void, pointer to function(int, pointer to const char, ...) returning void, pointer to function(int, pointer to const char, ...) returning void) returning pointer to function(int, pointer to const char, ...) returning void) returning void', expected 'function(void) returning void' [347] */
322 void static_function(change_logger);
323
324
325 void no_prototype_declaration();
326 void prototype_declaration(void);
327
328 // TODO: Warn about the missing 'void', for C99 and later.
329 void
330 no_prototype_definition()
331 {
332 }
333
334 void
335 prototype_definition(void)
336 {
337 }
338