diff mbox

fix libstdc++/60564

Message ID 20140318163205.GD31666@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely March 18, 2014, 4:32 p.m. UTC
This fixes a 4.8/4.9 regression where we move from an lvalue when
constructing a packaged_task.

Tested x86_64-linux, committed to trunk and 4.8 branch.
commit b07f31e30bc3ca1b91e199c37466824bb7c3bafa
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Mar 18 13:23:52 2014 +0000

    	PR libstdc++/60564
    	* include/std/future (__future_base::_Task_state<>): Change
    	constructors to template functions using perfect forwarding.
    	(__create_task_state): Use decayed type as stored task.
    	(packaged_task::packaged_task(_Fn&&)): Forward instead of moving.
    	* testsuite/30_threads/packaged_task/60564.cc: New.
diff mbox

Patch

diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index ca3dacd..717ce71 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -1285,9 +1285,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)> final
     : __future_base::_Task_state_base<_Res(_Args...)>
     {
-      _Task_state(_Fn&& __fn, const _Alloc& __a)
-      : _Task_state_base<_Res(_Args...)>(__a), _M_impl(std::move(__fn), __a)
-      { }
+      template<typename _Fn2>
+	_Task_state(_Fn2&& __fn, const _Alloc& __a)
+	: _Task_state_base<_Res(_Args...)>(__a),
+	  _M_impl(std::forward<_Fn2>(__fn), __a)
+	{ }
 
     private:
       virtual void
@@ -1316,19 +1318,21 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       struct _Impl : _Alloc
       {
-	_Impl(_Fn&& __fn, const _Alloc& __a)
-	  : _Alloc(__a), _M_fn(std::move(__fn)) { }
+	template<typename _Fn2>
+	  _Impl(_Fn2&& __fn, const _Alloc& __a)
+	  : _Alloc(__a), _M_fn(std::forward<_Fn2>(__fn)) { }
 	_Fn _M_fn;
       } _M_impl;
     };
 
-    template<typename _Signature, typename _Fn, typename _Alloc>
-      static shared_ptr<__future_base::_Task_state_base<_Signature>>
-      __create_task_state(_Fn&& __fn, const _Alloc& __a)
-      {
-	typedef __future_base::_Task_state<_Fn, _Alloc, _Signature> _State;
-	return std::allocate_shared<_State>(__a, std::move(__fn), __a);
-      }
+  template<typename _Signature, typename _Fn, typename _Alloc>
+    static shared_ptr<__future_base::_Task_state_base<_Signature>>
+    __create_task_state(_Fn&& __fn, const _Alloc& __a)
+    {
+      typedef typename decay<_Fn>::type _Fn2;
+      typedef __future_base::_Task_state<_Fn2, _Alloc, _Signature> _State;
+      return std::allocate_shared<_State>(__a, std::forward<_Fn>(__fn), __a);
+    }
 
   template<typename _Fn, typename _Alloc, typename _Res, typename... _Args>
     shared_ptr<__future_base::_Task_state_base<_Res(_Args...)>>
@@ -1368,7 +1372,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       __constrain_pkgdtask<packaged_task, _Fn>::__type>
 	explicit
 	packaged_task(_Fn&& __fn)
-	: packaged_task(allocator_arg, std::allocator<int>(), std::move(__fn))
+	: packaged_task(allocator_arg, std::allocator<int>(),
+			std::forward<_Fn>(__fn))
 	{ }
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
diff --git a/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc b/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc
new file mode 100644
index 0000000..956d506
--- /dev/null
+++ b/libstdc++-v3/testsuite/30_threads/packaged_task/60564.cc
@@ -0,0 +1,51 @@ 
+// { dg-do run { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* *-*-solaris* *-*-cygwin *-*-darwin* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthread" { target *-*-freebsd* *-*-netbsd* *-*-linux* *-*-gnu* powerpc-ibm-aix* } }
+// { dg-options " -std=gnu++11 -pthreads" { target *-*-solaris* } }
+// { dg-options " -std=gnu++11 " { target *-*-cygwin *-*-darwin* } }
+// { dg-require-cstdint "" }
+// { dg-require-gthreads "" }
+// { dg-require-atomic-builtins "" }
+
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+
+#include <future>
+#include <testsuite_hooks.h>
+
+struct X
+{
+  X() = default;
+  X(const X&) = default;
+  X(X&& x) { x.moved = true; }
+
+  void operator()() const { }
+
+  bool moved = false;
+};
+
+void test01()
+{
+  X x;
+  std::packaged_task<void()> p(x);
+  VERIFY( !x.moved );
+}
+
+int main()
+{
+  test01();
+}