Home | History | Annotate | Line # | Download | only in lint1
msg_132.c revision 1.43
      1 /*	$NetBSD: msg_132.c,v 1.43 2024/10/08 19:39:54 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 static inline u16_t
    210 be16dec(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  */
    225 static inline void
    226 be32enc(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 
    236 void
    237 test_ic_mult(void)
    238 {
    239 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    240 	u32 = u16 * 65536ULL;
    241 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    242 	u32 = u16 * 65537ULL;
    243 
    244 	/* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
    245 	u16 = 0 * u16;
    246 	/* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
    247 	u16 = 1 * u16;
    248 	/* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
    249 	u16 = 2 * u16;
    250 
    251 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    252 	u32 = (u16 & 1023ULL) / 1ULL * 1024ULL | (u16 & 1023ULL) / 1ULL * 1ULL;
    253 }
    254 
    255 u32_t
    256 test_ic_shr(u64_t x)
    257 {
    258 	if (x > 3)
    259 		return x >> 32;
    260 	if (x > 2)
    261 		/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    262 		return x >> 31;
    263 
    264 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    265 	u32 = u64 >> 31;
    266 	u32 = u64 >> 32;
    267 	u16 = u64 >> 48;
    268 	u8 = u64 >> 56;
    269 	u16 = u32 >> 16;
    270 	u8 = u32 >> 24;
    271 	u8 = u16 >> 8;
    272 
    273 	/*
    274 	 * No matter whether the big integer is signed or unsigned, the
    275 	 * result of '&' is guaranteed to be an unsigned value.
    276 	 */
    277 	u8 = (s64 & 0xf0) >> 4;
    278 	u8 = (s8 & 0xf0) >> 4;
    279 
    280 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
    281 	return x;
    282 }
    283 
    284 unsigned char
    285 test_bit_fields(unsigned long long m)
    286 {
    287 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:3' may lose accuracy [132] */
    288 	bits.u3 = bits.u32 & m;
    289 
    290 	bits.u5 = bits.u3 & m;
    291 	bits.u32 = bits.u5 & m;
    292 
    293 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
    294 	return bits.u32 & m;
    295 }
    296 
    297 /*
    298  * Traditional C has an extra rule that the right-hand operand of a bit shift
    299  * operator is converted to 'int'.  Before tree.c 1.467 from 2022-07-02, this
    300  * conversion was implemented as a CVT node, which means a cast, not an
    301  * implicit conversion.  Changing the CVT to NOOP would have caused a wrong
    302  * warning 'may lose accuracy' in language levels other than traditional C.
    303  */
    304 
    305 u64_t
    306 u64_shl(u64_t lhs, u64_t rhs)
    307 {
    308 	return lhs << rhs;
    309 }
    310 
    311 u64_t
    312 u64_shr(u64_t lhs, u64_t rhs)
    313 {
    314 	return lhs >> rhs;
    315 }
    316 
    317 s64_t
    318 s64_shl(s64_t lhs, s64_t rhs)
    319 {
    320 	return lhs << rhs;
    321 }
    322 
    323 s64_t
    324 s64_shr(s64_t lhs, s64_t rhs)
    325 {
    326 	return lhs >> rhs;
    327 }
    328 
    329 void
    330 test_ic_mod(void)
    331 {
    332 	/* The result is between 0 and 254. */
    333 	u8 = u64 % u8;
    334 
    335 	/* The result is between 0 and 255. */
    336 	u8 = u64 % 256;
    337 
    338 	/* The result is between 0 and 256. */
    339 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
    340 	u8 = u64 % 257;
    341 
    342 	/* The result is between 0 and 1000. */
    343 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
    344 	u8 = u64 % 1000;
    345 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */
    346 	bits.u9 = u64 % 1000;
    347 	bits.u10 = u64 % 1000;
    348 	u16 = u64 % 1000;
    349 
    350 	/*
    351 	 * For signed division, if the result of 'a / b' is not representable
    352 	 * exactly, the result of 'a % b' is defined such that
    353 	 * '(a / b) * a + a % b == a'.
    354 	 *
    355 	 * If the result of 'a / b' is not representable exactly, the result
    356 	 * of 'a % b' is not defined.  Due to this uncertainty, lint does not
    357 	 * narrow down the range for signed modulo expressions.
    358 	 *
    359 	 * C90 6.3.5, C99 6.5.5.
    360 	 */
    361 
    362 	/* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
    363 	s8 = s16 % s8;
    364 
    365 	/*
    366 	 * The result is always 0, it's a theoretical edge case though, so
    367 	 * lint doesn't care to implement this.
    368 	 */
    369 	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
    370 	s8 = s64 % 1;
    371 }
    372 
    373 void
    374 test_ic_bitand(void)
    375 {
    376 	/*
    377 	 * ic_bitand assumes that integers are represented in 2's complement,
    378 	 * and that the sign bit of signed integers behaves like a value bit.
    379 	 * That way, the following expressions get their constraints computed
    380 	 * correctly, regardless of whether ic_expr takes care of integer
    381 	 * promotions or not.  Compare ic_mod, which ignores signed types.
    382 	 */
    383 
    384 	u8 = u8 & u16;
    385 
    386 	/* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */
    387 	u8 = u16 & u32;
    388 }
    389 
    390 void
    391 test_ic_cvt(void)
    392 {
    393 	u16 = (u32 & 0x0000ff00);
    394 	u16 = (u32_t)(u32 & 0x0000ff00);
    395 }
    396 
    397 void
    398 test_ic_conditional(char c1, char c2)
    399 {
    400 	/* Both operands are representable as char. */
    401 	ch = cond ? '?' : ':';
    402 
    403 	/*
    404 	 * Both operands are representable as char. Clang-Tidy 17 wrongly
    405 	 * warns about a narrowing conversion from 'int' to signed type
    406 	 * 'char'.
    407 	 */
    408 	ch = cond ? c1 : c2;
    409 
    410 	/*
    411 	 * Mixing s8 and u8 results in a number from -128 to 255, which does
    412 	 * not necessarily fit into s8.
    413 	 */
    414 	/* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
    415 	s8 = cond ? s8 : u8;
    416 
    417 	/*
    418 	 * Mixing s8 and u8 results in a number from -128 to 255, which does
    419 	 * not necessarily fit into u8.
    420 	 */
    421 	/* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
    422 	u8 = cond ? s8 : u8;
    423 }
    424 
    425 void
    426 compare_bit_field_to_integer_constant(void)
    427 {
    428 	static _Bool b;
    429 	static struct {
    430 		short s16:15;
    431 		unsigned short u16:15;
    432 		int s32:15;
    433 		unsigned u32:15;
    434 		long long s64:15;
    435 		unsigned long long u64:15;
    436 	} s;
    437 
    438 	// Since decl.c 1.180 from 2021-05-02 and before tree.c 1.624 from
    439 	// 2024-03-12, lint warned about a possible loss of accuracy [132]
    440 	// when promoting an 'unsigned long long' bit-field to 'int'.
    441 	b = s.s16 == 0;
    442 	b = s.u16 == 0;
    443 	b = s.s32 == 0;
    444 	b = s.u32 == 0;
    445 	b = s.s64 == 0;
    446 	b = s.u64 == 0;
    447 	b = !b;
    448 }
    449 
    450 /*
    451  * Before tree.c 1.626 from 2024-03-26, the usual arithmetic conversions for
    452  * bit-field types with the same base type but different widths simply took
    453  * the type of the left operand, leading to wrong warnings about loss of
    454  * accuracy when the right operand was wider than the left operand.
    455  */
    456 void
    457 binary_operators_on_bit_fields(void)
    458 {
    459 	struct {
    460 		u64_t u15:15;
    461 		u64_t u48:48;
    462 		u64_t u64;
    463 	} s = { 0, 0, 0 };
    464 
    465 	u64 = s.u15 | s.u48;
    466 	u64 = s.u48 | s.u15;
    467 	u64 = s.u15 | s.u48 | s.u64;
    468 	u64 = s.u64 | s.u48 | s.u15;
    469 	cond = (s.u15 | s.u48 | s.u64) != 0;
    470 	cond = (s.u64 | s.u48 | s.u15) != 0;
    471 
    472 	// Before tree.c from 1.638 from 2024-05-01, lint wrongly warned:
    473 	// warning: conversion of 'int' to 'int:4' is out of range [119]
    474 	s32 = 8 - bits.u3;
    475 }
    476 
    477 unsigned char
    478 combine_arithmetic_and_bit_operations(void)
    479 {
    480 	return 0xc0 | (u32 & 0x07c0) / 64;
    481 }
    482