summaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2015-10-12 07:58:43 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2015-10-12 07:58:43 +0000
commitab48ece0923ded0cbd089ce31d1b3d26c239bc4e (patch)
tree4b583f1035c03ad2ebaa0d9fcea61f20f3086f54 /gcc/expr.c
parentb5f3ba2abffe26ee15d3a6a1f511166f8b4571eb (diff)
downloadgcc-ab48ece0923ded0cbd089ce31d1b3d26c239bc4e.tar.gz
PR c++/67557
* expr.c (store_field): Call store_constructor directly when storing a CONSTRUCTOR into a target smaller than its type. Guard against unsafe bitwise copy. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@228704 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 6f6554d25c0..595324dc395 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6616,7 +6616,11 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
operations. */
|| (bitsize >= 0
&& TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST
- && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0)
+ && compare_tree_int (TYPE_SIZE (TREE_TYPE (exp)), bitsize) != 0
+ /* Except for initialization of full bytes from a CONSTRUCTOR, which
+ we will handle specially below. */
+ && !(TREE_CODE (exp) == CONSTRUCTOR
+ && bitsize % BITS_PER_UNIT == 0))
/* If we are expanding a MEM_REF of a non-BLKmode non-addressable
decl we must use bitfield operations. */
|| (bitsize >= 0
@@ -6629,6 +6633,9 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
rtx temp;
gimple *nop_def;
+ /* Using bitwise copy is not safe for TREE_ADDRESSABLE types. */
+ gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (exp)));
+
/* If EXP is a NOP_EXPR of precision less than its mode, then that
implies a mask operation. If the precision is the same size as
the field we're storing into, that mask is redundant. This is
@@ -6743,6 +6750,15 @@ store_field (rtx target, HOST_WIDE_INT bitsize, HOST_WIDE_INT bitpos,
if (!MEM_KEEP_ALIAS_SET_P (to_rtx) && MEM_ALIAS_SET (to_rtx) != 0)
set_mem_alias_set (to_rtx, alias_set);
+ /* Above we avoided using bitfield operations for storing a CONSTRUCTOR
+ into a target smaller than its type; handle that case now. */
+ if (TREE_CODE (exp) == CONSTRUCTOR && bitsize >= 0)
+ {
+ gcc_assert (bitsize % BITS_PER_UNIT == 0);
+ store_constructor (exp, to_rtx, 0, bitsize/BITS_PER_UNIT);
+ return to_rtx;
+ }
+
return store_expr (exp, to_rtx, 0, nontemporal);
}
}