diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-27 09:19:47 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-27 09:19:47 +0000 |
commit | 50b6efd6cf220963dddfafc1c3fd6d4f531c2461 (patch) | |
tree | 464de63e1f69235378526adc3e4ce569d38fb10f | |
parent | bfb02355a080f309ad04fe9d5fa4310c3cfe8ef9 (diff) | |
download | gcc-50b6efd6cf220963dddfafc1c3fd6d4f531c2461.tar.gz |
PR middle-end/59138
* expr.c (emit_group_store): Don't write past the end of the structure.
(store_bit_field): Fix formatting.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@205437 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/expr.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/20131127-1.c | 34 |
4 files changed, 61 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d381a5e3a97..e443649dcfd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2013-11-27 Eric Botcazou <ebotcazou@adacore.com> + + PR middle-end/59138 + * expr.c (emit_group_store): Don't write past the end of the structure. + (store_bit_field): Fix formatting. + 2013-11-24 Sebastian Huber <sebastian.huber@embedded-brains.de> Backport from mainline diff --git a/gcc/expr.c b/gcc/expr.c index 785747be8d0..628a6d9abd9 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -1994,12 +1994,14 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1)); enum machine_mode mode = GET_MODE (tmps[i]); unsigned int bytelen = GET_MODE_SIZE (mode); - unsigned int adj_bytelen = bytelen; + unsigned int adj_bytelen; rtx dest = dst; /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) adj_bytelen = ssize - bytepos; + else + adj_bytelen = bytelen; if (GET_CODE (dst) == CONCAT) { @@ -2040,6 +2042,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) } } + /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) { /* store_bit_field always takes its value from the lsb. @@ -2057,16 +2060,22 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i], shift, tmps[i], 0); } - bytelen = adj_bytelen; + + /* Make sure not to write past the end of the struct. */ + store_bit_field (dest, + adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, + bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT, + VOIDmode, tmps[i]); } /* Optimize the access just a bit. */ - if (MEM_P (dest) - && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest)) - || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)) - && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 - && bytelen == GET_MODE_SIZE (mode)) + else if (MEM_P (dest) + && (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest)) + || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)) + && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 + && bytelen == GET_MODE_SIZE (mode)) emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]); + else store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, 0, 0, mode, tmps[i]); @@ -4668,8 +4677,7 @@ expand_assignment (tree to, tree from, bool nontemporal) expand_insn (icode, 2, ops); } else - store_bit_field (mem, GET_MODE_BITSIZE (mode), - 0, 0, 0, mode, reg); + store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg); return; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6c32a80a312..023a1c50481 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2013-11-27 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.c-torture/execute/20131127-1.c: New test. + 2013-11-25 Vidya Praveen <vidyapraveen@arm.com> Backport from mainline diff --git a/gcc/testsuite/gcc.c-torture/execute/20131127-1.c b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c new file mode 100644 index 00000000000..8ec49657741 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c @@ -0,0 +1,34 @@ +/* PR middle-end/59138 */ +/* Testcase by John Regehr <regehr@cs.utah.edu> */ + +extern void abort (void); + +#pragma pack(1) + +struct S0 { + int f0; + int f1; + int f2; + short f3; +}; + +short a = 1; + +struct S0 b = { 1 }, c, d, e; + +struct S0 fn1() { return c; } + +void fn2 (void) +{ + b = fn1 (); + a = 0; + d = e; +} + +int main (void) +{ + fn2 (); + if (a != 0) + abort (); + return 0; +} |