[libcxx] r239654 - LWG2442: call_once() shouldn't DECAY_COPY(). Patch from K-Ballo.

Eric Fiselier eric at efcs.ca
Fri Jun 12 19:23:00 PDT 2015


Author: ericwf
Date: Fri Jun 12 21:23:00 2015
New Revision: 239654

URL: http://llvm.org/viewvc/llvm-project?rev=239654&view=rev
Log:
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

Modified:
    libcxx/trunk/include/mutex
    libcxx/trunk/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp
    libcxx/trunk/www/cxx1z_status.html

Modified: libcxx/trunk/include/mutex
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/mutex?rev=239654&r1=239653&r2=239654&view=diff
==============================================================================
--- libcxx/trunk/include/mutex (original)
+++ libcxx/trunk/include/mutex Fri Jun 12 21:23:00 2015
@@ -442,7 +442,11 @@ void call_once(once_flag&, _Callable&&,
 
 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 @@ private:
 #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 @@ private:
 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 @@ private:
     _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 @@ private:
 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 @@ call_once(once_flag& __flag, _Callable&&
 {
     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 @@ call_once(once_flag& __flag, _Callable&&
 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 @@ call_once(once_flag& __flag, _Callable _
     }
 }
 
+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

Modified: libcxx/trunk/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp?rev=239654&r1=239653&r2=239654&view=diff
==============================================================================
--- libcxx/trunk/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp (original)
+++ libcxx/trunk/test/std/thread/thread.mutex/thread.once/thread.once.callonce/call_once.pass.cpp Fri Jun 12 21:23:00 2015
@@ -14,7 +14,7 @@
 // struct once_flag;
 
 // template<class Callable, class ...Args>
-//   void call_once(once_flag& flag, Callable func, Args&&... args);
+//   void call_once(once_flag& flag, Callable&& func, Args&&... args);
 
 #include <mutex>
 #include <thread>
@@ -153,6 +153,35 @@ public:
     }
 };
 
+class NonCopyable
+{
+#if !defined(__clang__)
+   // GCC 4.8 complains about the following being private
+public:
+    NonCopyable(const NonCopyable&)
+    {
+    }
+#else
+    NonCopyable(const NonCopyable&);
+#endif
+public:
+    NonCopyable() {}
+
+    void operator()(int&) {}
+};
+
+#if __cplusplus >= 201103L
+// reference qualifiers on functions are a C++11 extension
+struct RefQual
+{
+    int lv_called, rv_called;
+
+    RefQual() : lv_called(0), rv_called(0) {}
+
+    void operator()() & { ++lv_called; }
+    void operator()() && { ++rv_called; }
+};
+#endif
 #endif
 
 int main()
@@ -204,5 +233,22 @@ int main()
         std::once_flag f;
         std::call_once(f, MoveOnly(), MoveOnly());
     }
+    // check LWG2442: call_once() shouldn't DECAY_COPY()
+    {
+        std::once_flag f;
+        int i = 0;
+        std::call_once(f, NonCopyable(), i);
+    }
+#if __cplusplus >= 201103L
+// reference qualifiers on functions are a C++11 extension
+    {
+        std::once_flag f1, f2;
+        RefQual rq;
+        std::call_once(f1, rq);
+        assert(rq.lv_called == 1);
+        std::call_once(f2, std::move(rq));
+        assert(rq.rv_called == 1);
+    }
+#endif
 #endif  // _LIBCPP_HAS_NO_VARIADICS
 }

Modified: libcxx/trunk/www/cxx1z_status.html
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/www/cxx1z_status.html?rev=239654&r1=239653&r2=239654&view=diff
==============================================================================
--- libcxx/trunk/www/cxx1z_status.html (original)
+++ libcxx/trunk/www/cxx1z_status.html Fri Jun 12 21:23:00 2015
@@ -127,7 +127,7 @@
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2438">2438</td><td>std::iterator inheritance shouldn't be mandated</td><td>Lenexa</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2439">2439</td><td>unique_copy() sometimes can't fall back to reading its output</td><td>Lenexa</td><td></td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2440">2440</td><td>seed_seq::size() should be noexcept</td><td>Lenexa</td><td>Complete</td></tr>
-	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2442">2442</td><td>call_once() shouldn't DECAY_COPY()</td><td>Lenexa</td><td></td></tr>
+	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2442">2442</td><td>call_once() shouldn't DECAY_COPY()</td><td>Lenexa</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2448">2448</td><td>Non-normative Container destructor specification</td><td>Lenexa</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2454">2454</td><td>Add raw_storage_iterator::base() member</td><td>Lenexa</td><td>Complete</td></tr>
 	<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2455">2455</td><td>Allocator default construction should be allowed to throw</td><td>Lenexa</td><td>Complete</td></tr>





More information about the cfe-commits mailing list