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