xref: /netbsd-src/tests/usr.bin/xlint/lint1/decl.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*	$NetBSD: decl.c,v 1.31 2024/06/08 09:09: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