|
|
543165 |
2013-11-06 Jakub Jelinek <jakub@redhat.com>
|
|
|
543165 |
|
|
|
543165 |
PR middle-end/58970
|
|
|
543165 |
* expr.c (get_bit_range): Handle *offset == NULL_TREE.
|
|
|
543165 |
(expand_assignment): If *bitpos is negative, set *offset
|
|
|
543165 |
and adjust *bitpos, so that it is not negative.
|
|
|
543165 |
|
|
|
543165 |
* gcc.c-torture/compile/pr58970-1.c: New test.
|
|
|
543165 |
* gcc.c-torture/compile/pr58970-2.c: New test.
|
|
|
543165 |
|
|
|
543165 |
--- gcc/expr.c (revision 204443)
|
|
|
543165 |
+++ gcc/expr.c (revision 204444)
|
|
|
543165 |
@@ -4576,19 +4576,19 @@ get_bit_range (unsigned HOST_WIDE_INT *b
|
|
|
543165 |
- tree_low_cst (DECL_FIELD_BIT_OFFSET (repr), 1));
|
|
|
543165 |
|
|
|
543165 |
/* If the adjustment is larger than bitpos, we would have a negative bit
|
|
|
543165 |
- position for the lower bound and this may wreak havoc later. This can
|
|
|
543165 |
- occur only if we have a non-null offset, so adjust offset and bitpos
|
|
|
543165 |
- to make the lower bound non-negative. */
|
|
|
543165 |
+ position for the lower bound and this may wreak havoc later. Adjust
|
|
|
543165 |
+ offset and bitpos to make the lower bound non-negative in that case. */
|
|
|
543165 |
if (bitoffset > *bitpos)
|
|
|
543165 |
{
|
|
|
543165 |
HOST_WIDE_INT adjust = bitoffset - *bitpos;
|
|
|
543165 |
-
|
|
|
543165 |
gcc_assert ((adjust % BITS_PER_UNIT) == 0);
|
|
|
543165 |
- gcc_assert (*offset != NULL_TREE);
|
|
|
543165 |
|
|
|
543165 |
*bitpos += adjust;
|
|
|
543165 |
- *offset
|
|
|
543165 |
- = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
|
|
|
543165 |
+ if (*offset == NULL_TREE)
|
|
|
543165 |
+ *offset = size_int (-adjust / BITS_PER_UNIT);
|
|
|
543165 |
+ else
|
|
|
543165 |
+ *offset
|
|
|
543165 |
+ = size_binop (MINUS_EXPR, *offset, size_int (adjust / BITS_PER_UNIT));
|
|
|
543165 |
*bitstart = 0;
|
|
|
543165 |
}
|
|
|
543165 |
else
|
|
|
543165 |
@@ -4721,6 +4721,15 @@ expand_assignment (tree to, tree from, b
|
|
|
543165 |
tem = get_inner_reference (to, &bitsize, &bitpos, &offset, &mode1,
|
|
|
543165 |
&unsignedp, &volatilep, true);
|
|
|
543165 |
|
|
|
543165 |
+ /* Make sure bitpos is not negative, it can wreak havoc later. */
|
|
|
543165 |
+ if (bitpos < 0)
|
|
|
543165 |
+ {
|
|
|
543165 |
+ gcc_assert (offset == NULL_TREE);
|
|
|
543165 |
+ offset = size_int (bitpos >> (BITS_PER_UNIT == 8
|
|
|
543165 |
+ ? 3 : exact_log2 (BITS_PER_UNIT)));
|
|
|
543165 |
+ bitpos &= BITS_PER_UNIT - 1;
|
|
|
543165 |
+ }
|
|
|
543165 |
+
|
|
|
543165 |
if (TREE_CODE (to) == COMPONENT_REF
|
|
|
543165 |
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1)))
|
|
|
543165 |
get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset);
|
|
|
543165 |
--- gcc/testsuite/gcc.c-torture/compile/pr58970-1.c (revision 0)
|
|
|
543165 |
+++ gcc/testsuite/gcc.c-torture/compile/pr58970-1.c (revision 204444)
|
|
|
543165 |
@@ -0,0 +1,11 @@
|
|
|
543165 |
+/* PR middle-end/58970 */
|
|
|
543165 |
+
|
|
|
543165 |
+struct T { int b : 1; };
|
|
|
543165 |
+struct S { struct T t[1]; };
|
|
|
543165 |
+
|
|
|
543165 |
+void
|
|
|
543165 |
+foo (int x, struct S *s)
|
|
|
543165 |
+{
|
|
|
543165 |
+ if (x == -1)
|
|
|
543165 |
+ s->t[x].b = 0;
|
|
|
543165 |
+}
|
|
|
543165 |
--- gcc/testsuite/gcc.c-torture/compile/pr58970-2.c (revision 0)
|
|
|
543165 |
+++ gcc/testsuite/gcc.c-torture/compile/pr58970-2.c (revision 204444)
|
|
|
543165 |
@@ -0,0 +1,11 @@
|
|
|
543165 |
+/* PR middle-end/58970 */
|
|
|
543165 |
+
|
|
|
543165 |
+struct T { char a : 8; char b : 1; };
|
|
|
543165 |
+struct S { char x; struct T t[1]; };
|
|
|
543165 |
+
|
|
|
543165 |
+void
|
|
|
543165 |
+foo (int x, struct S *s)
|
|
|
543165 |
+{
|
|
|
543165 |
+ if (x == -1)
|
|
|
543165 |
+ s->t[x].b = 0;
|
|
|
543165 |
+}
|