From 8be719cb791cd1b1fe5059ddc70831515b5352eb Mon Sep 17 00:00:00 2001 From: Alex Guteniev Date: Sat, 4 Mar 2023 01:14:43 +0200 Subject: [PATCH 01/12] ``: improve code documentation (#3406) --- stl/inc/atomic | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/stl/inc/atomic b/stl/inc/atomic index babd2bf3d49..6848b13c053 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -107,6 +107,10 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { } } +// note: these macros are _not_ always safe to use with a trailing semicolon, +// we avoid wrapping them in do {} while (0) because MSVC generates code for such loops +// in debug mode. + #if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC)) #define _ATOMIC_CHOOSE_INTRINSIC(_Order, _Result, _Intrinsic, ...) \ _Check_memory_order(_Order); \ @@ -160,23 +164,20 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { #endif // _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 -// note: these macros are _not_ always safe to use with a trailing semicolon, -// we avoid wrapping them in do {} while (0) because MSVC generates code for such loops -// in debug mode. -#define _ATOMIC_LOAD_VERIFY_MEMORY_ORDER(_Order_var) \ - switch (_Order_var) { \ - case _Atomic_memory_order_relaxed: \ - break; \ - case _Atomic_memory_order_consume: \ - case _Atomic_memory_order_acquire: \ - case _Atomic_memory_order_seq_cst: \ - _Compiler_or_memory_barrier(); \ - break; \ - case _Atomic_memory_order_release: \ - case _Atomic_memory_order_acq_rel: \ - default: \ - _INVALID_MEMORY_ORDER; \ - break; \ +#define _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(_Order_var) \ + switch (_Order_var) { \ + case _Atomic_memory_order_relaxed: \ + break; \ + case _Atomic_memory_order_consume: \ + case _Atomic_memory_order_acquire: \ + case _Atomic_memory_order_seq_cst: \ + _Compiler_or_memory_barrier(); \ + break; \ + case _Atomic_memory_order_release: \ + case _Atomic_memory_order_acq_rel: \ + default: \ + _INVALID_MEMORY_ORDER; \ + break; \ } #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 @@ -185,13 +186,13 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { _Compiler_barrier(); \ __stlr##_Width(reinterpret_cast(_Ptr), (_Desired)); -#else +#else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 ^^^ / vvv _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv #define __STORE_RELEASE(_Width, _Ptr, _Desired) \ _Compiler_or_memory_barrier(); \ __iso_volatile_store##_Width((_Ptr), (_Desired)); -#endif +#endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ #define _ATOMIC_STORE_PREFIX(_Width, _Ptr, _Desired) \ case _Atomic_memory_order_relaxed: \ @@ -207,7 +208,6 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { _INVALID_MEMORY_ORDER; \ _FALLTHROUGH; - #define _ATOMIC_STORE_SEQ_CST_ARM(_Width, _Ptr, _Desired) \ _Memory_barrier(); \ __iso_volatile_store##_Width((_Ptr), (_Desired)); \ @@ -788,7 +788,7 @@ struct _Atomic_storage<_Ty, 1> { // lock-free using 1-byte intrinsics _ATOMIC_LOAD_ARM64(_As_bytes, 8, _Mem, static_cast(_Order)) #else _As_bytes = __iso_volatile_load8(_Mem); - _ATOMIC_LOAD_VERIFY_MEMORY_ORDER(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) #endif return reinterpret_cast<_TVal&>(_As_bytes); } @@ -896,7 +896,7 @@ struct _Atomic_storage<_Ty, 2> { // lock-free using 2-byte intrinsics _ATOMIC_LOAD_ARM64(_As_bytes, 16, _Mem, static_cast(_Order)) #else _As_bytes = __iso_volatile_load16(_Mem); - _ATOMIC_LOAD_VERIFY_MEMORY_ORDER(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) #endif return reinterpret_cast<_TVal&>(_As_bytes); } @@ -1003,7 +1003,7 @@ struct _Atomic_storage<_Ty, 4> { // lock-free using 4-byte intrinsics _ATOMIC_LOAD_ARM64(_As_bytes, 32, _Mem, static_cast(_Order)) #else _As_bytes = __iso_volatile_load32(_Mem); - _ATOMIC_LOAD_VERIFY_MEMORY_ORDER(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) #endif return reinterpret_cast<_TVal&>(_As_bytes); } @@ -1120,7 +1120,7 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics _As_bytes = __iso_volatile_load64(_Mem); #endif - _ATOMIC_LOAD_VERIFY_MEMORY_ORDER(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) #endif // _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 return reinterpret_cast<_TVal&>(_As_bytes); } @@ -3045,7 +3045,7 @@ _STD_END #undef _CMPXCHG_MASK_OUT_PADDING_BITS #undef _ATOMIC_CHOOSE_INTRINSIC -#undef _ATOMIC_LOAD_VERIFY_MEMORY_ORDER +#undef _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED #undef _ATOMIC_STORE_PREFIX #undef _ATOMIC_STORE_SEQ_CST_ARM #undef _ATOMIC_STORE_SEQ_CST_X86_X64 From 7155ea6f8805ff58da0467cf908204ab4616eebe Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 4 Mar 2023 07:17:26 +0800 Subject: [PATCH 02/12] Implement LWG-3734 Inconsistency in `inout_ptr` and `out_ptr` for empty case (#3503) Co-authored-by: Stephan T. Lavavej Co-authored-by: Casey Carter --- stl/inc/memory | 10 ++++++- tests/std/tests/P1132R7_out_ptr/test.cpp | 34 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 3ddb1c45401..e7ca9c2cfc2 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -4179,7 +4179,15 @@ public: explicit out_ptr_t(_SmartPtr& _Smart_ptr_, _ArgsT... _Args_) noexcept( is_nothrow_constructible_v, _ArgsT...>) /* strengthened */ : _Smart_ptr(_Smart_ptr_), - _Mypair(_One_then_variadic_args_t{}, tuple<_ArgsT...>{_STD forward<_ArgsT>(_Args_)...}) {} + _Mypair(_One_then_variadic_args_t{}, tuple<_ArgsT...>{_STD forward<_ArgsT>(_Args_)...}) { + constexpr bool _Is_resettable = requires { _Smart_ptr.reset(); }; // TRANSITION, DevCom-10291456 + if constexpr (_Is_resettable) { + _Smart_ptr.reset(); + } else { + static_assert(is_constructible_v<_SmartPtr>, "the adapted pointer type must be default constructible."); + _Smart_ptr = _SmartPtr(); + } + } out_ptr_t(const out_ptr_t&) = delete; diff --git a/tests/std/tests/P1132R7_out_ptr/test.cpp b/tests/std/tests/P1132R7_out_ptr/test.cpp index 32cc7e14225..c73a1f0726b 100644 --- a/tests/std/tests/P1132R7_out_ptr/test.cpp +++ b/tests/std/tests/P1132R7_out_ptr/test.cpp @@ -76,8 +76,22 @@ void test_shared_ptr() { assert(*int_ptr == 32); } + // LWG-3734 Inconsistency in inout_ptr and out_ptr for empty case + { + const auto f = [](void** ptr) { *ptr = new int(42); }; + + { + auto temp_adaptor = out_ptr(int_ptr, deleter); + assert(int_ptr.get() == nullptr); + f(temp_adaptor); + } + + assert(count == 2); + assert(*int_ptr == 42); + } + int_ptr.reset(); - assert(count == 2); + assert(count == 3); } template @@ -119,6 +133,19 @@ void test_smart_ptr(Args&&... args) { assert(*int_ptr == 19); } + // LWG-3734 Inconsistency in inout_ptr and out_ptr for empty case + { + const auto f = [](void** ptr) { *ptr = new int(42); }; + + { + auto temp_adaptor = out_ptr(int_ptr); + assert(int_ptr.get() == nullptr); + f(temp_adaptor); + } + + assert(*int_ptr == 42); + } + // LWG-3594 inout_ptr - inconsistent release() in destructor { const auto f = [](int** ptr) { @@ -141,6 +168,10 @@ struct resettable_ptr { explicit resettable_ptr(int* p) : ptr(p) {} + void reset() { + ptr.reset(); + } + void reset(int* p, reset_tag) { ptr.reset(p); } @@ -163,6 +194,7 @@ struct constructible_ptr { unique_ptr ptr; + constructible_ptr() = default; explicit constructible_ptr(int* p) : ptr(p) {} explicit constructible_ptr(int* p, reset_tag) : ptr(p) {} From 882d92ec47580a4ee88543f567b50e9382934059 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 4 Mar 2023 07:20:14 +0800 Subject: [PATCH 03/12] Implement LWG-3877 Incorrect constraints on `const`-qualified monadic overloads for `std::expected` (#3504) Co-authored-by: Stephan T. Lavavej --- stl/inc/expected | 24 +-- .../test.cpp | 146 ++++++++++++++++++ 2 files changed, 158 insertions(+), 12 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 9d4a583cfd0..573d1e7d69b 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -732,7 +732,7 @@ public: // [expected.object.monadic] template - requires is_copy_constructible_v<_Err> + requires is_constructible_v<_Err, _Err&> constexpr auto and_then(_Fn&& _Func) & { using _Uty = remove_cvref_t>; @@ -789,7 +789,7 @@ public: } template - requires is_move_constructible_v<_Err> + requires is_constructible_v<_Err, const _Err> constexpr auto and_then(_Fn&& _Func) const&& { using _Uty = remove_cvref_t>; @@ -808,7 +808,7 @@ public: } template - requires is_copy_constructible_v<_Ty> + requires is_constructible_v<_Ty, _Ty&> constexpr auto or_else(_Fn&& _Func) & { using _Uty = remove_cvref_t>; @@ -865,7 +865,7 @@ public: } template - requires is_move_constructible_v<_Ty> + requires is_constructible_v<_Ty, const _Ty> constexpr auto or_else(_Fn&& _Func) const&& { using _Uty = remove_cvref_t>; @@ -884,7 +884,7 @@ public: } template - requires is_copy_constructible_v<_Err> + requires is_constructible_v<_Err, _Err&> constexpr auto transform(_Fn&& _Func) & { static_assert(invocable<_Fn, _Ty&>, "expected::transform(F) requires that F is invocable with T. " "(N4928 [expected.object.monadic]/19)"); @@ -965,7 +965,7 @@ public: } template - requires is_move_constructible_v<_Err> + requires is_constructible_v<_Err, const _Err> constexpr auto transform(_Fn&& _Func) const&& { static_assert(invocable<_Fn, const _Ty>, "expected::transform(F) requires that F is invocable with T. " "(N4928 [expected.object.monadic]/23)"); @@ -992,7 +992,7 @@ public: } template - requires is_copy_constructible_v<_Ty> + requires is_constructible_v<_Ty, _Ty&> constexpr auto transform_error(_Fn&& _Func) & { static_assert(invocable<_Fn, _Err&>, "expected::transform_error(F) requires that F is invocable with E. " "(N4928 [expected.object.monadic]/27)"); @@ -1053,7 +1053,7 @@ public: } template - requires is_move_constructible_v<_Ty> + requires is_constructible_v<_Ty, const _Ty> constexpr auto transform_error(_Fn&& _Func) const&& { static_assert(invocable<_Fn, const _Err>, "expected::transform_error(F) requires that F is invocable with E. " @@ -1470,7 +1470,7 @@ public: // [expected.void.monadic] template - requires is_copy_constructible_v<_Err> + requires is_constructible_v<_Err, _Err&> constexpr auto and_then(_Fn&& _Func) & { using _Uty = remove_cvref_t>; @@ -1527,7 +1527,7 @@ public: } template - requires is_move_constructible_v<_Err> + requires is_constructible_v<_Err, const _Err> constexpr auto and_then(_Fn&& _Func) const&& { using _Uty = remove_cvref_t>; @@ -1618,7 +1618,7 @@ public: } template - requires is_copy_constructible_v<_Err> + requires is_constructible_v<_Err, _Err&> constexpr auto transform(_Fn&& _Func) & { static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " "(N4928 [expected.void.monadic]/17)"); @@ -1696,7 +1696,7 @@ public: } template - requires is_move_constructible_v<_Err> + requires is_constructible_v<_Err, const _Err> constexpr auto transform(_Fn&& _Func) const&& { static_assert(invocable<_Fn>, "expected::transform(F) requires that F is invocable with no arguments. " "(N4928 [expected.void.monadic]/21)"); diff --git a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp index 9ce4e74d8ae..39b6ffcc483 100644 --- a/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp +++ b/tests/std/tests/P2505R5_monadic_functions_for_std_expected/test.cpp @@ -375,7 +375,153 @@ constexpr bool test() { return true; } +template class Tmpl> +constexpr bool is_specialization_of = false; + +template