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