PR ipa/69241
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Feb 2016 11:59:00 +0000 (11:59 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 12 Feb 2016 11:59:00 +0000 (11:59 +0000)
* ipa-split.c (split_function): If split part returns TREE_ADDRESSABLE
type by reference, force lhs on the call.

* g++.dg/ipa/pr69241-4.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233375 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ipa-split.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/pr69241-4.C [new file with mode: 0644]

index 3588b15..642f7d3 100644 (file)
@@ -1,5 +1,9 @@
 2016-02-12  Jakub Jelinek  <jakub@redhat.com>
 
+       PR ipa/69241
+       * ipa-split.c (split_function): If split part returns TREE_ADDRESSABLE
+       type by reference, force lhs on the call.
+
        PR ipa/68672
        * ipa-split.c (split_function): Don't compute/use main_part_return_p.
        Compute retval and retbnd early in all cases if split_part_return_p
index 2528a79..ac8b478 100644 (file)
@@ -629,7 +629,18 @@ consider_split (struct split_point *current, bitmap non_ssa_vars,
        4) For non-SSA we need to look where the var is computed. */
   retval = find_retval (return_bb);
   if (!retval)
-    current->split_part_set_retval = true;
+    {
+      /* If there is a return_bb with no return value in function returning
+        value by reference, also make the split part return void, otherwise
+        we expansion would try to create a non-POD temporary, which is
+        invalid.  */
+      if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
+         && DECL_RESULT (current_function_decl)
+         && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
+       current->split_part_set_retval = false;
+      else
+       current->split_part_set_retval = true;
+    }
   else if (is_gimple_min_invariant (retval))
     current->split_part_set_retval = false;
   /* Special case is value returned by reference we record as if it was non-ssa
index 79f8f5a..33d2f22 100644 (file)
@@ -1,5 +1,8 @@
 2016-02-12  Jakub Jelinek  <jakub@redhat.com>
 
+       PR ipa/69241
+       * g++.dg/ipa/pr69241-4.C: New test.
+
        PR ipa/68672
        * g++.dg/ipa/pr68672-1.C: New test.
        * g++.dg/ipa/pr68672-2.C: New test.
diff --git a/gcc/testsuite/g++.dg/ipa/pr69241-4.C b/gcc/testsuite/g++.dg/ipa/pr69241-4.C
new file mode 100644 (file)
index 0000000..2805b0c
--- /dev/null
@@ -0,0 +1,55 @@
+// PR ipa/69241
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Wno-return-type" }
+
+template <typename> class A;
+struct B {
+  using pointer = int *;
+};
+template <typename _CharT, typename = A<_CharT>> class basic_string {
+  long _M_string_length;
+  enum { _S_local_capacity = 15 } _M_local_buf[_S_local_capacity];
+  B::pointer _M_local_data;
+
+public:
+  ~basic_string();
+};
+template <typename _CharT, typename _Traits, typename _Alloc>
+int operator<<(_Traits, basic_string<_CharT, _Alloc>);
+class C {
+  basic_string<A<char>> _M_string;
+};
+class D {
+  C _M_stringbuf;
+};
+class F {
+  int stream;
+  D stream_;
+};
+class G {
+public:
+  void operator&(int);
+};
+class H {
+public:
+  H(unsigned);
+  H(H &&);
+  bool m_fn1();
+};
+class I {
+  void m_fn2(const int &&);
+  static H m_fn3(const int &);
+};
+template <typename Functor> void Bind(Functor);
+class J {
+public:
+  static basic_string<char> m_fn4();
+};
+int a;
+void I::m_fn2(const int &&) { Bind(m_fn3); }
+H I::m_fn3(const int &) {
+  !false ? (void)0 : G() & F() << J::m_fn4();
+  H b(a);
+  if (b.m_fn1())
+    F();
+}