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