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