re PR middle-end/58970 (internal compiler error: in get_bit_range, at expr.c:4562)
authorJakub Jelinek <jakub@redhat.com>
Wed, 6 Nov 2013 07:48:50 +0000 (08:48 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 6 Nov 2013 07:48:50 +0000 (08:48 +0100)
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

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr58970-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/compile/pr58970-2.c [new file with mode: 0644]

index 453176f8822c157a0b82ecbb26552d2c288f0c8a..3b468540b62190e088c604da8d0f051f6044aa40 100644 (file)
@@ -1,3 +1,10 @@
+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-06  Ganesh Gopalasubramanian  <Ganesh.Gopalasubramanian@amd.com>
 
        * config/i386/bdver3.md : Added two additional decoder units 
index 8ef28709a4e7aa71f052b1afad4f521a4a180a16..4c64489976f1af0f6a86d8a87a3f13d719903bf6 100644 (file)
@@ -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);
index b88e5291902f2df9cd2a9600c8e0d548f1a24470..ad1d4db8373a028fc47c87a23650c04b6bea438c 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-06  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/58970
+       * gcc.c-torture/compile/pr58970.c: New test.
+
 2013-11-05  Wei Mi  <wmi@google.com>
 
        PR regression/58985
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 (file)
index 0000000..45aad2b
--- /dev/null
@@ -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 (file)
index 0000000..3103b31
--- /dev/null
@@ -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;
+}