aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-19 19:11:58 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2016-02-19 19:11:58 +0000
commitd91f5fbb59f1fa3773b061bf43a6b58ff1ad8ada (patch)
treead095f6a8fb1989c26f70257401d09f011e05436 /gcc/expr.c
parent5fe1f2827a5262d2e990a68a103bd9e3879e75d0 (diff)
PR c++/69851
* expr.c (store_field): Don't use bit-field path if exp is COMPONENT_REF with TREE_ADDRESSABLE type, where TYPE_SIZE is different from bitsize, but DECL_SIZE of FIELD_DECL is bitsize and the assignment can be performed by bitwise copy. Formatting fix. * g++.dg/torture/pr69851.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233566 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 29e9356a31e..4ad76e10e27 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6643,14 +6643,27 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
/* Except for initialization of full bytes from a CONSTRUCTOR, which
we will handle specially below. */
&& !(TREE_CODE (exp) == CONSTRUCTOR
- && bitsize % BITS_PER_UNIT == 0))
+ && bitsize % BITS_PER_UNIT == 0)
+ /* And except for bitwise copying of TREE_ADDRESSABLE types,
+ where the FIELD_DECL has the right bitsize, but TREE_TYPE (exp)
+ includes some extra padding. store_expr / expand_expr will in
+ that case call get_inner_reference that will have the bitsize
+ we check here and thus the block move will not clobber the
+ padding that shouldn't be clobbered. */
+ && (!TREE_ADDRESSABLE (TREE_TYPE (exp))
+ || TREE_CODE (exp) != COMPONENT_REF
+ || TREE_CODE (DECL_SIZE (TREE_OPERAND (exp, 1))) != INTEGER_CST
+ || (bitsize % BITS_PER_UNIT != 0)
+ || (bitpos % BITS_PER_UNIT != 0)
+ || (compare_tree_int (DECL_SIZE (TREE_OPERAND (exp, 1)), bitsize)
+ != 0)))
/* If we are expanding a MEM_REF of a non-BLKmode non-addressable
decl we must use bitfield operations. */
|| (bitsize >= 0
&& TREE_CODE (exp) == MEM_REF
&& TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
&& DECL_P (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
- && !TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (exp, 0),0 ))
+ && !TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
&& DECL_MODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != BLKmode))
{
rtx temp;