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