From: Eric Botcazou Date: Tue, 7 Feb 2012 17:21:36 +0000 (+0000) Subject: re PR middle-end/51994 (git-1.7.8.3 miscompiled due to negative bitpos from get_inner... X-Git-Tag: releases/gcc-4.7.0~533 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f22cfd73cd9eece5e426ddfe745f998ffc665945;p=thirdparty%2Fgcc.git re PR middle-end/51994 (git-1.7.8.3 miscompiled due to negative bitpos from get_inner_reference) 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a05e801a8e4f..3d6fe256e934 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2012-02-07 Eric Botcazou + + 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 PR rtl-optimization/52060 diff --git a/gcc/expr.c b/gcc/expr.c index fcf177b956a0..e63ed3b71f5c 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1f63642c0166..a433613b0c73 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-02-07 Eric Botcazou + + * gcc.c-torture/execute/20120207-1.c: New test. + 2012-02-07 Jakub Jelinek 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 index 000000000000..c4716aecad80 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20120207-1.c @@ -0,0 +1,27 @@ +/* PR middle-end/51994 */ +/* Testcase by Uros Bizjak */ + +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; +}