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/expr.c | |
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/expr.c')
-rw-r--r-- | gcc/expr.c | 18 |
1 files changed, 18 insertions, 0 deletions
@@ -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; } |