1 /* $NetBSD: msg_132.c,v 1.24 2022/07/07 18:11:29 rillig Exp $ */ 2 # 3 "msg_132.c" 3 4 // Test for message: conversion from '%s' to '%s' may lose accuracy [132] 5 6 /* 7 * NetBSD's default lint flags only include a single -a, which only flags 8 * narrowing conversions from long. To get warnings for all narrowing 9 * conversions, -a needs to be given more than once. 10 * 11 * https://gnats.netbsd.org/14531 12 */ 13 14 /* lint1-extra-flags: -aa */ 15 16 typedef unsigned char u8_t; 17 typedef unsigned short u16_t; 18 typedef unsigned int u32_t; 19 typedef unsigned long long u64_t; 20 typedef signed char s8_t; 21 typedef signed short s16_t; 22 typedef signed int s32_t; 23 typedef signed long long s64_t; 24 25 26 u8_t u8; 27 u16_t u16; 28 u32_t u32; 29 u64_t u64; 30 31 s8_t s8; 32 s16_t s16; 33 s32_t s32; 34 s64_t s64; 35 36 struct bit_fields { 37 unsigned u1:1; 38 unsigned u2:2; 39 unsigned u3:3; 40 unsigned u4:4; 41 unsigned u5:5; 42 unsigned u6:6; 43 unsigned u7:7; 44 unsigned u8:8; 45 unsigned u9:9; 46 unsigned u10:10; 47 unsigned u11:11; 48 unsigned u12:12; 49 unsigned u32:32; 50 } bits; 51 52 53 void 54 unsigned_to_unsigned(void) 55 { 56 /* expect+1: warning: conversion from 'unsigned short' to 'unsigned char' may lose accuracy [132] */ 57 u8 = u16; 58 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */ 59 u8 = u32; 60 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 61 u8 = u64; 62 63 u16 = u8; 64 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */ 65 u16 = u32; 66 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned short' may lose accuracy [132] */ 67 u16 = u64; 68 69 u32 = u8; 70 u32 = u16; 71 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 72 u32 = u64; 73 74 u64 = u8; 75 u64 = u16; 76 u64 = u32; 77 } 78 79 void 80 unsigned_to_signed(void) 81 { 82 /* expect+1: warning: conversion from 'unsigned short' to 'signed char' may lose accuracy [132] */ 83 s8 = u16; 84 /* expect+1: warning: conversion from 'unsigned int' to 'signed char' may lose accuracy [132] */ 85 s8 = u32; 86 /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */ 87 s8 = u64; 88 89 s16 = u8; 90 /* expect+1: warning: conversion from 'unsigned int' to 'short' may lose accuracy [132] */ 91 s16 = u32; 92 /* expect+1: warning: conversion from 'unsigned long long' to 'short' may lose accuracy [132] */ 93 s16 = u64; 94 95 s32 = u8; 96 s32 = u16; 97 /* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */ 98 s32 = u64; 99 100 s64 = u8; 101 s64 = u16; 102 s64 = u32; 103 } 104 105 void 106 signed_to_unsigned(void) 107 { 108 /* expect+1: warning: conversion from 'short' to 'unsigned char' may lose accuracy [132] */ 109 u8 = s16; 110 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */ 111 u8 = s32; 112 /* expect+1: warning: conversion from 'long long' to 'unsigned char' may lose accuracy [132] */ 113 u8 = s64; 114 115 u16 = s8; 116 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */ 117 u16 = s32; 118 /* expect+1: warning: conversion from 'long long' to 'unsigned short' may lose accuracy [132] */ 119 u16 = s64; 120 121 u32 = s8; 122 u32 = s16; 123 /* expect+1: warning: conversion from 'long long' to 'unsigned int' may lose accuracy [132] */ 124 u32 = s64; 125 126 u64 = s8; 127 u64 = s16; 128 u64 = s32; 129 } 130 131 void 132 signed_to_signed(void) 133 { 134 /* expect+1: warning: conversion from 'short' to 'signed char' may lose accuracy [132] */ 135 s8 = s16; 136 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ 137 s8 = s32; 138 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ 139 s8 = s64; 140 141 s16 = s8; 142 /* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */ 143 s16 = s32; 144 /* expect+1: warning: conversion from 'long long' to 'short' may lose accuracy [132] */ 145 s16 = s64; 146 147 s32 = s8; 148 s32 = s16; 149 /* expect+1: warning: conversion from 'long long' to 'int' may lose accuracy [132] */ 150 s32 = s64; 151 152 s64 = s8; 153 s64 = s16; 154 s64 = s32; 155 } 156 157 /* 158 * Before tree.c 1.268 from 2021-04-06, lint wrongly warned that conversion 159 * to _Bool might lose accuracy. C99 6.3.1.2 defines a special conversion 160 * rule from scalar to _Bool though by comparing the value to 0. 161 */ 162 _Bool 163 to_bool(long a, long b) 164 { 165 /* seen in fp_lib.h, function wideRightShiftWithSticky */ 166 return a | b; 167 } 168 169 /* ARGSUSED */ 170 const char * 171 cover_build_plus_minus(const char *arr, double idx) 172 { 173 /* expect+3: error: operands of '+' have incompatible types 'pointer' and 'double' [107] */ 174 /* expect+2: warning: function 'cover_build_plus_minus' expects to return value [214] */ 175 if (idx > 0.0) 176 return arr + idx; 177 return arr + (unsigned int)idx; 178 } 179 180 int 181 non_constant_expression(void) 182 { 183 /* 184 * Even though this variable definition looks like a constant, it 185 * does not fall within C's definition of an integer constant 186 * expression. Due to that, lint does not perform constant folding 187 * on the expression built from this variable and thus doesn't know 188 * that the conversion will always succeed. 189 */ 190 const int not_a_constant = 8; 191 /* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */ 192 return not_a_constant * 8ULL; 193 } 194 195 /* 196 * PR 36668 notices that lint wrongly complains about the possible loss. 197 * 198 * The expression 'u8_t << 8' is guaranteed to fit into an 'u16_t', and its 199 * lower 8 bits are guaranteed to be clear. 'u16_t | u8_t' is guaranteed to 200 * fit into 'u16_t'. 201 * 202 * Since tree.c 1.444 from 2022-05-26, lint tracks simple bitwise and 203 * arithmetic constraints across a single expression. 204 */ 205 static inline u16_t 206 be16dec(const void *buf) 207 { 208 const u8_t *p = buf; 209 210 /* 211 * Before tree.c 1.444 from 2022-05-26, lint complained that the 212 * conversion from 'int' to 'unsigned short' may lose accuracy. 213 */ 214 return ((u16_t)p[0]) << 8 | p[1]; 215 } 216 217 /* 218 * Since tree.c 1.434 from 2022-04-19, lint infers the possible values of 219 * expressions of the form 'integer & constant', see can_represent. 220 */ 221 static inline void 222 be32enc(void *buf, u32_t u) 223 { 224 u8_t *p = buf; 225 226 p[0] = u >> 24 & 0xff; 227 p[1] = u >> 16 & 0xff; 228 p[2] = u >> 8 & 0xff; 229 p[3] = u & 0xff; 230 } 231 232 u32_t 233 test_ic_shr(u64_t x) 234 { 235 if (x > 3) 236 return x >> 32; 237 if (x > 2) 238 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 239 return x >> 31; 240 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */ 241 return x; 242 } 243 244 unsigned char 245 test_bit_fields(unsigned long long m) 246 { 247 /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned int:3' may lose accuracy [132] */ 248 bits.u3 = bits.u32 & m; 249 250 bits.u5 = bits.u3 & m; 251 bits.u32 = bits.u5 & m; 252 253 /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned char' may lose accuracy [132] */ 254 return bits.u32 & m; 255 } 256 257 /* 258 * Traditional C has an extra rule that the right-hand operand of a bit shift 259 * operator is converted to 'int'. Before tree.c 1.467 from 2022-07-02, this 260 * conversion was implemented as a CVT node, which means a cast, not an 261 * implicit conversion. Changing the CVT to NOOP would have caused a wrong 262 * warning 'may lose accuracy' in language levels other than traditional C. 263 */ 264 265 u64_t 266 u64_shl(u64_t lhs, u64_t rhs) 267 { 268 return lhs << rhs; 269 } 270 271 u64_t 272 u64_shr(u64_t lhs, u64_t rhs) 273 { 274 return lhs >> rhs; 275 } 276 277 s64_t 278 s64_shl(s64_t lhs, s64_t rhs) 279 { 280 return lhs << rhs; 281 } 282 283 s64_t 284 s64_shr(s64_t lhs, s64_t rhs) 285 { 286 return lhs >> rhs; 287 } 288 289 void 290 test_ic_mod(void) 291 { 292 /* The result is between 0 and 254. */ 293 u8 = u64 % u8; 294 295 /* The result is between 0 and 255. */ 296 u8 = u64 % 256; 297 298 /* The result is between 0 and 256. */ 299 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 300 u8 = u64 % 257; 301 302 /* The result is between 0 and 1000. */ 303 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */ 304 u8 = u64 % 1000; 305 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */ 306 bits.u9 = u64 % 1000; 307 bits.u10 = u64 % 1000; 308 u16 = u64 % 1000; 309 310 /* 311 * For signed division, if the result of 'a / b' is not representable 312 * exactly, the result of 'a % b' is defined such that 313 * '(a / b) * a + a % b == a'. 314 * 315 * If the result of 'a / b' is not representable exactly, the result 316 * of 'a % b' is not defined. Due to this uncertainty, lint does not 317 * narrow down the range for signed modulo expressions. 318 * 319 * C90 6.3.5, C99 6.5.5. 320 */ 321 322 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */ 323 s8 = s16 % s8; 324 325 /* 326 * The result is always 0, it's a theoretical edge case though, so 327 * lint doesn't care to implement this. 328 */ 329 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */ 330 s8 = s64 % 1; 331 } 332 333 void 334 test_ic_bitand(void) 335 { 336 /* 337 * ic_bitand assumes that integers are represented in 2's complement, 338 * and that the sign bit of signed integers behaves like a value bit. 339 * That way, the following expressions get their constraints computed 340 * correctly, regardless of whether ic_expr takes care of integer 341 * promotions or not. Compare ic_mod, which ignores signed types. 342 */ 343 344 u8 = u8 & u16; 345 346 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */ 347 u8 = u16 & u32; 348 } 349