This avoids doing bitfield stores into the return object of calls
when using return-slot optimization and the type is addressable.
Instead we have to pass down the original target RTX to the call
expansion which otherwise tries to create a new temporary.

Bootstrapped and tested on x86_64-unknonw-linux-gnu, OK?

Thanks,
Richard.

2021-02-26  Richard Biener  <rguent...@suse.de>

        PR middle-end/99281
        * expr.c (store_field): For calls with return-slot optimization
        and addressable return type expand the store directly.

        * g++.dg/pr99218.C: New testcase.
---
 gcc/expr.c                     |  8 +++++++-
 gcc/testsuite/g++.dg/pr99218.C | 31 +++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/pr99218.C

diff --git a/gcc/expr.c b/gcc/expr.c
index 86dc1b6c973..92035c7c3c1 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -7214,7 +7214,13 @@ store_field (rtx target, poly_int64 bitsize, poly_int64 
bitpos,
              || !multiple_p (bitpos, BITS_PER_UNIT)
              || !poly_int_tree_p (DECL_SIZE (TREE_OPERAND (exp, 1)),
                                   &decl_bitsize)
-             || maybe_ne (decl_bitsize, bitsize)))
+             || maybe_ne (decl_bitsize, bitsize))
+         /* A call with an addressable return type and return-slot
+            optimization must not need bitfield operations but we must
+            pass down the original target.  */
+         && (TREE_CODE (exp) != CALL_EXPR
+             || !TREE_ADDRESSABLE (TREE_TYPE (exp))
+             || !CALL_EXPR_RETURN_SLOT_OPT (exp)))
       /* If we are expanding a MEM_REF of a non-BLKmode non-addressable
          decl we must use bitfield operations.  */
       || (known_size_p (bitsize)
diff --git a/gcc/testsuite/g++.dg/pr99218.C b/gcc/testsuite/g++.dg/pr99218.C
new file mode 100644
index 00000000000..477a6a2b117
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr99218.C
@@ -0,0 +1,31 @@
+// { dg-do compile }
+// { dg-require-effective-target c++17 }
+
+struct Data
+{
+  Data() {}
+  ~Data() {}
+
+  long long i;
+};
+
+struct X
+{
+  Data a;
+  int b;
+};
+
+template<class T>
+X get(T const&)
+{
+  return X{};
+}
+
+template<class... Ts>
+struct pack_type : Ts...
+{};
+
+int main()
+{
+  pack_type<X>{get(1)};
+}
-- 
2.26.2

Reply via email to