queries.c revision 1.35 1 /* $NetBSD: queries.c,v 1.35 2025/04/12 15:49:50 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: invalid combination of integer 'int' and pointer 'pointer to void' for 'return' [183] */
382 ;
383 case 10:
384 /* expect+1: warning: invalid combination of integer 'int' and pointer 'pointer to void' for 'return' [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: invalid combination of 'pointer to int' and 'pointer to char', op '=' [124] */
546 int_ptr = char_ptr;
547 /* expect+1: warning: invalid 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