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