xref: /netbsd-src/tests/usr.bin/xlint/lint1/expr_fold.c (revision 98412b5015f4d494913d9440a5ebd2476000e119)
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