xref: /netbsd-src/tests/usr.bin/xlint/lint1/expr_fold.c (revision 53b02e147d4ed531c0d2a5ca9b3e8026ba3e99b5)
1 /*	$NetBSD: expr_fold.c,v 1.5 2021/08/23 06:50:01 rillig Exp $	*/
2 # 3 "expr_fold.c"
3 
4 /*
5  * Test folding of constant expressions.
6  */
7 
8 /* lint1-extra-flags: -h */
9 
10 /*
11  * On ILP32 platforms, the integer constant 2147483648 cannot be represented
12  * as 'int' or 'long', therefore it becomes 'long long'.  This would
13  * influence the type names in the diagnostics.
14  */
15 /* lint1-only-if: lp64 */
16 
17 void take_bool(_Bool);
18 void take_int(int);
19 void take_uint(unsigned int);
20 
21 /*
22  * C99 6.4.4.1p5 defines that decimal integer constants without suffix get
23  * one of the signed integer types. On the other hand, octal and hexadecimal
24  * constants get either a signed or unsigned type, whichever fits first.
25  */
26 
27 void
28 fold_uplus(void)
29 {
30 	take_int(+(0));
31 	take_int(+(2147483647));
32 	/* XXX: one of these two messages is redundant */
33 	/* expect+2: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
34 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
35 	take_int(+(2147483648));
36 	/* XXX: one of these two messages is redundant */
37 	/* expect+2: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
38 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
39 	take_int(+(4294967295));
40 
41 	take_uint(+(0));
42 	take_uint(+(2147483647));
43 	/* expect+1: warning: argument #1 is converted from 'long' to 'unsigned int' due to prototype [259] */
44 	take_uint(+(2147483648));
45 	/* expect+1: warning: argument #1 is converted from 'long' to 'unsigned int' due to prototype [259] */
46 	take_uint(+(4294967295));
47 
48 	/*
49 	 * Hexadecimal constants and constants with the suffix 'U' get either
50 	 * a signed or an unsigned integer type, so no warning here.
51 	 */
52 	take_uint(+(2147483648U));
53 	take_uint(+(0x80000000));
54 	take_uint(+(0x80000000U));
55 }
56 
57 void
58 fold_uminus(void)
59 {
60 	take_int(-(0));
61 	take_int(-(2147483647));
62 
63 	/* expect+1: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
64 	take_int(-(2147483648));
65 
66 	/* The '-' is an operator, it is not part of the integer constant. */
67 	/* expect+1: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
68 	take_int(-2147483648);
69 
70 	/* expect+2: warning: integer overflow detected, op '+' [141] */
71 	/* expect+1: warning: integer overflow detected, op '-' [141] */
72 	take_int(-(2147483647 + 1));
73 	/* expect+1: warning: integer overflow detected, op '-' [141] */
74 	take_int(-(-2147483647 - 1));
75 	/* expect+2: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
76 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
77 	take_int(-(4294967295));
78 
79 	take_uint(-(0));
80 	/* expect+2: warning: conversion of negative constant to unsigned type, arg #1 [296] */
81 	/* expect+1: warning: argument #1 is converted from 'int' to 'unsigned int' due to prototype [259] */
82 	take_uint(-(2147483647));
83 	/* expect+2: warning: argument #1 is converted from 'long' to 'unsigned int' due to prototype [259] */
84 	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
85 	take_uint(-(2147483648));
86 	/* expect+2: warning: argument #1 is converted from 'long' to 'unsigned int' due to prototype [259] */
87 	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
88 	take_uint(-(4294967295));
89 }
90 
91 void
92 fold_compl(void)
93 {
94 	take_int(~(0));
95 	take_int(~(2147483647));
96 	/* expect+2: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
97 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
98 	take_int(~(2147483648));
99 	/* expect+2: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
100 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
101 	take_int(~(4294967295));
102 
103 	/* expect+2: warning: conversion of negative constant to unsigned type, arg #1 [296] */
104 	/* expect+1: warning: argument #1 is converted from 'int' to 'unsigned int' due to prototype [259] */
105 	take_uint(~(0));
106 	/* expect+2: warning: argument #1 is converted from 'int' to 'unsigned int' due to prototype [259] */
107 	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
108 	take_uint(~(2147483647));
109 	/* expect+2: warning: argument #1 is converted from 'long' to 'unsigned int' due to prototype [259] */
110 	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
111 	take_uint(~(2147483648));
112 	/* expect+2: warning: argument #1 is converted from 'long' to 'unsigned int' due to prototype [259] */
113 	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
114 	take_uint(~(4294967295));
115 }
116 
117 void
118 fold_mult(void)
119 {
120 	take_int(32767 * 65536);
121 	/* expect+1: warning: integer overflow detected, op '*' [141] */
122 	take_int(32768 * 65536);
123 	/* expect+1: warning: integer overflow detected, op '*' [141] */
124 	take_int(65536 * 65536);
125 
126 	take_uint(32767 * 65536U);
127 	take_uint(32768 * 65536U);
128 	/* expect+1: warning: integer overflow detected, op '*' [141] */
129 	take_uint(65536 * 65536U);
130 }
131 
132 void
133 fold_div(void)
134 {
135 	/* expect+3: error: division by 0 [139] */
136 	/* XXX: The following message is redundant. */
137 	/* expect+1: warning: integer overflow detected, op '/' [141] */
138 	take_int(0 / 0);
139 
140 	/* expect+2: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
141 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
142 	take_int(-2147483648 / -1);
143 }
144 
145 void
146 fold_mod(void)
147 {
148 	/* expect+1: error: modulus by 0 [140] */
149 	take_int(0 % 0);
150 	/* expect+1: error: modulus by 0 [140] */
151 	take_int(0 % 0U);
152 	/* expect+1: error: modulus by 0 [140] */
153 	take_int(0U % 0);
154 	/* expect+1: error: modulus by 0 [140] */
155 	take_int(0U % 0U);
156 
157 	/* expect+1: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
158 	take_int(-2147483648 % -1);
159 }
160 
161 void
162 fold_plus(void)
163 {
164 	/* expect+1: warning: integer overflow detected, op '+' [141] */
165 	take_int(2147483647 + 1);
166 
167 	/* Assume two's complement, so no overflow. */
168 	take_int(-2147483647 + -1);
169 
170 	/* expect+1: warning: integer overflow detected, op '+' [141] */
171 	take_int(-2147483647 + -2);
172 
173 	/*
174 	 * No overflow since one of the operands is unsigned, therefore the
175 	 * other operand is converted to unsigned as well.
176 	 * See C99 6.3.1.8p1, paragraph 8 of 10.
177 	 */
178 	/* wrong integer overflow warning before tree.c 1.338 from 2021-08-19 */
179 	take_uint(2147483647 + 1U);
180 	/* wrong integer overflow warning before tree.c 1.338 from 2021-08-19 */
181 	take_uint(2147483647U + 1);
182 }
183 
184 void
185 fold_minus(void)
186 {
187 	/* expect+1: warning: integer overflow detected, op '-' [141] */
188 	take_int(2147483647 - -1);
189 	/* Assume two's complement. */
190 	take_int(-2147483647 - 1);
191 	/* expect+1: warning: integer overflow detected, op '-' [141] */
192 	take_int(-2147483647 - 2);
193 
194 	/* expect+1: warning: argument #1 is converted from 'long' to 'int' due to prototype [259] */
195 	take_int(0 - 2147483648);
196 	/* expect+1: warning: integer overflow detected, op '-' [141] */
197 	take_uint(0 - 2147483648U);
198 }
199 
200 void
201 fold_shl(void)
202 {
203 	/* expect+1: warning: integer overflow detected, op '<<' [141] */
204 	take_int(1 << 24 << 24);
205 
206 	/* expect+1: warning: integer overflow detected, op '<<' [141] */
207 	take_uint(1U << 24 << 24);
208 
209 	/* FIXME: undefined behavior in 'fold' at 'uint64_t << 104'. */
210 	/* expect+1: warning: shift amount 104 is greater than bit-size 32 of 'unsigned int' [122] */
211 	take_uint(1U << 24 << 104);
212 }
213 
214 void
215 fold_shr(void)
216 {
217 	take_int(16777216 >> 24);
218 
219 	take_int(16777216 >> 25);
220 
221 	/* FIXME: undefined behavior in 'fold' at 'uint64_t >> 104'. */
222 	/* expect+1: warning: shift amount 104 is greater than bit-size 32 of 'int' [122] */
223 	take_int(16777216 >> 104);
224 }
225 
226 void
227 fold_lt(void)
228 {
229 	take_bool(1 < 3);
230 	take_bool(3 < 1);
231 }
232 
233 void
234 fold_le(void)
235 {
236 	take_bool(1 <= 3);
237 	take_bool(3 <= 1);
238 }
239 
240 void
241 fold_ge(void)
242 {
243 	take_bool(1 >= 3);
244 	take_bool(3 >= 1);
245 }
246 
247 void
248 fold_gt(void)
249 {
250 	take_bool(1 > 3);
251 	take_bool(3 > 1);
252 }
253 
254 void
255 fold_eq(void)
256 {
257 	take_bool(1 == 3);
258 	take_bool(3 == 1);
259 }
260 
261 void
262 fold_ne(void)
263 {
264 	take_bool(1 != 3);
265 	take_bool(3 != 1);
266 }
267 
268 void
269 fold_bitand(void)
270 {
271 	take_bool(1 & 3);
272 	take_bool(3 & 1);
273 }
274 
275 void
276 fold_bitxor(void)
277 {
278 	take_bool(1 ^ 3);
279 	take_bool(3 ^ 1);
280 }
281 
282 void
283 fold_bitor(void)
284 {
285 	take_bool(1 | 3);
286 	take_bool(3 | 1);
287 }
288 
289 /*
290  * The following expression originated in vndcompress.c 1.29 from 2017-07-29,
291  * where line 310 contained a seemingly harmless compile-time assertion that
292  * expanded to a real monster expression.
293  *
294  * __CTASSERT(MUL_OK(uint64_t, MAX_N_BLOCKS, MAX_BLOCKSIZE));
295  *
296  * Before tree.c 1.345 from 2021-08-22, lint wrongly assumed that the result
297  * of all binary operators were the common arithmetic type, but that was
298  * wrong for the comparison operators.  The expression '1ULL < 2ULL' does not
299  * have type 'unsigned long long' but 'int' in default mode, or '_Bool' in
300  * strict bool mode.
301  */
302 struct ctassert5_struct {
303 	unsigned int member:
304 	    /*CONSTCOND*/
305 	    0xfffffffeU
306 	    <=
307 		((1ULL << 63) + 1 < 1 ? ~(1ULL << 63) : ~0ULL) / 0xfffffe00U
308 		? 1
309 		: -1;
310 };
311