diff --git a/stl/inc/algorithm b/stl/inc/algorithm index cb816e26aa7..01c0873c378 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -3771,11 +3771,12 @@ _FwdIt2 remove_copy_if(_ExPo&&, _FwdIt1 _First, _FwdIt1 _Last, _FwdIt2 _Dest, _P #if _HAS_CXX17 template = 0> -_NODISCARD _FwdIt remove( +_NODISCARD_REMOVE_ALG _FwdIt remove( _ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) noexcept; // terminates template = 0> -_NODISCARD _FwdIt remove_if(_ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, _Pr _Pred) noexcept; // terminates +_NODISCARD_REMOVE_ALG _FwdIt remove_if( + _ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, _Pr _Pred) noexcept; // terminates #endif // _HAS_CXX17 #ifdef __cpp_lib_concepts @@ -3787,7 +3788,8 @@ namespace ranges { // clang-format off template _Se, class _Ty, class _Pj = identity> requires indirect_binary_predicate, const _Ty*> - _NODISCARD constexpr subrange<_It> operator()(_It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) const { + _NODISCARD_REMOVE_ALG constexpr subrange<_It> operator()( + _It _First, _Se _Last, const _Ty& _Val, _Pj _Proj = {}) const { _Adl_verify_range(_First, _Last); auto _UResult = _Remove_unchecked( _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Val, _Pass_fn(_Proj)); @@ -3798,7 +3800,7 @@ namespace ranges { template requires permutable> && indirect_binary_predicate, _Pj>, const _Ty*> - _NODISCARD constexpr borrowed_subrange_t<_Rng> operator()( + _NODISCARD_REMOVE_ALG constexpr borrowed_subrange_t<_Rng> operator()( _Rng&& _Range, const _Ty& _Val, _Pj _Proj = {}) const { auto _UResult = _Remove_unchecked(_Ubegin(_Range), _Uend(_Range), _Val, _Pass_fn(_Proj)); @@ -3839,7 +3841,8 @@ namespace ranges { template _Se, class _Pj = identity, indirect_unary_predicate> _Pr> - _NODISCARD constexpr subrange<_It> operator()(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const { + _NODISCARD_REMOVE_ALG constexpr subrange<_It> operator()( + _It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const { _Adl_verify_range(_First, _Last); auto _UResult = _Remove_if_unchecked( _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj)); @@ -3851,7 +3854,8 @@ namespace ranges { template , _Pj>> _Pr> requires permutable> - _NODISCARD constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const { + _NODISCARD_REMOVE_ALG constexpr borrowed_subrange_t<_Rng> operator()( + _Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const { auto _UResult = _Remove_if_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_subrange>(_Range, _STD move(_UResult)); @@ -4008,7 +4012,7 @@ namespace ranges { #endif // __cpp_lib_concepts template -_NODISCARD _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { +_NODISCARD_UNIQUE_ALG _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // remove each satisfying _Pred with previous _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -4033,20 +4037,20 @@ _NODISCARD _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { } template -_NODISCARD _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last) { // remove each matching previous +_NODISCARD_UNIQUE_ALG _CONSTEXPR20 _FwdIt unique(_FwdIt _First, _FwdIt _Last) { // remove each matching previous return _STD unique(_First, _Last, equal_to<>{}); } #if _HAS_CXX17 template = 0> -_NODISCARD _FwdIt unique(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept /* terminates */ { +_NODISCARD_UNIQUE_ALG _FwdIt unique(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept /* terminates */ { // remove each satisfying _Pred with previous // not parallelized at present, parallelism expected to be feasible in a future release return _STD unique(_First, _Last, _Pass_fn(_Pred)); } template = 0> -_NODISCARD _FwdIt unique(_ExPo&&, _FwdIt _First, _FwdIt _Last) noexcept /* terminates */ { +_NODISCARD_UNIQUE_ALG _FwdIt unique(_ExPo&&, _FwdIt _First, _FwdIt _Last) noexcept /* terminates */ { // remove each matching previous // not parallelized at present, parallelism expected to be feasible in a future release return _STD unique(_First, _Last); @@ -4061,7 +4065,8 @@ namespace ranges { template _Se, class _Pj = identity, indirect_equivalence_relation> _Pr = ranges::equal_to> - _NODISCARD constexpr subrange<_It> operator()(_It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const { + _NODISCARD_UNIQUE_ALG constexpr subrange<_It> operator()( + _It _First, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const { _Adl_verify_range(_First, _Last); auto _UResult = _Unique_unchecked( _Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj)); @@ -4073,7 +4078,8 @@ namespace ranges { template , _Pj>> _Pr = ranges::equal_to> requires permutable> - _NODISCARD constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { + _NODISCARD_UNIQUE_ALG constexpr borrowed_subrange_t<_Rng> operator()( + _Rng&& _Range, _Pr _Pred = {}, _Pj _Proj = {}) const { auto _UResult = _Unique_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_subrange>(_Range, _STD move(_UResult)); diff --git a/stl/inc/array b/stl/inc/array index 53f9d1de5c2..2f464061478 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -506,7 +506,7 @@ public: return _Size; } - _NODISCARD constexpr bool empty() const noexcept { + _NODISCARD_EMPTY_ARRAY_MEMBER constexpr bool empty() const noexcept { return false; } @@ -685,7 +685,7 @@ public: return 0; } - _NODISCARD constexpr bool empty() const noexcept { + _NODISCARD_EMPTY_ARRAY_MEMBER constexpr bool empty() const noexcept { return true; } diff --git a/stl/inc/barrier b/stl/inc/barrier index ee2f8d82ffd..c7332d508c0 100644 --- a/stl/inc/barrier +++ b/stl/inc/barrier @@ -92,7 +92,7 @@ public: return _Barrier_max; } - _NODISCARD arrival_token arrive(ptrdiff_t _Update = 1) noexcept /* strengthened */ { + _NODISCARD_BARRIER_TOKEN arrival_token arrive(ptrdiff_t _Update = 1) noexcept /* strengthened */ { // Shifting before precondition check, so that exceeding max() will trigger precondition check too _Update <<= _Barrier_value_shift; _STL_VERIFY(_Update > 0, "Precondition: update > 0 (N4861 [thread.barrier.class]/12)"); diff --git a/stl/inc/deque b/stl/inc/deque index 71cdb8ac5a9..04d535fc47b 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1041,7 +1041,7 @@ public: static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); } - _NODISCARD bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Mysize() == 0; } diff --git a/stl/inc/exception b/stl/inc/exception index d08e188a608..3d7088805c8 100644 --- a/stl/inc/exception +++ b/stl/inc/exception @@ -316,7 +316,7 @@ template void* __GetExceptionInfo(_Ex); template -_NODISCARD exception_ptr make_exception_ptr(_Ex _Except) noexcept { +_NODISCARD_SMART_PTR_ALLOC exception_ptr make_exception_ptr(_Ex _Except) noexcept { return exception_ptr::_Copy_exception(_STD addressof(_Except), __GetExceptionInfo(_Except)); } diff --git a/stl/inc/execution b/stl/inc/execution index 6ee644e9ee3..0953ef28cc3 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -2565,7 +2565,8 @@ struct _Static_partitioned_remove_if2 { }; template /* = 0 */> -_NODISCARD _FwdIt remove_if(_ExPo&&, _FwdIt _First, const _FwdIt _Last, _Pr _Pred) noexcept /* terminates */ { +_NODISCARD_REMOVE_ALG _FwdIt remove_if(_ExPo&&, _FwdIt _First, const _FwdIt _Last, _Pr _Pred) noexcept +/* terminates */ { // remove each satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -2592,7 +2593,7 @@ _NODISCARD _FwdIt remove_if(_ExPo&&, _FwdIt _First, const _FwdIt _Last, _Pr _Pre } template /* = 0 */> -_NODISCARD _FwdIt remove(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) noexcept +_NODISCARD_REMOVE_ALG _FwdIt remove(_ExPo&& _Exec, const _FwdIt _First, const _FwdIt _Last, const _Ty& _Val) noexcept /* terminates */ { // remove each matching _Val return _STD remove_if(_STD forward<_ExPo>(_Exec), _First, _Last, diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 77e35f6df3b..3def6d663bd 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -887,7 +887,7 @@ public: static_cast((numeric_limits::max)()), _Alnode_traits::max_size(_Getal())); } - _NODISCARD bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Mypair._Myval2._Myhead == nullptr; } diff --git a/stl/inc/future b/stl/inc/future index 0e5e076b2a2..8e3f4be8da9 100644 --- a/stl/inc/future +++ b/stl/inc/future @@ -1189,7 +1189,7 @@ public: _MyPromise._Swap(_Other._MyPromise); } - _NODISCARD future<_Ty> get_future() { + _NODISCARD_GET_FUTURE future<_Ty> get_future() { return future<_Ty>(_MyPromise._Get_state_for_future(), _Nil{}); } @@ -1251,7 +1251,7 @@ public: _MyPromise._Swap(_Other._MyPromise); } - _NODISCARD future<_Ty&> get_future() { + _NODISCARD_GET_FUTURE future<_Ty&> get_future() { return future<_Ty&>(_MyPromise._Get_state_for_future(), _Nil{}); } @@ -1305,7 +1305,7 @@ public: _MyPromise._Swap(_Other._MyPromise); } - _NODISCARD future get_future() { + _NODISCARD_GET_FUTURE future get_future() { return future(_MyPromise._Get_state_for_future(), _Nil{}); } @@ -1397,7 +1397,7 @@ public: return _MyPromise._Is_valid(); } - _NODISCARD future<_Ret> get_future() { + _NODISCARD_GET_FUTURE future<_Ret> get_future() { return future<_Ret>(_MyPromise._Get_state_for_future(), _Nil{}); } @@ -1519,7 +1519,7 @@ _Associated_state::type>* _Get_associated_state(launc } template -_NODISCARD future<_Invoke_result_t, decay_t<_ArgTypes>...>> async( +_NODISCARD_ASYNC future<_Invoke_result_t, decay_t<_ArgTypes>...>> async( launch _Policy, _Fty&& _Fnarg, _ArgTypes&&... _Args) { // manages a callable object launched with supplied policy using _Ret = _Invoke_result_t, decay_t<_ArgTypes>...>; @@ -1532,7 +1532,8 @@ _NODISCARD future<_Invoke_result_t, decay_t<_ArgTypes>...>> async( } template -_NODISCARD future<_Invoke_result_t, decay_t<_ArgTypes>...>> async(_Fty&& _Fnarg, _ArgTypes&&... _Args) { +_NODISCARD_ASYNC future<_Invoke_result_t, decay_t<_ArgTypes>...>> async( + _Fty&& _Fnarg, _ArgTypes&&... _Args) { // manages a callable object launched with default policy return _STD async(launch::async | launch::deferred, _STD forward<_Fty>(_Fnarg), _STD forward<_ArgTypes>(_Args)...); } diff --git a/stl/inc/latch b/stl/inc/latch index 91d32b7914a..7ca2d02cf9d 100644 --- a/stl/inc/latch +++ b/stl/inc/latch @@ -53,7 +53,7 @@ public: } } - _NODISCARD bool try_wait() const noexcept { + _NODISCARD_TRY_WAIT bool try_wait() const noexcept { // TRANSITION, GH-1133: should be memory_order_acquire return _Counter.load() == 0; } diff --git a/stl/inc/list b/stl/inc/list index fedc6b540db..7d248f34dea 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -1191,7 +1191,7 @@ public: static_cast((numeric_limits::max)()), _Alnode_traits::max_size(_Getal())); } - _NODISCARD bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Mypair._Myval2._Mysize == 0; } diff --git a/stl/inc/memory b/stl/inc/memory index 299c13f7830..fcbef65aa45 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -2693,7 +2693,7 @@ private: #endif // _HAS_CXX20 template -_NODISCARD +_NODISCARD_SMART_PTR_ALLOC #if _HAS_CXX20 enable_if_t, shared_ptr<_Ty>> #else // _HAS_CXX20 @@ -2736,18 +2736,18 @@ _NODISCARD shared_ptr<_Ty> _Make_shared_unbounded_array(const size_t _Count, con } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const size_t _Count) { +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared(const size_t _Count) { return _Make_shared_unbounded_array<_Ty>(_Count); } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared( const size_t _Count, const remove_extent_t<_Ty>& _Val) { return _Make_shared_unbounded_array<_Ty>(_Count, _Val); } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared() { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(); shared_ptr<_Ty> _Ret; @@ -2756,7 +2756,8 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const remove_extent_t<_Ty>& _Val) { +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared( + const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; @@ -2765,7 +2766,7 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(con } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared_for_overwrite() { +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared_for_overwrite() { shared_ptr<_Ty> _Ret; if constexpr (is_array_v<_Ty>) { // make a shared_ptr to a bounded array @@ -2780,13 +2781,14 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared_ } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared_for_overwrite(const size_t _Count) { +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> make_shared_for_overwrite( + const size_t _Count) { return _Make_shared_unbounded_array<_Ty>(_Count, _For_overwrite_tag{}); } #endif // _HAS_CXX20 template -_NODISCARD +_NODISCARD_SMART_PTR_ALLOC #if _HAS_CXX20 enable_if_t, shared_ptr<_Ty>> #else // _HAS_CXX20 @@ -2847,19 +2849,19 @@ _NODISCARD shared_ptr<_Ty> _Allocate_shared_unbounded_array( } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const size_t _Count) { return _Allocate_shared_unbounded_array<_Ty>(_Al, _Count); } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const size_t _Count, const remove_extent_t<_Ty>& _Val) { return _Allocate_shared_unbounded_array<_Ty>(_Al, _Count, _Val); } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared(const _Alloc& _Al) { +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared(const _Alloc& _Al) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; @@ -2874,7 +2876,7 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; @@ -2890,7 +2892,8 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared_for_overwrite(const _Alloc& _Al) { +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared_for_overwrite( + const _Alloc& _Al) { shared_ptr<_Ty> _Ret; if constexpr (is_array_v<_Ty>) { // make a shared_ptr to a bounded array @@ -2918,7 +2921,7 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_sha } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared_for_overwrite( +_NODISCARD_SMART_PTR_ALLOC enable_if_t, shared_ptr<_Ty>> allocate_shared_for_overwrite( const _Alloc& _Al, const size_t _Count) { return _Allocate_shared_unbounded_array<_Ty>(_Al, _Count, _For_overwrite_tag{}); } @@ -3425,12 +3428,12 @@ private: template , int> = 0> -_NODISCARD _CONSTEXPR23 unique_ptr<_Ty> make_unique(_Types&&... _Args) { // make a unique_ptr +_NODISCARD_SMART_PTR_ALLOC _CONSTEXPR23 unique_ptr<_Ty> make_unique(_Types&&... _Args) { // make a unique_ptr return unique_ptr<_Ty>(new _Ty(_STD forward<_Types>(_Args)...)); } template && extent_v<_Ty> == 0, int> = 0> -_NODISCARD _CONSTEXPR23 unique_ptr<_Ty> make_unique(const size_t _Size) { // make a unique_ptr +_NODISCARD_SMART_PTR_ALLOC _CONSTEXPR23 unique_ptr<_Ty> make_unique(const size_t _Size) { // make a unique_ptr using _Elem = remove_extent_t<_Ty>; return unique_ptr<_Ty>(new _Elem[_Size]()); } @@ -3440,13 +3443,13 @@ void make_unique(_Types&&...) = delete; #if _HAS_CXX20 template , int> = 0> -_NODISCARD _CONSTEXPR23 unique_ptr<_Ty> make_unique_for_overwrite() { +_NODISCARD_SMART_PTR_ALLOC _CONSTEXPR23 unique_ptr<_Ty> make_unique_for_overwrite() { // make a unique_ptr with default initialization return unique_ptr<_Ty>(new _Ty); } template , int> = 0> -_NODISCARD _CONSTEXPR23 unique_ptr<_Ty> make_unique_for_overwrite(const size_t _Size) { +_NODISCARD_SMART_PTR_ALLOC _CONSTEXPR23 unique_ptr<_Ty> make_unique_for_overwrite(const size_t _Size) { // make a unique_ptr with default initialization using _Elem = remove_extent_t<_Ty>; return unique_ptr<_Ty>(new _Elem[_Size]); @@ -3704,7 +3707,7 @@ struct hash> { #if _HAS_CXX20 template -_NODISCARD constexpr _Ty* assume_aligned(_Ty* const _Ptr) noexcept /* strengthened */ { +_NODISCARD_ASSUME_ALIGNED constexpr _Ty* assume_aligned(_Ty* const _Ptr) noexcept /* strengthened */ { if (_STD is_constant_evaluated()) { return _Ptr; } else { diff --git a/stl/inc/mutex b/stl/inc/mutex index 4d6ef1e0ea6..2dcf0352080 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -50,7 +50,7 @@ public: _Check_C_return(_Mtx_lock(_Mymtx())); } - _NODISCARD bool try_lock() { + _NODISCARD_TRY_CHANGE_STATE bool try_lock() { const auto _Res = _Mtx_trylock(_Mymtx()); switch (_Res) { case _Thrd_success: @@ -96,7 +96,7 @@ class recursive_mutex : public _Mutex_base { // class for recursive mutual exclu public: recursive_mutex() : _Mutex_base(_Mtx_recursive) {} - _NODISCARD bool try_lock() noexcept { + _NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept { return _Mutex_base::try_lock(); } @@ -128,27 +128,27 @@ public: unique_lock() noexcept : _Pmtx(nullptr), _Owns(false) {} - _NODISCARD_CTOR explicit unique_lock(_Mutex& _Mtx) + _NODISCARD_CTOR_LOCK explicit unique_lock(_Mutex& _Mtx) : _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // construct and lock _Pmtx->lock(); _Owns = true; } - _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, adopt_lock_t) + _NODISCARD_CTOR_LOCK unique_lock(_Mutex& _Mtx, adopt_lock_t) : _Pmtx(_STD addressof(_Mtx)), _Owns(true) {} // construct and assume already locked unique_lock(_Mutex& _Mtx, defer_lock_t) noexcept : _Pmtx(_STD addressof(_Mtx)), _Owns(false) {} // construct but don't lock - _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, try_to_lock_t) + _NODISCARD_CTOR_LOCK unique_lock(_Mutex& _Mtx, try_to_lock_t) : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock()) {} // construct and try to lock template - _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const chrono::duration<_Rep, _Period>& _Rel_time) + _NODISCARD_CTOR_LOCK unique_lock(_Mutex& _Mtx, const chrono::duration<_Rep, _Period>& _Rel_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_for(_Rel_time)) {} // construct and lock with timeout template - _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time) + _NODISCARD_CTOR_LOCK unique_lock(_Mutex& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(_Pmtx->try_lock_until(_Abs_time)) { // construct and lock with timeout #if _HAS_CXX20 @@ -156,12 +156,12 @@ public: #endif // _HAS_CXX20 } - _NODISCARD_CTOR unique_lock(_Mutex& _Mtx, const xtime* _Abs_time) + _NODISCARD_CTOR_LOCK unique_lock(_Mutex& _Mtx, const xtime* _Abs_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(false) { // try to lock until _Abs_time _Owns = _Pmtx->try_lock_until(_Abs_time); } - _NODISCARD_CTOR unique_lock(unique_lock&& _Other) noexcept : _Pmtx(_Other._Pmtx), _Owns(_Other._Owns) { + _NODISCARD_CTOR_LOCK unique_lock(unique_lock&& _Other) noexcept : _Pmtx(_Other._Pmtx), _Owns(_Other._Owns) { _Other._Pmtx = nullptr; _Other._Owns = false; } @@ -195,21 +195,21 @@ public: _Owns = true; } - _NODISCARD bool try_lock() { + _NODISCARD_TRY_CHANGE_STATE bool try_lock() { _Validate(); _Owns = _Pmtx->try_lock(); return _Owns; } template - _NODISCARD bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { _Validate(); _Owns = _Pmtx->try_lock_for(_Rel_time); return _Owns; } template - _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); #endif // _HAS_CXX20 @@ -218,7 +218,7 @@ public: return _Owns; } - _NODISCARD bool try_lock_until(const xtime* _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const xtime* _Abs_time) { _Validate(); _Owns = _Pmtx->try_lock_until(_Abs_time); return _Owns; @@ -347,7 +347,7 @@ int _Try_lock1(_Lock0& _Lk0, _Lock1& _Lk1) { } template -_NODISCARD int try_lock(_Lock0& _Lk0, _Lock1& _Lk1, _LockN&... _LkN) { // try to lock multiple locks +_NODISCARD_TRY_CHANGE_STATE int try_lock(_Lock0& _Lk0, _Lock1& _Lk1, _LockN&... _LkN) { // try to lock multiple locks return _Try_lock1(_Lk0, _Lk1, _LkN...); } @@ -419,7 +419,7 @@ void lock(_Lock0& _Lk0, _Lock1& _Lk1, _LockN&... _LkN) { // lock multiple locks, } template -class _NODISCARD lock_guard { // class with destructor that unlocks a mutex +class _NODISCARD_LOCK lock_guard { // class with destructor that unlocks a mutex public: using mutex_type = _Mutex; @@ -442,7 +442,7 @@ private: #if _HAS_CXX17 template -class _NODISCARD scoped_lock { // class with destructor that unlocks mutexes +class _NODISCARD_LOCK scoped_lock { // class with destructor that unlocks mutexes public: explicit scoped_lock(_Mutexes&... _Mtxes) : _MyMutexes(_Mtxes...) { // construct and lock _STD lock(_Mtxes...); @@ -462,7 +462,7 @@ private: }; template -class _NODISCARD scoped_lock<_Mutex> { +class _NODISCARD_LOCK scoped_lock<_Mutex> { public: using mutex_type = _Mutex; @@ -760,7 +760,7 @@ public: _My_locked = UINT_MAX; } - _NODISCARD bool try_lock() noexcept { // try to lock the mutex + _NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept { // try to lock the mutex lock_guard _Lock(_My_mutex); if (_My_locked != 0) { return false; @@ -780,7 +780,8 @@ public: } template - _NODISCARD bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock for duration + _NODISCARD_TRY_CHANGE_STATE bool try_lock_for( + const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock for duration return try_lock_until(_To_absolute_time(_Rel_time)); } @@ -796,7 +797,7 @@ public: } template - _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex with timeout #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); @@ -804,7 +805,7 @@ public: return _Try_lock_until(_Abs_time); } - _NODISCARD bool try_lock_until(const xtime* _Abs_time) { // try to lock the mutex with timeout + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const xtime* _Abs_time) { // try to lock the mutex with timeout return _Try_lock_until(_Abs_time); } @@ -842,7 +843,7 @@ public: } } - _NODISCARD bool try_lock() noexcept { // try to lock the mutex + _NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept { // try to lock the mutex const thread::id _Tid = this_thread::get_id(); lock_guard _Lock(_My_mutex); @@ -882,7 +883,8 @@ public: } template - _NODISCARD bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock for duration + _NODISCARD_TRY_CHANGE_STATE bool try_lock_for( + const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock for duration return try_lock_until(_To_absolute_time(_Rel_time)); } @@ -910,7 +912,7 @@ public: } template - _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex with timeout #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); @@ -918,7 +920,7 @@ public: return _Try_lock_until(_Abs_time); } - _NODISCARD bool try_lock_until(const xtime* _Abs_time) { // try to lock the mutex with timeout + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const xtime* _Abs_time) { // try to lock the mutex with timeout return _Try_lock_until(_Abs_time); } diff --git a/stl/inc/new b/stl/inc/new index 28d82a74ce1..da0f276cfda 100644 --- a/stl/inc/new +++ b/stl/inc/new @@ -28,7 +28,7 @@ inline constexpr destroying_delete_t destroying_delete{}; #if _HAS_CXX17 template -_NODISCARD constexpr _Ty* launder(_Ty* _Ptr) noexcept { +_NODISCARD_LAUNDER constexpr _Ty* launder(_Ty* _Ptr) noexcept { static_assert(!is_function_v<_Ty> && !is_void_v<_Ty>, "N4727 21.6.4 [ptr.launder]/3: The program is ill-formed if T is a function type or cv void."); return __builtin_launder(_Ptr); diff --git a/stl/inc/queue b/stl/inc/queue index 229c1ef1b54..ffa2955de20 100644 --- a/stl/inc/queue +++ b/stl/inc/queue @@ -87,7 +87,7 @@ public: #endif // __cpp_lib_concepts #endif // _HAS_CXX23 - _NODISCARD bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { + _NODISCARD_EMPTY_ADAPTOR_MEMBER bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { return c.empty(); } @@ -353,7 +353,7 @@ public: } #endif // _HAS_CXX23 && defined(__cpp_lib_concepts) - _NODISCARD bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { + _NODISCARD_EMPTY_ADAPTOR_MEMBER bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { return c.empty(); } diff --git a/stl/inc/scoped_allocator b/stl/inc/scoped_allocator index f9e73085c63..906b032287c 100644 --- a/stl/inc/scoped_allocator +++ b/stl/inc/scoped_allocator @@ -206,12 +206,12 @@ public: return static_cast(*this); } - _NODISCARD __declspec(allocator) pointer + _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) pointer allocate(_CRT_GUARDOVERFLOW size_type _Count) { // allocate array of _Count elements, ignore hint return _Outer_traits::allocate(outer_allocator(), _Count); } - _NODISCARD __declspec(allocator) pointer allocate( + _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) pointer allocate( _CRT_GUARDOVERFLOW size_type _Count, const_void_pointer _Hint) { // allocate array of _Count elements, with hint return _Outer_traits::allocate(outer_allocator(), _Count, _Hint); } diff --git a/stl/inc/semaphore b/stl/inc/semaphore index 78a8dd260d8..cea8b04d050 100644 --- a/stl/inc/semaphore +++ b/stl/inc/semaphore @@ -139,7 +139,7 @@ public: } } - _NODISCARD bool try_acquire() noexcept { + _NODISCARD_TRY_CHANGE_STATE bool try_acquire() noexcept { ptrdiff_t _Current = _Counter.load(); if (_Current == 0) { return false; @@ -152,7 +152,7 @@ public: } template - _NODISCARD bool try_acquire_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_acquire_for(const chrono::duration<_Rep, _Period>& _Rel_time) { auto _Deadline = _Semaphore_deadline(_Rel_time); ptrdiff_t _Current = _Counter.load(memory_order_relaxed); for (;;) { @@ -176,7 +176,7 @@ public: } template - _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); ptrdiff_t _Current = _Counter.load(memory_order_relaxed); for (;;) { @@ -245,7 +245,7 @@ public: } } - _NODISCARD bool try_acquire() noexcept { + _NODISCARD_TRY_CHANGE_STATE bool try_acquire() noexcept { // TRANSITION, GH-1133: should be memory_order_acquire unsigned char _Prev = _Counter.exchange(0); _STL_VERIFY((_Prev & ~1) == 0, "Invariant: semaphore counter is non-negative and doesn't exceed max(), " @@ -254,7 +254,7 @@ public: } template - _NODISCARD bool try_acquire_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_acquire_for(const chrono::duration<_Rep, _Period>& _Rel_time) { auto _Deadline = _Semaphore_deadline(_Rel_time); for (;;) { // "happens after release" ordering is provided by this exchange, so loads and waits can be relaxed @@ -274,7 +274,7 @@ public: } template - _NODISCARD bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_acquire_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); for (;;) { // "happens after release" ordering is provided by this exchange, so loads and waits can be relaxed diff --git a/stl/inc/shared_mutex b/stl/inc/shared_mutex index d1c213f3943..1ff40ea7eb1 100644 --- a/stl/inc/shared_mutex +++ b/stl/inc/shared_mutex @@ -40,7 +40,7 @@ public: _Smtx_lock_exclusive(&_Myhandle); } - _NODISCARD bool try_lock() noexcept /* strengthened */ { // try to lock exclusive + _NODISCARD_TRY_CHANGE_STATE bool try_lock() noexcept /* strengthened */ { // try to lock exclusive return _Smtx_try_lock_exclusive(&_Myhandle) != 0; } @@ -52,7 +52,7 @@ public: _Smtx_lock_shared(&_Myhandle); } - _NODISCARD bool try_lock_shared() noexcept /* strengthened */ { // try to lock non-exclusive + _NODISCARD_TRY_CHANGE_STATE bool try_lock_shared() noexcept /* strengthened */ { // try to lock non-exclusive return _Smtx_try_lock_shared(&_Myhandle) != 0; } @@ -97,7 +97,7 @@ public: } } - _NODISCARD bool try_lock() { // try to lock exclusive + _NODISCARD_TRY_CHANGE_STATE bool try_lock() { // try to lock exclusive lock_guard _Lock(_Mymtx); if (_Writing || 0 < _Readers) { return false; @@ -108,12 +108,13 @@ public: } template - _NODISCARD bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock for duration + _NODISCARD_TRY_CHANGE_STATE bool try_lock_for( + const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock for duration return try_lock_until(_To_absolute_time(_Rel_time)); } template - _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock until time point #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); @@ -157,7 +158,7 @@ public: ++_Readers; } - _NODISCARD bool try_lock_shared() { // try to lock non-exclusive + _NODISCARD_TRY_CHANGE_STATE bool try_lock_shared() { // try to lock non-exclusive lock_guard _Lock(_Mymtx); if (_Writing || _Readers == _Max_readers) { return false; @@ -168,7 +169,7 @@ public: } template - _NODISCARD bool try_lock_shared_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_shared_for(const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock non-exclusive for relative time return try_lock_shared_until(_To_absolute_time(_Rel_time)); } @@ -188,7 +189,7 @@ public: } template - _NODISCARD bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_shared_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock non-exclusive until absolute time #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); @@ -196,7 +197,8 @@ public: return _Try_lock_shared_until(_Abs_time); } - _NODISCARD bool try_lock_shared_until(const xtime* _Abs_time) { // try to lock non-exclusive until absolute time + _NODISCARD_TRY_CHANGE_STATE bool try_lock_shared_until( + const xtime* _Abs_time) { // try to lock non-exclusive until absolute time return _Try_lock_shared_until(_Abs_time); } @@ -237,7 +239,7 @@ public: shared_lock() noexcept : _Pmtx(nullptr), _Owns(false) {} - _NODISCARD_CTOR explicit shared_lock(mutex_type& _Mtx) + _NODISCARD_CTOR_LOCK explicit shared_lock(mutex_type& _Mtx) : _Pmtx(_STD addressof(_Mtx)), _Owns(true) { // construct with mutex and lock shared _Mtx.lock_shared(); } @@ -245,20 +247,20 @@ public: shared_lock(mutex_type& _Mtx, defer_lock_t) noexcept : _Pmtx(_STD addressof(_Mtx)), _Owns(false) {} // construct with unlocked mutex - _NODISCARD_CTOR shared_lock(mutex_type& _Mtx, try_to_lock_t) + _NODISCARD_CTOR_LOCK shared_lock(mutex_type& _Mtx, try_to_lock_t) : _Pmtx(_STD addressof(_Mtx)), _Owns(_Mtx.try_lock_shared()) {} // construct with mutex and try to lock shared - _NODISCARD_CTOR shared_lock(mutex_type& _Mtx, adopt_lock_t) + _NODISCARD_CTOR_LOCK shared_lock(mutex_type& _Mtx, adopt_lock_t) : _Pmtx(_STD addressof(_Mtx)), _Owns(true) {} // construct with mutex and adopt ownership template - _NODISCARD_CTOR shared_lock(mutex_type& _Mtx, const chrono::duration<_Rep, _Period>& _Rel_time) + _NODISCARD_CTOR_LOCK shared_lock(mutex_type& _Mtx, const chrono::duration<_Rep, _Period>& _Rel_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(_Mtx.try_lock_shared_for(_Rel_time)) { // construct with mutex and try to lock for relative time } template - _NODISCARD_CTOR shared_lock(mutex_type& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time) + _NODISCARD_CTOR_LOCK shared_lock(mutex_type& _Mtx, const chrono::time_point<_Clock, _Duration>& _Abs_time) : _Pmtx(_STD addressof(_Mtx)), _Owns(_Mtx.try_lock_shared_until(_Abs_time)) { // construct with mutex and try to lock until absolute time #if _HAS_CXX20 @@ -272,7 +274,7 @@ public: } } - _NODISCARD_CTOR shared_lock(shared_lock&& _Other) noexcept : _Pmtx(_Other._Pmtx), _Owns(_Other._Owns) { + _NODISCARD_CTOR_LOCK shared_lock(shared_lock&& _Other) noexcept : _Pmtx(_Other._Pmtx), _Owns(_Other._Owns) { _Other._Pmtx = nullptr; _Other._Owns = false; } @@ -298,14 +300,14 @@ public: _Owns = true; } - _NODISCARD bool try_lock() { // try to lock the mutex + _NODISCARD_TRY_CHANGE_STATE bool try_lock() { // try to lock the mutex _Validate(); _Owns = _Pmtx->try_lock_shared(); return _Owns; } template - _NODISCARD bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_for(const chrono::duration<_Rep, _Period>& _Rel_time) { // try to lock the mutex for _Rel_time _Validate(); _Owns = _Pmtx->try_lock_shared_for(_Rel_time); @@ -313,7 +315,7 @@ public: } template - _NODISCARD bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { + _NODISCARD_TRY_CHANGE_STATE bool try_lock_until(const chrono::time_point<_Clock, _Duration>& _Abs_time) { // try to lock the mutex until _Abs_time #if _HAS_CXX20 static_assert(chrono::is_clock_v<_Clock>, "Clock type required"); diff --git a/stl/inc/stack b/stl/inc/stack index 85bb24772b9..24d6afe6d9c 100644 --- a/stl/inc/stack +++ b/stl/inc/stack @@ -85,7 +85,7 @@ public: #endif // __cpp_lib_concepts #endif // _HAS_CXX23 - _NODISCARD bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { + _NODISCARD_EMPTY_ADAPTOR_MEMBER bool empty() const noexcept(noexcept(c.empty())) /* strengthened */ { return c.empty(); } diff --git a/stl/inc/stacktrace b/stl/inc/stacktrace index 43f765af56e..e693af7add7 100644 --- a/stl/inc/stacktrace +++ b/stl/inc/stacktrace @@ -232,7 +232,7 @@ public: return _Frames.crend(); } - _NODISCARD bool empty() const noexcept { + _NODISCARD_EMPTY_STACKTRACE_MEMBER bool empty() const noexcept { return _Frames.empty(); } diff --git a/stl/inc/thread b/stl/inc/thread index 23db3449276..72ed590631c 100644 --- a/stl/inc/thread +++ b/stl/inc/thread @@ -86,7 +86,7 @@ private: public: template , thread>, int> = 0> - _NODISCARD_CTOR explicit thread(_Fn&& _Fx, _Args&&... _Ax) { + _NODISCARD_CTOR_THREAD explicit thread(_Fn&& _Fx, _Args&&... _Ax) { _Start(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...); } @@ -295,7 +295,7 @@ public: jthread() noexcept : _Impl{}, _Ssource{nostopstate} {} template , jthread>, int> = 0> - _NODISCARD_CTOR explicit jthread(_Fn&& _Fx, _Args&&... _Ax) { + _NODISCARD_CTOR_JTHREAD explicit jthread(_Fn&& _Fx, _Args&&... _Ax) { if constexpr (is_invocable_v, stop_token, decay_t<_Args>...>) { _Impl._Start(_STD forward<_Fn>(_Fx), _Ssource.get_token(), _STD forward<_Args>(_Ax)...); } else { diff --git a/stl/inc/vector b/stl/inc/vector index 1cc9d835f8b..1d3062f6266 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1922,7 +1922,7 @@ public: return _Mypair._Myval2._Mylast; } - _NODISCARD _CONSTEXPR20 bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER _CONSTEXPR20 bool empty() const noexcept { auto& _My_data = _Mypair._Myval2; return _My_data._Myfirst == _My_data._Mylast; } @@ -3224,7 +3224,7 @@ public: return _Ints_max * _VBITS; } - _NODISCARD _CONSTEXPR20 bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER _CONSTEXPR20 bool empty() const noexcept { return this->_Mysize == 0; } diff --git a/stl/inc/xhash b/stl/inc/xhash index 9b58de3739a..4b36dd4989b 100644 --- a/stl/inc/xhash +++ b/stl/inc/xhash @@ -830,7 +830,7 @@ public: return _List.max_size(); } - _NODISCARD bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _List.empty(); } diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 62eeda578f8..266978943ae 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -542,12 +542,12 @@ struct _Normal_allocator_traits { // defines traits for allocators template using rebind_traits = allocator_traits>; - _NODISCARD static _CONSTEXPR20 __declspec(allocator) pointer + _NODISCARD_RAW_PTR_ALLOC static _CONSTEXPR20 __declspec(allocator) pointer allocate(_Alloc& _Al, _CRT_GUARDOVERFLOW const size_type _Count) { return _Al.allocate(_Count); } - _NODISCARD static _CONSTEXPR20 __declspec(allocator) pointer + _NODISCARD_RAW_PTR_ALLOC static _CONSTEXPR20 __declspec(allocator) pointer allocate(_Alloc& _Al, _CRT_GUARDOVERFLOW const size_type _Count, const const_void_pointer _Hint) { if constexpr (_Has_allocate_hint<_Alloc, size_type, const_void_pointer>::value) { return _Al.allocate(_Count, _Hint); @@ -628,7 +628,7 @@ struct _Default_allocator_traits { // traits for std::allocator template using rebind_traits = allocator_traits>; - _NODISCARD static _CONSTEXPR20 __declspec(allocator) pointer + _NODISCARD_RAW_PTR_ALLOC static _CONSTEXPR20 __declspec(allocator) pointer allocate(_Alloc& _Al, _CRT_GUARDOVERFLOW const size_type _Count) { #if _HAS_CXX20 // TRANSITION, GH-1532 if (_STD is_constant_evaluated()) { @@ -642,7 +642,7 @@ struct _Default_allocator_traits { // traits for std::allocator } } - _NODISCARD static _CONSTEXPR20 __declspec(allocator) pointer + _NODISCARD_RAW_PTR_ALLOC static _CONSTEXPR20 __declspec(allocator) pointer allocate(_Alloc& _Al, _CRT_GUARDOVERFLOW const size_type _Count, const_void_pointer) { #if _HAS_CXX20 // TRANSITION, GH-1532 if (_STD is_constant_evaluated()) { @@ -830,19 +830,20 @@ public: _Deallocate<_New_alignof<_Ty>>(_Ptr, sizeof(_Ty) * _Count); } - _NODISCARD _CONSTEXPR20 __declspec(allocator) _Ty* allocate(_CRT_GUARDOVERFLOW const size_t _Count) { + _NODISCARD_RAW_PTR_ALLOC _CONSTEXPR20 __declspec(allocator) _Ty* allocate(_CRT_GUARDOVERFLOW const size_t _Count) { static_assert(sizeof(value_type) > 0, "value_type must be complete before calling allocate."); return static_cast<_Ty*>(_Allocate<_New_alignof<_Ty>>(_Get_size_of_n(_Count))); } #if _HAS_CXX23 - _NODISCARD constexpr allocation_result<_Ty*> allocate_at_least(_CRT_GUARDOVERFLOW const size_t _Count) { + _NODISCARD_RAW_PTR_ALLOC constexpr allocation_result<_Ty*> allocate_at_least( + _CRT_GUARDOVERFLOW const size_t _Count) { return {allocate(_Count), _Count}; } #endif // _HAS_CXX23 #if _HAS_DEPRECATED_ALLOCATOR_MEMBERS - _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS _NODISCARD __declspec(allocator) _Ty* allocate( + _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) _Ty* allocate( _CRT_GUARDOVERFLOW const size_t _Count, const void*) { return allocate(_Count); } @@ -2033,7 +2034,7 @@ _NODISCARD constexpr bool _Allocators_equal(const _Alloc& _Lhs, const _Alloc& _R } template -_NODISCARD _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { +_NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { // remove each matching _Val _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); @@ -2054,7 +2055,7 @@ _NODISCARD _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _ } template -_NODISCARD _CONSTEXPR20 _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { +_NODISCARD_REMOVE_ALG _CONSTEXPR20 _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { // remove each satisfying _Pred _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); diff --git a/stl/inc/xpolymorphic_allocator.h b/stl/inc/xpolymorphic_allocator.h index d065085328e..278843e3ba5 100644 --- a/stl/inc/xpolymorphic_allocator.h +++ b/stl/inc/xpolymorphic_allocator.h @@ -130,7 +130,7 @@ namespace pmr { public: virtual ~memory_resource() noexcept = default; - _NODISCARD __declspec(allocator) void* allocate(_CRT_GUARDOVERFLOW const size_t _Bytes, + _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) void* allocate(_CRT_GUARDOVERFLOW const size_t _Bytes, const size_t _Align = alignof(max_align_t)) { // allocate _Bytes bytes of memory with alignment _Align _STL_ASSERT(_Is_pow_2(_Align), "memory_resource::allocate(): Alignment must be a power of two."); void* _Ptr = do_allocate(_Bytes, _Align); @@ -203,7 +203,7 @@ namespace pmr { polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; - _NODISCARD __declspec(allocator) _Ty* allocate(_CRT_GUARDOVERFLOW const size_t _Count) { + _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) _Ty* allocate(_CRT_GUARDOVERFLOW const size_t _Count) { // get space for _Count objects of type _Ty from _Resource void* const _Vp = _Resource->allocate(_Get_size_of_n(_Count), alignof(_Ty)); return static_cast<_Ty*>(_Vp); @@ -216,7 +216,7 @@ namespace pmr { } #if _HAS_CXX20 - _NODISCARD __declspec(allocator) void* allocate_bytes( + _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) void* allocate_bytes( const size_t _Bytes, const size_t _Align = alignof(max_align_t)) { return _Resource->allocate(_Bytes, _Align); } @@ -227,7 +227,8 @@ namespace pmr { } template - _NODISCARD __declspec(allocator) _Uty* allocate_object(_CRT_GUARDOVERFLOW const size_t _Count = 1) { + _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) _Uty* allocate_object( + _CRT_GUARDOVERFLOW const size_t _Count = 1) { void* const _Vp = allocate_bytes(_Get_size_of_n(_Count), alignof(_Uty)); return static_cast<_Uty*>(_Vp); } @@ -238,7 +239,7 @@ namespace pmr { } template - _NODISCARD __declspec(allocator) _Uty* new_object(_Types&&... _Args) { + _NODISCARD_RAW_PTR_ALLOC __declspec(allocator) _Uty* new_object(_Types&&... _Args) { _Uty* const _Ptr = allocate_object<_Uty>(); _TRY_BEGIN construct(_Ptr, _STD forward<_Types>(_Args)...); diff --git a/stl/inc/xstring b/stl/inc/xstring index 2a91996e6d9..715b2437e94 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -4317,7 +4317,7 @@ public: } #endif // _HAS_CXX20 - _NODISCARD _CONSTEXPR20 bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER _CONSTEXPR20 bool empty() const noexcept { return _Mypair._Myval2._Mysize == 0; } diff --git a/stl/inc/xtree b/stl/inc/xtree index b43e6bbd16a..6c6767e0c00 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -1198,7 +1198,7 @@ public: static_cast((numeric_limits::max)()), _Alnode_traits::max_size(_Getal())); } - _NODISCARD bool empty() const noexcept { + _NODISCARD_EMPTY_MEMBER bool empty() const noexcept { return _Get_scary()->_Mysize == 0; } diff --git a/stl/inc/xutility b/stl/inc/xutility index 86e212dc222..02daef1538c 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1649,18 +1649,19 @@ _NODISCARD constexpr ptrdiff_t ssize(const _Ty (&)[_Size]) noexcept { #endif // _HAS_CXX20 template -_NODISCARD constexpr auto empty(const _Container& _Cont) noexcept(noexcept(_Cont.empty())) /* strengthened */ +_NODISCARD_EMPTY_NON_MEMBER constexpr auto empty(const _Container& _Cont) noexcept( + noexcept(_Cont.empty())) /* strengthened */ -> decltype(_Cont.empty()) { return _Cont.empty(); } template -_NODISCARD constexpr bool empty(const _Ty (&)[_Size]) noexcept { +_NODISCARD_EMPTY_NON_MEMBER constexpr bool empty(const _Ty (&)[_Size]) noexcept { return false; } template -_NODISCARD constexpr bool empty(initializer_list<_Elem> _Ilist) noexcept { +_NODISCARD_EMPTY_NON_MEMBER constexpr bool empty(initializer_list<_Elem> _Ilist) noexcept { return _Ilist.size() == 0; } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 213263eced5..313a9d0a791 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -474,12 +474,26 @@ // _HAS_NODISCARD (in vcruntime.h) controls: // [[nodiscard]] attributes on STL functions +// TRANSITION, This should go to vcruntime.h +#ifndef __has_cpp_attribute +#define _NODISCARD_MSG(_Msg) +#elif __has_cpp_attribute(nodiscard) >= 201907L +#define _NODISCARD_MSG(_Msg) [[nodiscard(_Msg)]] +#elif __has_cpp_attribute(nodiscard) >= 201603L +#define _NODISCARD_MSG(_Msg) [[nodiscard]] +#else +#define _NODISCARD_MSG(_Msg) +#endif + #ifndef __has_cpp_attribute #define _NODISCARD_CTOR +#define _NODISCARD_CTOR_MSG(_Msg) #elif __has_cpp_attribute(nodiscard) >= 201907L -#define _NODISCARD_CTOR _NODISCARD +#define _NODISCARD_CTOR _NODISCARD +#define _NODISCARD_CTOR_MSG(_Msg) _NODISCARD_MSG(_Msg) #else #define _NODISCARD_CTOR +#define _NODISCARD_CTOR_MSG(_Msg) #endif #if defined(__CUDACC__) && !defined(__clang__) // TRANSITION, VSO-568006 @@ -488,6 +502,110 @@ #define _NODISCARD_FRIEND _NODISCARD friend #endif // TRANSITION, VSO-568006 +#define _NODISCARD_REMOVE_ALG \ + _NODISCARD_MSG("The 'remove' and 'remove_if' algorithms return the iterator past the last element " \ + "that should be kept. You need to call container.erase(result, container.end()) afterwards. " \ + "In C++20, 'std::erase' and 'std::erase_if' are simpler replacements for these two steps.") + +#define _NODISCARD_UNIQUE_ALG \ + _NODISCARD_MSG("The 'unique' algorithm returns the iterator past the last element that should be kept. " \ + "You need to call container.erase(result, container.end()) afterwards.") + +#define _NODISCARD_EMPTY_MEMBER \ + _NODISCARD_MSG( \ + "This member function returns a bool indicating whether the container is empty and has no other effects. " \ + "It is not useful to call this member function and discard the return value. " \ + "Use the 'clear()' member function if you want to erase all elements.") + +#define _NODISCARD_EMPTY_ARRAY_MEMBER \ + _NODISCARD_MSG( \ + "This member function returns a bool indicating whether the container is empty and has no other effects. " \ + "It is not useful to call this member function and discard the return value. " \ + "There's no way to clear an array as its size is fixed.") + +#define _NODISCARD_EMPTY_STACKTRACE_MEMBER \ + _NODISCARD_MSG( \ + "This member function returns a bool indicating whether the container is empty and has no other effects. " \ + "It is not useful to call this member function and discard the return value. " \ + "'std::stacktrace' can be cleared by assigning an empty value to it.") + +#define _NODISCARD_EMPTY_NON_MEMBER \ + _NODISCARD_MSG( \ + "This function returns a bool indicating whether the container or container-like object is empty and " \ + "has no other effects. It is not useful to call this function and discard the return value.") + +#define _NODISCARD_EMPTY_ADAPTOR_MEMBER \ + _NODISCARD_MSG( \ + "This member function returns a bool indicating whether the container is empty and has no other effects. " \ + "It is not useful to call this member function and discard the return value. " \ + "Container adaptors don't provide 'clear()' member functions, but you can assign an empty object to them.") + +#define _NODISCARD_BARRIER_TOKEN \ + _NODISCARD_MSG("The token from 'arrive()' should not be discarded; it should be passed to 'wait()'.") + +#define _NODISCARD_TRY_WAIT \ + _NODISCARD_MSG( \ + "This member function returns the state of the synchronization object and does not do anything else; " \ + "it is not useful to call this member function and discard the return value.") + +#define _NODISCARD_TRY_CHANGE_STATE \ + _NODISCARD_MSG("This function returns whether the operation succeeded in modifying object state. " \ + "It is dangerous to ignore the return value.") + +#define _NODISCARD_SMART_PTR_ALLOC \ + _NODISCARD_MSG("This function constructs an object wrapped by a smart pointer and has no other effects; " \ + "it is not useful to call this function and discard the return value.") + +#define _NODISCARD_RAW_PTR_ALLOC \ + _NODISCARD_MSG("This function allocates memory and returns a raw pointer. " \ + "Discarding the return value will cause a memory leak.") + +#define _NODISCARD_ASSUME_ALIGNED \ + _NODISCARD_MSG("'std::assume_aligned' has a potential effect on the return value (not on the passed argument). " \ + "It is not useful to call 'std::assume_aligned' and discard the return value.") + +#define _NODISCARD_LAUNDER \ + _NODISCARD_MSG("'std::launder' has a potential effect on the return value (not on the passed argument). " \ + "It is not useful to call 'std::launder' and discard the return value.") + +#ifdef _SILENCE_NODISCARD_LOCK_WARNINGS + +#define _NODISCARD_LOCK +#define _NODISCARD_CTOR_LOCK + +#else // ^^^ defined(_SILENCE_NODISCARD_LOCK_WARNINGS) ^^^ / vvv !defined(_SILENCE_NODISCARD_LOCK_WARNINGS) vvv + +#define _NODISCARD_LOCK \ + _NODISCARD_MSG("A lock should be stored in a variable to protect the scope. If you're intentionally constructing " \ + "a temporary to protect the rest of the current expression using the comma operator, you can cast " \ + "the temporary to void or define _SILENCE_NODISCARD_LOCK_WARNINGS to suppress this warning.") + +#define _NODISCARD_CTOR_LOCK \ + _NODISCARD_CTOR_MSG( \ + "A lock should be stored in a variable to protect the scope. If you're intentionally constructing " \ + "a temporary to protect the rest of the current expression using the comma operator, you can cast " \ + "the temporary to void or define _SILENCE_NODISCARD_LOCK_WARNINGS to suppress this warning.") + +#endif // ^^^ !defined(_SILENCE_NODISCARD_LOCK_WARNINGS) ^^^ + +#define _NODISCARD_CTOR_THREAD \ + _NODISCARD_CTOR_MSG("This temporary 'std::thread' is not joined or detached, " \ + "so 'std::terminate' will be called at the end of the statement.") + +#define _NODISCARD_CTOR_JTHREAD \ + _NODISCARD_CTOR_MSG("This temporary 'std::jthread' is implicitly joined at the end of the statement. " \ + "If this is intentional, you can add '.join()' to suppress this warning. " \ + "Otherwise, this 'std::jthread' should be stored in a variable.") + +#define _NODISCARD_ASYNC \ + _NODISCARD_MSG("The result of 'std::async' should be stored in a variable. If the return value is discarded, " \ + "the temporary 'std::future' is destroyed, waiting for an async result or evaluating " \ + "a deferred result, thus defeating the purpose of 'std::async'.") + +#define _NODISCARD_GET_FUTURE \ + _NODISCARD_MSG("Getting the future more than once or not satisfying the obtained future will throw a " \ + "future_error exception, so it is incorrect to call 'get_future' and discard the return value.") + #pragma push_macro("msvc") #pragma push_macro("known_semantics") #pragma push_macro("noop_dtor")