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
18typedef unsigned char u8_t;
19typedef unsigned short u16_t;
20typedef unsigned int u32_t;
21typedef unsigned long long u64_t;
22typedef signed char s8_t;
23typedef signed short s16_t;
24typedef signed int s32_t;
25typedef signed long long s64_t;
26
27_Bool cond;
28char ch;
29
30u8_t u8;
31u16_t u16;
32u32_t u32;
33u64_t u64;
34
35s8_t s8;
36s16_t s16;
37s32_t s32;
38s64_t s64;
39
40struct 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
57void
58unsigned_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
83void
84unsigned_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
109void
110signed_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
135void
136signed_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
167to_bool(long a, long b)
168{
169	/* seen in fp_lib.h, function wideRightShiftWithSticky */
170	return a | b;
171}
172
173/* ARGSUSED */
174const char *
175cover_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
184int
185non_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 */
209static inline u16_t
210be16dec(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 */
225static inline void
226be32enc(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
236u32_t
237test_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
265unsigned char
266test_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
286u64_t
287u64_shl(u64_t lhs, u64_t rhs)
288{
289	return lhs << rhs;
290}
291
292u64_t
293u64_shr(u64_t lhs, u64_t rhs)
294{
295	return lhs >> rhs;
296}
297
298s64_t
299s64_shl(s64_t lhs, s64_t rhs)
300{
301	return lhs << rhs;
302}
303
304s64_t
305s64_shr(s64_t lhs, s64_t rhs)
306{
307	return lhs >> rhs;
308}
309
310void
311test_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
354void
355test_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
371void
372test_ic_cvt(void)
373{
374	u16 = (u32 & 0x0000ff00);
375	u16 = (u32_t)(u32 & 0x0000ff00);
376}
377
378void
379test_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
406void
407compare_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 */
437void
438binary_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