diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-19 19:11:58 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-19 19:11:58 +0000 |
commit | d91f5fbb59f1fa3773b061bf43a6b58ff1ad8ada (patch) | |
tree | ad095f6a8fb1989c26f70257401d09f011e05436 /gcc/expr.c | |
parent | 5fe1f2827a5262d2e990a68a103bd9e3879e75d0 (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.c | 17 |
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; |