diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-11-06 08:48:50 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2013-11-06 08:48:50 +0100 |
commit | fda1ba0aeacbbe986bd29677a8165e23a0d7d178 (patch) | |
tree | a98bd0cd4b8f5495fcad8eaad4dd8f843662c5bc /gcc/expr.c | |
parent | 10180dd30203ea20aca4b05902d5fd26603b1ec6 (diff) | |
download | gcc-fda1ba0aeacbbe986bd29677a8165e23a0d7d178.zip gcc-fda1ba0aeacbbe986bd29677a8165e23a0d7d178.tar.gz gcc-fda1ba0aeacbbe986bd29677a8165e23a0d7d178.tar.bz2 |
re PR middle-end/58970 (internal compiler error: in get_bit_range, at expr.c:4562)
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.c: New test.
From-SVN: r204444
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 23 |
1 files changed, 16 insertions, 7 deletions
@@ -4576,19 +4576,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 @@ -4721,6 +4721,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); |