msg_132.c revision 1.51 1 /* $NetBSD: msg_132.c,v 1.51 2025/01/02 18:36:52 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 -X 351 */
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 _Bool cond;
26 char ch;
27
28 u8_t u8;
29 u16_t u16;
30 u32_t u32;
31 u64_t u64;
32
33 s8_t s8;
34 s16_t s16;
35 s32_t s32;
36 s64_t s64;
37
38 const char *ptr;
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 void
210 be16dec(void)
211 {
212 /*
213 * Before tree.c 1.444 from 2022-05-26, lint complained that the
214 * conversion from 'int' to 'unsigned short' may lose accuracy.
215 */
216 u16 = (u16_t)u8 << 8 | u8;
217 }
218
219 /*
220 * Since tree.c 1.434 from 2022-04-19, lint infers the possible values of
221 * expressions of the form 'integer & constant', see can_represent.
222 */
223 void
224 be32enc(void)
225 {
226 u8 = u32 >> 24 & 0xff;
227 u8 = u32 >> 16 & 0xff;
228 u8 = u32 >> 8 & 0xff;
229 u8 = u32 & 0xff;
230 }
231
232 void
233 test_ic_mult(void)
234 {
235 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
236 u8 = u8 * u8;
237 u16 = u8 * u8;
238 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
239 u16 = u16 * u8;
240 u32 = u16 * u16;
241
242 u32 = u16 * 65537ULL;
243 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
244 u32 = u16 * 65538ULL;
245
246 u16 = 0 * u16;
247 u16 = 1 * u16;
248 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
249 u16 = 2 * u16;
250
251 // from __BITS, __SHIFTIN, __SHIFTOUT
252 u32 = (u16 & 1023ULL) / 1ULL * 1024ULL | (u16 & 1023ULL) / 1ULL * 1ULL;
253
254 // FIXME
255 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
256 s8 = 1 * s8;
257 // FIXME
258 /* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */
259 s16 = 1 * s16;
260 s32 = 1 * s32;
261 s64 = 1 * s64;
262 }
263
264 void
265 test_ic_div(void)
266 {
267 u8 = u8 / u8;
268 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
269 u8 = u16 / u8;
270 u16 = u8 / u8;
271 u16 = u32 / 65536;
272 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
273 u16 = u32 / 65535;
274
275 // FIXME
276 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
277 s8 = s8 / 1;
278 // FIXME
279 /* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */
280 s16 = s16 / 1;
281 s32 = s32 / 1;
282 s64 = s64 / 1;
283 }
284
285 void
286 test_ic_mod(void)
287 {
288 /* The result is between 0 and 254. */
289 u8 = u64 % u8;
290
291 /* The result is between 0 and 255. */
292 u8 = u64 % 256;
293
294 /* The result is between 0 and 256. */
295 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
296 u8 = u64 % 257;
297
298 /* The result is between 0 and 1000. */
299 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
300 u8 = 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 bits.u10 = u64 % 1000;
304 u16 = u64 % 1000;
305
306 s8 = s16 % s8;
307 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
308 s8 = s16 % s16;
309 s8 = s64 % 1;
310 s8 = s64 % (s16 & 1);
311 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
312 s8 = s64 % (s16 & 0);
313 s8 = (s64 & 0x7f) % s64;
314 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
315 s8 = (s64 & 0xff) % s64;
316 }
317
318 void
319 test_ic_plus(void)
320 {
321 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
322 s8 = -129 + s64 % 1;
323 s8 = -128 + s64 % 1;
324 s8 = 127 + s64 % 1;
325 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
326 s8 = 128 + s64 % 1;
327
328 /* expect+2: warning: conversion of negative constant -129 to unsigned type 'unsigned long long' [222] */
329 /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
330 s8 = -129 + u64 % 1;
331 /* expect+2: warning: conversion of negative constant -128 to unsigned type 'unsigned long long' [222] */
332 /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
333 s8 = -128 + u64 % 1;
334 s8 = 127 + u64 % 1;
335 /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
336 s8 = 128 + u64 % 1;
337
338 u8 = 0 + u64 % 1;
339 u8 = 255 + u64 % 1;
340 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
341 u8 = 256 + u64 % 1;
342
343 u8 = s8 + 0x80;
344 u16 = s16 + 0x8000;
345 u32 = s32 + 0x80000000;
346 u64 = s64 + 0x8000000000000000;
347
348 // XXX: No warnings since portable_rank_cmp is the same for both sides.
349 bits.u11 = bits.u10 + bits.u10 + 1;
350 bits.u11 = bits.u10 + bits.u10 + 2;
351 bits.u11 = bits.u10 + 1024;
352 bits.u11 = bits.u10 + 1025;
353
354 u8 = bits.u7 + bits.u7 + 1;
355 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
356 u8 = bits.u7 + bits.u7 + 2;
357 u8 = bits.u7 + 128;
358 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
359 u8 = bits.u7 + 129;
360
361 // The result of the second '+' wraps around, thus the warning,
362 // even though the final result fits in a u16.
363 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
364 u16 = u32 % 0x00010000 + 0x80000000 + 0x80000000;
365
366 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
367 u16 = u32 % 0x00010000 + 0xffff8000;
368 /* expect+1: warning: conversion from 'unsigned int' to 'short' may lose accuracy [132] */
369 s16 = u32 % 0x00010000 + 0xffff8000;
370
371 /* expect+1: warning: conversion from 'long long' to 'unsigned short' may lose accuracy [132] */
372 u16 = s64 % 0x00010000 + 0xffffffffLL + -0xffffffffLL;
373 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
374 u16 = s32 % 0x00010000 + 0x7fff0000 + -0x7fff0000;
375 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
376 u16 = u32 % 0x00010000 + 0xffff0000 + 0x00010000;
377
378 s8 = '0' + s64 % 10;
379
380 ptr = ptr + 3;
381 }
382
383 void
384 test_ic_minus(void)
385 {
386 // Shift the range [0x00 to 0xff] to [-0x80 to 0x7f].
387 s8 = (s64 & 0xff) - 0x80;
388
389 // Sign-extend the lowest bits.
390 s8 = ((s64 & 0xff) ^ 0x80) - 0x80;
391 s16 = ((s64 & 0xffff) ^ 0x8000) - 0x8000;
392 /* expect+1: warning: extra bits set to 0 in conversion of 'unsigned int' to 'long long', op '&' [309] */
393 s32 = ((s64 & 0xffffffff) ^ 0x80000000) - 0x80000000;
394
395 // Trying to sign-extend, but with off-by-one errors.
396 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
397 s8 = ((s64 & 0xff) ^ 0x80) - 0x7f;
398 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
399 s8 = ((s64 & 0xff) ^ 0x80) - 0x81;
400
401 u8 = s8 - -0x80;
402 u16 = s16 - -0x8000;
403 u32 = s32 - -0x80000000;
404 u64 = s64 - -0x8000000000000000;
405
406 ptr = ptr - 3;
407 s64 = ptr + 3 - ptr;
408 /* expect+1: warning: conversion from 'long' to 'unsigned int' may lose accuracy [132] */
409 u32 = ptr + 3 - ptr;
410 }
411
412 void
413 test_ic_shl(void)
414 {
415 u64 = u64 << u64;
416 s64 = s64 << s64;
417
418 u16 = u8 << 8;
419 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
420 u16 = u8 << 9;
421 u32 = u16 << 16;
422 // XXX: missing warning as UINT has the same rank as INT, see portable_rank_cmp.
423 u32 = u16 << 17;
424 /* expect+1: warning: shift amount 56 is greater than bit-size 32 of 'int' [122] */
425 u64 = u8 << 56;
426 u64 = (u64_t)u8 << 56;
427 // XXX: missing warning, as the operand types of '=' are the same, thus no conversion.
428 u64 = (u64_t)u8 << 57;
429 /* expect+1: warning: shift amount 48 is greater than bit-size 32 of 'int' [122] */
430 u64 = u16 << 48;
431 u64 = (u64_t)u16 << 48;
432 // XXX: missing warning, as the operand types of '=' are the same, thus no conversion.
433 u64 = (u64_t)u16 << 49;
434 /* expect+1: warning: shift amount 32 equals bit-size of 'unsigned int' [267] */
435 u64 = u32 << 32;
436 u64 = (u64_t)u32 << 32;
437 // XXX: missing warning, as the operand types of '=' are the same, thus no conversion.
438 u64 = (u64_t)u32 << 33;
439 }
440
441 void
442 test_ic_shr(void)
443 {
444 u64 = u64 >> u64;
445 s64 = s64 >> s64;
446
447 u32 = u64 >> 32;
448 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
449 u32 = u64 >> 31;
450 u16 = u64 >> 48;
451 u16 = u32 >> 16;
452 u8 = u64 >> 56;
453 u8 = u32 >> 24;
454 u8 = u16 >> 8;
455
456 /*
457 * No matter whether the big integer is signed or unsigned, the
458 * result of '&' is guaranteed to be an unsigned value.
459 */
460 u8 = (s64 & 0xf0) >> 4;
461 u8 = (s8 & 0xf0) >> 4;
462 }
463
464 void
465 test_ic_bitand(void)
466 {
467 u8 = u8 & u16;
468
469 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */
470 u8 = u16 & u32;
471 }
472
473 void
474 test_ic_bitxor(void)
475 {
476 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
477 u8 = u8 ^ u16;
478 u16 = u8 ^ u16;
479
480 // Sign-extend.
481 s8 = (u8 ^ 0x80) - 0x80;
482 s16 = (u16 ^ 0x8000) - 0x8000;
483 s32 = (u32 ^ 0x80000000) - 0x80000000;
484 s64 = (u64 ^ 0x8000000000000000) - 0x8000000000000000;
485 }
486
487 void
488 test_ic_bitor(void)
489 {
490 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
491 u8 = u8 | u16;
492 u16 = u8 | u16;
493 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
494 u16 = u8 | u32;
495 u32 = u8 | u32;
496 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
497 u32 = u8 | u64;
498 u64 = u8 | u64;
499 }
500
501 void
502 test_ic_quest_colon(char c1, char c2)
503 {
504 /* Both operands are representable as char. */
505 ch = cond ? '?' : ':';
506
507 /*
508 * Both operands are representable as char. Clang-Tidy 17 wrongly
509 * warns about a narrowing conversion from 'int' to signed type
510 * 'char'.
511 */
512 ch = cond ? c1 : c2;
513
514 /*
515 * Mixing s8 and u8 results in a number from -128 to 255, which neither
516 * fits in s8 nor u8.
517 */
518 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
519 s8 = cond ? s8 : u8;
520 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
521 u8 = cond ? s8 : u8;
522 }
523
524 void
525 test_ic_con(void)
526 {
527 /* expect+1: warning: assignment of negative constant -1 to unsigned type 'unsigned char' [164] */
528 u8 = -1;
529 u8 = 0;
530 u8 = 255;
531 /* expect+1: warning: constant truncated by assignment [165] */
532 u8 = 256;
533
534 /* expect+1: warning: conversion of 'int' to 'signed char' is out of range [119] */
535 s8 = -129;
536 s8 = -128;
537 s8 = 127;
538 /* expect+1: warning: conversion of 'int' to 'signed char' is out of range [119] */
539 s8 = 128;
540 }
541
542 void
543 test_ic_cvt(void)
544 {
545 u16 = (u32 & 0x0000ff00);
546 u16 = (u32_t)(u32 & 0x0000ff00);
547 u16 = (u16_t)u32;
548 u16 = (u8_t)(u32 & 0xffff) << 8;
549 u16 = (int)3.0;
550
551 u8 = (u8_t)(u64 & 0x0f);
552 u8 = (u8_t)(u64 & 0x0f) << 4;
553 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
554 u8 = (u8_t)(u64 & 0x0f) << 5;
555 }
556
557 unsigned char
558 test_bit_fields(unsigned long long m)
559 {
560 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:3' may lose accuracy [132] */
561 bits.u3 = bits.u32 & m;
562
563 bits.u5 = bits.u3 & m;
564 bits.u32 = bits.u5 & m;
565
566 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
567 return bits.u32 & m;
568 }
569
570 void
571 compare_bit_field_to_integer_constant(void)
572 {
573 static _Bool b;
574 static struct {
575 short s16:15;
576 unsigned short u16:15;
577 int s32:15;
578 unsigned u32:15;
579 long long s64:15;
580 unsigned long long u64:15;
581 } s;
582
583 // Since decl.c 1.180 from 2021-05-02 and before tree.c 1.624 from
584 // 2024-03-12, lint warned about a possible loss of accuracy [132]
585 // when promoting an 'unsigned long long' bit-field to 'int'.
586 b = s.s16 == 0;
587 b = s.u16 == 0;
588 b = s.s32 == 0;
589 b = s.u32 == 0;
590 b = s.s64 == 0;
591 b = s.u64 == 0;
592 b = !b;
593 }
594
595 /*
596 * Before tree.c 1.626 from 2024-03-26, the usual arithmetic conversions for
597 * bit-field types with the same base type but different widths simply took
598 * the type of the left operand, leading to wrong warnings about loss of
599 * accuracy when the right operand was wider than the left operand.
600 */
601 void
602 binary_operators_on_bit_fields(void)
603 {
604 struct {
605 u64_t u15:15;
606 u64_t u48:48;
607 u64_t u64;
608 } s = { 0, 0, 0 };
609
610 u64 = s.u15 | s.u48;
611 u64 = s.u48 | s.u15;
612 u64 = s.u15 | s.u48 | s.u64;
613 u64 = s.u64 | s.u48 | s.u15;
614 cond = (s.u15 | s.u48 | s.u64) != 0;
615 cond = (s.u64 | s.u48 | s.u15) != 0;
616
617 // Before tree.c from 1.638 from 2024-05-01, lint wrongly warned:
618 // warning: conversion of 'int' to 'int:4' is out of range [119]
619 s32 = 8 - bits.u3;
620 }
621
622 unsigned char
623 combine_arithmetic_and_bit_operations(void)
624 {
625 return 0xc0 | (u32 & 0x07c0) / 64;
626 }
627