msg_132.c revision 1.23 1 /* $NetBSD: msg_132.c,v 1.23 2022/07/06 22:26:31 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 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int' may lose accuracy [132] */
241 return x;
242 }
243
244 unsigned char
245 test_bit_fields(unsigned long long m)
246 {
247 /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned int:3' may lose accuracy [132] */
248 bits.u3 = bits.u32 & m;
249
250 bits.u5 = bits.u3 & m;
251 bits.u32 = bits.u5 & m;
252
253 /* expect+1: warning: conversion from 'unsigned long long:32' to 'unsigned char' may lose accuracy [132] */
254 return bits.u32 & m;
255 }
256
257 /*
258 * Traditional C has an extra rule that the right-hand operand of a bit shift
259 * operator is converted to 'int'. Before tree.c 1.467 from 2022-07-02, this
260 * conversion was implemented as a CVT node, which means a cast, not an
261 * implicit conversion. Changing the CVT to NOOP would have caused a wrong
262 * warning 'may lose accuracy' in language levels other than traditional C.
263 */
264
265 u64_t
266 u64_shl(u64_t lhs, u64_t rhs)
267 {
268 return lhs << rhs;
269 }
270
271 u64_t
272 u64_shr(u64_t lhs, u64_t rhs)
273 {
274 return lhs >> rhs;
275 }
276
277 s64_t
278 s64_shl(s64_t lhs, s64_t rhs)
279 {
280 return lhs << rhs;
281 }
282
283 s64_t
284 s64_shr(s64_t lhs, s64_t rhs)
285 {
286 return lhs >> rhs;
287 }
288
289 void
290 test_ic_mod(void)
291 {
292 /* The result is between 0 and 254. */
293 u8 = u64 % u8;
294
295 /* The result is between 0 and 255. */
296 u8 = u64 % 256;
297
298 /* The result is between 0 and 256. */
299 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
300 u8 = u64 % 257;
301
302 /* The result is between 0 and 1000. */
303 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned char' may lose accuracy [132] */
304 u8 = u64 % 1000;
305 /* expect+1: warning: conversion from 'unsigned long long' to 'unsigned int:9' may lose accuracy [132] */
306 bits.u9 = u64 % 1000;
307 bits.u10 = u64 % 1000;
308 u16 = u64 % 1000;
309
310 /*
311 * For signed division, if the result of 'a / b' is not representable
312 * exactly, the result of 'a % b' is defined such that
313 * '(a / b) * a + a % b == a'.
314 *
315 * If the result of 'a / b' is not representable exactly, the result
316 * of 'a % b' is not defined. Due to this uncertainty, lint does not
317 * narrow down the range for signed modulo expressions.
318 *
319 * C90 6.3.5, C99 6.5.5.
320 */
321
322 /* expect+1: warning: conversion from 'int' to 'signed char' may lose accuracy [132] */
323 s8 = s16 % s8;
324
325 /*
326 * The result is always 0, it's a theoretical edge case though, so
327 * lint doesn't care to implement this.
328 */
329 /* expect+1: warning: conversion from 'long long' to 'signed char' may lose accuracy [132] */
330 s8 = s64 % 1;
331 }
332