msg_132.c revision 1.26 1 /* $NetBSD: msg_132.c,v 1.26 2023/03/28 14:44:34 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
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 struct bit_fields {
39 unsigned u1:1;
40 unsigned u2:2;
41 unsigned u3:3;
42 unsigned u4:4;
43 unsigned u5:5;
44 unsigned u6:6;
45 unsigned u7:7;
46 unsigned u8:8;
47 unsigned u9:9;
48 unsigned u10:10;
49 unsigned u11:11;
50 unsigned u12:12;
51 unsigned u32:32;
52 } bits;
53
54
55 void
56 unsigned_to_unsigned(void)
57 {
58 /* expect+1: warning: conversion from 'unsigned short' to 'unsigned char' may lose accuracy [132] */
59 u8 = u16;
60 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */
61 u8 = u32;
62 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
63 u8 = u64;
64
65 u16 = u8;
66 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned short' may lose accuracy [132] */
67 u16 = u32;
68 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned short' may lose accuracy [132] */
69 u16 = u64;
70
71 u32 = u8;
72 u32 = u16;
73 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
74 u32 = u64;
75
76 u64 = u8;
77 u64 = u16;
78 u64 = u32;
79 }
80
81 void
82 unsigned_to_signed(void)
83 {
84 /* expect+1: warning: conversion from 'unsigned short' to 'signed char' may lose accuracy [132] */
85 s8 = u16;
86 /* expect+1: warning: conversion from 'unsigned int' to 'signed char' may lose accuracy [132] */
87 s8 = u32;
88 /* expect+1: warning: conversion from 'unsigned long long' to 'signed char' may lose accuracy [132] */
89 s8 = u64;
90
91 s16 = u8;
92 /* expect+1: warning: conversion from 'unsigned int' to 'short' may lose accuracy [132] */
93 s16 = u32;
94 /* expect+1: warning: conversion from 'unsigned long long' to 'short' may lose accuracy [132] */
95 s16 = u64;
96
97 s32 = u8;
98 s32 = u16;
99 /* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */
100 s32 = u64;
101
102 s64 = u8;
103 s64 = u16;
104 s64 = u32;
105 }
106
107 void
108 signed_to_unsigned(void)
109 {
110 /* expect+1: warning: conversion from 'short' to 'unsigned char' may lose accuracy [132] */
111 u8 = s16;
112 /* expect+1: warning: conversion from 'int' to 'unsigned char' may lose accuracy [132] */
113 u8 = s32;
114 /* expect+1: warning: conversion from 'long long' to 'unsigned char' may lose accuracy [132] */
115 u8 = s64;
116
117 u16 = s8;
118 /* expect+1: warning: conversion from 'int' to 'unsigned short' may lose accuracy [132] */
119 u16 = s32;
120 /* expect+1: warning: conversion from 'long long' to 'unsigned short' may lose accuracy [132] */
121 u16 = s64;
122
123 u32 = s8;
124 u32 = s16;
125 /* expect+1: warning: conversion from 'long long' to 'unsigned int' may lose accuracy [132] */
126 u32 = s64;
127
128 u64 = s8;
129 u64 = s16;
130 u64 = s32;
131 }
132
133 void
134 signed_to_signed(void)
135 {
136 /* expect+1: warning: conversion from 'short' to 'signed char' may lose accuracy [132] */
137 s8 = s16;
138 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
139 s8 = s32;
140 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
141 s8 = s64;
142
143 s16 = s8;
144 /* expect+1: warning: conversion from 'int' to 'short' may lose accuracy [132] */
145 s16 = s32;
146 /* expect+1: warning: conversion from 'long long' to 'short' may lose accuracy [132] */
147 s16 = s64;
148
149 s32 = s8;
150 s32 = s16;
151 /* expect+1: warning: conversion from 'long long' to 'int' may lose accuracy [132] */
152 s32 = s64;
153
154 s64 = s8;
155 s64 = s16;
156 s64 = s32;
157 }
158
159 /*
160 * Before tree.c 1.268 from 2021-04-06, lint wrongly warned that conversion
161 * to _Bool might lose accuracy. C99 6.3.1.2 defines a special conversion
162 * rule from scalar to _Bool though by comparing the value to 0.
163 */
164 _Bool
165 to_bool(long a, long b)
166 {
167 /* seen in fp_lib.h, function wideRightShiftWithSticky */
168 return a | b;
169 }
170
171 /* ARGSUSED */
172 const char *
173 cover_build_plus_minus(const char *arr, double idx)
174 {
175 /* expect+3: error: operands of '+' have incompatible types 'pointer' and 'double' [107] */
176 /* expect+2: warning: function 'cover_build_plus_minus' expects to return value [214] */
177 if (idx > 0.0)
178 return arr + idx;
179 return arr + (unsigned int)idx;
180 }
181
182 int
183 non_constant_expression(void)
184 {
185 /*
186 * Even though this variable definition looks like a constant, it
187 * does not fall within C's definition of an integer constant
188 * expression. Due to that, lint does not perform constant folding
189 * on the expression built from this variable and thus doesn't know
190 * that the conversion will always succeed.
191 */
192 const int not_a_constant = 8;
193 /* expect+1: warning: conversion from 'unsigned long long' to 'int' may lose accuracy [132] */
194 return not_a_constant * 8ULL;
195 }
196
197 /*
198 * PR 36668 notices that lint wrongly complains about the possible loss.
199 *
200 * The expression 'u8_t << 8' is guaranteed to fit into an 'u16_t', and its
201 * lower 8 bits are guaranteed to be clear. 'u16_t | u8_t' is guaranteed to
202 * fit into 'u16_t'.
203 *
204 * Since tree.c 1.444 from 2022-05-26, lint tracks simple bitwise and
205 * arithmetic constraints across a single expression.
206 */
207 static inline u16_t
208 be16dec(const void *buf)
209 {
210 const u8_t *p = buf;
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 return ((u16_t)p[0]) << 8 | p[1];
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 static inline void
224 be32enc(void *buf, u32_t u)
225 {
226 u8_t *p = buf;
227
228 p[0] = u >> 24 & 0xff;
229 p[1] = u >> 16 & 0xff;
230 p[2] = u >> 8 & 0xff;
231 p[3] = u & 0xff;
232 }
233
234 u32_t
235 test_ic_shr(u64_t x)
236 {
237 if (x > 3)
238 return x >> 32;
239 if (x > 2)
240 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
241 return x >> 31;
242
243 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
244 u32 = u64 >> 31;
245 u32 = u64 >> 32;
246 u16 = u64 >> 48;
247 u8 = u64 >> 56;
248 u16 = u32 >> 16;
249 u8 = u32 >> 24;
250 u8 = u16 >> 8;
251
252 /*
253 * No matter whether the big integer is signed or unsigned, the
254 * result of '&' is guaranteed to be an unsigned value.
255 */
256 u8 = (s64 & 0xf0) >> 4;
257 u8 = (s8 & 0xf0) >> 4;
258
259 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
260 return x;
261 }
262
263 unsigned char
264 test_bit_fields(unsigned long long m)
265 {
266 /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned int:3' may lose accuracy [132] */
267 bits.u3 = bits.u32 & m;
268
269 bits.u5 = bits.u3 & m;
270 bits.u32 = bits.u5 & m;
271
272 /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned char' may lose accuracy [132] */
273 return bits.u32 & m;
274 }
275
276 /*
277 * Traditional C has an extra rule that the right-hand operand of a bit shift
278 * operator is converted to 'int'. Before tree.c 1.467 from 2022-07-02, this
279 * conversion was implemented as a CVT node, which means a cast, not an
280 * implicit conversion. Changing the CVT to NOOP would have caused a wrong
281 * warning 'may lose accuracy' in language levels other than traditional C.
282 */
283
284 u64_t
285 u64_shl(u64_t lhs, u64_t rhs)
286 {
287 return lhs << rhs;
288 }
289
290 u64_t
291 u64_shr(u64_t lhs, u64_t rhs)
292 {
293 return lhs >> rhs;
294 }
295
296 s64_t
297 s64_shl(s64_t lhs, s64_t rhs)
298 {
299 return lhs << rhs;
300 }
301
302 s64_t
303 s64_shr(s64_t lhs, s64_t rhs)
304 {
305 return lhs >> rhs;
306 }
307
308 void
309 test_ic_mod(void)
310 {
311 /* The result is between 0 and 254. */
312 u8 = u64 % u8;
313
314 /* The result is between 0 and 255. */
315 u8 = u64 % 256;
316
317 /* The result is between 0 and 256. */
318 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
319 u8 = u64 % 257;
320
321 /* The result is between 0 and 1000. */
322 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
323 u8 = u64 % 1000;
324 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */
325 bits.u9 = u64 % 1000;
326 bits.u10 = u64 % 1000;
327 u16 = u64 % 1000;
328
329 /*
330 * For signed division, if the result of 'a / b' is not representable
331 * exactly, the result of 'a % b' is defined such that
332 * '(a / b) * a + a % b == a'.
333 *
334 * If the result of 'a / b' is not representable exactly, the result
335 * of 'a % b' is not defined. Due to this uncertainty, lint does not
336 * narrow down the range for signed modulo expressions.
337 *
338 * C90 6.3.5, C99 6.5.5.
339 */
340
341 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
342 s8 = s16 % s8;
343
344 /*
345 * The result is always 0, it's a theoretical edge case though, so
346 * lint doesn't care to implement this.
347 */
348 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
349 s8 = s64 % 1;
350 }
351
352 void
353 test_ic_bitand(void)
354 {
355 /*
356 * ic_bitand assumes that integers are represented in 2's complement,
357 * and that the sign bit of signed integers behaves like a value bit.
358 * That way, the following expressions get their constraints computed
359 * correctly, regardless of whether ic_expr takes care of integer
360 * promotions or not. Compare ic_mod, which ignores signed types.
361 */
362
363 u8 = u8 & u16;
364
365 /* expect+1: warning: conversion from 'unsigned int' to 'unsigned char' may lose accuracy [132] */
366 u8 = u16 & u32;
367 }
368