xref: /netbsd-src/tests/usr.bin/xlint/lint1/msg_132.c (revision 7d62b00eb9ad855ffcd7da46b41e23feb5476fac)
1 /*	$NetBSD: msg_132.c,v 1.25 2023/01/29 17:02:09 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 
241 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
242 	u32 = u64 >> 31;
243 	u32 = u64 >> 32;
244 	u16 = u64 >> 48;
245 	u8 = u64 >> 56;
246 	u16 = u32 >> 16;
247 	u8 = u32 >> 24;
248 	u8 = u16 >> 8;
249 
250 	/*
251 	 * No matter whether the big integer is signed or unsigned, the
252 	 * result of '&' is guaranteed to be an unsigned value.
253 	 */
254 	u8 = (s64 & 0xf0) >> 4;
255 	u8 = (s8 & 0xf0) >> 4;
256 
257 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
258 	return x;
259 }
260 
261 unsigned char
262 test_bit_fields(unsigned long long m)
263 {
264 	/* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned int:3' may lose accuracy [132] */
265 	bits.u3 = bits.u32 & m;
266 
267 	bits.u5 = bits.u3 & m;
268 	bits.u32 = bits.u5 & m;
269 
270 	/* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned char' may lose accuracy [132] */
271 	return bits.u32 & m;
272 }
273 
274 /*
275  * Traditional C has an extra rule that the right-hand operand of a bit shift
276  * operator is converted to 'int'.  Before tree.c 1.467 from 2022-07-02, this
277  * conversion was implemented as a CVT node, which means a cast, not an
278  * implicit conversion.  Changing the CVT to NOOP would have caused a wrong
279  * warning 'may lose accuracy' in language levels other than traditional C.
280  */
281 
282 u64_t
283 u64_shl(u64_t lhs, u64_t rhs)
284 {
285 	return lhs << rhs;
286 }
287 
288 u64_t
289 u64_shr(u64_t lhs, u64_t rhs)
290 {
291 	return lhs >> rhs;
292 }
293 
294 s64_t
295 s64_shl(s64_t lhs, s64_t rhs)
296 {
297 	return lhs << rhs;
298 }
299 
300 s64_t
301 s64_shr(s64_t lhs, s64_t rhs)
302 {
303 	return lhs >> rhs;
304 }
305 
306 void
307 test_ic_mod(void)
308 {
309 	/* The result is between 0 and 254. */
310 	u8 = u64 % u8;
311 
312 	/* The result is between 0 and 255. */
313 	u8 = u64 % 256;
314 
315 	/* The result is between 0 and 256. */
316 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
317 	u8 = u64 % 257;
318 
319 	/* The result is between 0 and 1000. */
320 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
321 	u8 = u64 % 1000;
322 	/* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */
323 	bits.u9 = u64 % 1000;
324 	bits.u10 = u64 % 1000;
325 	u16 = u64 % 1000;
326 
327 	/*
328 	 * For signed division, if the result of 'a / b' is not representable
329 	 * exactly, the result of 'a % b' is defined such that
330 	 * '(a / b) * a + a % b == a'.
331 	 *
332 	 * If the result of 'a / b' is not representable exactly, the result
333 	 * of 'a % b' is not defined.  Due to this uncertainty, lint does not
334 	 * narrow down the range for signed modulo expressions.
335 	 *
336 	 * C90 6.3.5, C99 6.5.5.
337 	 */
338 
339 	/* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
340 	s8 = s16 % s8;
341 
342 	/*
343 	 * The result is always 0, it's a theoretical edge case though, so
344 	 * lint doesn't care to implement this.
345 	 */
346 	/* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
347 	s8 = s64 % 1;
348 }
349 
350 void
351 test_ic_bitand(void)
352 {
353 	/*
354 	 * ic_bitand assumes that integers are represented in 2's complement,
355 	 * and that the sign bit of signed integers behaves like a value bit.
356 	 * That way, the following expressions get their constraints computed
357 	 * correctly, regardless of whether ic_expr takes care of integer
358 	 * promotions or not.  Compare ic_mod, which ignores signed types.
359 	 */
360 
361 	u8 = u8 & u16;
362 
363 	/* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */
364 	u8 = u16 & u32;
365 }
366