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