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