expr_fold.c revision 1.7
11.7Srillig/*	$NetBSD: expr_fold.c,v 1.7 2022/04/19 23:16:14 rillig Exp $	*/
21.1Srillig# 3 "expr_fold.c"
31.1Srillig
41.1Srillig/*
51.1Srillig * Test folding of constant expressions.
61.1Srillig */
71.1Srillig
81.1Srillig/* lint1-extra-flags: -h */
91.1Srillig
101.1Srillig/*
111.1Srillig * On ILP32 platforms, the integer constant 2147483648 cannot be represented
121.1Srillig * as 'int' or 'long', therefore it becomes 'long long'.  This would
131.1Srillig * influence the type names in the diagnostics.
141.1Srillig */
151.1Srillig/* lint1-only-if: lp64 */
161.1Srillig
171.1Srilligvoid take_bool(_Bool);
181.1Srilligvoid take_int(int);
191.1Srilligvoid take_uint(unsigned int);
201.1Srillig
211.1Srillig/*
221.1Srillig * C99 6.4.4.1p5 defines that decimal integer constants without suffix get
231.1Srillig * one of the signed integer types. On the other hand, octal and hexadecimal
241.1Srillig * constants get either a signed or unsigned type, whichever fits first.
251.1Srillig */
261.1Srillig
271.1Srilligvoid
281.1Srilligfold_uplus(void)
291.1Srillig{
301.1Srillig	take_int(+(0));
311.1Srillig	take_int(+(2147483647));
321.1Srillig	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
331.1Srillig	take_int(+(2147483648));
341.1Srillig	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
351.1Srillig	take_int(+(4294967295));
361.1Srillig
371.1Srillig	take_uint(+(0));
381.1Srillig	take_uint(+(2147483647));
391.1Srillig	take_uint(+(2147483648));
401.1Srillig	take_uint(+(4294967295));
411.1Srillig
421.1Srillig	/*
431.1Srillig	 * Hexadecimal constants and constants with the suffix 'U' get either
441.1Srillig	 * a signed or an unsigned integer type, so no warning here.
451.1Srillig	 */
461.1Srillig	take_uint(+(2147483648U));
471.1Srillig	take_uint(+(0x80000000));
481.1Srillig	take_uint(+(0x80000000U));
491.1Srillig}
501.1Srillig
511.1Srilligvoid
521.1Srilligfold_uminus(void)
531.1Srillig{
541.1Srillig	take_int(-(0));
551.1Srillig	take_int(-(2147483647));
561.1Srillig
571.1Srillig	take_int(-(2147483648));
581.1Srillig
591.1Srillig	/* The '-' is an operator, it is not part of the integer constant. */
601.1Srillig	take_int(-2147483648);
611.1Srillig
621.5Srillig	/* expect+2: warning: integer overflow detected, op '+' [141] */
631.5Srillig	/* expect+1: warning: integer overflow detected, op '-' [141] */
641.1Srillig	take_int(-(2147483647 + 1));
651.5Srillig	/* expect+1: warning: integer overflow detected, op '-' [141] */
661.1Srillig	take_int(-(-2147483647 - 1));
671.1Srillig	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
681.1Srillig	take_int(-(4294967295));
691.1Srillig
701.1Srillig	take_uint(-(0));
711.6Srillig	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
721.1Srillig	take_uint(-(2147483647));
731.1Srillig	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
741.1Srillig	take_uint(-(2147483648));
751.1Srillig	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
761.1Srillig	take_uint(-(4294967295));
771.1Srillig}
781.1Srillig
791.1Srilligvoid
801.1Srilligfold_compl(void)
811.1Srillig{
821.1Srillig	take_int(~(0));
831.1Srillig	take_int(~(2147483647));
841.1Srillig	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
851.1Srillig	take_int(~(2147483648));
861.1Srillig	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
871.1Srillig	take_int(~(4294967295));
881.1Srillig
891.6Srillig	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
901.1Srillig	take_uint(~(0));
911.1Srillig	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
921.1Srillig	take_uint(~(2147483647));
931.1Srillig	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
941.1Srillig	take_uint(~(2147483648));
951.1Srillig	/* expect+1: warning: conversion of negative constant to unsigned type, arg #1 [296] */
961.1Srillig	take_uint(~(4294967295));
971.1Srillig}
981.1Srillig
991.1Srilligvoid
1001.1Srilligfold_mult(void)
1011.1Srillig{
1021.1Srillig	take_int(32767 * 65536);
1031.5Srillig	/* expect+1: warning: integer overflow detected, op '*' [141] */
1041.1Srillig	take_int(32768 * 65536);
1051.5Srillig	/* expect+1: warning: integer overflow detected, op '*' [141] */
1061.1Srillig	take_int(65536 * 65536);
1071.1Srillig
1081.1Srillig	take_uint(32767 * 65536U);
1091.1Srillig	take_uint(32768 * 65536U);
1101.5Srillig	/* expect+1: warning: integer overflow detected, op '*' [141] */
1111.1Srillig	take_uint(65536 * 65536U);
1121.1Srillig}
1131.1Srillig
1141.1Srilligvoid
1151.1Srilligfold_div(void)
1161.1Srillig{
1171.1Srillig	/* expect+3: error: division by 0 [139] */
1181.1Srillig	/* XXX: The following message is redundant. */
1191.5Srillig	/* expect+1: warning: integer overflow detected, op '/' [141] */
1201.1Srillig	take_int(0 / 0);
1211.1Srillig
1221.1Srillig	/* expect+1: warning: conversion of 'long' to 'int' is out of range, arg #1 [295] */
1231.1Srillig	take_int(-2147483648 / -1);
1241.1Srillig}
1251.1Srillig
1261.1Srilligvoid
1271.1Srilligfold_mod(void)
1281.1Srillig{
1291.1Srillig	/* expect+1: error: modulus by 0 [140] */
1301.1Srillig	take_int(0 % 0);
1311.1Srillig	/* expect+1: error: modulus by 0 [140] */
1321.1Srillig	take_int(0 % 0U);
1331.1Srillig	/* expect+1: error: modulus by 0 [140] */
1341.1Srillig	take_int(0U % 0);
1351.1Srillig	/* expect+1: error: modulus by 0 [140] */
1361.1Srillig	take_int(0U % 0U);
1371.1Srillig
1381.1Srillig	take_int(-2147483648 % -1);
1391.1Srillig}
1401.1Srillig
1411.1Srilligvoid
1421.1Srilligfold_plus(void)
1431.1Srillig{
1441.5Srillig	/* expect+1: warning: integer overflow detected, op '+' [141] */
1451.1Srillig	take_int(2147483647 + 1);
1461.1Srillig
1471.1Srillig	/* Assume two's complement, so no overflow. */
1481.1Srillig	take_int(-2147483647 + -1);
1491.1Srillig
1501.5Srillig	/* expect+1: warning: integer overflow detected, op '+' [141] */
1511.1Srillig	take_int(-2147483647 + -2);
1521.1Srillig
1531.1Srillig	/*
1541.1Srillig	 * No overflow since one of the operands is unsigned, therefore the
1551.1Srillig	 * other operand is converted to unsigned as well.
1561.1Srillig	 * See C99 6.3.1.8p1, paragraph 8 of 10.
1571.1Srillig	 */
1581.2Srillig	/* wrong integer overflow warning before tree.c 1.338 from 2021-08-19 */
1591.1Srillig	take_uint(2147483647 + 1U);
1601.2Srillig	/* wrong integer overflow warning before tree.c 1.338 from 2021-08-19 */
1611.1Srillig	take_uint(2147483647U + 1);
1621.1Srillig}
1631.1Srillig
1641.1Srilligvoid
1651.1Srilligfold_minus(void)
1661.1Srillig{
1671.5Srillig	/* expect+1: warning: integer overflow detected, op '-' [141] */
1681.1Srillig	take_int(2147483647 - -1);
1691.1Srillig	/* Assume two's complement. */
1701.1Srillig	take_int(-2147483647 - 1);
1711.5Srillig	/* expect+1: warning: integer overflow detected, op '-' [141] */
1721.1Srillig	take_int(-2147483647 - 2);
1731.1Srillig
1741.1Srillig	take_int(0 - 2147483648);
1751.5Srillig	/* expect+1: warning: integer overflow detected, op '-' [141] */
1761.1Srillig	take_uint(0 - 2147483648U);
1771.1Srillig}
1781.1Srillig
1791.1Srilligvoid
1801.1Srilligfold_shl(void)
1811.1Srillig{
1821.5Srillig	/* expect+1: warning: integer overflow detected, op '<<' [141] */
1831.1Srillig	take_int(1 << 24 << 24);
1841.1Srillig
1851.5Srillig	/* expect+1: warning: integer overflow detected, op '<<' [141] */
1861.1Srillig	take_uint(1U << 24 << 24);
1871.1Srillig
1881.1Srillig	/* FIXME: undefined behavior in 'fold' at 'uint64_t << 104'. */
1891.1Srillig	/* expect+1: warning: shift amount 104 is greater than bit-size 32 of 'unsigned int' [122] */
1901.1Srillig	take_uint(1U << 24 << 104);
1911.1Srillig}
1921.1Srillig
1931.1Srilligvoid
1941.1Srilligfold_shr(void)
1951.1Srillig{
1961.1Srillig	take_int(16777216 >> 24);
1971.1Srillig
1981.1Srillig	take_int(16777216 >> 25);
1991.1Srillig
2001.1Srillig	/* FIXME: undefined behavior in 'fold' at 'uint64_t >> 104'. */
2011.1Srillig	/* expect+1: warning: shift amount 104 is greater than bit-size 32 of 'int' [122] */
2021.1Srillig	take_int(16777216 >> 104);
2031.1Srillig}
2041.1Srillig
2051.1Srilligvoid
2061.1Srilligfold_lt(void)
2071.1Srillig{
2081.1Srillig	take_bool(1 < 3);
2091.1Srillig	take_bool(3 < 1);
2101.1Srillig}
2111.1Srillig
2121.1Srilligvoid
2131.1Srilligfold_le(void)
2141.1Srillig{
2151.1Srillig	take_bool(1 <= 3);
2161.1Srillig	take_bool(3 <= 1);
2171.1Srillig}
2181.1Srillig
2191.1Srilligvoid
2201.1Srilligfold_ge(void)
2211.1Srillig{
2221.1Srillig	take_bool(1 >= 3);
2231.1Srillig	take_bool(3 >= 1);
2241.1Srillig}
2251.1Srillig
2261.1Srilligvoid
2271.1Srilligfold_gt(void)
2281.1Srillig{
2291.1Srillig	take_bool(1 > 3);
2301.1Srillig	take_bool(3 > 1);
2311.1Srillig}
2321.1Srillig
2331.1Srilligvoid
2341.1Srilligfold_eq(void)
2351.1Srillig{
2361.1Srillig	take_bool(1 == 3);
2371.1Srillig	take_bool(3 == 1);
2381.1Srillig}
2391.1Srillig
2401.1Srilligvoid
2411.1Srilligfold_ne(void)
2421.1Srillig{
2431.1Srillig	take_bool(1 != 3);
2441.1Srillig	take_bool(3 != 1);
2451.1Srillig}
2461.1Srillig
2471.1Srilligvoid
2481.1Srilligfold_bitand(void)
2491.1Srillig{
2501.1Srillig	take_bool(1 & 3);
2511.1Srillig	take_bool(3 & 1);
2521.1Srillig}
2531.1Srillig
2541.1Srilligvoid
2551.1Srilligfold_bitxor(void)
2561.1Srillig{
2571.1Srillig	take_bool(1 ^ 3);
2581.1Srillig	take_bool(3 ^ 1);
2591.1Srillig}
2601.1Srillig
2611.1Srilligvoid
2621.1Srilligfold_bitor(void)
2631.1Srillig{
2641.1Srillig	take_bool(1 | 3);
2651.1Srillig	take_bool(3 | 1);
2661.1Srillig}
2671.3Srillig
2681.3Srillig/*
2691.3Srillig * The following expression originated in vndcompress.c 1.29 from 2017-07-29,
2701.3Srillig * where line 310 contained a seemingly harmless compile-time assertion that
2711.3Srillig * expanded to a real monster expression.
2721.3Srillig *
2731.3Srillig * __CTASSERT(MUL_OK(uint64_t, MAX_N_BLOCKS, MAX_BLOCKSIZE));
2741.4Srillig *
2751.4Srillig * Before tree.c 1.345 from 2021-08-22, lint wrongly assumed that the result
2761.4Srillig * of all binary operators were the common arithmetic type, but that was
2771.4Srillig * wrong for the comparison operators.  The expression '1ULL < 2ULL' does not
2781.4Srillig * have type 'unsigned long long' but 'int' in default mode, or '_Bool' in
2791.4Srillig * strict bool mode.
2801.3Srillig */
2811.3Srilligstruct ctassert5_struct {
2821.3Srillig	unsigned int member:
2831.3Srillig	    /*CONSTCOND*/
2841.3Srillig	    0xfffffffeU
2851.3Srillig	    <=
2861.3Srillig		((1ULL << 63) + 1 < 1 ? ~(1ULL << 63) : ~0ULL) / 0xfffffe00U
2871.3Srillig		? 1
2881.3Srillig		: -1;
2891.3Srillig};
2901.7Srillig
2911.7Srillig/*
2921.7Srillig * Since Makefile.inc 1.21 from 2022-04-08 (which added -ftrapv) and before
2931.7Srillig * tree.c 1.436 from 2022-04-20, lint crashed with an integer overflow when
2941.7Srillig * calculating '-(uint64_t)INT64_MIN' in val_t.v_quad.
2951.7Srillig */
2961.7Srilligvoid
2971.7Srilligunary_minus_overflow(unsigned long long val)
2981.7Srillig{
2991.7Srillig	/* expect+1: warning: integer overflow detected, op '-' [141] */
3001.7Srillig	if (val > -(unsigned long long)(-0x7fffffffffffffffL - 1))
3011.7Srillig		return;
3021.7Srillig}
303