aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2004-04-01 17:50:11 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2004-04-01 17:50:11 +0200
commit0b612185938e178cce2cb547424e27e7d8deeac7 (patch)
tree1615e48fce0014662e719f1204572e9e274a295f /gcc
parenta150de295117d1e8f76a01180541eff7d0eb380c (diff)
downloadgcc-0b612185938e178cce2cb547424e27e7d8deeac7.zip
gcc-0b612185938e178cce2cb547424e27e7d8deeac7.tar.gz
gcc-0b612185938e178cce2cb547424e27e7d8deeac7.tar.bz2
re PR c++/14755 (miscompilation in bitfielded signed integers)
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. From-SVN: r80294
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/fold-const.c30
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20040331-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/20040331-1.c14
5 files changed, 46 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a1fffe7..d49190d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2004-04-01 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.
+
2004-04-01 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* expr.c (get_inner_reference): Use DECL_UNSIGNED, not TREE_UNSIGNED.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 51e986a..772e64e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7338,12 +7338,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
@@ -7355,25 +7354,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 (build2 (BIT_AND_EXPR, TREE_TYPE (varop),
- newconst, mask));
- }
+ shift = build_int_2 (TYPE_PRECISION (TREE_TYPE (varop)) - size,
+ 0);
+ newconst = fold (build2 (LSHIFT_EXPR, TREE_TYPE (varop),
+ newconst, shift));
+ newconst = fold (build2 (RSHIFT_EXPR, TREE_TYPE (varop),
+ newconst, shift));
}
return fold (build2 (code, type, varop, newconst));
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 07d0501..af93d21 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2004-04-01 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/14755
+ * gcc.c-torture/execute/20040331-1.c: New test.
+ * gcc.dg/20040331-1.c: New test.
+
2004-04-01 Paul Brook <paul@codesourcery.com>
* gcc.dg/arm-mmx-1.c: Add -mabi=iwmmxt to dg-options.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20040331-1.c b/gcc/testsuite/gcc.c-torture/execute/20040331-1.c
new file mode 100644
index 0000000..67b3e3a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20040331-1.c
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.dg/20040331-1.c b/gcc/testsuite/gcc.dg/20040331-1.c
new file mode 100644
index 0000000..4cef3d3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/20040331-1.c
@@ -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);
+}