LWG2442: call_once() shouldn't DECAY_COPY(). Patch from K-Ballo.

This patch fixes LWG issue 2422 by removing the DECAY_COPY from call once.
The review can be found here: http://reviews.llvm.org/D10191

llvm-svn: 239654
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 793f59e7676ca997ffe0a919d9135bb3dcad7ecf
diff --git a/include/mutex b/include/mutex
index e2a0daa..0adf1e6 100644
--- a/include/mutex
+++ b/include/mutex
@@ -442,7 +442,11 @@
 
 template<class _Callable>
 _LIBCPP_INLINE_VISIBILITY
-void call_once(once_flag&, _Callable);
+void call_once(once_flag&, _Callable&);
+
+template<class _Callable>
+_LIBCPP_INLINE_VISIBILITY
+void call_once(once_flag&, const _Callable&);
 
 #endif  // _LIBCPP_HAS_NO_VARIADICS
 
@@ -465,7 +469,11 @@
 #else  // _LIBCPP_HAS_NO_VARIADICS
     template<class _Callable>
     friend
-    void call_once(once_flag&, _Callable);
+    void call_once(once_flag&, _Callable&);
+
+    template<class _Callable>
+    friend
+    void call_once(once_flag&, const _Callable&);
 #endif  // _LIBCPP_HAS_NO_VARIADICS
 };
 
@@ -474,15 +482,10 @@
 template <class _Fp>
 class __call_once_param
 {
-    _Fp __f_;
+    _Fp& __f_;
 public:
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     _LIBCPP_INLINE_VISIBILITY
-    explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
-#else
-    _LIBCPP_INLINE_VISIBILITY
-    explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
-#endif
+    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
 
     _LIBCPP_INLINE_VISIBILITY
     void operator()()
@@ -496,7 +499,7 @@
     _LIBCPP_INLINE_VISIBILITY
     void __execute(__tuple_indices<_Indices...>)
     {
-        __invoke(_VSTD::move(_VSTD::get<0>(__f_)), _VSTD::move(_VSTD::get<_Indices>(__f_))...);
+        __invoke(_VSTD::get<0>(_VSTD::move(__f_)), _VSTD::get<_Indices>(_VSTD::move(__f_))...);
     }
 };
 
@@ -505,15 +508,10 @@
 template <class _Fp>
 class __call_once_param
 {
-    _Fp __f_;
+    _Fp& __f_;
 public:
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
     _LIBCPP_INLINE_VISIBILITY
-    explicit __call_once_param(_Fp&& __f) : __f_(_VSTD::move(__f)) {}
-#else
-    _LIBCPP_INLINE_VISIBILITY
-    explicit __call_once_param(const _Fp& __f) : __f_(__f) {}
-#endif
+    explicit __call_once_param(_Fp& __f) : __f_(__f) {}
 
     _LIBCPP_INLINE_VISIBILITY
     void operator()()
@@ -543,9 +541,9 @@
 {
     if (__flag.__state_ != ~0ul)
     {
-        typedef tuple<typename decay<_Callable>::type, typename decay<_Args>::type...> _Gp;
-        __call_once_param<_Gp> __p(_Gp(__decay_copy(_VSTD::forward<_Callable>(__func)),
-                                __decay_copy(_VSTD::forward<_Args>(__args))...));
+        typedef tuple<_Callable&&, _Args&&...> _Gp;
+        _Gp __f(_VSTD::forward<_Callable>(__func), _VSTD::forward<_Args>(__args)...);
+        __call_once_param<_Gp> __p(__f);
         __call_once(__flag.__state_, &__p, &__call_once_proxy<_Gp>);
     }
 }
@@ -555,7 +553,7 @@
 template<class _Callable>
 inline _LIBCPP_INLINE_VISIBILITY
 void
-call_once(once_flag& __flag, _Callable __func)
+call_once(once_flag& __flag, _Callable& __func)
 {
     if (__flag.__state_ != ~0ul)
     {
@@ -564,6 +562,18 @@
     }
 }
 
+template<class _Callable>
+inline _LIBCPP_INLINE_VISIBILITY
+void
+call_once(once_flag& __flag, const _Callable& __func)
+{
+    if (__flag.__state_ != ~0ul)
+    {
+        __call_once_param<const _Callable> __p(__func);
+        __call_once(__flag.__state_, &__p, &__call_once_proxy<const _Callable>);
+    }
+}
+
 #endif  // _LIBCPP_HAS_NO_VARIADICS
 
 _LIBCPP_END_NAMESPACE_STD