xref: /netbsd-src/tests/usr.bin/xlint/lint1/queries.c (revision cd4ee416b8ecb6a5d3739b2d808bd6e8e4173867)
1 /*	$NetBSD: queries.c,v 1.33 2024/11/30 11:27:20 rillig Exp $	*/
2 # 3 "queries.c"
3 
4 /*
5  * Demonstrate the case-by-case queries.  Unlike warnings, queries do not
6  * point to questionable code but rather to code that may be interesting to
7  * inspect manually on a case-by-case basis.
8  *
9  * Possible use cases are:
10  *
11  *	Understanding how C works internally, by making the usual arithmetic
12  *	conversions visible.
13  *
14  *	Finding code that intentionally suppresses a regular lint warning,
15  *	such as casts between arithmetic types.
16  */
17 
18 /* lint1-extra-flags: -q 1,2,3,4,5,6,7,8,9,10 */
19 /* lint1-extra-flags: -q 11,12,13,14,15,16,17,18,19,20 */
20 /* lint1-extra-flags: -q 21,22,23,24 */
21 /* lint1-extra-flags: -X 351 */
22 
23 typedef unsigned char u8_t;
24 typedef unsigned short u16_t;
25 typedef unsigned int u32_t;
26 typedef unsigned long long u64_t;
27 typedef signed char s8_t;
28 typedef signed short s16_t;
29 typedef signed int s32_t;
30 typedef signed long long s64_t;
31 
32 typedef float f32_t;
33 typedef double f64_t;
34 typedef float _Complex c32_t;
35 typedef double _Complex c64_t;
36 
37 typedef char *str_t;
38 typedef const char *cstr_t;
39 typedef volatile char *vstr_t;
40 typedef typeof(sizeof 0) size_t;
41 
42 _Bool cond;
43 
44 u8_t u8;
45 u16_t u16;
46 u32_t u32;
47 u64_t u64;
48 
49 s8_t s8;
50 s16_t s16;
51 s32_t s32;
52 s64_t s64;
53 
54 struct {
55 	unsigned u8:8;
56 	unsigned u9:9;
57 	unsigned u10:10;
58 	unsigned u32:32;
59 	int s8:8;
60 	int s9:9;
61 	int s10:10;
62 	int s32:32;
63 } bits;
64 
65 f32_t f32;
66 f64_t f64;
67 
68 c32_t c32;
69 c64_t c64;
70 
71 char *str;
72 const char *cstr;
73 volatile char *vstr;
74 const volatile char *cvstr;
75 
76 void *void_ptr;
77 const void *const_void_ptr;
78 char *char_ptr;
79 int *int_ptr;
80 
81 int
82 Q1(double dbl)
83 {
84 	/* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */
85 	return dbl;
86 }
87 
88 int
89 Q2(double dbl)
90 {
91 	/* expect+1: cast from floating point 'double' to integer 'int' [Q2] */
92 	return (int)dbl;
93 }
94 
95 // The Q3 query triggers so often that it also occurs outside this function.
96 void
97 Q3(int i, unsigned u)
98 {
99 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
100 	u = i;
101 
102 	/* expect+1: implicit conversion changes sign from 'unsigned int' to 'int' [Q3] */
103 	i = u;
104 
105 	/* expect+2: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
106 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned short' [Q3] */
107 	u16 += u8;
108 	/* expect+2: implicit conversion changes sign from 'unsigned short' to 'int' [Q3] */
109 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
110 	u32 += u16;
111 }
112 
113 unsigned long long
114 Q4(signed char *ptr, int i, unsigned long long ull, size_t sz)
115 {
116 
117 	/*
118 	 * For constants, the usual arithmetic conversions are usually not
119 	 * interesting, so omit them.
120 	 */
121 	u32 = u32 & 0xff;
122 	u32 &= 0xff;
123 
124 	/* expect+2: usual arithmetic conversion for '&' from 'int' to 'unsigned int' [Q4] */
125 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
126 	u32 = u32 & s32;
127 	/*
128 	 * XXX: C99 5.6.16.2 says that the usual arithmetic conversions
129 	 * happen for compound assignments as well.
130 	 */
131 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
132 	u32 &= s32;
133 
134 	/* expect+3: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
135 	/* expect+2: usual arithmetic conversion for '&' from 'int' to 'unsigned int' [Q4] */
136 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
137 	u32 = u32 & u8;
138 
139 	s8 = ptr[sz];
140 
141 	/*
142 	 * The conversion from 'signed char' to 'int' is done by the integer
143 	 * promotions (C11 6.3.1.1p2), not by the usual arithmetic
144 	 * conversions (C11 6.3.1.8p1).
145 	 */
146 	/* expect+2: usual arithmetic conversion for '+' from 'int' to 'unsigned long long' [Q4] */
147 	/* expect+1: implicit conversion changes sign from 'int' to 'unsigned long long' [Q3] */
148 	return ptr[0] + ptr[1] + i + ull;
149 }
150 
151 void
152 Q5(signed char *ptr, int i)
153 {
154 	if (ptr + i > ptr)
155 		return;
156 
157 	/* expect+1: pointer addition has integer on the left-hand side [Q5] */
158 	if (i + ptr > ptr)
159 		return;
160 
161 	if (ptr[i] != '\0')
162 		return;
163 
164 	/* expect+1: pointer addition has integer on the left-hand side [Q5] */
165 	if (i[ptr] != '\0')
166 		return;
167 }
168 
169 void
170 Q6(int i)
171 {
172 	/* expect+1: no-op cast from 'int' to 'int' [Q6] */
173 	i = (int)4;
174 
175 	/* expect+1: no-op cast from 'int' to 'int' [Q6] */
176 	i = (int)i + 1;
177 }
178 
179 void *allocate(void);
180 
181 void
182 Q7(void)
183 {
184 
185 	/* expect+2: no-op cast from '_Bool' to '_Bool' [Q6] */
186 	/* expect+1: redundant cast from '_Bool' to '_Bool' before assignment [Q7] */
187 	cond = (_Bool)cond;
188 	cond = (_Bool)u8;
189 	u8 = (u8_t)cond;
190 
191 	/* expect+2: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
192 	/* expect+1: redundant cast from 'unsigned char' to 'unsigned char' before assignment [Q7] */
193 	u8 = (u8_t)u8;
194 	u8 = (u8_t)u16;
195 	u8 = (u16_t)u8;
196 	/* expect+1: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
197 	u8 = (u16_t)u16;
198 	/* expect+1: no-op cast from 'unsigned char' to 'unsigned char' [Q6] */
199 	u16 = (u8_t)u8;
200 	u16 = (u8_t)u16;
201 	/* expect+1: redundant cast from 'unsigned char' to 'unsigned short' before assignment [Q7] */
202 	u16 = (u16_t)u8;
203 	/* expect+2: no-op cast from 'unsigned short' to 'unsigned short' [Q6] */
204 	/* expect+1: redundant cast from 'unsigned short' to 'unsigned short' before assignment [Q7] */
205 	u16 = (u16_t)u16;
206 
207 	/* Mixing signed and unsigned types. */
208 	u8 = (u8_t)s8;
209 	s8 = (s8_t)u8;
210 	/* expect+1: redundant cast from 'unsigned char' to 'short' before assignment [Q7] */
211 	s16 = (s16_t)u8;
212 	/* expect+1: redundant cast from 'signed char' to 'short' before assignment [Q7] */
213 	s16 = (s16_t)s8;
214 
215 
216 	/*
217 	 * Neither GCC nor Clang accept typeof(bit-field), as that would add
218 	 * unnecessary complexity.  Lint accepts it but silently discards the
219 	 * bit-field portion from the type; see dcs_add_type.
220 	 */
221 	/* expect+1: redundant cast from 'unsigned char' to 'unsigned int' before assignment [Q7] */
222 	bits.u9 = (typeof(bits.u9))u8;
223 
224 
225 	/* expect+2: no-op cast from 'float' to 'float' [Q6] */
226 	/* expect+1: redundant cast from 'float' to 'float' before assignment [Q7] */
227 	f32 = (f32_t)f32;
228 	f32 = (f32_t)f64;
229 	f32 = (f64_t)f32;
230 	/* expect+1: no-op cast from 'double' to 'double' [Q6] */
231 	f32 = (f64_t)f64;
232 	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
233 	f64 = (f32_t)f32;
234 	f64 = (f32_t)f64;
235 	/* expect+1: redundant cast from 'float' to 'double' before assignment [Q7] */
236 	f64 = (f64_t)f32;
237 	/* expect+2: no-op cast from 'double' to 'double' [Q6] */
238 	/* expect+1: redundant cast from 'double' to 'double' before assignment [Q7] */
239 	f64 = (f64_t)f64;
240 
241 
242 	/* expect+2: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
243 	/* expect+1: redundant cast from 'float _Complex' to 'float _Complex' before assignment [Q7] */
244 	c32 = (c32_t)c32;
245 	c32 = (c32_t)c64;
246 	c32 = (c64_t)c32;
247 	/* expect+1: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
248 	c32 = (c64_t)c64;
249 	/* expect+1: no-op cast from 'float _Complex' to 'float _Complex' [Q6] */
250 	c64 = (c32_t)c32;
251 	c64 = (c32_t)c64;
252 	/* expect+1: redundant cast from 'float _Complex' to 'double _Complex' before assignment [Q7] */
253 	c64 = (c64_t)c32;
254 	/* expect+2: no-op cast from 'double _Complex' to 'double _Complex' [Q6] */
255 	/* expect+1: redundant cast from 'double _Complex' to 'double _Complex' before assignment [Q7] */
256 	c64 = (c64_t)c64;
257 
258 
259 	/* Mixing real and complex floating point types. */
260 	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
261 	c32 = (f32_t)f32;
262 	c32 = (c32_t)f32;
263 	/* expect+1: no-op cast from 'float' to 'float' [Q6] */
264 	c64 = (f32_t)f32;
265 	c64 = (f64_t)f32;
266 	c64 = (c32_t)f32;
267 	c64 = (c64_t)f32;
268 
269 
270 	/*
271 	 * Converting a void pointer type to an object pointer type requires
272 	 * an explicit cast in C++, as it is a narrowing conversion. In C,
273 	 * that conversion is done implicitly.
274 	 */
275 
276 	/* expect+1: redundant cast from 'pointer to void' to 'pointer to char' before assignment [Q7] */
277 	str = (char *)allocate();
278 	/* expect+1: redundant cast from 'pointer to void' to 'pointer to const char' before assignment [Q7] */
279 	cstr = (const char *)allocate();
280 	cstr = (char *)allocate();
281 
282 	/* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
283 	/* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
284 	str = (str_t)str;
285 	str = (str_t)cstr;
286 	/* expect+1: warning: operator '=' discards 'const' from 'pointer to const char' [128] */
287 	str = (cstr_t)str;
288 	/* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
289 	/* expect+1: warning: operator '=' discards 'const' from 'pointer to const char' [128] */
290 	str = (cstr_t)cstr;
291 	/* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
292 	cstr = (str_t)str;
293 	cstr = (str_t)cstr;
294 	cstr = (cstr_t)str;
295 	/* expect+2: no-op cast from 'pointer to const char' to 'pointer to const char' [Q6] */
296 	/* expect+1: redundant cast from 'pointer to const char' to 'pointer to const char' before assignment [Q7] */
297 	cstr = (cstr_t)cstr;
298 
299 	/* expect+2: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
300 	/* expect+1: redundant cast from 'pointer to char' to 'pointer to char' before assignment [Q7] */
301 	str = (str_t)str;
302 	str = (str_t)vstr;
303 	/* expect+1: warning: operator '=' discards 'volatile' from 'pointer to volatile char' [128] */
304 	str = (vstr_t)str;
305 	/* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
306 	/* expect+1: warning: operator '=' discards 'volatile' from 'pointer to volatile char' [128] */
307 	str = (vstr_t)vstr;
308 	/* expect+1: no-op cast from 'pointer to char' to 'pointer to char' [Q6] */
309 	vstr = (str_t)str;
310 	vstr = (str_t)vstr;
311 	vstr = (vstr_t)str;
312 	/* expect+2: no-op cast from 'pointer to volatile char' to 'pointer to volatile char' [Q6] */
313 	/* expect+1: redundant cast from 'pointer to volatile char' to 'pointer to volatile char' before assignment [Q7] */
314 	vstr = (vstr_t)vstr;
315 
316 	/* expect+1: warning: operator '=' discards 'const volatile' from 'pointer to const volatile char' [128] */
317 	str = cvstr;
318 	/* expect+1: warning: operator '=' discards 'volatile' from 'pointer to const volatile char' [128] */
319 	cstr = cvstr;
320 	/* expect+1: warning: operator '=' discards 'const' from 'pointer to const volatile char' [128] */
321 	vstr = cvstr;
322 }
323 
324 /*
325  * Octal numbers were common in the 1970s, especially on 36-bit machines.
326  * 50 years later, they are still used in numeric file permissions.
327  */
328 void
329 Q8(void)
330 {
331 
332 	u16 = 0;
333 	/* expect+1: octal number '000000' [Q8] */
334 	u16 = 000000;
335 	/* expect+1: octal number '0123' [Q8] */
336 	u16 = 0123ULL;
337 	u16 = 1;
338 	u16 = 10;
339 	/* expect+1: octal number '0644' [Q8] */
340 	u16 = 0644;
341 	/* expect+1: octal number '0000644' [Q8] */
342 	u16 = 0000644;
343 }
344 
345 int
346 Q9(int x)
347 {
348 	switch (x) {
349 	case 0:
350 		return 0;
351 	case 1:
352 		/* expect+1: parenthesized return value [Q9] */
353 		return (0);
354 	case 2:
355 		return +(0);
356 	case 3:
357 		return -(13);
358 	case 4:
359 		/* expect+2: comma operator with types 'int' and 'int' [Q12] */
360 		/* expect+1: parenthesized return value [Q9] */
361 		return (0), (1);
362 	case 5:
363 		/* expect+2: comma operator with types 'int' and 'int' [Q12] */
364 		/* expect+1: parenthesized return value [Q9] */
365 		return (0, 1);
366 	case 6:
367 		/* expect+1: comma operator with types 'int' and 'int' [Q12] */
368 		return 0, 1;
369 	case 7:
370 		/* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */
371 		return 0.0;
372 	case 8:
373 		/* expect+2: parenthesized return value [Q9] */
374 		/* expect+1: implicit conversion from floating point 'double' to integer 'int' [Q1] */
375 		return (0.0);
376 	case 9:
377 		return
378 # 379 "queries.c" 3 4
379 		((void *)0)
380 # 381 "queries.c"
381 		/* expect+1: warning: illegal combination of integer 'int' and pointer 'pointer to void' [183] */
382 		;
383 	case 10:
384 		/* expect+1: warning: illegal combination of integer 'int' and pointer 'pointer to void' [183] */
385 		return (void *)(0);
386 	default:
387 		return 0;
388 	}
389 }
390 
391 void
392 Q10(void)
393 {
394 	int a, b, c;
395 
396 	/* expect+2: chained assignment with '=' and '=' [Q10] */
397 	/* expect+1: chained assignment with '=' and '=' [Q10] */
398 	a = b = c = 0;
399 
400 	/* expect+2: chained assignment with '*=' and '-=' [Q10] */
401 	/* expect+1: chained assignment with '+=' and '*=' [Q10] */
402 	a += b *= c -= 0;
403 }
404 
405 void
406 Q11(void)
407 {
408 	/* expect+1: static variable 'static_var_no_init' in function [Q11] */
409 	static int static_var_no_init;
410 	/* expect+1: static variable 'static_var_init' in function [Q11] */
411 	static int static_var_init = 1;
412 
413 	static_var_no_init++;
414 	static_var_init++;
415 }
416 
417 void
418 Q12(void)
419 {
420 	/* expect+1: comma operator with types 'void' and '_Bool' [Q12] */
421 	if (Q11(), cond)
422 		return;
423 
424 	/* expect+5: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
425 	/* expect+4: implicit conversion changes sign from 'int' to 'unsigned short' [Q3] */
426 	/* expect+3: implicit conversion changes sign from 'unsigned short' to 'int' [Q3] */
427 	/* expect+2: implicit conversion changes sign from 'int' to 'unsigned int' [Q3] */
428 	/* expect+1: comma operator with types 'unsigned short' and 'unsigned int' [Q12] */
429 	u16 += u8, u32 += u16;
430 }
431 
432 /* expect+1: redundant 'extern' in function declaration of 'extern_Q13' [Q13] */
433 extern void extern_Q13(void);
434 void extern_Q13(void);
435 /* expect+1: redundant 'extern' in function declaration of 'extern_Q13' [Q13] */
436 extern void extern_Q13(void), *extern_ptr;
437 
438 int
439 Q14(signed char sc, unsigned char uc, int wc)
440 {
441 	// Plain 'char' is platform-dependent, see queries-{schar,uchar}.c.
442 
443 	if (sc == 'c' || sc == L'w' || sc == 92 || sc == 0)
444 		return 2;
445 	/* expect+4: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
446 	/* expect+3: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
447 	/* expect+2: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
448 	/* expect+1: implicit conversion changes sign from 'unsigned char' to 'int' [Q3] */
449 	if (uc == 'c' || uc == L'w' || uc == 92 || uc == 0)
450 		return 3;
451 	if (wc == 'c' || wc == L'w' || wc == 92 || wc == 0)
452 		return 4;
453 	return 5;
454 }
455 
456 void *
457 Q15(void)
458 {
459 	/* expect+1: implicit conversion from integer 0 to pointer 'pointer to void' [Q15] */
460 	void *ptr_from_int = 0;
461 	/* expect+1: implicit conversion from integer 0 to pointer 'pointer to void' [Q15] */
462 	void *ptr_from_uint = 0U;
463 	/* expect+1: implicit conversion from integer 0 to pointer 'pointer to void' [Q15] */
464 	void *ptr_from_long = 0L;
465 
466 	ptr_from_int = &ptr_from_int;
467 	ptr_from_uint = &ptr_from_uint;
468 	ptr_from_long = &ptr_from_long;
469 
470 	void_ptr = (void *)0;
471 	const_void_ptr = (const void *)0;
472 
473 	/* expect+1: implicit conversion from integer 0 to pointer 'pointer to void' [Q15] */
474 	return 0;
475 }
476 
477 /*
478  * Even though C99 6.2.2p4 allows a 'static' declaration followed by a
479  * non-'static' declaration, it may look confusing.
480  */
481 static void Q16(void);
482 /* expect+3: 'Q16' was declared 'static', now non-'static' [Q16] */
483 /* expect+2: warning: static function 'Q16' unused [236] */
484 void
485 Q16(void)
486 {
487 }
488 
489 /* expect+1: invisible character U+0009 in character constant [Q17] */
490 char Q17_char[] = { ' ', '\0', '	' };
491 /* expect+1: invisible character U+0009 in string literal [Q17] */
492 char Q17_char_string[] = " \0	";
493 /* expect+1: invisible character U+0009 in character constant [Q17] */
494 int Q17_wide[] = { L' ', L'\0', L'	' };
495 /* expect+1: invisible character U+0009 in string literal [Q17] */
496 int Q17_wide_string[] = L" \0	";
497 
498 /* For Q18, see queries_schar.c and queries_uchar.c. */
499 
500 void
501 convert_from_integer_to_floating(void)
502 {
503 	/* expect+1: implicit conversion from integer 'unsigned int' to floating point 'float' [Q19] */
504 	f32 = 0xffff0000;
505 	/* expect+1: implicit conversion from integer 'unsigned int' to floating point 'float' [Q19] */
506 	f32 = 0xffffffff;
507 	/* expect+1: implicit conversion from integer 'int' to floating point 'float' [Q19] */
508 	f32 = s32;
509 	/* expect+1: implicit conversion from integer 'unsigned int' to floating point 'float' [Q19] */
510 	f32 = u32;
511 	/* expect+1: implicit conversion from integer 'int' to floating point 'double' [Q19] */
512 	f64 = s32;
513 	/* expect+1: implicit conversion from integer 'unsigned int' to floating point 'double' [Q19] */
514 	f64 = u32;
515 	/* expect+1: implicit conversion from integer 'long long' to floating point 'double' [Q19] */
516 	f64 = s64;
517 	/* expect+1: implicit conversion from integer 'unsigned long long' to floating point 'double' [Q19] */
518 	f64 = u64;
519 
520 	f32 = 0.0F;
521 	f32 = 0.0;
522 	f64 = 0.0;
523 
524 	f64 = (double)0;
525 	f64 = (double)u32;
526 }
527 
528 // C allows implicit narrowing conversions from a void pointer to an arbitrary
529 // object pointer. C++ doesn't allow this conversion since it is narrowing.
530 void
531 Q20_void_pointer_conversion(void)
532 {
533 	/* expect+1: warning: operator '=' discards 'const' from 'pointer to const void' [128] */
534 	void_ptr = const_void_ptr;
535 	const_void_ptr = void_ptr;
536 	/* expect+1: implicit narrowing conversion from void pointer to 'pointer to int' [Q20] */
537 	int_ptr = void_ptr;
538 	/* expect+1: redundant cast from 'pointer to void' to 'pointer to int' before assignment [Q7] */
539 	int_ptr = (int *)void_ptr;
540 	/* expect+1: implicit narrowing conversion from void pointer to 'pointer to char' [Q20] */
541 	char_ptr = void_ptr;
542 	void_ptr = char_ptr;
543 	/* expect+1: implicit narrowing conversion from void pointer to 'pointer to int' [Q20] */
544 	int_ptr = void_ptr;
545 	/* expect+1: warning: illegal combination of 'pointer to int' and 'pointer to char', op '=' [124] */
546 	int_ptr = char_ptr;
547 	/* expect+1: warning: illegal combination of 'pointer to char' and 'pointer to int', op '=' [124] */
548 	char_ptr = int_ptr;
549 
550 	int_ptr = (void *)0;
551 }
552 
553 /*
554  * Q21, Q22, Q23 and Q24 detect typedefs for struct and union types and
555  * pointers to them. By using the tagged types directly instead of their
556  * typedefs, it may be possible to save including some system headers.
557  */
558 
559 struct struct_tag {
560 };
561 union union_tag {
562 };
563 
564 /* expect+2: typedef 'struct_typedef' of struct type 'struct struct_tag' [Q21] */
565 /* expect+1: typedef 'struct_ptr' of pointer to struct type 'pointer to struct struct_tag' [Q23] */
566 typedef struct struct_tag struct_typedef, *struct_ptr;
567 /* expect+2: typedef 'union_typedef' of union type 'union union_tag' [Q22] */
568 /* expect+1: typedef 'union_ptr' of pointer to union type 'pointer to union union_tag' [Q24] */
569 typedef union union_tag union_typedef, *union_ptr;
570 typedef int int_typedef, *int_pointer;
571 typedef void (function_typedef)(int), (*function_ptr)(int);
572