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