(left_shift_overflows, same_sign, overflow_sum_sign): New macros.

(add_double, div_and_round_double, lshift_double, mul_double):
(neg_double, const_binop, fold): Check for signed integer overflow.
Propagate overflow flags from operands to result.
(const_binop, fold_convert): Use pedwarn for overflow warnings.
Say `constant expression', not `constant folding', for user's sake.

From-SVN: r2053
This commit is contained in:
Richard Stallman 1992-09-05 02:02:17 +00:00
parent 9e9bd45dd9
commit fe3e8e402b
1 changed files with 119 additions and 52 deletions

View File

@ -48,7 +48,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Handle floating overflow for `const_binop'. */ /* Handle floating overflow for `const_binop'. */
static jmp_buf float_error; static jmp_buf float_error;
void lshift_double (); int lshift_double ();
void rshift_double (); void rshift_double ();
void lrotate_double (); void lrotate_double ();
void rrotate_double (); void rrotate_double ();
@ -57,6 +57,19 @@ static tree const_binop ();
#ifndef BRANCH_COST #ifndef BRANCH_COST
#define BRANCH_COST 1 #define BRANCH_COST 1
#endif #endif
/* Yield nonzero if a signed left shift of A by B bits overflows. */
#define left_shift_overflows(a, b) ((a) != ((a) << (b)) >> (b))
/* Yield nonzero if A and B have the same sign. */
#define same_sign(a, b) ((a) ^ (b) >= 0)
/* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
Then this yields nonzero if overflow occurred during the addition.
Overflow occurs if A and B have the same sign, but A and SUM differ in sign.
Use `^' to test whether signs differ, and `< 0' to isolate the sign. */
#define overflow_sum_sign(a, b, sum) ((~((a) ^ (b)) & ((a) ^ (sum))) < 0)
/* To do constant folding on INTEGER_CST nodes requires two-word arithmetic. /* To do constant folding on INTEGER_CST nodes requires two-word arithmetic.
We do that by representing the two-word integer as MAX_SHORTS shorts, We do that by representing the two-word integer as MAX_SHORTS shorts,
@ -161,7 +174,7 @@ force_fit_type (t)
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.
We use the 8-shorts representation internally. */ We use the 8-shorts representation internally. */
void int
add_double (l1, h1, l2, h2, lv, hv) add_double (l1, h1, l2, h2, lv, hv)
HOST_WIDE_INT l1, h1, l2, h2; HOST_WIDE_INT l1, h1, l2, h2;
HOST_WIDE_INT *lv, *hv; HOST_WIDE_INT *lv, *hv;
@ -182,14 +195,16 @@ add_double (l1, h1, l2, h2, lv, hv)
} }
decode (arg1, lv, hv); decode (arg1, lv, hv);
return overflow_sum_sign (h1, h2, *hv);
} }
/* Negate a doubleword integer with doubleword result. /* Negate a doubleword integer with doubleword result.
Return nonzero if the operation overflows, assuming it's signed.
The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1. The argument is given as two `HOST_WIDE_INT' pieces in L1 and H1.
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.
We use the 8-shorts representation internally. */ We use the 8-shorts representation internally. */
void int
neg_double (l1, h1, lv, hv) neg_double (l1, h1, lv, hv)
HOST_WIDE_INT l1, h1; HOST_WIDE_INT l1, h1;
HOST_WIDE_INT *lv, *hv; HOST_WIDE_INT *lv, *hv;
@ -198,21 +213,24 @@ neg_double (l1, h1, lv, hv)
{ {
*lv = 0; *lv = 0;
*hv = - h1; *hv = - h1;
return same_sign (h1, *hv);
} }
else else
{ {
*lv = - l1; *lv = - l1;
*hv = ~ h1; *hv = ~ h1;
return 0;
} }
} }
/* Multiply two doubleword integers with doubleword result. /* Multiply two doubleword integers with doubleword result.
Return nonzero if the operation overflows, assuming it's signed.
Each argument is given as two `HOST_WIDE_INT' pieces. Each argument is given as two `HOST_WIDE_INT' pieces.
One argument is L1 and H1; the other, L2 and H2. One argument is L1 and H1; the other, L2 and H2.
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV.
We use the 8-shorts representation internally. */ We use the 8-shorts representation internally. */
void int
mul_double (l1, h1, l2, h2, lv, hv) mul_double (l1, h1, l2, h2, lv, hv)
HOST_WIDE_INT l1, h1, l2, h2; HOST_WIDE_INT l1, h1, l2, h2;
HOST_WIDE_INT *lv, *hv; HOST_WIDE_INT *lv, *hv;
@ -222,33 +240,36 @@ mul_double (l1, h1, l2, h2, lv, hv)
short prod[MAX_SHORTS * 2]; short prod[MAX_SHORTS * 2];
register int carry = 0; register int carry = 0;
register int i, j, k; register int i, j, k;
HOST_WIDE_INT toplow, tophigh, neglow, neghigh;
/* These two cases are used extensively, arising from pointer /* These cases are used extensively, arising from pointer combinations. */
combinations. */
if (h2 == 0) if (h2 == 0)
{ {
if (l2 == 2) if (l2 == 2)
{ {
int overflow = left_shift_overflows (h1, 1);
unsigned HOST_WIDE_INT temp = l1 + l1; unsigned HOST_WIDE_INT temp = l1 + l1;
*hv = h1 * 2 + (temp < l1); *hv = (h1 << 1) + (temp < l1);
*lv = temp; *lv = temp;
return; return overflow;
} }
if (l2 == 4) if (l2 == 4)
{ {
int overflow = left_shift_overflows (h1, 2);
unsigned HOST_WIDE_INT temp = l1 + l1; unsigned HOST_WIDE_INT temp = l1 + l1;
h1 = h1 * 4 + ((temp < l1) << 1); h1 = (h1 << 2) + ((temp < l1) << 1);
l1 = temp; l1 = temp;
temp += temp; temp += temp;
h1 += (temp < l1); h1 += (temp < l1);
*lv = temp; *lv = temp;
*hv = h1; *hv = h1;
return; return overflow;
} }
if (l2 == 8) if (l2 == 8)
{ {
int overflow = left_shift_overflows (h1, 3);
unsigned HOST_WIDE_INT temp = l1 + l1; unsigned HOST_WIDE_INT temp = l1 + l1;
h1 = h1 * 8 + ((temp < l1) << 2); h1 = (h1 << 3) + ((temp < l1) << 2);
l1 = temp; l1 = temp;
temp += temp; temp += temp;
h1 += (temp < l1) << 1; h1 += (temp < l1) << 1;
@ -257,7 +278,7 @@ mul_double (l1, h1, l2, h2, lv, hv)
h1 += (temp < l1); h1 += (temp < l1);
*lv = temp; *lv = temp;
*hv = h1; *hv = h1;
return; return overflow;
} }
} }
@ -280,17 +301,33 @@ mul_double (l1, h1, l2, h2, lv, hv)
} }
} }
decode (prod, lv, hv); /* ?? decode ignores decode (prod, lv, hv); /* This ignores
prod[MAX_SHORTS] -> prod[MAX_SHORTS*2-1] */ prod[MAX_SHORTS] -> prod[MAX_SHORTS*2-1] */
/* Check for overflow by calculating the top half of the answer in full;
it should agree with the low half's sign bit. */
decode (prod+MAX_SHORTS, &toplow, &tophigh);
if (h1 < 0)
{
neg_double (l2, h2, &neglow, &neghigh);
add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
}
if (h2 < 0)
{
neg_double (l1, h1, &neglow, &neghigh);
add_double (neglow, neghigh, toplow, tophigh, &toplow, &tophigh);
}
return (*hv < 0 ? ~(toplow & tophigh) : toplow | tophigh) != 0;
} }
/* Shift the doubleword integer in L1, H1 left by COUNT places /* Shift the doubleword integer in L1, H1 left by COUNT places
keeping only PREC bits of result. keeping only PREC bits of result.
Shift right if COUNT is negative. Shift right if COUNT is negative.
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift. ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
Return nonzero if the arithmetic shift overflows, assuming it's signed.
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */ Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
void int
lshift_double (l1, h1, count, prec, lv, hv, arith) lshift_double (l1, h1, count, prec, lv, hv, arith)
HOST_WIDE_INT l1, h1; HOST_WIDE_INT l1, h1;
int count, prec; int count, prec;
@ -299,12 +336,12 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
{ {
short arg1[MAX_SHORTS]; short arg1[MAX_SHORTS];
register int i; register int i;
register int carry; register int carry, overflow;
if (count < 0) if (count < 0)
{ {
rshift_double (l1, h1, - count, prec, lv, hv, arith); rshift_double (l1, h1, - count, prec, lv, hv, arith);
return; return 0;
} }
encode (arg1, l1, h1); encode (arg1, l1, h1);
@ -312,6 +349,7 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
if (count > prec) if (count > prec)
count = prec; count = prec;
overflow = 0;
while (count > 0) while (count > 0)
{ {
carry = 0; carry = 0;
@ -322,9 +360,11 @@ lshift_double (l1, h1, count, prec, lv, hv, arith)
carry >>= 8; carry >>= 8;
} }
count--; count--;
overflow |= carry ^ (arg1[7] >> 7);
} }
decode (arg1, lv, hv); decode (arg1, lv, hv);
return overflow;
} }
/* Shift the doubleword integer in L1, H1 right by COUNT places /* Shift the doubleword integer in L1, H1 right by COUNT places
@ -440,10 +480,11 @@ rrotate_double (l1, h1, count, prec, lv, hv)
CODE is a tree code for a kind of division, one of CODE is a tree code for a kind of division, one of
TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR TRUNC_DIV_EXPR, FLOOR_DIV_EXPR, CEIL_DIV_EXPR, ROUND_DIV_EXPR
or EXACT_DIV_EXPR or EXACT_DIV_EXPR
It controls how the quotient is rounded to an integer. It controls how the quotient is rounded to a integer.
Return nonzero if the operation overflows.
UNS nonzero says do unsigned division. */ UNS nonzero says do unsigned division. */
static void static int
div_and_round_double (code, uns, div_and_round_double (code, uns,
lnum_orig, hnum_orig, lden_orig, hden_orig, lnum_orig, hnum_orig, lden_orig, hden_orig,
lquo, hquo, lrem, hrem) lquo, hquo, lrem, hrem)
@ -462,6 +503,7 @@ div_and_round_double (code, uns,
HOST_WIDE_INT hnum = hnum_orig; HOST_WIDE_INT hnum = hnum_orig;
unsigned HOST_WIDE_INT lden = lden_orig; unsigned HOST_WIDE_INT lden = lden_orig;
HOST_WIDE_INT hden = hden_orig; HOST_WIDE_INT hden = hden_orig;
int overflow = 0;
if ((hden == 0) && (lden == 0)) if ((hden == 0) && (lden == 0))
abort (); abort ();
@ -469,16 +511,18 @@ div_and_round_double (code, uns,
/* calculate quotient sign and convert operands to unsigned. */ /* calculate quotient sign and convert operands to unsigned. */
if (!uns) if (!uns)
{ {
if (hnum < 0)
{
quo_neg = ~ quo_neg;
/* (minimum integer) / (-1) is the only overflow case. */
if (neg_double (lnum, hnum, &lnum, &hnum) && (lden & hden) == -1)
overflow = 1;
}
if (hden < 0) if (hden < 0)
{ {
quo_neg = ~ quo_neg; quo_neg = ~ quo_neg;
neg_double (lden, hden, &lden, &hden); neg_double (lden, hden, &lden, &hden);
} }
if (hnum < 0)
{
quo_neg = ~ quo_neg;
neg_double (lnum, hnum, &lnum, &hnum);
}
} }
if (hnum == 0 && hden == 0) if (hnum == 0 && hden == 0)
@ -650,7 +694,7 @@ div_and_round_double (code, uns,
case TRUNC_DIV_EXPR: case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR: /* round toward zero */ case TRUNC_MOD_EXPR: /* round toward zero */
case EXACT_DIV_EXPR: /* for this one, it shouldn't matter */ case EXACT_DIV_EXPR: /* for this one, it shouldn't matter */
return; return overflow;
case FLOOR_DIV_EXPR: case FLOOR_DIV_EXPR:
case FLOOR_MOD_EXPR: /* round toward negative infinity */ case FLOOR_MOD_EXPR: /* round toward negative infinity */
@ -660,7 +704,7 @@ div_and_round_double (code, uns,
add_double (*lquo, *hquo, (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1, add_double (*lquo, *hquo, (HOST_WIDE_INT) -1, (HOST_WIDE_INT) -1,
lquo, hquo); lquo, hquo);
} }
else return; else return overflow;
break; break;
case CEIL_DIV_EXPR: case CEIL_DIV_EXPR:
@ -670,7 +714,7 @@ div_and_round_double (code, uns,
add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0, add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
lquo, hquo); lquo, hquo);
} }
else return; else return overflow;
break; break;
case ROUND_DIV_EXPR: case ROUND_DIV_EXPR:
@ -702,7 +746,7 @@ div_and_round_double (code, uns,
add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0, add_double (*lquo, *hquo, (HOST_WIDE_INT) 1, (HOST_WIDE_INT) 0,
lquo, hquo); lquo, hquo);
} }
else return; else return overflow;
} }
break; break;
@ -714,6 +758,7 @@ div_and_round_double (code, uns,
mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem); mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
neg_double (*lrem, *hrem, lrem, hrem); neg_double (*lrem, *hrem, lrem, hrem);
add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem); add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
return overflow;
} }
/* Effectively truncate a real value to represent /* Effectively truncate a real value to represent
@ -1002,6 +1047,9 @@ const_binop (code, arg1, arg2)
HOST_WIDE_INT garbagel, garbageh; HOST_WIDE_INT garbagel, garbageh;
register tree t; register tree t;
int uns = TREE_UNSIGNED (TREE_TYPE (arg1)); int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
/* Propagate overflow flags from operands; also record new overflow. */
int overflow
= TREE_CONSTANT_OVERFLOW (arg0) | TREE_CONSTANT_OVERFLOW (arg1);
switch (code) switch (code)
{ {
@ -1024,10 +1072,10 @@ const_binop (code, arg1, arg2)
case RSHIFT_EXPR: case RSHIFT_EXPR:
int2l = - int2l; int2l = - int2l;
case LSHIFT_EXPR: case LSHIFT_EXPR:
lshift_double (int1l, int1h, int2l, overflow = lshift_double (int1l, int1h, int2l,
TYPE_PRECISION (TREE_TYPE (arg1)), TYPE_PRECISION (TREE_TYPE (arg1)),
&low, &hi, &low, &hi,
!uns); !uns);
t = build_int_2 (low, hi); t = build_int_2 (low, hi);
break; break;
@ -1045,7 +1093,10 @@ const_binop (code, arg1, arg2)
{ {
int2l += int1l; int2l += int1l;
if ((unsigned HOST_WIDE_INT) int2l < int1l) if ((unsigned HOST_WIDE_INT) int2l < int1l)
int2h += 1; {
hi = int2h++;
overflow = ! same_sign (hi, int2h);
}
t = build_int_2 (int2l, int2h); t = build_int_2 (int2l, int2h);
break; break;
} }
@ -1053,11 +1104,14 @@ const_binop (code, arg1, arg2)
{ {
int1l += int2l; int1l += int2l;
if ((unsigned HOST_WIDE_INT) int1l < int2l) if ((unsigned HOST_WIDE_INT) int1l < int2l)
int1h += 1; {
hi = int1h++;
overflow = ! same_sign (hi, int1h);
}
t = build_int_2 (int1l, int1h); t = build_int_2 (int1l, int1h);
break; break;
} }
add_double (int1l, int1h, int2l, int2h, &low, &hi); overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi); t = build_int_2 (low, hi);
break; break;
@ -1067,8 +1121,9 @@ const_binop (code, arg1, arg2)
t = build_int_2 (int1l, int1h); t = build_int_2 (int1l, int1h);
break; break;
} }
neg_double (int2l, int2h, &int2l, &int2h); neg_double (int2l, int2h, &low, &hi);
add_double (int1l, int1h, int2l, int2h, &low, &hi); add_double (int1l, int1h, low, hi, &low, &hi);
overflow = overflow_sum_sign (hi, int2h, int1h);
t = build_int_2 (low, hi); t = build_int_2 (low, hi);
break; break;
@ -1087,8 +1142,9 @@ const_binop (code, arg1, arg2)
t = build_int_2 (int2l, int2h); t = build_int_2 (int2l, int2h);
goto got_it; goto got_it;
case 2: case 2:
overflow = left_shift_overflows (int2h, 1);
temp = int2l + int2l; temp = int2l + int2l;
int2h = int2h * 2 + (temp < int2l); int2h = (int2h << 1) + (temp < int2l);
t = build_int_2 (temp, int2h); t = build_int_2 (temp, int2h);
goto got_it; goto got_it;
#if 0 /* This code can lose carries. */ #if 0 /* This code can lose carries. */
@ -1099,16 +1155,18 @@ const_binop (code, arg1, arg2)
goto got_it; goto got_it;
#endif #endif
case 4: case 4:
overflow = left_shift_overflows (int2h, 2);
temp = int2l + int2l; temp = int2l + int2l;
int2h = int2h * 4 + ((temp < int2l) << 1); int2h = (int2h << 2) + ((temp < int2l) << 1);
int2l = temp; int2l = temp;
temp += temp; temp += temp;
int2h += (temp < int2l); int2h += (temp < int2l);
t = build_int_2 (temp, int2h); t = build_int_2 (temp, int2h);
goto got_it; goto got_it;
case 8: case 8:
overflow = left_shift_overflows (int2h, 3);
temp = int2l + int2l; temp = int2l + int2l;
int2h = int2h * 8 + ((temp < int2l) << 2); int2h = (int2h << 3) + ((temp < int2l) << 2);
int2l = temp; int2l = temp;
temp += temp; temp += temp;
int2h += (temp < int2l) << 1; int2h += (temp < int2l) << 1;
@ -1136,7 +1194,7 @@ const_binop (code, arg1, arg2)
} }
} }
mul_double (int1l, int1h, int2l, int2h, &low, &hi); overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi); t = build_int_2 (low, hi);
break; break;
@ -1167,15 +1225,17 @@ const_binop (code, arg1, arg2)
t = build_int_2 (1, 0); t = build_int_2 (1, 0);
break; break;
} }
div_and_round_double (code, uns, int1l, int1h, int2l, int2h, overflow = div_and_round_double (code, uns,
&low, &hi, &garbagel, &garbageh); int1l, int1h, int2l, int2h,
&low, &hi, &garbagel, &garbageh);
t = build_int_2 (low, hi); t = build_int_2 (low, hi);
break; break;
case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR: case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR:
case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR: case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
div_and_round_double (code, uns, int1l, int1h, int2l, int2h, overflow = div_and_round_double (code, uns,
&garbagel, &garbageh, &low, &hi); int1l, int1h, int2l, int2h,
&garbagel, &garbageh, &low, &hi);
t = build_int_2 (low, hi); t = build_int_2 (low, hi);
break; break;
@ -1209,6 +1269,7 @@ const_binop (code, arg1, arg2)
got_it: got_it:
TREE_TYPE (t) = TREE_TYPE (arg1); TREE_TYPE (t) = TREE_TYPE (arg1);
force_fit_type (t); force_fit_type (t);
TREE_CONSTANT_OVERFLOW (t) = overflow;
return t; return t;
} }
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC) #if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
@ -1223,7 +1284,7 @@ const_binop (code, arg1, arg2)
d2 = TREE_REAL_CST (arg2); d2 = TREE_REAL_CST (arg2);
if (setjmp (float_error)) if (setjmp (float_error))
{ {
warning ("floating overflow in constant folding"); pedwarn ("floating overflow in constant expression");
return build (code, TREE_TYPE (arg1), arg1, arg2); return build (code, TREE_TYPE (arg1), arg1, arg2);
} }
set_float_handler (float_error); set_float_handler (float_error);
@ -1415,6 +1476,9 @@ fold_convert (t, arg1)
appropriately sign-extended or truncated. */ appropriately sign-extended or truncated. */
t = build_int_2 (TREE_INT_CST_LOW (arg1), t = build_int_2 (TREE_INT_CST_LOW (arg1),
TREE_INT_CST_HIGH (arg1)); TREE_INT_CST_HIGH (arg1));
/* Carry forward overflow indication unless truncating. */
if (TYPE_PRECISION (type) >= TYPE_PRECISION (TREE_TYPE (t)))
TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg1);
TREE_TYPE (t) = type; TREE_TYPE (t) = type;
force_fit_type (t); force_fit_type (t);
} }
@ -1437,7 +1501,7 @@ fold_convert (t, arg1)
#endif #endif
if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u))) if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u)))
{ {
warning ("real constant out of range for integer conversion"); pedwarn ("real constant out of range for integer conversion");
return t; return t;
} }
#ifndef REAL_ARITHMETIC #ifndef REAL_ARITHMETIC
@ -1481,7 +1545,7 @@ fold_convert (t, arg1)
{ {
if (setjmp (float_error)) if (setjmp (float_error))
{ {
warning ("floating overflow in constant folding"); pedwarn ("floating overflow in constant expression");
return t; return t;
} }
set_float_handler (float_error); set_float_handler (float_error);
@ -3142,11 +3206,13 @@ fold (expr)
{ {
if (TREE_CODE (arg0) == INTEGER_CST) if (TREE_CODE (arg0) == INTEGER_CST)
{ {
if (TREE_INT_CST_LOW (arg0) == 0) HOST_WIDE_INT low, high;
t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0)); int overflow = neg_double (TREE_INT_CST_LOW (arg0),
else TREE_INT_CST_HIGH (arg0),
t = build_int_2 (- TREE_INT_CST_LOW (arg0), &low, &high);
~ TREE_INT_CST_HIGH (arg0)); t = build_int_2 (low, high);
TREE_CONSTANT_OVERFLOW (t)
= overflow | TREE_CONSTANT_OVERFLOW (arg0);
TREE_TYPE (t) = type; TREE_TYPE (t) = type;
force_fit_type (t); force_fit_type (t);
} }
@ -3199,6 +3265,7 @@ fold (expr)
~ TREE_INT_CST_HIGH (arg0)); ~ TREE_INT_CST_HIGH (arg0));
TREE_TYPE (t) = type; TREE_TYPE (t) = type;
force_fit_type (t); force_fit_type (t);
TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (arg0);
} }
else if (TREE_CODE (arg0) == BIT_NOT_EXPR) else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
return TREE_OPERAND (arg0, 0); return TREE_OPERAND (arg0, 0);