[PATCH] Fix PR c++/14755

Jakub Jelinek jakub@redhat.com
Wed Mar 31 18:39:00 GMT 2004


Hi!

This bug marked as critical has been introduced by the 
2004-03-08  Roger Sayle  <roger@eyesopen.com>

        * fold-const.c (fold) <EQ_EXPR>: Rewrite optimization to transform
        "foo++ == const" into "++foo == const+incr".
The masking is only correct for TREE_UNSIGNED (TREE_TYPE (varop)), otherwise
it needs sign extension to the bit fields precision.
Fixed thusly, ok to commit if bootstrap/regression testing succeeds?
Ok for 3.4/3.3 as well?

2004-03-31  Jakub Jelinek  <jakub@redhat.com>

	PR c++/14755
	* fold-const.c (fold) <EQ_EXPR>: Properly compute newconst in
	"bitfld++ == const" to "++bitfld == const + incr" transformations.

	* gcc.c-torture/execute/20040331-1.c: New test.
	* gcc.dg/20040331-1.c: New test.

--- gcc/fold-const.c.jj	2004-03-27 09:48:10.000000000 +0100
+++ gcc/fold-const.c	2004-03-31 20:29:51.209894745 +0200
@@ -7254,12 +7254,11 @@ fold (tree expr)
 	  /* If VAROP is a reference to a bitfield, we must mask
 	     the constant by the width of the field.  */
 	  if (TREE_CODE (TREE_OPERAND (varop, 0)) == COMPONENT_REF
-	      && DECL_BIT_FIELD(TREE_OPERAND (TREE_OPERAND (varop, 0), 1)))
+	      && DECL_BIT_FIELD (TREE_OPERAND (TREE_OPERAND (varop, 0), 1)))
 	    {
 	      tree fielddecl = TREE_OPERAND (TREE_OPERAND (varop, 0), 1);
 	      int size = TREE_INT_CST_LOW (DECL_SIZE (fielddecl));
-	      tree folded_compare;
-	      tree mask = 0;
+	      tree folded_compare, shift;
 
 	      /* First check whether the comparison would come out
 		 always the same.  If we don't do that we would
@@ -7271,25 +7270,12 @@ fold (tree expr)
 		  || integer_onep (folded_compare))
 		return omit_one_operand (type, folded_compare, varop);
 
-	      if (size < HOST_BITS_PER_WIDE_INT)
-		{
-		  unsigned HOST_WIDE_INT lo = ((unsigned HOST_WIDE_INT) 1
-					       << size) - 1;
-		  mask = build_int_2 (lo, 0);
-		}
-	      else if (size < 2 * HOST_BITS_PER_WIDE_INT)
-		{
-		  HOST_WIDE_INT hi = ((HOST_WIDE_INT) 1
-				      << (size - HOST_BITS_PER_WIDE_INT)) - 1;
-		  mask = build_int_2 (~0, hi);
-		}
-		   
-	      if (mask)
-		{
-		  mask = fold_convert (TREE_TYPE (varop), mask);
-		  newconst = fold (build (BIT_AND_EXPR, TREE_TYPE (varop),
-					  newconst, mask));
-		}
+	      shift = build_int_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size,
+				   0);
+	      newconst = fold (build (LSHIFT_EXPR, TREE_TYPE (varop),
+				      newconst, shift));
+	      newconst = fold (build (RSHIFT_EXPR, TREE_TYPE (varop),
+				      newconst, shift));
 	    }
 
 	  return fold (build (code, type, varop, newconst));
--- gcc/testsuite/gcc.c-torture/execute/20040331-1.c.jj	2004-01-21 17:12:41.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20040331-1.c	2004-03-31 19:00:39.244036708 +0200
@@ -0,0 +1,12 @@
+/* PR c++/14755 */
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+  struct { int count: 31; } s = { 0 };
+  while (s.count--)
+    abort ();
+  exit (0);
+}
--- gcc/testsuite/gcc.dg/20040331-1.c.jj	2004-01-21 17:12:41.000000000 +0100
+++ gcc/testsuite/gcc.dg/20040331-1.c	2004-03-31 19:31:59.405087369 +0200
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fwrapv" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int
+main (void)
+{
+  struct { int count: 2; } s = { -2 };
+  while (s.count-- != -2)
+    abort ();
+  exit (0);
+}

	Jakub



More information about the Gcc-patches mailing list