summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-11 07:57:11 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2013-11-11 07:57:11 +0000
commit3e09bc82dc951f6a424b4fd1726abdf9633a045d (patch)
treede94b40cfe08cfd234233acae546f6176a0329c3
parentc17d9a29b3d389f64fcea52787ad94df8afece1d (diff)
downloadgcc-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/ChangeLog7
-rw-r--r--gcc/expr.c23
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58970-1.c11
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr58970-2.c11
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;
+}