From: eggert@twinsun.COM (Paul Eggert)
Subject: GCC 2.2.2 patches for overflow detection in constant expressions
Organization: GNUs Not Usenet
Distribution: gnu
Date: Thu, 3 Sep 1992 04:12:21 GMT

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)
  

Newsgroups: gnu.gcc.bug