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