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
specifier_qualifier(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
qualifier_specifier(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
declarator_with_prefix_qualifier(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
declarator_with_postfix_qualifier(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
declarators(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
enum_error_handling(void)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
unused_local_variable(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
declaration_without_type_specifier(void)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
unused(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
unused_linted(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] */
cover_func_declarator(void)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 *
bit_and_data(struct bit_and_data * node)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
symbol_type_in_unnamed_bit_field_member(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
get_x(struct point3d{ struct point3d_number { int v; } x, y, z; } arg)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
offsetof_on_array_member(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
long_double_vs_long_int(long double * a,long int * b)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
type_name_as_member_name(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
static_function(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
no_prototype_definition()330 no_prototype_definition()
331 {
332 }
333 
334 void
prototype_definition(void)335 prototype_definition(void)
336 {
337 }
338