1/* $NetBSD: msg_132.c,v 1.40 2024/05/01 05:49:33 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 18typedef unsigned char u8_t; 19typedef unsigned short u16_t; 20typedef unsigned int u32_t; 21typedef unsigned long long u64_t; 22typedef signed char s8_t; 23typedef signed short s16_t; 24typedef signed int s32_t; 25typedef signed long long s64_t; 26 27_Bool cond; 28char ch; 29 30u8_t u8; 31u16_t u16; 32u32_t u32; 33u64_t u64; 34 35s8_t s8; 36s16_t s16; 37s32_t s32; 38s64_t s64; 39 40struct 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 57void 58unsigned_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 83void 84unsigned_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 109void 110signed_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 135void 136signed_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 167to_bool(long a, long b) 168{ 169 /* seen in fp_lib.h, function wideRightShiftWithSticky */ 170 return a | b; 171} 172 173/* ARGSUSED */ 174const char * 175cover_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 184int 185non_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 */ 209static inline u16_t 210be16dec(const void *buf) 211{ 212 const u8_t *p = buf; 213 214 /* 215 * Before tree.c 1.444 from 2022-05-26, lint complained that the 216 * conversion from 'int' to 'unsigned short' may lose accuracy. 217 */ 218 return ((u16_t)p[0]) << 8 | p[1]; 219} 220 221/* 222 * Since tree.c 1.434 from 2022-04-19, lint infers the possible values of 223 * expressions of the form 'integer & constant', see can_represent. 224 */ 225static inline void 226be32enc(void *buf, u32_t u) 227{ 228 u8_t *p = buf; 229 230 p[0] = u >> 24 & 0xff; 231 p[1] = u >> 16 & 0xff; 232 p[2] = u >> 8 & 0xff; 233 p[3] = u & 0xff; 234} 235 236u32_t 237test_ic_shr(u64_t x) 238{ 239 if (x > 3) 240 return x >> 32; 241 if (x > 2) 242 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 243 return x >> 31; 244 245 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 246 u32 = u64 >> 31; 247 u32 = u64 >> 32; 248 u16 = u64 >> 48; 249 u8 = u64 >> 56; 250 u16 = u32 >> 16; 251 u8 = u32 >> 24; 252 u8 = u16 >> 8; 253 254 /* 255 * No matter whether the big integer is signed or unsigned, the 256 * result of '&' is guaranteed to be an unsigned value. 257 */ 258 u8 = (s64 & 0xf0) >> 4; 259 u8 = (s8 & 0xf0) >> 4; 260 261 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 262 return x; 263} 264 265unsigned char 266test_bit_fields(unsigned long long m) 267{ 268 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:3' may lose accuracy [132] */ 269 bits.u3 = bits.u32 & m; 270 271 bits.u5 = bits.u3 & m; 272 bits.u32 = bits.u5 & m; 273 274 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 275 return bits.u32 & m; 276} 277 278/* 279 * Traditional C has an extra rule that the right-hand operand of a bit shift 280 * operator is converted to 'int'. Before tree.c 1.467 from 2022-07-02, this 281 * conversion was implemented as a CVT node, which means a cast, not an 282 * implicit conversion. Changing the CVT to NOOP would have caused a wrong 283 * warning 'may lose accuracy' in language levels other than traditional C. 284 */ 285 286u64_t 287u64_shl(u64_t lhs, u64_t rhs) 288{ 289 return lhs << rhs; 290} 291 292u64_t 293u64_shr(u64_t lhs, u64_t rhs) 294{ 295 return lhs >> rhs; 296} 297 298s64_t 299s64_shl(s64_t lhs, s64_t rhs) 300{ 301 return lhs << rhs; 302} 303 304s64_t 305s64_shr(s64_t lhs, s64_t rhs) 306{ 307 return lhs >> rhs; 308} 309 310void 311test_ic_mod(void) 312{ 313 /* The result is between 0 and 254. */ 314 u8 = u64 % u8; 315 316 /* The result is between 0 and 255. */ 317 u8 = u64 % 256; 318 319 /* The result is between 0 and 256. */ 320 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 321 u8 = u64 % 257; 322 323 /* The result is between 0 and 1000. */ 324 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 325 u8 = u64 % 1000; 326 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */ 327 bits.u9 = u64 % 1000; 328 bits.u10 = u64 % 1000; 329 u16 = u64 % 1000; 330 331 /* 332 * For signed division, if the result of 'a / b' is not representable 333 * exactly, the result of 'a % b' is defined such that 334 * '(a / b) * a + a % b == a'. 335 * 336 * If the result of 'a / b' is not representable exactly, the result 337 * of 'a % b' is not defined. Due to this uncertainty, lint does not 338 * narrow down the range for signed modulo expressions. 339 * 340 * C90 6.3.5, C99 6.5.5. 341 */ 342 343 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ 344 s8 = s16 % s8; 345 346 /* 347 * The result is always 0, it's a theoretical edge case though, so 348 * lint doesn't care to implement this. 349 */ 350 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ 351 s8 = s64 % 1; 352} 353 354void 355test_ic_bitand(void) 356{ 357 /* 358 * ic_bitand assumes that integers are represented in 2's complement, 359 * and that the sign bit of signed integers behaves like a value bit. 360 * That way, the following expressions get their constraints computed 361 * correctly, regardless of whether ic_expr takes care of integer 362 * promotions or not. Compare ic_mod, which ignores signed types. 363 */ 364 365 u8 = u8 & u16; 366 367 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */ 368 u8 = u16 & u32; 369} 370 371void 372test_ic_cvt(void) 373{ 374 u16 = (u32 & 0x0000ff00); 375 u16 = (u32_t)(u32 & 0x0000ff00); 376} 377 378void 379test_ic_conditional(char c1, char c2) 380{ 381 /* Both operands are representable as char. */ 382 ch = cond ? '?' : ':'; 383 384 /* 385 * Both operands are representable as char. Clang-Tidy 17 wrongly 386 * warns about a narrowing conversion from 'int' to signed type 387 * 'char'. 388 */ 389 ch = cond ? c1 : c2; 390 391 /* 392 * Mixing s8 and u8 results in a number from -128 to 255, which does 393 * not necessarily fit into s8. 394 */ 395 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ 396 s8 = cond ? s8 : u8; 397 398 /* 399 * Mixing s8 and u8 results in a number from -128 to 255, which does 400 * not necessarily fit into u8. 401 */ 402 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 403 u8 = cond ? s8 : u8; 404} 405 406void 407compare_bit_field_to_integer_constant(void) 408{ 409 static _Bool b; 410 static struct { 411 short s16:15; 412 unsigned short u16:15; 413 int s32:15; 414 unsigned u32:15; 415 long long s64:15; 416 unsigned long long u64:15; 417 } s; 418 419 // Since decl.c 1.180 from 2021-05-02 and before tree.c 1.624 from 420 // 2024-03-12, lint warned about a possible loss of accuracy [132] 421 // when promoting an 'unsigned long long' bit-field to 'int'. 422 b = s.s16 == 0; 423 b = s.u16 == 0; 424 b = s.s32 == 0; 425 b = s.u32 == 0; 426 b = s.s64 == 0; 427 b = s.u64 == 0; 428 b = !b; 429} 430 431/* 432 * Before tree.c 1.626 from 2024-03-26, the usual arithmetic conversions for 433 * bit-field types with the same base type but different widths simply took 434 * the type of the left operand, leading to wrong warnings about loss of 435 * accuracy when the right operand was wider than the left operand. 436 */ 437void 438binary_operators_on_bit_fields(void) 439{ 440 struct { 441 u64_t u15:15; 442 u64_t u48:48; 443 u64_t u64; 444 } s = { 0, 0, 0 }; 445 446 u64 = s.u15 | s.u48; 447 u64 = s.u48 | s.u15; 448 u64 = s.u15 | s.u48 | s.u64; 449 u64 = s.u64 | s.u48 | s.u15; 450 cond = (s.u15 | s.u48 | s.u64) != 0; 451 cond = (s.u64 | s.u48 | s.u15) != 0; 452 453 // Before tree.c from 1.638 from 2024-05-01, lint wrongly warned: 454 // warning: conversion of 'int' to 'int:4' is out of range [119] 455 s32 = 8 - bits.u3; 456} 457