diff options
author | Eric Botcazou <ebotcazou@adacore.com> | 2012-02-07 17:21:36 +0000 |
---|---|---|
committer | Eric Botcazou <ebotcazou@gcc.gnu.org> | 2012-02-07 17:21:36 +0000 |
commit | f22cfd73cd9eece5e426ddfe745f998ffc665945 (patch) | |
tree | 051e03d16190d715181a74c0cea2613985c0cdd3 /gcc | |
parent | 13a72c0ba3e023f0f585654ed389c76efd4c1590 (diff) | |
download | gcc-f22cfd73cd9eece5e426ddfe745f998ffc665945.zip gcc-f22cfd73cd9eece5e426ddfe745f998ffc665945.tar.gz gcc-f22cfd73cd9eece5e426ddfe745f998ffc665945.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/expr.c | 18 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20120207-1.c | 27 |
4 files changed, 55 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a05e801..3d6fe25 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 @@ -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 1f63642..a433613 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..c4716ae --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20120207-1.c @@ -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; +} |