xref: /netbsd-src/tests/usr.bin/xlint/lint1/decl.c (revision cd4ee416b8ecb6a5d3739b2d808bd6e8e4173867)
1 /*	$NetBSD: decl.c,v 1.33 2024/11/30 11:27:20 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: illegal 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: illegal 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