summaryrefslogtreecommitdiff
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
parent5fe1f2827a5262d2e990a68a103bd9e3879e75d0 (diff)
downloadgcc-d91f5fbb59f1fa3773b061bf43a6b58ff1ad8ada.tar.gz
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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/expr.c17
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/torture/pr69851.C24
4 files changed, 51 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 587a53461cf..c39390c3eab 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,12 @@
2016-02-19 Jakub Jelinek <jakub@redhat.com>
+ 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.
+
PR middle-end/69838
* lra.c (lra_process_new_insns): If non-call exceptions are enabled,
call copy_reg_eh_region_note_forward on before and/or after sequences
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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index adc10721b31..f753e7bdec8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/69851
+ * g++.dg/torture/pr69851.C: New test.
+
2016-02-19 Martin Sebor <msebor@redhat.com>
PR testsuite/69573
diff --git a/gcc/testsuite/g++.dg/torture/pr69851.C b/gcc/testsuite/g++.dg/torture/pr69851.C
new file mode 100644
index 00000000000..17dbfa66b62
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr69851.C
@@ -0,0 +1,24 @@
+// PR c++/69851
+// { dg-do compile }
+// { dg-options "-std=c++11" }
+
+template <typename T>
+struct A { T a; };
+template <unsigned long, typename...>
+struct B;
+template <unsigned long N, typename T, typename... U>
+struct B<N, T, U...> : B<1, U...>, A<T>
+{
+ B (B &) = default;
+ B (B &&x) : B(x) {}
+};
+template <unsigned long N, typename T>
+struct B<N, T> {};
+struct C { C (C &); };
+struct D {};
+
+void
+foo (B<0, C, D, int, int> a)
+{
+ B<0, C, D, int, int> b (a);
+}