Article View: gnu.gcc.bug
Article #79GCC 2.3.1 overlooks int overflow in constant expressions (correction)
From: Paul Eggert
Date: Wed, 04 Nov 1992 21:02
Date: Wed, 04 Nov 1992 21:02
221 lines
7720 bytes
7720 bytes
My message ``GCC 2.3.1 overlooks int overflow in constant expressions''
(Message-ID: <9211030133.AA05430@farside.twinsun.com>, 3 Nov 1992) contains a
patch which unfortunately causes GCC to ignore the arithmetic overflow in the
program:
long long x = 9223372036854775807LL + 1;
Here is a fix, expressed as both (1) a patch to my earlier patch, and (2) a
corrected version of my earlier patch, which you can use if you haven't
applied the earlier patch.
1. a patch to the earlier patch:
Wed Nov 4 20:12:02 1992 Paul Eggert (eggert@twinsun.com)
* fold-const.c (force_fit_type): Don't ignore long long overflow.
===================================================================
RCS file: fold-const.c,v
retrieving revision 2.3.1.3
retrieving revision 2.3.1.4
diff -c -r2.3.1.3 -r2.3.1.4
*** fold-const.c 1992/11/03 02:49:59 2.3.1.3
--- fold-const.c 1992/11/04 20:29:55 2.3.1.4
***************
*** 131,142 ****
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
prec = POINTER_SIZE;
- /* Do nothing if all the bits are in use. */
- if (prec == 2 * HOST_BITS_PER_WIDE_INT)
- return 0;
-
/* First clear all bits that are beyond the type's precision. */
! if (prec > HOST_BITS_PER_WIDE_INT)
{
TREE_INT_CST_HIGH (t)
&= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
--- 131,141 ----
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
prec = POINTER_SIZE;
/* First clear all bits that are beyond the type's precision. */
!
! if (prec == 2 * HOST_BITS_PER_WIDE_INT)
! ;
! else if (prec > HOST_BITS_PER_WIDE_INT)
{
TREE_INT_CST_HIGH (t)
&= ~((HOST_WIDE_INT) (-1) << (prec - HOST_BITS_PER_WIDE_INT));
***************
*** 153,162 ****
return 0;
/* If the value's sign bit is set, extend the sign. */
! if (prec > HOST_BITS_PER_WIDE_INT
! ? (TREE_INT_CST_HIGH (t)
! & ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
! : TREE_INT_CST_LOW (t) & ((HOST_WIDE_INT) 1 << (prec - 1)))
{
/* Value is negative:
set to 1 all the bits that are outside this type's precision. */
--- 152,162 ----
return 0;
/* If the value's sign bit is set, extend the sign. */
! if (prec != 2 * HOST_BITS_PER_WIDE_INT
! && (prec > HOST_BITS_PER_WIDE_INT
! ? (TREE_INT_CST_HIGH (t)
! & ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
! : TREE_INT_CST_LOW (t) & ((HOST_WIDE_INT) 1 << (prec - 1))))
{
/* Value is negative:
set to 1 all the bits that are outside this type's precision. */
2. A corrected version of my earlier patch:
Wed Nov 4 20:12:02 1992 Paul Eggert (eggert@twinsun.com)
* fold-const.c (force_fit_type): Yield nonzero if target int overflows.
(const_binop, fold): Report an overflow if the target int overflows,
even if the HOST_WIDE_INT pair that represents it does not.
===================================================================
RCS file: fold-const.c,v
retrieving revision 2.3.1.1
retrieving revision 2.3.1.2.1.1
diff -c -r2.3.1.1 -r2.3.1.2.1.1
*** fold-const.c 1992/11/02 23:51:14 2.3.1.1
--- fold-const.c 1992/11/04 20:59:37 2.3.1.2.1.1
***************
*** 116,127 ****
/* 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));
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
--- 116,129 ----
/* 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.
! Yield nonzero if an arithmetic overflow occurs. */
! static int
force_fit_type (t)
tree t;
{
+ HOST_WIDE_INT low = TREE_INT_CST_LOW (t), high = TREE_INT_CST_HIGH (t);
register int prec = TYPE_PRECISION (TREE_TYPE (t));
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
***************
*** 143,152 ****
TREE_INT_CST_LOW (t) &= ~((HOST_WIDE_INT) (-1) << prec);
}
! /* If it's a signed type and value's sign bit is set, extend the sign. */
! if (! TREE_UNSIGNED (TREE_TYPE (t))
! && prec != 2 * HOST_BITS_PER_WIDE_INT
&& (prec > HOST_BITS_PER_WIDE_INT
? (TREE_INT_CST_HIGH (t)
& ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
--- 145,156 ----
TREE_INT_CST_LOW (t) &= ~((HOST_WIDE_INT) (-1) << prec);
}
! /* Unsigned types do not suffer sign extension or overflow. */
! if (TREE_UNSIGNED (TREE_TYPE (t)))
! return 0;
! /* If the value's sign bit is set, extend the sign. */
! if (prec != 2 * HOST_BITS_PER_WIDE_INT
&& (prec > HOST_BITS_PER_WIDE_INT
? (TREE_INT_CST_HIGH (t)
& ((HOST_WIDE_INT) 1 << (prec - HOST_BITS_PER_WIDE_INT - 1)))
***************
*** 166,171 ****
--- 170,178 ----
TREE_INT_CST_LOW (t) |= ((HOST_WIDE_INT) (-1) << prec);
}
}
+
+ /* Yield nonzero if overflow occurred. */
+ return ((low ^ TREE_INT_CST_LOW (t)) | (high ^ TREE_INT_CST_HIGH (t))) != 0;
}
/* Add two doubleword integers with doubleword result.
***************
*** 1269,1276 ****
}
got_it:
TREE_TYPE (t) = TREE_TYPE (arg1);
! force_fit_type (t);
! TREE_CONSTANT_OVERFLOW (t) = overflow;
return t;
}
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
--- 1276,1282 ----
}
got_it:
TREE_TYPE (t) = TREE_TYPE (arg1);
! TREE_CONSTANT_OVERFLOW (t) = overflow | force_fit_type (t);
return t;
}
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
***************
*** 3224,3233 ****
TREE_INT_CST_HIGH (arg0),
&low, &high);
t = build_int_2 (low, high);
- TREE_CONSTANT_OVERFLOW (t)
- = overflow | TREE_CONSTANT_OVERFLOW (arg0);
TREE_TYPE (t) = type;
! force_fit_type (t);
}
else if (TREE_CODE (arg0) == REAL_CST)
t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
--- 3230,3240 ----
TREE_INT_CST_HIGH (arg0),
&low, &high);
t = build_int_2 (low, high);
TREE_TYPE (t) = type;
! TREE_CONSTANT_OVERFLOW (t)
! = (overflow
! | TREE_CONSTANT_OVERFLOW (arg0)
! | force_fit_type (t));
}
else if (TREE_CODE (arg0) == REAL_CST)
t = build_real (type, REAL_VALUE_NEGATE (TREE_REAL_CST (arg0)));
***************
*** 3257,3263 ****
&low, &high);
t = build_int_2 (low, high);
TREE_TYPE (t) = type;
! force_fit_type (t, overflow);
}
}
else if (TREE_CODE (arg0) == REAL_CST)
--- 3264,3273 ----
&low, &high);
t = build_int_2 (low, high);
TREE_TYPE (t) = type;
! TREE_CONSTANT_OVERFLOW (t)
! = (overflow
! | TREE_CONSTANT_OVERFLOW (arg0)
! | force_fit_type (t));
}
}
else if (TREE_CODE (arg0) == REAL_CST)
Technical Details
Message-ID:
<9211042102.AA13417@farside.twinsun.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!charon.amdahl.com!pacbell.com!decwrl!sdd.hp.com!cs.utexas.edu!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!twinsun.COM!eggertShow Full Headers
Complete Article Headers
Newsgroups: gnu.gcc.bug Path: arc1-ca.pugleaf.net!sparky!uunet!charon.amdahl.com!pacbell.com!decwrl!sdd.hp.com!cs.utexas.edu!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!twinsun.COM!eggert From: eggert@twinsun.COM (Paul Eggert) Subject: GCC 2.3.1 overlooks int overflow in constant expressions (correction) Message-ID: <9211042102.AA13417@farside.twinsun.com> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet Distribution: gnu Date: Wed, 4 Nov 1992 21:02:50 GMT Approved: bug-gcc@prep.ai.mit.edu Lines: 222