1 /* $NetBSD: msg_132.c,v 1.46 2024/10/12 09:45:26 rillig Exp $ */ 2 # 3 "msg_132.c" 3 4 // Test for message: conversion from '%s' to '%s' may lose accuracy [132] 5 6 /* lint1-extra-flags: -X 351 */ 7 8 /* 9 * NetBSD's default lint flags only include a single -a, which only flags 10 * narrowing conversions from long. To get warnings for all narrowing 11 * conversions, -a needs to be given more than once. 12 * 13 * https://gnats.netbsd.org/14531 14 */ 15 16 /* lint1-extra-flags: -aa */ 17 18 typedef unsigned char u8_t; 19 typedef unsigned short u16_t; 20 typedef unsigned int u32_t; 21 typedef unsigned long long u64_t; 22 typedef signed char s8_t; 23 typedef signed short s16_t; 24 typedef signed int s32_t; 25 typedef signed long long s64_t; 26 27 _Bool cond; 28 char ch; 29 30 u8_t u8; 31 u16_t u16; 32 u32_t u32; 33 u64_t u64; 34 35 s8_t s8; 36 s16_t s16; 37 s32_t s32; 38 s64_t s64; 39 40 struct bit_fields { 41 unsigned u1:1; 42 unsigned u2:2; 43 unsigned u3:3; 44 unsigned u4:4; 45 unsigned u5:5; 46 unsigned u6:6; 47 unsigned u7:7; 48 unsigned u8:8; 49 unsigned u9:9; 50 unsigned u10:10; 51 unsigned u11:11; 52 unsigned u12:12; 53 unsigned u32:32; 54 } bits; 55 56 57 void 58 unsigned_to_unsigned(void) 59 { 60 /* expect+1: warning: conversion from 'unsigned short' to 'unsigned char' may lose accuracy [132] */ 61 u8 = u16; 62 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */ 63 u8 = u32; 64 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 65 u8 = u64; 66 67 u16 = u8; 68 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */ 69 u16 = u32; 70 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned short' may lose accuracy [132] */ 71 u16 = u64; 72 73 u32 = u8; 74 u32 = u16; 75 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 76 u32 = u64; 77 78 u64 = u8; 79 u64 = u16; 80 u64 = u32; 81 } 82 83 void 84 unsigned_to_signed(void) 85 { 86 /* expect+1: warning: conversion from 'unsigned short' to 'signed char' may lose accuracy [132] */ 87 s8 = u16; 88 /* expect+1: warning: conversion from 'unsigned int' to 'signed char' may lose accuracy [132] */ 89 s8 = u32; 90 /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */ 91 s8 = u64; 92 93 s16 = u8; 94 /* expect+1: warning: conversion from 'unsigned int' to 'short' may lose accuracy [132] */ 95 s16 = u32; 96 /* expect+1: warning: conversion from 'unsigned long long' to 'short' may lose accuracy [132] */ 97 s16 = u64; 98 99 s32 = u8; 100 s32 = u16; 101 /* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */ 102 s32 = u64; 103 104 s64 = u8; 105 s64 = u16; 106 s64 = u32; 107 } 108 109 void 110 signed_to_unsigned(void) 111 { 112 /* expect+1: warning: conversion from 'short' to 'unsigned char' may lose accuracy [132] */ 113 u8 = s16; 114 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 115 u8 = s32; 116 /* expect+1: warning: conversion from 'long long' to 'unsigned char' may lose accuracy [132] */ 117 u8 = s64; 118 119 u16 = s8; 120 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ 121 u16 = s32; 122 /* expect+1: warning: conversion from 'long long' to 'unsigned short' may lose accuracy [132] */ 123 u16 = s64; 124 125 u32 = s8; 126 u32 = s16; 127 /* expect+1: warning: conversion from 'long long' to 'unsigned int' may lose accuracy [132] */ 128 u32 = s64; 129 130 u64 = s8; 131 u64 = s16; 132 u64 = s32; 133 } 134 135 void 136 signed_to_signed(void) 137 { 138 /* expect+1: warning: conversion from 'short' to 'signed char' may lose accuracy [132] */ 139 s8 = s16; 140 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ 141 s8 = s32; 142 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ 143 s8 = s64; 144 145 s16 = s8; 146 /* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */ 147 s16 = s32; 148 /* expect+1: warning: conversion from 'long long' to 'short' may lose accuracy [132] */ 149 s16 = s64; 150 151 s32 = s8; 152 s32 = s16; 153 /* expect+1: warning: conversion from 'long long' to 'int' may lose accuracy [132] */ 154 s32 = s64; 155 156 s64 = s8; 157 s64 = s16; 158 s64 = s32; 159 } 160 161 /* 162 * Before tree.c 1.268 from 2021-04-06, lint wrongly warned that conversion 163 * to _Bool might lose accuracy. C99 6.3.1.2 defines a special conversion 164 * rule from scalar to _Bool though by comparing the value to 0. 165 */ 166 _Bool 167 to_bool(long a, long b) 168 { 169 /* seen in fp_lib.h, function wideRightShiftWithSticky */ 170 return a | b; 171 } 172 173 /* ARGSUSED */ 174 const char * 175 cover_build_plus_minus(const char *arr, double idx) 176 { 177 if (idx > 0.0) 178 /* expect+2: error: operands of '+' have incompatible types 'pointer to const char' and 'double' [107] */ 179 /* expect+1: error: function 'cover_build_plus_minus' expects to return value [214] */ 180 return arr + idx; 181 return arr + (unsigned int)idx; 182 } 183 184 int 185 non_constant_expression(void) 186 { 187 /* 188 * Even though this variable definition looks like a constant, it 189 * does not fall within C's definition of an integer constant 190 * expression. Due to that, lint does not perform constant folding 191 * on the expression built from this variable and thus doesn't know 192 * that the conversion will always succeed. 193 */ 194 const int not_a_constant = 8; 195 /* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */ 196 return not_a_constant * 8ULL; 197 } 198 199 /* 200 * PR 36668 notices that lint wrongly complains about the possible loss. 201 * 202 * The expression 'u8_t << 8' is guaranteed to fit into an 'u16_t', and its 203 * lower 8 bits are guaranteed to be clear. 'u16_t | u8_t' is guaranteed to 204 * fit into 'u16_t'. 205 * 206 * Since tree.c 1.444 from 2022-05-26, lint tracks simple bitwise and 207 * arithmetic constraints across a single expression. 208 */ 209 void 210 be16dec(void) 211 { 212 /* 213 * Before tree.c 1.444 from 2022-05-26, lint complained that the 214 * conversion from 'int' to 'unsigned short' may lose accuracy. 215 */ 216 u16 = (u16_t)u8 << 8 | u8; 217 } 218 219 /* 220 * Since tree.c 1.434 from 2022-04-19, lint infers the possible values of 221 * expressions of the form 'integer & constant', see can_represent. 222 */ 223 void 224 be32enc(void) 225 { 226 u8 = u32 >> 24 & 0xff; 227 u8 = u32 >> 16 & 0xff; 228 u8 = u32 >> 8 & 0xff; 229 u8 = u32 & 0xff; 230 } 231 232 void 233 test_ic_mult(void) 234 { 235 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 236 u8 = u8 * u8; 237 u16 = u8 * u8; 238 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ 239 u16 = u16 * u8; 240 u32 = u16 * u16; 241 242 u32 = u16 * 65537ULL; 243 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 244 u32 = u16 * 65538ULL; 245 246 u16 = 0 * u16; 247 u16 = 1 * u16; 248 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ 249 u16 = 2 * u16; 250 251 // from __BITS, __SHIFTIN, __SHIFTOUT 252 u32 = (u16 & 1023ULL) / 1ULL * 1024ULL | (u16 & 1023ULL) / 1ULL * 1ULL; 253 } 254 255 void 256 test_ic_div(void) 257 { 258 // FIXME 259 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 260 u8 = u8 / u8; 261 // FIXME 262 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 263 u8 = u16 / u8; 264 // FIXME 265 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ 266 u16 = u8 / u8; 267 u16 = u32 / 65536; 268 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */ 269 u16 = u32 / 65535; 270 } 271 272 void 273 test_ic_mod(void) 274 { 275 /* The result is between 0 and 254. */ 276 u8 = u64 % u8; 277 278 /* The result is between 0 and 255. */ 279 u8 = u64 % 256; 280 281 /* The result is between 0 and 256. */ 282 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 283 u8 = u64 % 257; 284 285 /* The result is between 0 and 1000. */ 286 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 287 u8 = u64 % 1000; 288 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */ 289 bits.u9 = u64 % 1000; 290 bits.u10 = u64 % 1000; 291 u16 = u64 % 1000; 292 293 s8 = s16 % s8; 294 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ 295 s8 = s16 % s16; 296 s8 = s64 % 1; 297 s8 = s64 % (s16 & 1); 298 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ 299 s8 = s64 % (s16 & 0); 300 s8 = (s64 & 0x7f) % s64; 301 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ 302 s8 = (s64 & 0xff) % s64; 303 } 304 305 void 306 test_ic_shl(void) 307 { 308 u64 = u64 << u64; 309 s64 = s64 << s64; 310 311 u16 = u8 << 8; 312 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ 313 u16 = u8 << 9; 314 u32 = u16 << 16; 315 // XXX: missing warning as UINT has the same rank as INT, see portable_rank_cmp. 316 u32 = u16 << 17; 317 /* expect+1: warning: shift amount 56 is greater than bit-size 32 of 'int' [122] */ 318 u64 = u8 << 56; 319 u64 = (u64_t)u8 << 56; 320 // XXX: missing warning, as the operand types of '=' are the same, thus no conversion. 321 u64 = (u64_t)u8 << 57; 322 /* expect+1: warning: shift amount 48 is greater than bit-size 32 of 'int' [122] */ 323 u64 = u16 << 48; 324 u64 = (u64_t)u16 << 48; 325 // XXX: missing warning, as the operand types of '=' are the same, thus no conversion. 326 u64 = (u64_t)u16 << 49; 327 /* expect+1: warning: shift amount 32 equals bit-size of 'unsigned int' [267] */ 328 u64 = u32 << 32; 329 u64 = (u64_t)u32 << 32; 330 // XXX: missing warning, as the operand types of '=' are the same, thus no conversion. 331 u64 = (u64_t)u32 << 33; 332 } 333 334 void 335 test_ic_shr(void) 336 { 337 u64 = u64 >> u64; 338 s64 = s64 >> s64; 339 340 u32 = u64 >> 32; 341 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 342 u32 = u64 >> 31; 343 u16 = u64 >> 48; 344 u16 = u32 >> 16; 345 u8 = u64 >> 56; 346 u8 = u32 >> 24; 347 u8 = u16 >> 8; 348 349 /* 350 * No matter whether the big integer is signed or unsigned, the 351 * result of '&' is guaranteed to be an unsigned value. 352 */ 353 u8 = (s64 & 0xf0) >> 4; 354 u8 = (s8 & 0xf0) >> 4; 355 } 356 357 void 358 test_ic_bitand(void) 359 { 360 u8 = u8 & u16; 361 362 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */ 363 u8 = u16 & u32; 364 } 365 366 void 367 test_ic_bitor(void) 368 { 369 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 370 u8 = u8 | u16; 371 u16 = u8 | u16; 372 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */ 373 u16 = u8 | u32; 374 u32 = u8 | u32; 375 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 376 u32 = u8 | u64; 377 u64 = u8 | u64; 378 } 379 380 void 381 test_ic_quest_colon(char c1, char c2) 382 { 383 /* Both operands are representable as char. */ 384 ch = cond ? '?' : ':'; 385 386 /* 387 * Both operands are representable as char. Clang-Tidy 17 wrongly 388 * warns about a narrowing conversion from 'int' to signed type 389 * 'char'. 390 */ 391 ch = cond ? c1 : c2; 392 393 /* 394 * Mixing s8 and u8 results in a number from -128 to 255, which neither 395 * fits in s8 nor u8. 396 */ 397 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ 398 s8 = cond ? s8 : u8; 399 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 400 u8 = cond ? s8 : u8; 401 } 402 403 void 404 test_ic_con(void) 405 { 406 /* expect+1: warning: assignment of negative constant -1 to unsigned type 'unsigned char' [164] */ 407 u8 = -1; 408 u8 = 0; 409 u8 = 255; 410 /* expect+1: warning: constant truncated by assignment [165] */ 411 u8 = 256; 412 413 /* expect+1: warning: conversion of 'int' to 'signed char' is out of range [119] */ 414 s8 = -129; 415 s8 = -128; 416 s8 = 127; 417 /* expect+1: warning: conversion of 'int' to 'signed char' is out of range [119] */ 418 s8 = 128; 419 } 420 421 void 422 test_ic_cvt(void) 423 { 424 u16 = (u32 & 0x0000ff00); 425 u16 = (u32_t)(u32 & 0x0000ff00); 426 u16 = (u16_t)u32; 427 u16 = (u8_t)(u32 & 0xffff) << 8; 428 } 429 430 unsigned char 431 test_bit_fields(unsigned long long m) 432 { 433 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:3' may lose accuracy [132] */ 434 bits.u3 = bits.u32 & m; 435 436 bits.u5 = bits.u3 & m; 437 bits.u32 = bits.u5 & m; 438 439 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 440 return bits.u32 & m; 441 } 442 443 void 444 compare_bit_field_to_integer_constant(void) 445 { 446 static _Bool b; 447 static struct { 448 short s16:15; 449 unsigned short u16:15; 450 int s32:15; 451 unsigned u32:15; 452 long long s64:15; 453 unsigned long long u64:15; 454 } s; 455 456 // Since decl.c 1.180 from 2021-05-02 and before tree.c 1.624 from 457 // 2024-03-12, lint warned about a possible loss of accuracy [132] 458 // when promoting an 'unsigned long long' bit-field to 'int'. 459 b = s.s16 == 0; 460 b = s.u16 == 0; 461 b = s.s32 == 0; 462 b = s.u32 == 0; 463 b = s.s64 == 0; 464 b = s.u64 == 0; 465 b = !b; 466 } 467 468 /* 469 * Before tree.c 1.626 from 2024-03-26, the usual arithmetic conversions for 470 * bit-field types with the same base type but different widths simply took 471 * the type of the left operand, leading to wrong warnings about loss of 472 * accuracy when the right operand was wider than the left operand. 473 */ 474 void 475 binary_operators_on_bit_fields(void) 476 { 477 struct { 478 u64_t u15:15; 479 u64_t u48:48; 480 u64_t u64; 481 } s = { 0, 0, 0 }; 482 483 u64 = s.u15 | s.u48; 484 u64 = s.u48 | s.u15; 485 u64 = s.u15 | s.u48 | s.u64; 486 u64 = s.u64 | s.u48 | s.u15; 487 cond = (s.u15 | s.u48 | s.u64) != 0; 488 cond = (s.u64 | s.u48 | s.u15) != 0; 489 490 // Before tree.c from 1.638 from 2024-05-01, lint wrongly warned: 491 // warning: conversion of 'int' to 'int:4' is out of range [119] 492 s32 = 8 - bits.u3; 493 } 494 495 unsigned char 496 combine_arithmetic_and_bit_operations(void) 497 { 498 return 0xc0 | (u32 & 0x07c0) / 64; 499 } 500