From a7378633ee868146dc46f7e108c2a0c63956f4cf Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 10 Sep 2024 11:42:09 +0800 Subject: [PATCH 1/2] [libc++] Reland LWG2921 and LWG2976 They were originally implemented in d42db7e083ee0edda327782aa122ad6474c126d1 but reverted later in a2f3c63282330be0226158cdfdc27c4c2aef9cdc. This PR implement both LWG issues again, guarding the removed functions with `_LIBCPP_STD_VER <= 14`, because they should be treated as patches for P0302R1 which was adopted for C++17. --- libcxx/docs/Status/Cxx17Issues.csv | 2 +- libcxx/docs/Status/Cxx20Issues.csv | 2 +- libcxx/include/future | 14 ++++++++++++-- .../ctor2.compile.pass.cpp | 19 ++++++++++++++----- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/libcxx/docs/Status/Cxx17Issues.csv b/libcxx/docs/Status/Cxx17Issues.csv index 7119382eb5cfb..af3dee9ca50c9 100644 --- a/libcxx/docs/Status/Cxx17Issues.csv +++ b/libcxx/docs/Status/Cxx17Issues.csv @@ -306,7 +306,7 @@ "`LWG2905 `__","is_constructible_v, P, D const &> should be false when D is not copy constructible","2017-02 (Kona)","|Complete|","","" "`LWG2908 `__","The less-than operator for shared pointers could do more","2017-02 (Kona)","|Complete|","","" "`LWG2911 `__","An is_aggregate type trait is needed","2017-02 (Kona)","|Complete|","","" -"`LWG2921 `__","packaged_task and type-erased allocators","2017-02 (Kona)","|Complete|","","" +"`LWG2921 `__","packaged_task and type-erased allocators","2017-02 (Kona)","|Complete|","20.0","Originally implemented in LLVM 6.0 but reverted later. Old documentation incorrectly said it was implemented." "`LWG2934 `__","optional doesn't compare with T","2017-02 (Kona)","|Complete|","","" "","","","","","" "`LWG2901 `__","Variants cannot properly support allocators","2017-07 (Toronto)","|Complete|","","" diff --git a/libcxx/docs/Status/Cxx20Issues.csv b/libcxx/docs/Status/Cxx20Issues.csv index e5d2498473ecd..8c4224616d73e 100644 --- a/libcxx/docs/Status/Cxx20Issues.csv +++ b/libcxx/docs/Status/Cxx20Issues.csv @@ -27,7 +27,7 @@ "`LWG2964 `__","Apparently redundant requirement for dynamic_pointer_cast","2017-11 (Albuquerque)","","","" "`LWG2965 `__","Non-existing path::native_string() in filesystem_error::what() specification","2017-11 (Albuquerque)","|Nothing To Do|","","" "`LWG2972 `__","What is ``is_trivially_destructible_v``\ ?","2017-11 (Albuquerque)","|Complete|","","" -"`LWG2976 `__","Dangling uses_allocator specialization for packaged_task","2017-11 (Albuquerque)","|Complete|","","" +"`LWG2976 `__","Dangling uses_allocator specialization for packaged_task","2017-11 (Albuquerque)","|Complete|","20.0","Originally implemented in LLVM 6.0 but reverted later. Old documentation incorrectly said it was implemented." "`LWG2977 `__","unordered_meow::merge() has incorrect Throws: clause","2017-11 (Albuquerque)","|Nothing To Do|","","" "`LWG2978 `__","Hash support for pmr::string and friends","2017-11 (Albuquerque)","|Complete|","16.0","" "`LWG2979 `__","aligned_union should require complete object types","2017-11 (Albuquerque)","|Complete|","","" diff --git a/libcxx/include/future b/libcxx/include/future index 01c0b10172cd3..b52bcc7e25452 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -329,7 +329,7 @@ public: template explicit packaged_task(F&& f); template - packaged_task(allocator_arg_t, const Allocator& a, F&& f); + packaged_task(allocator_arg_t, const Allocator& a, F&& f); // removed in C++17 ~packaged_task(); // no copy @@ -356,7 +356,7 @@ public: template void swap(packaged_task&) noexcept; -template struct uses_allocator, Alloc>; +template struct uses_allocator, Alloc>; // removed in C++17 } // std @@ -1460,8 +1460,10 @@ public: _LIBCPP_HIDE_FROM_ABI __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} template _LIBCPP_HIDE_FROM_ABI __packaged_task_function(_Fp&& __f); +# if _LIBCPP_STD_VER <= 14 template _LIBCPP_HIDE_FROM_ABI __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); +# endif _LIBCPP_HIDE_FROM_ABI __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; @@ -1507,6 +1509,7 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) } } +# if _LIBCPP_STD_VER <= 14 template template __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(allocator_arg_t, const _Alloc& __a0, _Fp&& __f) @@ -1525,6 +1528,7 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(allocator_ __f_ = std::addressof(*__hold.release()); } } +# endif template __packaged_task_function<_Rp(_ArgTypes...)>& @@ -1606,9 +1610,11 @@ public: template , packaged_task>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI explicit packaged_task(_Fp&& __f) : __f_(std::forward<_Fp>(__f)) {} +# if _LIBCPP_STD_VER <= 14 template , packaged_task>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) : __f_(allocator_arg_t(), __a, std::forward<_Fp>(__f)), __p_(allocator_arg_t(), __a) {} +# endif // ~packaged_task() = default; // no copy @@ -1696,9 +1702,11 @@ public: _LIBCPP_HIDE_FROM_ABI packaged_task() _NOEXCEPT : __p_(nullptr) {} template , packaged_task>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI explicit packaged_task(_Fp&& __f) : __f_(std::forward<_Fp>(__f)) {} +# if _LIBCPP_STD_VER <= 14 template , packaged_task>::value, int> = 0> _LIBCPP_HIDE_FROM_ABI packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f) : __f_(allocator_arg_t(), __a, std::forward<_Fp>(__f)), __p_(allocator_arg_t(), __a) {} +# endif // ~packaged_task() = default; // no copy @@ -1790,8 +1798,10 @@ swap(packaged_task<_Rp(_ArgTypes...)>& __x, packaged_task<_Rp(_ArgTypes...)>& __ __x.swap(__y); } +# if _LIBCPP_STD_VER <= 14 template struct _LIBCPP_TEMPLATE_VIS uses_allocator, _Alloc> : public true_type {}; +# endif template _LIBCPP_HIDE_FROM_ABI future<_Rp> __make_deferred_assoc_state(_Fp&& __f) { diff --git a/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp index 3ab59909cfafb..a3bdd45975c96 100644 --- a/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp +++ b/libcxx/test/std/thread/futures/futures.task/futures.task.members/ctor2.compile.pass.cpp @@ -18,11 +18,13 @@ #include #include +#include +#include #include "test_allocator.h" struct A {}; -using PT = std::packaged_task; +using PT = std::packaged_task; using VPT = volatile std::packaged_task; static_assert(!std::is_constructible, VPT>::value, ""); @@ -35,7 +37,14 @@ static_assert(!std::is_constructible static_assert(!std::is_constructible, volatile PA&>::value, ""); static_assert(!std::is_constructible, volatile PA&&>::value, ""); -static_assert( std::is_constructible, const PI&>::value, ""); -static_assert( std::is_constructible, const PI&&>::value, ""); -static_assert( std::is_constructible, volatile PI&>::value, ""); -static_assert( std::is_constructible, volatile PI&&>::value, ""); +#if TEST_STD_VER >= 17 // packaged_task allocator support was removed in C++17 (LWG 2921) +static_assert(!std::is_constructible_v, const PI&>); +static_assert(!std::is_constructible_v, const PI&&>); +static_assert(!std::is_constructible_v, volatile PI&>); +static_assert(!std::is_constructible_v, volatile PI&&>); +#else +static_assert(std::is_constructible, const PI&>::value, ""); +static_assert(std::is_constructible, const PI&&>::value, ""); +static_assert(std::is_constructible, volatile PI&>::value, ""); +static_assert(std::is_constructible, volatile PI&&>::value, ""); +#endif From 5a7cec41ba8d3da8c549a7a0f5d6d5fb610cdc84 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Tue, 10 Sep 2024 21:09:41 +0800 Subject: [PATCH 2/2] Unguard implementation details --- libcxx/include/future | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libcxx/include/future b/libcxx/include/future index b52bcc7e25452..4e9039ea42543 100644 --- a/libcxx/include/future +++ b/libcxx/include/future @@ -1460,10 +1460,8 @@ public: _LIBCPP_HIDE_FROM_ABI __packaged_task_function() _NOEXCEPT : __f_(nullptr) {} template _LIBCPP_HIDE_FROM_ABI __packaged_task_function(_Fp&& __f); -# if _LIBCPP_STD_VER <= 14 template _LIBCPP_HIDE_FROM_ABI __packaged_task_function(allocator_arg_t, const _Alloc& __a, _Fp&& __f); -# endif _LIBCPP_HIDE_FROM_ABI __packaged_task_function(__packaged_task_function&&) _NOEXCEPT; _LIBCPP_HIDE_FROM_ABI __packaged_task_function& operator=(__packaged_task_function&&) _NOEXCEPT; @@ -1509,7 +1507,6 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(_Fp&& __f) } } -# if _LIBCPP_STD_VER <= 14 template template __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(allocator_arg_t, const _Alloc& __a0, _Fp&& __f) @@ -1528,7 +1525,6 @@ __packaged_task_function<_Rp(_ArgTypes...)>::__packaged_task_function(allocator_ __f_ = std::addressof(*__hold.release()); } } -# endif template __packaged_task_function<_Rp(_ArgTypes...)>&