xref: /netbsd-src/tests/usr.bin/xlint/lint1/expr_fold.c (revision afab4e300d3a9fb07dd8c80daf53d0feb3345706)
1 /*	$NetBSD: expr_fold.c,v 1.8 2023/03/28 14:44:34 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
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
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+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 
79 void
80 fold_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 
99 void
100 fold_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 
114 void
115 fold_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 
126 void
127 fold_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 
141 void
142 fold_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 
164 void
165 fold_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 
179 void
180 fold_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 
193 void
194 fold_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 
205 void
206 fold_lt(void)
207 {
208 	take_bool(1 < 3);
209 	take_bool(3 < 1);
210 }
211 
212 void
213 fold_le(void)
214 {
215 	take_bool(1 <= 3);
216 	take_bool(3 <= 1);
217 }
218 
219 void
220 fold_ge(void)
221 {
222 	take_bool(1 >= 3);
223 	take_bool(3 >= 1);
224 }
225 
226 void
227 fold_gt(void)
228 {
229 	take_bool(1 > 3);
230 	take_bool(3 > 1);
231 }
232 
233 void
234 fold_eq(void)
235 {
236 	take_bool(1 == 3);
237 	take_bool(3 == 1);
238 }
239 
240 void
241 fold_ne(void)
242 {
243 	take_bool(1 != 3);
244 	take_bool(3 != 1);
245 }
246 
247 void
248 fold_bitand(void)
249 {
250 	take_bool(1 & 3);
251 	take_bool(3 & 1);
252 }
253 
254 void
255 fold_bitxor(void)
256 {
257 	take_bool(1 ^ 3);
258 	take_bool(3 ^ 1);
259 }
260 
261 void
262 fold_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  */
281 struct 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  */
296 void
297 unary_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