Article View: gnu.gcc.bug
Article #1053GCC 2.2.2 patches for overflow detection in constant expressions
From: Paul Eggert
Date: Thu, 03 Sep 1992 04:12
Date: Thu, 03 Sep 1992 04:12
900 lines
25974 bytes
25974 bytes
GCC 2.2.2 doesn't check for overflow in constant expressions, even though it
really should -- not only because ANSI says so, but because it catches several
all-too-common coding errors. Here is a patch.
Thu Sep 3 02:33:55 1992 Paul Eggert (eggert@twinsun.com)
* c-typeck.c (constant_expression_warning): Now works;
it reports signed integer overflow in constant expressions,
and uncasted negative constants that appear in unsigned contexts.
(build_c_cast, convert_for_assignment, parser_build_binary_op,
store_init_value) Check for overflow.
* c-parse.y (unary_expr): Likewise.
* c-tree.h (constant_expression_warning): Now exported.
* fold-const.c (left_shift_overflows, possible_sum_sign) New macros.
(force_fit_type): Mark overflowed or truncated INTEGER_CSTs.
(add_double, div_and_round_double, lshift_double, mul_double,
neg_double, const_binop, fold): Check for signed integer overflow.
(const_binop, fold_convert): Use pedwarn for overflow warnings.
Say `constant expression', not `constant folding', for user's sake.
===================================================================
RCS file: c-parse.y,v
retrieving revision 2.2.2.3
diff -c2 -r2.2.2.3 c-parse.y
*** c-parse.y 1992/08/13 23:59:47 2.2.2.3
--- c-parse.y 1992/09/02 19:17:38
***************
*** 331,335 ****
pedantic = $<itype>1; }
| unop cast_expr %prec UNARY
! { $$ = build_unary_op ($1, $2, 0); }
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
--- 331,336 ----
pedantic = $<itype>1; }
| unop cast_expr %prec UNARY
! { $$ = build_unary_op ($1, $2, 0);
! constant_expression_warning ($$, 0); }
/* Refer to the address of a label as a pointer. */
| ANDAND identifier
===================================================================
RCS file: c-tree.h,v
retrieving revision 2.2
diff -c2 -r2.2 c-tree.h
*** c-tree.h 1992/03/14 20:55:54 2.2
--- c-tree.h 1992/09/02 19:15:57
***************
*** 108,111 ****
--- 108,112 ----
extern tree c_expand_start_case ();
extern tree default_conversion ();
+ extern void constant_expression_warning ();
/* Given two integer or real types, return the type for their sum.
===================================================================
RCS file: c-typeck.c,v
retrieving revision 2.2.2.7
diff -c2 -r2.2.2.7 c-typeck.c
*** c-typeck.c 1992/08/29 23:55:12 2.2.2.7
--- c-typeck.c 1992/09/03 02:27:45
***************
*** 785,796 ****
/* Print a warning if a constant expression had overflow in folding.
! This doesn't really work--it is waiting for changes in fold. */
void
! constant_expression_warning (value)
tree value;
{
! if (TREE_CODE (value) == NON_LVALUE_EXPR && TREE_CONSTANT_OVERFLOW (value))
! pedwarn ("overflow in constant expression");
}
--- 785,804 ----
/* Print a warning if a constant expression had overflow in folding.
! If EVEN_IF_UNSIGNED is nonzero, warn even if the expression is unsigned. */
void
! constant_expression_warning (value, even_if_unsigned)
tree value;
+ int even_if_unsigned;
{
! if (TREE_CODE (value) == INTEGER_CST
! && TREE_CONSTANT_OVERFLOW (value)
! && (! TREE_UNSIGNED (TREE_TYPE (value)) || even_if_unsigned))
! {
! TREE_CONSTANT_OVERFLOW (value) = 0;
! pedwarn (TREE_UNSIGNED (TREE_TYPE (value))
! ? "constant expression out of range for unsigned type"
! : "signed integer overflow in constant expression");
! }
}
***************
*** 2135,2138 ****
--- 2143,2148 ----
warning ("comparisons like X<=Y<=Z do not have the usual meaning");
+ constant_expression_warning (result, 0);
+
class = TREE_CODE_CLASS (TREE_CODE (result));
***************
*** 3728,3731 ****
--- 3738,3742 ----
value = convert (type, value);
+ constant_expression_warning (value, 0);
}
***************
*** 3946,3950 ****
(coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE))
{
! return convert (type, rhs);
}
/* Conversions among pointers */
--- 3957,3963 ----
(coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE))
{
! tree t = convert (type, rhs);
! constant_expression_warning (t, 1);
! return t;
}
/* Conversions among pointers */
***************
*** 4233,4237 ****
/* ANSI wants warnings about out-of-range constant initializers. */
! constant_expression_warning (value);
DECL_INITIAL (decl) = value;
--- 4246,4250 ----
/* ANSI wants warnings about out-of-range constant initializers. */
! constant_expression_warning (value, 1);
DECL_INITIAL (decl) = value;
===================================================================
RCS file: fold-const.c,v
retrieving revision 2.2.2.4
diff -c2 -r2.2.2.4 fold-const.c
*** fold-const.c 1992/08/29 08:21:30 2.2.2.4
--- fold-const.c 1992/09/03 02:33:55
***************
*** 49,53 ****
static jmp_buf float_error;
! void lshift_double ();
void rshift_double ();
void lrotate_double ();
--- 49,53 ----
static jmp_buf float_error;
! int lshift_double ();
void rshift_double ();
void lrotate_double ();
***************
*** 54,57 ****
--- 54,65 ----
void rrotate_double ();
static tree const_binop ();
+
+ /* Yield nonzero if a signed left shift of A by B bits overflows.
+ A is a C int; B is nonnegative. */
+ #define left_shift_overflows(a, b) ((a) ^ ((a) << (b)) >> (b))
+
+ /* Yield nonzero if adding two numbers with A's and B's signs can yield a
+ number with SUM's sign, where A, B, and SUM are all C ints. */
+ #define possible_sum_sign(a, b, sum) ((((a) ^ (b)) | ~ ((a) ^ (sum))) < 0)
/* To do constant folding on INTEGER_CST nodes requires 64-bit arithmetic.
***************
*** 97,106 ****
/* Make the integer constant T valid for its type
by setting to 0 or 1 all the bits in the constant
! that don't belong in the type. */
static void
! force_fit_type (t)
tree t;
{
register int prec = TYPE_PRECISION (TREE_TYPE (t));
--- 105,119 ----
/* Make the integer constant T valid for its type
by setting to 0 or 1 all the bits in the constant
! that don't belong in the type.
! Mark the constant if it has overflowed.
! If OVERFLOW is nonzero and the result is signed,
! the calculation has already overflowed. */
static void
! force_fit_type (t, overflow)
tree t;
+ int overflow;
{
+ int low = TREE_INT_CST_LOW (t), high = TREE_INT_CST_HIGH (t);
register int prec = TYPE_PRECISION (TREE_TYPE (t));
***************
*** 148,154 ****
--- 161,174 ----
}
}
+
+ /* In C, by definition, unsigned arithmetic does not overflow.
+ But sometimes we want to warn about unsigned truncation. */
+ if ((low ^ TREE_INT_CST_LOW (t)) | (high ^ TREE_INT_CST_HIGH (t))
+ || overflow && ! TREE_UNSIGNED (TREE_TYPE (t)))
+ TREE_CONSTANT_OVERFLOW (t) = 1;
}
/* Add two 64-bit integers with 64-bit result.
+ Yield nonzero if the (signed) operation overflows.
Each argument is given as two `int' pieces.
One argument is L1 and H1; the other, L2 and H2.
***************
*** 156,160 ****
We use the 8-shorts representation internally. */
! void
add_double (l1, h1, l2, h2, lv, hv)
int l1, h1, l2, h2;
--- 176,180 ----
We use the 8-shorts representation internally. */
! int
add_double (l1, h1, l2, h2, lv, hv)
int l1, h1, l2, h2;
***************
*** 177,183 ****
--- 197,205 ----
decode (arg1, lv, hv);
+ return !possible_sum_sign (h1, h2, *hv);
}
/* Negate a 64-bit integers with 64-bit result.
+ Yield nonzero if the (signed) operation overflows.
The argument is given as two `int' pieces in L1 and H1.
The value is stored as two `int' pieces in *LV and *HV.
***************
*** 184,188 ****
We use the 8-shorts representation internally. */
! void
neg_double (l1, h1, lv, hv)
int l1, h1;
--- 206,210 ----
We use the 8-shorts representation internally. */
! int
neg_double (l1, h1, lv, hv)
int l1, h1;
***************
*** 199,205 ****
--- 221,229 ----
*hv = ~ h1;
}
+ return (h1 & *hv) < 0;
}
/* Multiply two 64-bit integers with 64-bit result.
+ Yield nonzero if the (signed) operation overflows.
Each argument is given as two `int' pieces.
One argument is L1 and H1; the other, L2 and H2.
***************
*** 207,211 ****
We use the 8-shorts representation internally. */
! void
mul_double (l1, h1, l2, h2, lv, hv)
int l1, h1, l2, h2;
--- 231,235 ----
We use the 8-shorts representation internally. */
! int
mul_double (l1, h1, l2, h2, lv, hv)
int l1, h1, l2, h2;
***************
*** 217,223 ****
register int carry = 0;
register int i, j, k;
! /* These two cases are used extensively, arising from pointer
! combinations. */
if (h2 == 0)
{
--- 241,247 ----
register int carry = 0;
register int i, j, k;
+ int toplow, tophigh, neglow, neghigh;
! /* These cases are used extensively, arising from pointer combinations. */
if (h2 == 0)
{
***************
*** 224,236 ****
if (l2 == 2)
{
unsigned temp = l1 + l1;
! *hv = h1 * 2 + (temp < l1);
*lv = temp;
! return;
}
if (l2 == 4)
{
unsigned temp = l1 + l1;
! h1 = h1 * 4 + ((temp < l1) << 1);
l1 = temp;
temp += temp;
--- 248,262 ----
if (l2 == 2)
{
+ int overflow = left_shift_overflows (h1, 1);
unsigned temp = l1 + l1;
! *hv = (h1 << 1) + (temp < l1);
*lv = temp;
! return overflow;
}
if (l2 == 4)
{
+ int overflow = left_shift_overflows (h1, 2);
unsigned temp = l1 + l1;
! h1 = (h1 << 2) + ((temp < l1) << 1);
l1 = temp;
temp += temp;
***************
*** 238,247 ****
*lv = temp;
*hv = h1;
! return;
}
if (l2 == 8)
{
unsigned temp = l1 + l1;
! h1 = h1 * 8 + ((temp < l1) << 2);
l1 = temp;
temp += temp;
--- 264,274 ----
*lv = temp;
*hv = h1;
! return overflow;
}
if (l2 == 8)
{
+ int overflow = left_shift_overflows (h1, 3);
unsigned temp = l1 + l1;
! h1 = (h1 << 3) + ((temp < l1) << 2);
l1 = temp;
temp += temp;
***************
*** 252,256 ****
*lv = temp;
*hv = h1;
! return;
}
}
--- 279,283 ----
*lv = temp;
*hv = h1;
! return overflow;
}
}
***************
*** 276,279 ****
--- 303,321 ----
decode (prod, lv, hv); /* @@decode ignores prod[8] -> prod[15] */
+
+ /* 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+8, &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);
}
***************
*** 282,288 ****
Shift right if COUNT is negative.
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
Store the value as two `int' pieces in *LV and *HV. */
! void
lshift_double (l1, h1, count, prec, lv, hv, arith)
int l1, h1, count, prec;
--- 324,331 ----
Shift right if COUNT is negative.
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
+ Yield nonzero if the arithmetic shift overflows.
Store the value as two `int' pieces in *LV and *HV. */
! int
lshift_double (l1, h1, count, prec, lv, hv, arith)
int l1, h1, count, prec;
***************
*** 292,296 ****
short arg1[8];
register int i;
! register int carry;
if (count < 0)
--- 335,339 ----
short arg1[8];
register int i;
! register int carry, overflow;
if (count < 0)
***************
*** 297,301 ****
{
rshift_double (l1, h1, - count, prec, lv, hv, arith);
! return;
}
--- 340,344 ----
{
rshift_double (l1, h1, - count, prec, lv, hv, arith);
! return 0;
}
***************
*** 305,308 ****
--- 348,352 ----
count = prec;
+ overflow = 0;
while (count > 0)
{
***************
*** 315,325 ****
}
count--;
}
decode (arg1, lv, hv);
}
/* Shift the 64-bit integer in L1, H1 right by COUNT places
! keeping only PREC bits of result. COUNT must be positive.
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
Store the value as two `int' pieces in *LV and *HV. */
--- 359,371 ----
}
count--;
+ overflow |= carry ^ (arg1[7] >> 7);
}
decode (arg1, lv, hv);
+ return overflow;
}
/* Shift the 64-bit integer in L1, H1 right by COUNT places
! keeping only PREC bits of result. COUNT must be nonnegative.
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
Store the value as two `int' pieces in *LV and *HV. */
***************
*** 434,440 ****
or EXACT_DIV_EXPR
It controls how the quotient is rounded to a integer.
UNS nonzero says do unsigned division. */
! static void
div_and_round_double (code, uns,
lnum_orig, hnum_orig, lden_orig, hden_orig,
--- 480,487 ----
or EXACT_DIV_EXPR
It controls how the quotient is rounded to a integer.
+ Yield nonzero if the operation overflows.
UNS nonzero says do unsigned division. */
! static int
div_and_round_double (code, uns,
lnum_orig, hnum_orig, lden_orig, hden_orig,
***************
*** 454,457 ****
--- 501,505 ----
unsigned int lden = lden_orig;
int hden = hden_orig;
+ int overflow = 0;
if ((hden == 0) && (lden == 0))
***************
*** 461,473 ****
if (!uns)
{
! if (hden < 0)
{
quo_neg = ~ quo_neg;
! neg_double (lden, hden, &lden, &hden);
}
! if (hnum < 0)
{
quo_neg = ~ quo_neg;
! neg_double (lnum, hnum, &lnum, &hnum);
}
}
--- 509,523 ----
if (!uns)
{
! if (hnum < 0)
{
quo_neg = ~ quo_neg;
! /* (minimum integer) / (-1) is the only overflow case. */
! if (neg_double (lnum, hnum, &lnum, &hnum))
! overflow = ~(hden & lden);
}
! if (hden < 0)
{
quo_neg = ~ quo_neg;
! neg_double (lden, hden, &lden, &hden);
}
}
***************
*** 642,646 ****
case TRUNC_MOD_EXPR: /* round toward zero */
case EXACT_DIV_EXPR: /* for this one, it shouldn't matter */
! return;
case FLOOR_DIV_EXPR:
--- 692,696 ----
case TRUNC_MOD_EXPR: /* round toward zero */
case EXACT_DIV_EXPR: /* for this one, it shouldn't matter */
! return overflow;
case FLOOR_DIV_EXPR:
***************
*** 651,655 ****
add_double (*lquo, *hquo, -1, -1, lquo, hquo);
}
! else return;
break;
--- 701,705 ----
add_double (*lquo, *hquo, -1, -1, lquo, hquo);
}
! else return overflow;
break;
***************
*** 660,664 ****
add_double (*lquo, *hquo, 1, 0, lquo, hquo);
}
! else return;
break;
--- 710,714 ----
add_double (*lquo, *hquo, 1, 0, lquo, hquo);
}
! else return overflow;
break;
***************
*** 686,690 ****
add_double (*lquo, *hquo, 1, 0, lquo, hquo);
}
! else return;
}
break;
--- 736,740 ----
add_double (*lquo, *hquo, 1, 0, lquo, hquo);
}
! else return overflow;
}
break;
***************
*** 698,701 ****
--- 748,752 ----
neg_double (*lrem, *hrem, lrem, hrem);
add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
+ return overflow;
}
***************
*** 957,960 ****
--- 1008,1012 ----
register tree t;
int uns = TREE_UNSIGNED (TREE_TYPE (arg1));
+ int overflow = 0;
switch (code)
***************
*** 979,986 ****
int2l = - int2l;
case LSHIFT_EXPR:
! lshift_double (int1l, int1h, int2l,
! TYPE_PRECISION (TREE_TYPE (arg1)),
! &low, &hi,
! !uns);
t = build_int_2 (low, hi);
break;
--- 1031,1038 ----
int2l = - int2l;
case LSHIFT_EXPR:
! overflow = lshift_double (int1l, int1h, int2l,
! TYPE_PRECISION (TREE_TYPE (arg1)),
! &low, &hi,
! !uns);
t = build_int_2 (low, hi);
break;
***************
*** 1000,1004 ****
int2l += int1l;
if ((unsigned) int2l < int1l)
! int2h += 1;
t = build_int_2 (int2l, int2h);
break;
--- 1052,1056 ----
int2l += int1l;
if ((unsigned) int2l < int1l)
! overflow = int2h++ >= 0 && int2h < 0;
t = build_int_2 (int2l, int2h);
break;
***************
*** 1008,1016 ****
int1l += int2l;
if ((unsigned) int1l < int2l)
! int1h += 1;
t = build_int_2 (int1l, int1h);
break;
}
! add_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi);
break;
--- 1060,1068 ----
int1l += int2l;
if ((unsigned) int1l < int2l)
! overflow = int1h++ >= 0 && int1h < 0;
t = build_int_2 (int1l, int1h);
break;
}
! overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi);
break;
***************
*** 1022,1027 ****
break;
}
! neg_double (int2l, int2h, &int2l, &int2h);
! add_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi);
break;
--- 1074,1080 ----
break;
}
! neg_double (int2l, int2h, &low, &hi);
! add_double (int1l, int1h, low, hi, &low, &hi);
! overflow = !possible_sum_sign (hi, int2h, int1h);
t = build_int_2 (low, hi);
break;
***************
*** 1042,1052 ****
goto got_it;
case 2:
temp = int2l + int2l;
! int2h = int2h * 2 + (temp < int2l);
t = build_int_2 (temp, int2h);
goto got_it;
case 4:
temp = int2l + int2l;
! int2h = int2h * 4 + ((temp < int2l) << 1);
int2l = temp;
temp += temp;
--- 1095,1107 ----
goto got_it;
case 2:
+ overflow = left_shift_overflows (int2h, 1);
temp = int2l + int2l;
! int2h = (int2h << 1) + (temp < int2l);
t = build_int_2 (temp, int2h);
goto got_it;
case 4:
+ overflow = left_shift_overflows (int2h, 2);
temp = int2l + int2l;
! int2h = (int2h << 2) + ((temp < int2l) << 1);
int2l = temp;
temp += temp;
***************
*** 1055,1060 ****
goto got_it;
case 8:
temp = int2l + int2l;
! int2h = int2h * 8 + ((temp < int2l) << 2);
int2l = temp;
temp += temp;
--- 1110,1116 ----
goto got_it;
case 8:
+ overflow = left_shift_overflows (int2h, 3);
temp = int2l + int2l;
! int2h = (int2h << 3) + ((temp < int2l) << 2);
int2l = temp;
temp += temp;
***************
*** 1084,1088 ****
}
! mul_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi);
break;
--- 1140,1144 ----
}
! overflow = mul_double (int1l, int1h, int2l, int2h, &low, &hi);
t = build_int_2 (low, hi);
break;
***************
*** 1115,1120 ****
break;
}
! div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
! &low, &hi, &garbagel, &garbageh);
t = build_int_2 (low, hi);
break;
--- 1171,1177 ----
break;
}
! overflow = div_and_round_double (code, uns,
! int1l, int1h, int2l, int2h,
! &low, &hi, &garbagel, &garbageh);
t = build_int_2 (low, hi);
break;
***************
*** 1122,1127 ****
case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR:
case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
! div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
! &garbagel, &garbageh, &low, &hi);
t = build_int_2 (low, hi);
break;
--- 1179,1185 ----
case TRUNC_MOD_EXPR: case ROUND_MOD_EXPR:
case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
! overflow = div_and_round_double (code, uns,
! int1l, int1h, int2l, int2h,
! &garbagel, &garbageh, &low, &hi);
t = build_int_2 (low, hi);
break;
***************
*** 1152,1156 ****
got_it:
TREE_TYPE (t) = TREE_TYPE (arg1);
! force_fit_type (t);
return t;
}
--- 1210,1214 ----
got_it:
TREE_TYPE (t) = TREE_TYPE (arg1);
! force_fit_type (t, overflow);
return t;
}
***************
*** 1167,1171 ****
if (setjmp (float_error))
{
! warning ("floating overflow in constant folding");
return build (code, TREE_TYPE (arg1), arg1, arg2);
}
--- 1225,1229 ----
if (setjmp (float_error))
{
! pedwarn ("floating overflow in constant expression");
return build (code, TREE_TYPE (arg1), arg1, arg2);
}
***************
*** 1359,1363 ****
TREE_INT_CST_HIGH (arg1));
TREE_TYPE (t) = type;
! force_fit_type (t);
}
#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
--- 1417,1421 ----
TREE_INT_CST_HIGH (arg1));
TREE_TYPE (t) = type;
! force_fit_type (t, 0);
}
#if !defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
***************
*** 1377,1381 ****
if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u)))
{
! warning ("real constant out of range for integer conversion");
return t;
}
--- 1435,1439 ----
if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u)))
{
! pedwarn ("real constant out of range for integer conversion");
return t;
}
***************
*** 1405,1409 ****
#endif
TREE_TYPE (t) = type;
! force_fit_type (t);
}
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
--- 1463,1467 ----
#endif
TREE_TYPE (t) = type;
! force_fit_type (t, 0);
}
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
***************
*** 1420,1424 ****
if (setjmp (float_error))
{
! warning ("floating overflow in constant folding");
return t;
}
--- 1478,1482 ----
if (setjmp (float_error))
{
! pedwarn ("floating overflow in constant expression");
return t;
}
***************
*** 2805,2809 ****
t = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0);
TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (arg0));
! force_fit_type (t);
}
}
--- 2863,2867 ----
t = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0);
TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (arg0));
! force_fit_type (t, 0);
}
}
***************
*** 2820,2830 ****
if (TREE_CODE (arg0) == INTEGER_CST)
{
! if (TREE_INT_CST_LOW (arg0) == 0)
! t = build_int_2 (0, - TREE_INT_CST_HIGH (arg0));
! else
! t = build_int_2 (- TREE_INT_CST_LOW (arg0),
! ~ TREE_INT_CST_HIGH (arg0));
TREE_TYPE (t) = type;
! force_fit_type (t);
}
else if (TREE_CODE (arg0) == REAL_CST)
--- 2878,2888 ----
if (TREE_CODE (arg0) == INTEGER_CST)
{
! int low, high;
! int overflow = neg_double (TREE_INT_CST_LOW (arg0),
! TREE_INT_CST_HIGH (arg0),
! &low, &high);
! t = build_int_2 (low, high);
TREE_TYPE (t) = type;
! force_fit_type (t, overflow);
}
else if (TREE_CODE (arg0) == REAL_CST)
***************
*** 2876,2880 ****
~ TREE_INT_CST_HIGH (arg0));
TREE_TYPE (t) = type;
! force_fit_type (t);
}
else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
--- 2934,2938 ----
~ TREE_INT_CST_HIGH (arg0));
TREE_TYPE (t) = type;
! force_fit_type (t, 0);
}
else if (TREE_CODE (arg0) == BIT_NOT_EXPR)
===================================================================
RCS file: tree.h,v
retrieving revision 2.2.2.1
diff -c2 -r2.2.2.1 tree.h
*** tree.h 1992/06/21 05:34:02 2.2.2.1
--- tree.h 1992/09/03 02:15:57
***************
*** 219,224 ****
#define TREE_NO_UNUSED_WARNING(NODE) ((NODE)->common.static_flag)
! /* In a NON_LVALUE_EXPR, this means there was overflow in folding.
! The folded constant is inside the NON_LVALUE_EXPR. */
#define TREE_CONSTANT_OVERFLOW(NODE) ((NODE)->common.static_flag)
--- 219,223 ----
#define TREE_NO_UNUSED_WARNING(NODE) ((NODE)->common.static_flag)
! /* In an INTEGER_CST, this means there was overflow in folding. */
#define TREE_CONSTANT_OVERFLOW(NODE) ((NODE)->common.static_flag)
Technical Details
Message-ID:
<9209030412.AA26982@farside.twinsun.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!twinsun.COM!eggertShow Full Headers
Complete Article Headers
Newsgroups: gnu.gcc.bug Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!twinsun.COM!eggert From: eggert@twinsun.COM (Paul Eggert) Subject: GCC 2.2.2 patches for overflow detection in constant expressions Message-ID: <9209030412.AA26982@farside.twinsun.com> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet Distribution: gnu Date: Thu, 3 Sep 1992 04:12:21 GMT Approved: bug-gcc@prep.ai.mit.edu Lines: 901