msg_132.c revision 1.25 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