diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-11 07:57:11 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-11 07:57:11 +0000 |
commit | 3e09bc82dc951f6a424b4fd1726abdf9633a045d (patch) | |
tree | de94b40cfe08cfd234233acae546f6176a0329c3 | |
parent | c17d9a29b3d389f64fcea52787ad94df8afece1d (diff) | |
download | gcc-3e09bc82dc951f6a424b4fd1726abdf9633a045d.tar.gz |
Backported from mainline
2013-11-06 Jakub Jelinek <jakub@redhat.com>
PR middle-end/58970
* expr.c (get_bit_range): Handle *offset == NULL_TREE.
(expand_assignment): If *bitpos is negative, set *offset
and adjust *bitpos, so that it is not negative.
* gcc.c-torture/compile/pr58970-1.c: New test.
* gcc.c-torture/compile/pr58970-2.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@204663 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/expr.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr58970-1.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr58970-2.c | 11 |
5 files changed, 51 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b8fd391a8b..c9e0feee51f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,6 +1,13 @@ 2013-11-11 Jakub Jelinek <jakub@redhat.com> Backported from mainline + 2013-11-06 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/58970 + * expr.c (get_bit_range): Handle *offset == NULL_TREE. + (expand_assignment): If *bitpos is negative, set *offset + and adjust *bitpos, so that it is not negative. + 2013-11-05 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/58997 diff --git a/gcc/expr.c b/gcc/expr.c index 7e909bc0f5c..785747be8d0 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4551,19 +4551,19 @@ get_bit_range (unsigned HOST_WIDE_INT *bitstart, - tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1)); /* If the adjustment is larger than bitpos, we would have a negative bit - position for the lower bound and this may wreak havoc later. This can - occur only if we have a non-null offset, so adjust offset and bitpos - to make the lower bound non-negative. */ + position for the lower bound and this may wreak havoc later. Adjust + offset and bitpos to make the lower bound non-negative in that case. */ if (bitoffset > *bitpos) { HOST_WIDE_INT adjust = bitoffset - *bitpos; - gcc_assert ((adjust % BITS_PER_UNIT) == 0); - gcc_assert (*offset != NULL_TREE); *bitpos += adjust; - *offset - = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT)); + if (*offset == NULL_TREE) + *offset = size_int (-adjust / BITS_PER_UNIT); + else + *offset + = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT)); *bitstart = 0; } else @@ -4698,6 +4698,15 @@ expand_assignment (tree to, tree from, bool nontemporal) tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1, &unsignedp, &volatilep, true); + /* Make sure bitpos is not negative, it can wreak havoc later. */ + if (bitpos < 0) + { + gcc_assert (offset == NULL_TREE); + offset = size_int (bitpos >> (BITS_PER_UNIT == 8 + ? 3 : exact_log2 (BITS_PER_UNIT))); + bitpos &= BITS_PER_UNIT - 1; + } + if (TREE_CODE (to) == COMPONENT_REF && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f50ecc48547..5cef1aff591 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,12 @@ 2013-11-11 Jakub Jelinek <jakub@redhat.com> Backported from mainline + 2013-11-06 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/58970 + * gcc.c-torture/compile/pr58970-1.c: New test. + * gcc.c-torture/compile/pr58970-2.c: New test. + 2013-11-05 Jakub Jelinek <jakub@redhat.com> PR rtl-optimization/58997 diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c b/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c new file mode 100644 index 00000000000..45aad2b2e65 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr58970-1.c @@ -0,0 +1,11 @@ +/* PR middle-end/58970 */ + +struct T { int b : 1; }; +struct S { struct T t[1]; }; + +void +foo (int x, struct S *s) +{ + if (x == -1) + s->t[x].b = 0; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c b/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c new file mode 100644 index 00000000000..3103b31e179 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr58970-2.c @@ -0,0 +1,11 @@ +/* PR middle-end/58970 */ + +struct T { char a : 8; char b : 1; }; +struct S { char x; struct T t[1]; }; + +void +foo (int x, struct S *s) +{ + if (x == -1) + s->t[x].b = 0; +} |