re PR middle-end/51994 (git-1.7.8.3 miscompiled due to negative bitpos from get_inner...
authorEric Botcazou <ebotcazou@adacore.com>
Tue, 7 Feb 2012 17:21:36 +0000 (17:21 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Tue, 7 Feb 2012 17:21:36 +0000 (17:21 +0000)
PR middle-end/51994
* expr.c (get_inner_reference): If there is an offset, add a negative
bit position to it (if any).

From-SVN: r183974

gcc/ChangeLog
gcc/expr.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/20120207-1.c [new file with mode: 0644]

index a05e801..3d6fe25 100644 (file)
@@ -1,3 +1,9 @@
+2012-02-07  Eric Botcazou  <ebotcazou@adacore.com>
+
+       PR middle-end/51994
+       * expr.c (get_inner_reference): If there is an offset, add a negative
+       bit position to it (if any).
+
 2012-02-07  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/52060
index fcf177b..e63ed3b 100644 (file)
@@ -6716,6 +6716,24 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize,
   /* Otherwise, split it up.  */
   if (offset)
     {
+      /* Avoid returning a negative bitpos as this may wreak havoc later.  */
+      if (double_int_negative_p (bit_offset))
+        {
+         double_int mask
+           = double_int_mask (BITS_PER_UNIT == 8
+                              ? 3 : exact_log2 (BITS_PER_UNIT));
+         double_int tem = double_int_and_not (bit_offset, mask);
+         /* TEM is the bitpos rounded to BITS_PER_UNIT towards -Inf.
+            Subtract it to BIT_OFFSET and add it (scaled) to OFFSET.  */
+         bit_offset = double_int_sub (bit_offset, tem);
+         tem = double_int_rshift (tem,
+                                  BITS_PER_UNIT == 8
+                                  ? 3 : exact_log2 (BITS_PER_UNIT),
+                                  HOST_BITS_PER_DOUBLE_INT, true);
+         offset = size_binop (PLUS_EXPR, offset,
+                              double_int_to_tree (sizetype, tem));
+       }
+
       *pbitpos = double_int_to_shwi (bit_offset);
       *poffset = offset;
     }
index 1f63642..a433613 100644 (file)
@@ -1,3 +1,7 @@
+2012-02-07  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gcc.c-torture/execute/20120207-1.c: New test.
+
 2012-02-07  Jakub Jelinek  <jakub@redhat.com>
 
        PR rtl-optimization/52060
diff --git a/gcc/testsuite/gcc.c-torture/execute/20120207-1.c b/gcc/testsuite/gcc.c-torture/execute/20120207-1.c
new file mode 100644 (file)
index 0000000..c4716ae
--- /dev/null
@@ -0,0 +1,27 @@
+/* PR middle-end/51994 */
+/* Testcase by Uros Bizjak <ubizjak@gmail.com> */
+
+extern char *strcpy (char *, const char *);
+extern void abort (void);
+
+char __attribute__((noinline))
+test (int a)
+{
+  char buf[16];
+  char *output = buf;
+
+  strcpy (&buf[0], "0123456789");
+
+  output += a;
+  output -= 1;
+
+  return output[0];
+}
+
+int main ()
+{
+  if (test (2) != '1')
+    abort ();
+
+  return 0;
+}