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