xref: /netbsd-src/tests/usr.bin/xlint/lint1/expr_fold.c (revision 98412b5015f4d494913d9440a5ebd2476000e119)
1*98412b50Srillig /*	$NetBSD: expr_fold.c,v 1.16 2024/06/08 06:37:06 rillig Exp $	*/
259e08a43Srillig # 3 "expr_fold.c"
359e08a43Srillig 
459e08a43Srillig /*
559e08a43Srillig  * Test folding of constant expressions.
659e08a43Srillig  */
759e08a43Srillig 
8b2baa501Srillig /* lint1-extra-flags: -h -X 351 */
959e08a43Srillig 
1059e08a43Srillig /*
1159e08a43Srillig  * On ILP32 platforms, the integer constant 2147483648 cannot be represented
1259e08a43Srillig  * as 'int' or 'long', therefore it becomes 'long long'.  This would
1359e08a43Srillig  * influence the type names in the diagnostics.
1459e08a43Srillig  */
1559e08a43Srillig /* lint1-only-if: lp64 */
1659e08a43Srillig 
1759e08a43Srillig void take_bool(_Bool);
1859e08a43Srillig void take_int(int);
1959e08a43Srillig void take_uint(unsigned int);
2059e08a43Srillig 
2159e08a43Srillig /*
2259e08a43Srillig  * C99 6.4.4.1p5 defines that decimal integer constants without suffix get
2359e08a43Srillig  * one of the signed integer types. On the other hand, octal and hexadecimal
2459e08a43Srillig  * constants get either a signed or unsigned type, whichever fits first.
2559e08a43Srillig  */
2659e08a43Srillig 
2759e08a43Srillig void
fold_uplus(void)2859e08a43Srillig fold_uplus(void)
2959e08a43Srillig {
3059e08a43Srillig 	take_int(+(0));
3159e08a43Srillig 	take_int(+(2147483647));
3259e08a43Srillig 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
3359e08a43Srillig 	take_int(+(2147483648));
3459e08a43Srillig 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
3559e08a43Srillig 	take_int(+(4294967295));
3659e08a43Srillig 
3759e08a43Srillig 	take_uint(+(0));
3859e08a43Srillig 	take_uint(+(2147483647));
3959e08a43Srillig 	take_uint(+(2147483648));
4059e08a43Srillig 	take_uint(+(4294967295));
4159e08a43Srillig 
4259e08a43Srillig 	/*
4359e08a43Srillig 	 * Hexadecimal constants and constants with the suffix 'U' get either
4459e08a43Srillig 	 * a signed or an unsigned integer type, so no warning here.
4559e08a43Srillig 	 */
4659e08a43Srillig 	take_uint(+(2147483648U));
4759e08a43Srillig 	take_uint(+(0x80000000));
4859e08a43Srillig 	take_uint(+(0x80000000U));
4959e08a43Srillig }
5059e08a43Srillig 
5159e08a43Srillig void
fold_uminus(void)5259e08a43Srillig fold_uminus(void)
5359e08a43Srillig {
5459e08a43Srillig 	take_int(-(0));
5559e08a43Srillig 	take_int(-(2147483647));
5659e08a43Srillig 
5759e08a43Srillig 	take_int(-(2147483648));
5859e08a43Srillig 
5959e08a43Srillig 	/* The '-' is an operator, it is not part of the integer constant. */
6059e08a43Srillig 	take_int(-2147483648);
6159e08a43Srillig 
62dd848decSrillig 	/* expect+1: warning: '2147483647 + 1' overflows 'int' [141] */
6359e08a43Srillig 	take_int(-(2147483647 + 1));
64dd848decSrillig 	/* expect+1: warning: '-(-2147483648)' overflows 'int' [141] */
6559e08a43Srillig 	take_int(-(-2147483647 - 1));
6659e08a43Srillig 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
6759e08a43Srillig 	take_int(-(4294967295));
6859e08a43Srillig 
6959e08a43Srillig 	take_uint(-(0));
70*98412b50Srillig 	/* expect+1: warning: conversion of negative constant -2147483647 to unsigned type 'unsigned int', arg #1 [296] */
7159e08a43Srillig 	take_uint(-(2147483647));
72*98412b50Srillig 	/* expect+1: warning: conversion of negative constant -2147483648 to unsigned type 'unsigned int', arg #1 [296] */
7359e08a43Srillig 	take_uint(-(2147483648));
74*98412b50Srillig 	/* expect+1: warning: conversion of negative constant -4294967295 to unsigned type 'unsigned int', arg #1 [296] */
7559e08a43Srillig 	take_uint(-(4294967295));
7659e08a43Srillig }
7759e08a43Srillig 
7859e08a43Srillig void
fold_compl(void)7959e08a43Srillig fold_compl(void)
8059e08a43Srillig {
8159e08a43Srillig 	take_int(~(0));
8259e08a43Srillig 	take_int(~(2147483647));
8359e08a43Srillig 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
8459e08a43Srillig 	take_int(~(2147483648));
8559e08a43Srillig 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
8659e08a43Srillig 	take_int(~(4294967295));
8759e08a43Srillig 
88*98412b50Srillig 	/* expect+1: warning: conversion of negative constant -1 to unsigned type 'unsigned int', arg #1 [296] */
8959e08a43Srillig 	take_uint(~(0));
90*98412b50Srillig 	/* expect+1: warning: conversion of negative constant -2147483648 to unsigned type 'unsigned int', arg #1 [296] */
9159e08a43Srillig 	take_uint(~(2147483647));
92*98412b50Srillig 	/* expect+1: warning: conversion of negative constant -2147483649 to unsigned type 'unsigned int', arg #1 [296] */
9359e08a43Srillig 	take_uint(~(2147483648));
94*98412b50Srillig 	/* expect+1: warning: conversion of negative constant -4294967296 to unsigned type 'unsigned int', arg #1 [296] */
9559e08a43Srillig 	take_uint(~(4294967295));
9659e08a43Srillig }
9759e08a43Srillig 
9859e08a43Srillig void
fold_mult(void)9959e08a43Srillig fold_mult(void)
10059e08a43Srillig {
10159e08a43Srillig 	take_int(32767 * 65536);
102dd848decSrillig 	/* expect+1: warning: '32768 * 65536' overflows 'int' [141] */
10359e08a43Srillig 	take_int(32768 * 65536);
104dd848decSrillig 	/* expect+1: warning: '65536 * 65536' overflows 'int' [141] */
10559e08a43Srillig 	take_int(65536 * 65536);
10659e08a43Srillig 
10759e08a43Srillig 	take_uint(32767 * 65536U);
10859e08a43Srillig 	take_uint(32768 * 65536U);
109dd848decSrillig 	/* expect+1: warning: '65536 * 65536' overflows 'unsigned int' [141] */
11059e08a43Srillig 	take_uint(65536 * 65536U);
11159e08a43Srillig }
11259e08a43Srillig 
11359e08a43Srillig void
fold_div(void)11459e08a43Srillig fold_div(void)
11559e08a43Srillig {
1163e856647Srillig 	/* expect+1: error: division by 0 [139] */
11759e08a43Srillig 	take_int(0 / 0);
11859e08a43Srillig 
11959e08a43Srillig 	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
12059e08a43Srillig 	take_int(-2147483648 / -1);
12159e08a43Srillig }
12259e08a43Srillig 
12359e08a43Srillig void
fold_mod(void)12459e08a43Srillig fold_mod(void)
12559e08a43Srillig {
12659e08a43Srillig 	/* expect+1: error: modulus by 0 [140] */
12759e08a43Srillig 	take_int(0 % 0);
12859e08a43Srillig 	/* expect+1: error: modulus by 0 [140] */
12959e08a43Srillig 	take_int(0 % 0U);
13059e08a43Srillig 	/* expect+1: error: modulus by 0 [140] */
13159e08a43Srillig 	take_int(0U % 0);
13259e08a43Srillig 	/* expect+1: error: modulus by 0 [140] */
13359e08a43Srillig 	take_int(0U % 0U);
13459e08a43Srillig 
13559e08a43Srillig 	take_int(-2147483648 % -1);
13659e08a43Srillig }
13759e08a43Srillig 
13859e08a43Srillig void
fold_plus(void)13959e08a43Srillig fold_plus(void)
14059e08a43Srillig {
141dd848decSrillig 	/* expect+1: warning: '2147483647 + 1' overflows 'int' [141] */
14259e08a43Srillig 	take_int(2147483647 + 1);
14359e08a43Srillig 
14459e08a43Srillig 	/* Assume two's complement, so no overflow. */
14559e08a43Srillig 	take_int(-2147483647 + -1);
14659e08a43Srillig 
147dd848decSrillig 	/* expect+1: warning: '-2147483647 + -2' overflows 'int' [141] */
14859e08a43Srillig 	take_int(-2147483647 + -2);
14959e08a43Srillig 
15059e08a43Srillig 	/*
15159e08a43Srillig 	 * No overflow since one of the operands is unsigned, therefore the
15259e08a43Srillig 	 * other operand is converted to unsigned as well.
15359e08a43Srillig 	 * See C99 6.3.1.8p1, paragraph 8 of 10.
15459e08a43Srillig 	 */
1552de04c81Srillig 	/* wrong integer overflow warning before tree.c 1.338 from 2021-08-19 */
15659e08a43Srillig 	take_uint(2147483647 + 1U);
1572de04c81Srillig 	/* wrong integer overflow warning before tree.c 1.338 from 2021-08-19 */
15859e08a43Srillig 	take_uint(2147483647U + 1);
15959e08a43Srillig }
16059e08a43Srillig 
16159e08a43Srillig void
fold_minus(void)16259e08a43Srillig fold_minus(void)
16359e08a43Srillig {
164dd848decSrillig 	/* expect+1: warning: '2147483647 - -1' overflows 'int' [141] */
16559e08a43Srillig 	take_int(2147483647 - -1);
16659e08a43Srillig 	/* Assume two's complement. */
16759e08a43Srillig 	take_int(-2147483647 - 1);
168dd848decSrillig 	/* expect+1: warning: '-2147483647 - 2' overflows 'int' [141] */
16959e08a43Srillig 	take_int(-2147483647 - 2);
17059e08a43Srillig 
17159e08a43Srillig 	take_int(0 - 2147483648);
172dd848decSrillig 	/* expect+1: warning: '0 - 2147483648' overflows 'unsigned int' [141] */
17359e08a43Srillig 	take_uint(0 - 2147483648U);
17459e08a43Srillig }
17559e08a43Srillig 
17659e08a43Srillig void
fold_shl(void)17759e08a43Srillig fold_shl(void)
17859e08a43Srillig {
179dd848decSrillig 	/* expect+1: warning: '16777216 << 24' overflows 'int' [141] */
18059e08a43Srillig 	take_int(1 << 24 << 24);
18159e08a43Srillig 
182dd848decSrillig 	/* expect+1: warning: '16777216 << 24' overflows 'unsigned int' [141] */
18359e08a43Srillig 	take_uint(1U << 24 << 24);
18459e08a43Srillig 
18559e08a43Srillig 	/* expect+1: warning: shift amount 104 is greater than bit-size 32 of 'unsigned int' [122] */
18659e08a43Srillig 	take_uint(1U << 24 << 104);
18759e08a43Srillig }
18859e08a43Srillig 
18959e08a43Srillig void
fold_shr(void)19059e08a43Srillig fold_shr(void)
19159e08a43Srillig {
19259e08a43Srillig 	take_int(16777216 >> 24);
19359e08a43Srillig 
19459e08a43Srillig 	take_int(16777216 >> 25);
19559e08a43Srillig 
19659e08a43Srillig 	/* expect+1: warning: shift amount 104 is greater than bit-size 32 of 'int' [122] */
19759e08a43Srillig 	take_int(16777216 >> 104);
19859e08a43Srillig }
19959e08a43Srillig 
20059e08a43Srillig void
fold_lt(void)20159e08a43Srillig fold_lt(void)
20259e08a43Srillig {
20359e08a43Srillig 	take_bool(1 < 3);
20459e08a43Srillig 	take_bool(3 < 1);
20559e08a43Srillig }
20659e08a43Srillig 
20759e08a43Srillig void
fold_le(void)20859e08a43Srillig fold_le(void)
20959e08a43Srillig {
21059e08a43Srillig 	take_bool(1 <= 3);
21159e08a43Srillig 	take_bool(3 <= 1);
21259e08a43Srillig }
21359e08a43Srillig 
21459e08a43Srillig void
fold_ge(void)21559e08a43Srillig fold_ge(void)
21659e08a43Srillig {
21759e08a43Srillig 	take_bool(1 >= 3);
21859e08a43Srillig 	take_bool(3 >= 1);
21959e08a43Srillig }
22059e08a43Srillig 
22159e08a43Srillig void
fold_gt(void)22259e08a43Srillig fold_gt(void)
22359e08a43Srillig {
22459e08a43Srillig 	take_bool(1 > 3);
22559e08a43Srillig 	take_bool(3 > 1);
22659e08a43Srillig }
22759e08a43Srillig 
22859e08a43Srillig void
fold_eq(void)22959e08a43Srillig fold_eq(void)
23059e08a43Srillig {
23159e08a43Srillig 	take_bool(1 == 3);
23259e08a43Srillig 	take_bool(3 == 1);
23359e08a43Srillig }
23459e08a43Srillig 
23559e08a43Srillig void
fold_ne(void)23659e08a43Srillig fold_ne(void)
23759e08a43Srillig {
23859e08a43Srillig 	take_bool(1 != 3);
23959e08a43Srillig 	take_bool(3 != 1);
24059e08a43Srillig }
24159e08a43Srillig 
24259e08a43Srillig void
fold_bitand(void)24359e08a43Srillig fold_bitand(void)
24459e08a43Srillig {
24559e08a43Srillig 	take_bool(1 & 3);
24659e08a43Srillig 	take_bool(3 & 1);
24759e08a43Srillig }
24859e08a43Srillig 
24959e08a43Srillig void
fold_bitxor(void)25059e08a43Srillig fold_bitxor(void)
25159e08a43Srillig {
25259e08a43Srillig 	take_bool(1 ^ 3);
25359e08a43Srillig 	take_bool(3 ^ 1);
25459e08a43Srillig }
25559e08a43Srillig 
25659e08a43Srillig void
fold_bitor(void)25759e08a43Srillig fold_bitor(void)
25859e08a43Srillig {
25959e08a43Srillig 	take_bool(1 | 3);
26059e08a43Srillig 	take_bool(3 | 1);
26159e08a43Srillig }
26254836453Srillig 
26354836453Srillig /*
26454836453Srillig  * The following expression originated in vndcompress.c 1.29 from 2017-07-29,
26554836453Srillig  * where line 310 contained a seemingly harmless compile-time assertion that
26654836453Srillig  * expanded to a real monster expression.
26754836453Srillig  *
26854836453Srillig  * __CTASSERT(MUL_OK(uint64_t, MAX_N_BLOCKS, MAX_BLOCKSIZE));
269a8096716Srillig  *
270a8096716Srillig  * Before tree.c 1.345 from 2021-08-22, lint wrongly assumed that the result
271a8096716Srillig  * of all binary operators were the common arithmetic type, but that was
272a8096716Srillig  * wrong for the comparison operators.  The expression '1ULL < 2ULL' does not
273a8096716Srillig  * have type 'unsigned long long' but 'int' in default mode, or '_Bool' in
274a8096716Srillig  * strict bool mode.
27554836453Srillig  */
27654836453Srillig struct ctassert5_struct {
27754836453Srillig 	unsigned int member:
27854836453Srillig 	    /*CONSTCOND*/
27954836453Srillig 	    0xfffffffeU
28054836453Srillig 	    <=
28154836453Srillig 		((1ULL << 63) + 1 < 1 ? ~(1ULL << 63) : ~0ULL) / 0xfffffe00U
28254836453Srillig 		? 1
28354836453Srillig 		: -1;
28454836453Srillig };
285598b5fa3Srillig 
286598b5fa3Srillig /*
287598b5fa3Srillig  * Since Makefile.inc 1.21 from 2022-04-08 (which added -ftrapv) and before
288598b5fa3Srillig  * tree.c 1.436 from 2022-04-20, lint crashed with an integer overflow when
289ad4700f6Srillig  * calculating '-(uint64_t)INT64_MIN' in val_t.u.integer.
290598b5fa3Srillig  */
291598b5fa3Srillig void
unary_minus_overflow(unsigned long long val)292598b5fa3Srillig unary_minus_overflow(unsigned long long val)
293598b5fa3Srillig {
294598b5fa3Srillig 	if (val > -(unsigned long long)(-0x7fffffffffffffffL - 1))
295598b5fa3Srillig 		return;
296598b5fa3Srillig }
297