Patch for bug 7284

Joseph S. Myers jsm@polyomino.org.uk
Thu Jul 22 20:38:00 GMT 2004


This patch fixes bug 7284, signed left-shift overflow being wrongly
treated as undefined in C90 (it being implementation-defined in C90
and maybe in C++ and only undefined in C99).  I didn't feel it
worthwhile to add a flag front ends can set to control when signed
left shift is defined (so the optimization can stay in C99 mode),
instead just disabling the transformation of signed left shift to
multiplication, but will add such a flag if requested.

(The other known C90 conformance issues are relevant to C99 as well,
although the details may differ in the two standards.)

Bootstrapped with no regressions on i686-pc-linux-gnu.  OK to commit?

-- 
Joseph S. Myers               http://www.srcf.ucam.org/~jsm28/gcc/
    jsm@polyomino.org.uk (personal mail)
    jsm28@gcc.gnu.org (Bugzilla assignments and CCs)

2004-07-22  Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/7284
	* fold-const.c (extract_muldiv_1): Do not treat signed left shift
	as multiplication.

testsuite:
2004-07-22  Joseph S. Myers  <jsm@polyomino.org.uk>

	PR c/7284
	* gcc.c-torture/execute/pr7284-1.c: New test.

diff -rupN GCC.orig/gcc/fold-const.c GCC/gcc/fold-const.c
--- GCC.orig/gcc/fold-const.c	2004-07-21 23:37:28.000000000 +0000
+++ GCC/gcc/fold-const.c	2004-07-22 08:44:21.000000000 +0000
@@ -5139,8 +5139,12 @@ extract_muldiv_1 (tree t, tree c, enum t
     case LSHIFT_EXPR:  case RSHIFT_EXPR:
       /* If the second operand is constant, this is a multiplication
 	 or floor division, by a power of two, so we can treat it that
-	 way unless the multiplier or divisor overflows.  */
+	 way unless the multiplier or divisor overflows.  Signed
+	 left-shift overflow is implementation-defined rather than
+	 undefined in C90, so do not convert signed left shift into
+	 multiplication.  */
       if (TREE_CODE (op1) == INTEGER_CST
+	  && (tcode == RSHIFT_EXPR || TYPE_UNSIGNED (TREE_TYPE (op0)))
 	  /* const_binop may not detect overflow correctly,
 	     so check for it explicitly here.  */
 	  && TYPE_PRECISION (TREE_TYPE (size_one_node)) > TREE_INT_CST_LOW (op1)
diff -rupN GCC.orig/gcc/testsuite/gcc.c-torture/execute/pr7284-1.c GCC/gcc/testsuite/gcc.c-torture/execute/pr7284-1.c
--- GCC.orig/gcc/testsuite/gcc.c-torture/execute/pr7284-1.c	1970-01-01 00:00:00.000000000 +0000
+++ GCC/gcc/testsuite/gcc.c-torture/execute/pr7284-1.c	2004-07-22 08:33:23.000000000 +0000
@@ -0,0 +1,24 @@
+/* Signed left-shift is implementation-defined in C89 (and see
+   DR#081), not undefined.  Bug 7284 from Al Grant (AlGrant at
+   myrealbox.com).  */
+
+/* { dg-options "-std=c89" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+f (int n)
+{
+  return (n << 24) / (1 << 23);
+}
+
+volatile int x = 128;
+
+int
+main (void)
+{
+  if (f(x) != -256)
+    abort ();
+  exit (0);
+}



More information about the Gcc-patches mailing list