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 | |
parent | 5fe1f2827a5262d2e990a68a103bd9e3879e75d0 (diff) | |
download | gcc-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/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/expr.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr69851.C | 24 |
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); +} |