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