Home | History | Annotate | Line # | Download | only in lint1
msg_132.c revision 1.22
      1 /*	$NetBSD: msg_132.c,v 1.22 2022/07/06 21:59:06 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 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
    294 	u8 = u64 % u8;
    295 
    296 	/* The result is between 0 and 1000. */
    297 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
    298 	u8 = u64 % 1000;
    299 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned short' may lose accuracy [132] */
    300 	u16 = u64 % 1000;
    301 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */
    302 	bits.u9 = u64 % 1000;
    303 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:10' may lose accuracy [132] */
    304 	bits.u10 = u64 % 1000;
    305 
    306 	/*
    307 	 * For signed division, if the result of 'a / b' is not representable
    308 	 * exactly, the result of 'a % b' is defined such that
    309 	 * '(a / b) * a + a % b == a'.
    310 	 *
    311 	 * If the result of 'a / b' is not representable exactly, the result
    312 	 * of 'a % b' is not defined.
    313 	 *
    314 	 * C90 6.3.5, C99 6.5.5.
    315 	 */
    316 }
    317