diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a1fffe747d4442920597aefcfcd45a7f2aadcd9a..d49190d45372d675be935ae6c3a794efc8db64ee 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 51e986abf38a4fcb37a884e72df4d937e49b9442..772e64e5d2ae6a1d9f2310df4070dc4edbc6925a 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 07d0501371015fe3878495b9dd5a4f5ab402376d..af93d21eb559d90e8d7bf9a91f51a06936235d61 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 0000000000000000000000000000000000000000..67b3e3a2e0cea58baf2086bf6f9c85c5b68c524e --- /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 0000000000000000000000000000000000000000..4cef3d3297aaf105bed6e01f378a65805533d2e1 --- /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); +}