diff --git a/docs/import_library.md b/docs/import_library.md index 124b8f3016c..b4951bbba5a 100644 --- a/docs/import_library.md +++ b/docs/import_library.md @@ -41,7 +41,7 @@ The caveats of this technique are: + This limitation is subtle (not readily apparent from the source code) and critical. If shared global state is necessary, our only option while preserving bincompat is adding a satellite DLL. * Due to having just two flavors of the import library (debug and release), - we cannot use anything that depends on `_CONTAINER_DEBUG_LEVEL` or `_ITERATOR_DEBUG_LEVEL`. + we cannot use anything that depends on `_ITERATOR_DEBUG_LEVEL`. For these reasons, especially the last one, we need to strictly control what is used by the import library. In particular, `basic_string` must not be used there. diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index 9b4595db7a3..5d1989e5a66 100644 --- a/stl/inc/__msvc_ranges_tuple_formatter.hpp +++ b/stl/inc/__msvc_ranges_tuple_formatter.hpp @@ -324,7 +324,7 @@ class basic_format_arg { case _Basic_format_arg_type::_Custom_type: return _STD forward<_Visitor>(_Vis)(_Custom_state); default: - _STL_VERIFY(false, "basic_format_arg is in impossible state"); + _STL_REPORT_ERROR("basic_format_arg contains an impossible type"); int _Dummy{}; return _STD forward<_Visitor>(_Vis)(_Dummy); } diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 14198cbdf6b..5e973ade480 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -1381,7 +1381,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer : _Mydata(_Cts), _Mysize(_Count) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count == 0 || _Cts, "non-zero size null string_view"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } #if _HAS_CXX20 @@ -1476,7 +1476,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer _NODISCARD constexpr const_reference operator[](const size_type _Off) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < _Mysize, "string_view subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // CodeQL [SM01954] This index is optionally validated above. return _Mydata[_Off]; @@ -1490,30 +1490,30 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer _NODISCARD constexpr const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mysize != 0, "cannot call front on empty string_view"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mysize != 0, "front() called on empty string_view"); +#endif return _Mydata[0]; } _NODISCARD constexpr const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mysize != 0, "cannot call back on empty string_view"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mysize != 0, "back() called on empty string_view"); +#endif return _Mydata[_Mysize - 1]; } constexpr void remove_prefix(const size_type _Count) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mysize >= _Count, "cannot remove prefix longer than total size"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mysize >= _Count, "cannot remove_prefix() larger than string_view size"); +#endif _Mydata += _Count; _Mysize -= _Count; } constexpr void remove_suffix(const size_type _Count) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mysize >= _Count, "cannot remove suffix longer than total size"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mysize >= _Count, "cannot remove_suffix() larger than string_view size"); +#endif _Mysize -= _Count; } diff --git a/stl/inc/algorithm b/stl/inc/algorithm index ef3fa2e1f54..0bfef44a07b 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -7157,9 +7157,7 @@ _CONSTEXPR20 void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred) { // order h const auto _ULast = _STD _Get_unwrapped(_Last); #if _ITERATOR_DEBUG_LEVEL == 2 const auto _Counterexample = _STD _Is_heap_until_unchecked(_UFirst, _ULast, _STD _Pass_fn(_Pred)); - if (_Counterexample != _ULast) { - _STL_REPORT_ERROR("invalid heap in sort_heap()"); - } + _STL_VERIFY(_Counterexample == _ULast, "invalid heap in sort_heap()"); #endif // _ITERATOR_DEBUG_LEVEL == 2 _STD _Sort_heap_unchecked(_UFirst, _ULast, _STD _Pass_fn(_Pred)); } diff --git a/stl/inc/array b/stl/inc/array index b8eef281ba1..77bf40f14f1 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -533,7 +533,7 @@ public: _NODISCARD _CONSTEXPR17 reference operator[](_In_range_(<, _Size) size_type _Pos) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Size, "array subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Elems[_Pos]; } @@ -542,7 +542,7 @@ public: /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Size, "array subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Elems[_Pos]; } @@ -708,48 +708,48 @@ public: _NODISCARD reference operator[](size_type) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_REPORT_ERROR("array subscript is invalid"); +#endif return *data(); } _NODISCARD const_reference operator[](size_type) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_REPORT_ERROR("array subscript is invalid"); +#endif return *data(); } _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::front() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_REPORT_ERROR("array::front() is invalid"); +#endif return *data(); } _NODISCARD const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::front() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_REPORT_ERROR("array::front() is invalid"); +#endif return *data(); } _NODISCARD reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::back() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_REPORT_ERROR("array::back() is invalid"); +#endif return *data(); } _NODISCARD const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::back() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_REPORT_ERROR("array::back() is invalid"); +#endif return *data(); } diff --git a/stl/inc/atomic b/stl/inc/atomic index e69bb281481..000559221f9 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -134,55 +134,21 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 #define _ATOMIC_LOAD_ARM64(_Result, _Width, _Ptr, _Order_var) \ - switch (_Order_var) { \ - case _Atomic_memory_order_relaxed: \ + _Check_load_memory_order(_Order_var); \ + if (_Order_var == memory_order_relaxed) { \ _Result = __iso_volatile_load##_Width(_Ptr); \ - break; \ - case _Atomic_memory_order_consume: \ - case _Atomic_memory_order_acquire: \ - case _Atomic_memory_order_seq_cst: \ + } else { \ _Result = __LOAD_ACQUIRE_ARM64(_Width, _Ptr); \ _Compiler_barrier(); \ - break; \ - case _Atomic_memory_order_release: \ - case _Atomic_memory_order_acq_rel: \ - default: \ - _Result = __iso_volatile_load##_Width(_Ptr); \ - _INVALID_MEMORY_ORDER; \ - break; \ } #endif // _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 #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: \ + _Check_load_memory_order(_Order_var); \ + if (_Order_var != memory_order_relaxed) { \ _Compiler_or_memory_barrier(); \ - break; \ - case _Atomic_memory_order_release: \ - case _Atomic_memory_order_acq_rel: \ - default: \ - _INVALID_MEMORY_ORDER; \ - break; \ - } - -#define _ATOMIC_STORE_PREFIX(_Width, _Ptr, _Desired) \ - case _Atomic_memory_order_relaxed: \ - __iso_volatile_store##_Width((_Ptr), (_Desired)); \ - return; \ - case _Atomic_memory_order_release: \ - __STORE_RELEASE(_Width, _Ptr, _Desired); \ - return; \ - default: \ - case _Atomic_memory_order_consume: \ - case _Atomic_memory_order_acquire: \ - case _Atomic_memory_order_acq_rel: \ - _INVALID_MEMORY_ORDER; \ - _FALLTHROUGH; + } #define _ATOMIC_STORE_SEQ_CST_ARM(_Width, _Ptr, _Desired) \ _Memory_barrier(); \ @@ -731,11 +697,15 @@ struct _Atomic_storage<_Ty, 1> { // lock-free using 1-byte intrinsics void store(const _TVal _Value, const memory_order _Order) noexcept { // store with given memory order const auto _Mem = _STD _Atomic_address_as(_Storage); const char _As_bytes = _STD _Atomic_reinterpret_as(_Value); - switch (static_cast(_Order)) { - _ATOMIC_STORE_PREFIX(8, _Mem, _As_bytes) - case _Atomic_memory_order_seq_cst: + + _Check_store_memory_order(_Order); + + if (_Order == memory_order_relaxed) { + __iso_volatile_store8(_Mem, _As_bytes); + } else if (_Order == memory_order_release) { + __STORE_RELEASE(8, _Mem, _As_bytes); + } else { store(_Value); - return; } } @@ -744,10 +714,10 @@ struct _Atomic_storage<_Ty, 1> { // lock-free using 1-byte intrinsics const auto _Mem = _STD _Atomic_address_as(_Storage); char _As_bytes; #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 - _ATOMIC_LOAD_ARM64(_As_bytes, 8, _Mem, static_cast(_Order)) + _ATOMIC_LOAD_ARM64(_As_bytes, 8, _Mem, _Order) #else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv _As_bytes = __iso_volatile_load8(_Mem); - _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(_Order) #endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -834,11 +804,15 @@ struct _Atomic_storage<_Ty, 2> { // lock-free using 2-byte intrinsics void store(const _TVal _Value, const memory_order _Order) noexcept { // store with given memory order const auto _Mem = _STD _Atomic_address_as(_Storage); const short _As_bytes = _STD _Atomic_reinterpret_as(_Value); - switch (static_cast(_Order)) { - _ATOMIC_STORE_PREFIX(16, _Mem, _As_bytes) - case _Atomic_memory_order_seq_cst: + + _Check_store_memory_order(_Order); + + if (_Order == memory_order_relaxed) { + __iso_volatile_store16(_Mem, _As_bytes); + } else if (_Order == memory_order_release) { + __STORE_RELEASE(16, _Mem, _As_bytes); + } else { store(_Value); - return; } } @@ -847,10 +821,10 @@ struct _Atomic_storage<_Ty, 2> { // lock-free using 2-byte intrinsics const auto _Mem = _STD _Atomic_address_as(_Storage); short _As_bytes; #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 - _ATOMIC_LOAD_ARM64(_As_bytes, 16, _Mem, static_cast(_Order)) + _ATOMIC_LOAD_ARM64(_As_bytes, 16, _Mem, _Order) #else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv _As_bytes = __iso_volatile_load16(_Mem); - _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(_Order) #endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -936,11 +910,15 @@ struct _Atomic_storage<_Ty, 4> { // lock-free using 4-byte intrinsics void store(const _TVal _Value, const memory_order _Order) noexcept { // store with given memory order const auto _Mem = _STD _Atomic_address_as(_Storage); const int _As_bytes = _STD _Atomic_reinterpret_as(_Value); - switch (static_cast(_Order)) { - _ATOMIC_STORE_PREFIX(32, _Mem, _As_bytes) - case _Atomic_memory_order_seq_cst: + + _Check_store_memory_order(_Order); + + if (_Order == memory_order_relaxed) { + __iso_volatile_store32(_Mem, _As_bytes); + } else if (_Order == memory_order_release) { + __STORE_RELEASE(32, _Mem, _As_bytes); + } else { store(_Value); - return; } } @@ -949,10 +927,10 @@ struct _Atomic_storage<_Ty, 4> { // lock-free using 4-byte intrinsics const auto _Mem = _STD _Atomic_address_as(_Storage); int _As_bytes; #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 - _ATOMIC_LOAD_ARM64(_As_bytes, 32, _Mem, static_cast(_Order)) + _ATOMIC_LOAD_ARM64(_As_bytes, 32, _Mem, _Order) #else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 vvv _As_bytes = __iso_volatile_load32(_Mem); - _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(_Order) #endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 0 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -1038,11 +1016,15 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics void store(const _TVal _Value, const memory_order _Order) noexcept { // store with given memory order const auto _Mem = _STD _Atomic_address_as(_Storage); const long long _As_bytes = _STD _Atomic_reinterpret_as(_Value); - switch (static_cast(_Order)) { - _ATOMIC_STORE_PREFIX(64, _Mem, _As_bytes) - case _Atomic_memory_order_seq_cst: + + _Check_store_memory_order(_Order); + + if (_Order == memory_order_relaxed) { + __iso_volatile_store64(_Mem, _As_bytes); + } else if (_Order == memory_order_release) { + __STORE_RELEASE(64, _Mem, _As_bytes); + } else { store(_Value); - return; } } @@ -1051,7 +1033,7 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics const auto _Mem = _STD _Atomic_address_as(_Storage); long long _As_bytes; #if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 - _ATOMIC_LOAD_ARM64(_As_bytes, 64, _Mem, static_cast(_Order)) + _ATOMIC_LOAD_ARM64(_As_bytes, 64, _Mem, _Order) #else // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1 / _STD_ATOMIC_USE_ARM64_LDAR_STLR != 1 vvv #ifdef _M_ARM @@ -1060,7 +1042,7 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics _As_bytes = __iso_volatile_load64(_Mem); #endif - _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(static_cast(_Order)) + _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED(_Order) #endif // ^^^ _STD_ATOMIC_USE_ARM64_LDAR_STLR != 1 ^^^ return reinterpret_cast<_TVal&>(_As_bytes); } @@ -1180,9 +1162,9 @@ struct _Atomic_storage<_Ty&, 16> { // lock-free using 16-byte intrinsics case memory_order_acquire: (void) _INTRIN_ACQUIRE(_InterlockedCompareExchange128)(_Storage_ptr, 0, 0, &_Result._Low); break; - default: case memory_order_release: case memory_order_acq_rel: + default: _INVALID_MEMORY_ORDER; _FALLTHROUGH; case memory_order_seq_cst: @@ -2328,7 +2310,8 @@ public: explicit atomic_ref(_Ty& _Value) noexcept /* strengthened */ : _Base(_Value) { if constexpr (is_always_lock_free) { - _Check_alignment(_Value); + _STL_ASSERT((reinterpret_cast(_STD addressof(_Value)) & (required_alignment - 1)) == 0, + "atomic_ref underlying object is not aligned as required_alignment"); } else { this->_Init_spinlock_for_ref(); } @@ -2436,13 +2419,6 @@ public: { const_cast(this)->_Base::notify_all(); } - -private: - static void _Check_alignment([[maybe_unused]] const _Ty& _Value) { - _ATOMIC_REF_CHECK_ALIGNMENT( - (reinterpret_cast(_STD addressof(_Value)) & (required_alignment - 1)) == 0, - "atomic_ref underlying object is not aligned as required_alignment"); - } }; #endif // _HAS_CXX20 @@ -3042,7 +3018,6 @@ _STD_END #undef _ATOMIC_CHOOSE_INTRINSIC #undef _ATOMIC_POST_LOAD_BARRIER_AS_NEEDED -#undef _ATOMIC_STORE_PREFIX #undef _ATOMIC_STORE_SEQ_CST_ARM #undef _ATOMIC_STORE_SEQ_CST_X86_X64 #undef _ATOMIC_STORE_32_SEQ_CST_X86_X64 diff --git a/stl/inc/bitset b/stl/inc/bitset index b6e493d957c..7374ea0676b 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -120,7 +120,7 @@ private: #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Pos; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv - _STL_VERIFY(_Pos < _Bits, "bitset index outside range"); + _STL_VERIFY(_Pos < _Bits, "bitset subscript out of range"); #endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ } @@ -132,7 +132,7 @@ private: static constexpr unsigned long long _Mask = (1ULL << (_Need_mask ? _Bits : 0)) - 1ULL; public: - _NODISCARD constexpr bool operator[](size_t _Pos) const noexcept /* strengthened */ { + _NODISCARD constexpr bool operator[](const size_t _Pos) const noexcept /* strengthened */ { _Validate(_Pos); return _Subscript(_Pos); } diff --git a/stl/inc/chrono b/stl/inc/chrono index c017d6b5068..b71235f710d 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1608,8 +1608,11 @@ namespace chrono { // Returns the number of fractional digits of _Num / _Den in the range [0, 18]. // If it can't be represented, 6 is returned. // Example: _Fractional_width(1, 8) would return 3 for 0.125. - auto _Den = _Duration::period::den; - _STL_ASSERT(_Duration::period::num > 0 && _Den > 0, "Numerator and denominator can't be less than 1."); + + _STL_INTERNAL_STATIC_ASSERT(_Duration::period::num > 0); // N5001 [time.duration.general]/3 + _STL_INTERNAL_STATIC_ASSERT(_Duration::period::den > 0); // N5001 [ratio.ratio]/1, /2.2 + + auto _Den = _Duration::period::den; unsigned int _Power_of_2_in_den = 0u; unsigned int _Power_of_5_in_den = 0u; for (; _Den % 2 == 0; _Den /= 2, ++_Power_of_2_in_den) { diff --git a/stl/inc/deque b/stl/inc/deque index 9bba528c614..cab1a2a804e 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1065,7 +1065,7 @@ public: _NODISCARD const_reference operator[](size_type _Pos) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Subscript(_Pos); } @@ -1073,7 +1073,7 @@ public: _NODISCARD reference operator[](size_type _Pos) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Subscript(_Pos); } @@ -1097,7 +1097,7 @@ public: _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "front() called on empty deque"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Subscript(0); } @@ -1105,7 +1105,7 @@ public: _NODISCARD const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "front() called on empty deque"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Subscript(0); } @@ -1113,7 +1113,7 @@ public: _NODISCARD reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "back() called on empty deque"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Subscript(_Mysize() - 1); } @@ -1121,7 +1121,7 @@ public: _NODISCARD const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!empty(), "back() called on empty deque"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Subscript(_Mysize() - 1); } @@ -1475,7 +1475,7 @@ public: void pop_front() noexcept /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL == 2 if (empty()) { - _STL_REPORT_ERROR("deque empty before pop"); + _STL_REPORT_ERROR("pop_front() called on empty deque"); } else { // something to erase, do it _Orphan_off(_Myoff()); _Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Myoff())); @@ -1498,7 +1498,7 @@ public: void pop_back() noexcept /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL == 2 if (empty()) { - _STL_REPORT_ERROR("deque empty before pop"); + _STL_REPORT_ERROR("pop_back() called on empty deque"); } else { // something to erase, do it size_type _Newoff = _Myoff() + _Mysize() - 1; _Orphan_off(_Newoff); @@ -1528,14 +1528,14 @@ public: #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_First <= _Last && begin() <= _First && _Last <= end(), "deque erase iterator outside range"); _STD _Adl_verify_range(_First, _Last); +#endif auto _Off = static_cast(_First - begin()); auto _Count = static_cast(_Last - _First); - bool _Moved = _Off > 0 && _Off + _Count < _Mysize(); -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv - auto _Off = static_cast(_First - begin()); - auto _Count = static_cast(_Last - _First); -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ + +#if _ITERATOR_DEBUG_LEVEL == 2 + const bool _Moved = _Off > 0 && _Off + _Count < _Mysize(); +#endif if (_Count == 0) { return _First; diff --git a/stl/inc/expected b/stl/inc/expected index f27e3fc7007..45eb51a5fb6 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -621,39 +621,39 @@ public: // [expected.object.obs] _NODISCARD constexpr const _Ty* operator->() const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Has_value, "operator->() called on a std::expected that contains an error, not a value"); +#endif return _STD addressof(_Value); } _NODISCARD constexpr _Ty* operator->() noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Has_value, "operator->() called on a std::expected that contains an error, not a value"); +#endif return _STD addressof(_Value); } _NODISCARD constexpr const _Ty& operator*() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); +#endif return _Value; } _NODISCARD constexpr _Ty& operator*() & noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); +#endif return _Value; } _NODISCARD constexpr const _Ty&& operator*() const&& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); +#endif return _STD move(_Value); } _NODISCARD constexpr _Ty&& operator*() && noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); +#endif return _STD move(_Value); } @@ -707,26 +707,26 @@ public: _NODISCARD constexpr const _Err& error() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _Unexpected; } _NODISCARD constexpr _Err& error() & noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _Unexpected; } _NODISCARD constexpr const _Err&& error() const&& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _STD move(_Unexpected); } _NODISCARD constexpr _Err&& error() && noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _STD move(_Unexpected); } @@ -1469,8 +1469,8 @@ public: constexpr void operator*() const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); +#endif } constexpr void value() const& { @@ -1490,26 +1490,26 @@ public: _NODISCARD constexpr const _Err& error() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _Unexpected; } _NODISCARD constexpr _Err& error() & noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _Unexpected; } _NODISCARD constexpr const _Err&& error() const&& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _STD move(_Unexpected); } _NODISCARD constexpr _Err&& error() && noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); +#endif return _STD move(_Unexpected); } diff --git a/stl/inc/format b/stl/inc/format index 53b960dbdd6..74bda572cef 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -2698,7 +2698,7 @@ struct _Arg_formatter { _Basic_format_specs<_CharT>* _Specs = nullptr; _OutputIt operator()(basic_format_arg<_Context>::handle) { - _STL_VERIFY(false, "The custom handler should be structurally unreachable for _Arg_formatter"); + _STL_REPORT_ERROR("The custom handler should be structurally unreachable for _Arg_formatter"); _STL_INTERNAL_CHECK(_Ctx); return _Ctx->out(); } diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 0d556e5639a..3e801e48e23 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -131,7 +131,7 @@ public: _NODISCARD reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 const auto _Mycont = static_cast(this->_Getcont()); - _STL_ASSERT(_Mycont, "cannot dereference value-initialized forward_list iterator"); + _STL_VERIFY(_Mycont, "cannot dereference value-initialized forward_list iterator"); _STL_VERIFY(this->_Ptr != _Mycont->_Before_head(), "cannot dereference forward_list before_begin"); #endif // _ITERATOR_DEBUG_LEVEL == 2 @@ -902,7 +902,7 @@ public: _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Myhead != nullptr, "front() called on empty forward_list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myhead->_Myval; } @@ -910,7 +910,7 @@ public: _NODISCARD const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Myhead != nullptr, "front() called on empty forward_list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myhead->_Myval; } diff --git a/stl/inc/generator b/stl/inc/generator index 524b9a22687..09c16afc339 100644 --- a/stl/inc/generator +++ b/stl/inc/generator @@ -479,14 +479,14 @@ namespace _Gen_detail { noexcept(noexcept(static_cast<_Ref>(*_Coro.promise()._Get_top().promise()._Ptr))) /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!_Coro.done(), "Can't dereference generator end iterator"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return static_cast<_Ref>(*_Coro.promise()._Get_top().promise()._Ptr); } _Iterator& operator++() { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(!_Coro.done(), "Can't increment generator end iterator"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif _Coro.promise()._Get_top().resume(); return *this; } @@ -567,7 +567,7 @@ public: // Pre: _Coro is suspended at its initial suspend point #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Coro, "Can't call begin on moved-from generator"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif _Coro.resume(); return typename _Gen_detail::_Iter_provider<_Value, _Ref>::_Iterator{_Gen_detail::_Secret_tag{}, coroutine_handle<_Gen_detail::_Promise_base>::from_address(_Coro.address())}; diff --git a/stl/inc/list b/stl/inc/list index 58d87142ffe..fc5093dca87 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -143,7 +143,7 @@ public: _NODISCARD reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 const auto _Mycont = static_cast(this->_Getcont()); - _STL_ASSERT(_Mycont, "cannot dereference value-initialized list iterator"); + _STL_VERIFY(_Mycont, "cannot dereference value-initialized list iterator"); _STL_VERIFY(this->_Ptr != _Mycont->_Myhead, "cannot dereference end list iterator"); #endif // _ITERATOR_DEBUG_LEVEL == 2 @@ -157,7 +157,7 @@ public: _List_const_iterator& operator++() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 const auto _Mycont = static_cast(this->_Getcont()); - _STL_ASSERT(_Mycont, "cannot increment value-initialized list iterator"); + _STL_VERIFY(_Mycont, "cannot increment value-initialized list iterator"); _STL_VERIFY(this->_Ptr != _Mycont->_Myhead, "cannot increment end list iterator"); #endif // _ITERATOR_DEBUG_LEVEL == 2 @@ -175,7 +175,7 @@ public: const auto _New_ptr = this->_Ptr->_Prev; #if _ITERATOR_DEBUG_LEVEL == 2 const auto _Mycont = static_cast(this->_Getcont()); - _STL_ASSERT(_Mycont, "cannot decrement value-initialized list iterator"); + _STL_VERIFY(_Mycont, "cannot decrement value-initialized list iterator"); _STL_VERIFY(_New_ptr != _Mycont->_Myhead, "cannot decrement begin list iterator"); #endif // _ITERATOR_DEBUG_LEVEL == 2 @@ -1210,7 +1210,7 @@ public: _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myhead->_Next->_Myval; } @@ -1218,7 +1218,7 @@ public: _NODISCARD const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myhead->_Next->_Myval; } @@ -1226,7 +1226,7 @@ public: _NODISCARD reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myhead->_Prev->_Myval; } @@ -1234,7 +1234,7 @@ public: _NODISCARD const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myhead->_Prev->_Myval; } @@ -1254,8 +1254,8 @@ public: void pop_front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_front called on empty list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_front() called on empty list"); +#endif _Unchecked_erase(_Mypair._Myval2._Myhead->_Next); } @@ -1275,8 +1275,8 @@ public: void pop_back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_back called on empty list"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_back() called on empty list"); +#endif _Unchecked_erase(_Mypair._Myval2._Myhead->_Prev); } @@ -1543,9 +1543,7 @@ public: const auto _UFirst = _First._Ptr; #if _ITERATOR_DEBUG_LEVEL == 2 - if (_UFirst == _Right._Mypair._Myval2._Myhead) { - _STL_REPORT_ERROR("list splice iterator outside range"); - } + _STL_VERIFY(_UFirst != _Right._Mypair._Myval2._Myhead, "list splice iterator outside range"); #endif // _ITERATOR_DEBUG_LEVEL == 2 const auto _ULast = _UFirst->_Next; diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 99b6b7333bf..714c6120c71 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -185,14 +185,14 @@ public: _NODISCARD static constexpr size_t static_extent(_In_range_(<, _Rank) const rank_type _Idx) noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < _Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/1)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Static_extents[_Idx]; } _NODISCARD constexpr index_type extent(_In_range_(<, _Rank) const rank_type _Idx) const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < _Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/3)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif if constexpr (rank_dynamic() == 0) { return static_cast(_Static_extents[_Idx]); } else if constexpr (rank_dynamic() == rank()) { @@ -465,7 +465,7 @@ struct _Maybe_fully_static_extents<_Extents> { constexpr explicit _Maybe_fully_static_extents([[maybe_unused]] const _OtherExtents& _Exts_) { #if _CONTAINER_DEBUG_LEVEL > 0 (void) _Extents{_Exts_}; // NB: temporary created for preconditions check -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } static constexpr _Extents _Exts{}; @@ -513,7 +513,7 @@ public: _STL_VERIFY(_STD in_range(_Other.required_span_size()), "Value of other.required_span_size() must be representable as a value of type index_type (N4950 " "[mdspan.layout.left.cons]/4)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } template @@ -525,7 +525,7 @@ public: _STL_VERIFY(_STD in_range(_Other.required_span_size()), "Value of other.required_span_size() must be representable as a value of type index_type (N4950 " "[mdspan.layout.left.cons]/7)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } template @@ -597,7 +597,7 @@ public: #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < extents_type::_Rank, "Value of i must be less than extents_type::rank() (N4950 [mdspan.layout.left.obs]/6)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Fwd_prod_of_extents::_Calculate(this->_Exts, _Idx); } @@ -616,7 +616,7 @@ private: _STL_VERIFY(this->_Exts._Contains_multidimensional_index(_Index_seq, _Indices...), "Value of extents_type::index-cast(i) must be a multidimensional index in extents_ (N4950 " "[mdspan.layout.left.obs]/3)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif index_type _Stride = 1; index_type _Result = 0; @@ -667,7 +667,7 @@ public: _STL_VERIFY(_STD in_range(_Other.required_span_size()), "Value of other.required_span_size() must be representable as a value of type index_type (N4950 " "[mdspan.layout.right.cons]/4)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } template @@ -679,7 +679,7 @@ public: _STL_VERIFY(_STD in_range(_Other.required_span_size()), "Value of other.required_span_size() must be representable as a value of type index_type (N4950 " "[mdspan.layout.right.cons]/7)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } template @@ -750,7 +750,7 @@ public: #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < extents_type::_Rank, "Value of i must be less than extents_type::rank() (N4950 [mdspan.layout.right.obs]/6)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Rev_prod_of_extents::_Calculate(this->_Exts, _Idx); } @@ -769,7 +769,7 @@ private: _STL_VERIFY(this->_Exts._Contains_multidimensional_index(_Index_seq, _Indices...), "Value of extents_type::index-cast(i) must be a multidimensional index in extents_ (N4950 " "[mdspan.layout.right.obs]/3)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif index_type _Result = 0; ((_Result = static_cast(_Indices + this->_Exts.extent(_Seq) * _Result)), ...); @@ -900,7 +900,7 @@ public: #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Stride > 0, "Value of other.stride(r) must be greater than 0 for every rank index r of " "extents() (N4950 [mdspan.layout.stride.cons]/7.2)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif this->_Array[_Idx] = static_cast(_Stride); } } @@ -977,12 +977,13 @@ public: _NODISCARD constexpr index_type stride(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept { if constexpr (extents_type::rank() == 0) { - _STL_VERIFY(false, "The argument to stride must be nonnegative and less than extents_type::rank()."); + _STL_REPORT_ERROR("The argument to stride must be nonnegative and less than extents_type::rank()."); + return 1; } else { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < extents_type::_Rank, "The argument to stride must be nonnegative and less than extents_type::rank()."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return this->_Array[_Idx]; } } @@ -1031,7 +1032,7 @@ private: _STL_VERIFY(this->_Exts._Contains_multidimensional_index(_Index_seq, _Indices...), "Value of extents_type::index-cast(i) must be a multidimensional index in extents_ (N4950 " "[mdspan.layout.stride.obs]/3)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return static_cast(((_Indices * this->_Array[_Seq]) + ... + 0)); } @@ -1202,7 +1203,7 @@ public: _NODISCARD static constexpr size_t static_extent(_In_range_(<, extents_type::_Rank) const rank_type _Idx) noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Idx < extents_type::_Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/1)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return extents_type::_Static_extents[_Idx]; } @@ -1435,8 +1436,9 @@ private: _STL_INTERNAL_STATIC_ASSERT(conjunction_v...>); #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Map.extents()._Contains_multidimensional_index(make_index_sequence{}, _Indices...), - "I must be a multidimensional index in extents() (N4950 [mdspan.mdspan.members]/3)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + "mdspan subscript out of range; extents_type::index-cast(std::move(indices)) must be " + "a multidimensional index in extents() (N5001 [mdspan.mdspan.members]/3)."); +#endif return this->_Acc.access(_Ptr, static_cast(this->_Map(_Indices...))); } diff --git a/stl/inc/memory b/stl/inc/memory index 49d0e0af838..3770d48706d 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -92,24 +92,31 @@ namespace ranges { _STL_INTERNAL_STATIC_ASSERT(_No_throw_sentinel_for<_OSe, _Out>); _STL_INTERNAL_STATIC_ASSERT(constructible_from, iter_reference_t<_It>>); - constexpr bool _Is_sized1 = sized_sentinel_for<_Se, _It>; - constexpr bool _Is_sized2 = sized_sentinel_for<_OSe, _Out>; - if constexpr (_Iter_copy_cat<_It, _Out>::_Bitcopy_constructible - && _Sized_or_unreachable_sentinel_for<_Se, _It> - && _Sized_or_unreachable_sentinel_for<_OSe, _Out>) { + constexpr bool _Is_sized1 = sized_sentinel_for<_Se, _It>; + constexpr bool _Is_sized2 = sized_sentinel_for<_OSe, _Out>; + constexpr bool _Can_memcpy = _Iter_copy_cat<_It, _Out>::_Bitcopy_constructible + && _Sized_or_unreachable_sentinel_for<_Se, _It> + && _Sized_or_unreachable_sentinel_for<_OSe, _Out>; + if constexpr (_Can_memcpy && (_Is_sized1 || _Is_sized2)) { if constexpr (_Is_sized1 && _Is_sized2) { return _RANGES _Copy_memcpy_common(_IFirst, _RANGES next(_IFirst, _STD move(_ILast)), _OFirst, _RANGES next(_OFirst, _STD move(_OLast))); } else if constexpr (_Is_sized1) { return _RANGES _Copy_memcpy_distance( _IFirst, _OFirst, _IFirst, _RANGES next(_IFirst, _STD move(_ILast))); - } else if constexpr (_Is_sized2) { + } else { + _STL_INTERNAL_STATIC_ASSERT(_Is_sized2); return _RANGES _Copy_memcpy_distance( _IFirst, _OFirst, _OFirst, _RANGES next(_OFirst, _STD move(_OLast))); - } else { - _STL_ASSERT(false, "Tried to uninitialized_copy two ranges with unreachable sentinels"); } } else { + if constexpr (_Can_memcpy) { + // We were eligible for the memcpy optimization above, except for both sentinels being unreachable. + // The following classic code is doomed, because no exceptions will end the infinite loop. + // Following our usual pattern, let's emit a debug assertion, then run the loop anyways. + _STL_ASSERT(false, "Tried to std::uninitialized_copy() two ranges with unreachable sentinels"); + } + _Uninitialized_backout _Backout{_STD move(_OFirst)}; for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) { @@ -1042,18 +1049,10 @@ public: } _NODISCARD _Ty& operator*() const noexcept { -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Myptr, "auto_ptr not dereferenceable"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - return *get(); } _NODISCARD _Ty* operator->() const noexcept { -#if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Myptr, "auto_ptr not dereferenceable"); -#endif // _ITERATOR_DEBUG_LEVEL == 2 - return get(); } diff --git a/stl/inc/memory_resource b/stl/inc/memory_resource index dc66ebaa365..141524b3b40 100644 --- a/stl/inc/memory_resource +++ b/stl/inc/memory_resource @@ -361,12 +361,10 @@ namespace pmr { void _Deallocate_oversized(void* _Ptr, size_t _Bytes, size_t _Align) noexcept { // deallocate a block directly from the upstream resource - if (!_Prepare_oversized(_Bytes, _Align)) { - // no room for header + alignment padding; this memory WAS NOT allocated by this pool resource -#ifdef _DEBUG - _STL_REPORT_ERROR("Cannot deallocate memory not allocated by this memory pool."); -#endif // defined(_DEBUG) - } + [[maybe_unused]] const bool _Has_room_for_padding = _Prepare_oversized(_Bytes, _Align); + + // If there's no room for header + alignment padding, this memory WAS NOT allocated by this pool resource + _STL_ASSERT(_Has_room_for_padding, "Cannot deallocate memory not allocated by this memory pool."); _Oversized_header* _Hdr = reinterpret_cast<_Oversized_header*>(static_cast(_Ptr) + _Bytes) - 1; diff --git a/stl/inc/numeric b/stl/inc/numeric index 5b564506268..338abe4ca3c 100644 --- a/stl/inc/numeric +++ b/stl/inc/numeric @@ -671,10 +671,9 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> gcd(const _Mt _Mx, const _Nt _Nx) n #endif // ^^^ !defined(_DEBUG) ^^^ { constexpr auto _Min_common = _STD _Min_limit<_Common>(); - if (_Mx == _Min_common || _Nx == _Min_common) { - _STL_REPORT_ERROR("Preconditions: |m| and |n| are representable as a value of common_type_t. " - "(N4981 [numeric.ops.gcd]/2, N4981 [numeric.ops.lcm]/2)"); - } + _STL_VERIFY(_Mx != _Min_common && _Nx != _Min_common, + "Preconditions: |m| and |n| are representable as a value of common_type_t. " + "(N4981 [numeric.ops.gcd]/2, N4981 [numeric.ops.lcm]/2)"); } } @@ -731,11 +730,10 @@ _NODISCARD constexpr common_type_t<_Mt, _Nt> lcm(const _Mt _Mx, const _Nt _Nx) n _Common_unsigned _Result = 0; _Common_unsigned _Tmp = static_cast<_Common_unsigned>(_Mx_magnitude / _STD gcd(_Mx_magnitude, _Nx_magnitude)); + const bool _Overflow = _Mul_overflow(_Tmp, _Nx_magnitude, _Result) || !_In_range<_Common>(_Result); - if (_Mul_overflow(_Tmp, _Nx_magnitude, _Result) || !_In_range<_Common>(_Result)) { - _STL_REPORT_ERROR("Preconditions: The least common multiple of |m| and |n| is representable as a value of " - "type common_type_t. (N4981 [numeric.ops.lcm]/2)"); - } + _STL_VERIFY(!_Overflow, "Preconditions: The least common multiple of |m| and |n| is representable as a value of " + "type common_type_t. (N4981 [numeric.ops.lcm]/2)"); return static_cast<_Common>(_Result); } diff --git a/stl/inc/optional b/stl/inc/optional index 28e41c46abf..7a527fff616 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -182,29 +182,29 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { _NODISCARD constexpr _Ty& operator*() & noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Has_value, "Cannot access value of empty optional"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); +#endif return this->_Value; } _NODISCARD constexpr const _Ty& operator*() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Has_value, "Cannot access value of empty optional"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); +#endif return this->_Value; } _NODISCARD constexpr _Ty&& operator*() && noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Has_value, "Cannot access value of empty optional"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); +#endif return _STD move(this->_Value); } _NODISCARD constexpr const _Ty&& operator*() const&& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Has_value, "Cannot access value of empty optional"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); +#endif return _STD move(this->_Value); } }; @@ -377,14 +377,14 @@ public: _NODISCARD constexpr const _Ty* operator->() const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Has_value, "Cannot access value of empty optional"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Has_value, "operator->() called on empty optional"); +#endif return _STD addressof(this->_Value); } _NODISCARD constexpr _Ty* operator->() noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Has_value, "Cannot access value of empty optional"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(this->_Has_value, "operator->() called on empty optional"); +#endif return _STD addressof(this->_Value); } diff --git a/stl/inc/ranges b/stl/inc/ranges index 53da3d6daa2..3af972f8847 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1112,7 +1112,7 @@ namespace ranges { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Current < (numeric_limits<_Index_type>::max)(), "cannot increment repeat_view iterator past end (integer overflow)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif ++_Current; return *this; } @@ -1761,7 +1761,7 @@ namespace ranges { _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "filter_view has no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *_Pred; } @@ -1769,7 +1769,7 @@ namespace ranges { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY( _Pred, "N4950 [range.filter.view]/3 forbids calling begin on a filter_view that holds no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif if constexpr (forward_range<_Vw>) { if (this->_Has_cache()) { return _Iterator{*this, this->_Get_cache(_Range)}; @@ -1917,7 +1917,7 @@ namespace ranges { : _Range(_STD move(_Range_)), _Count{_Count_} { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count_ >= 0, "Number of elements to take must be non-negative (N4971 [range.take.view]/1)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } _NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ @@ -2225,7 +2225,7 @@ namespace ranges { _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "take_while_view has no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *_Pred; } @@ -2247,7 +2247,7 @@ namespace ranges { { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; } @@ -2257,7 +2257,7 @@ namespace ranges { { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; } }; @@ -2337,7 +2337,7 @@ namespace ranges { : _Range(_STD move(_Range_)), _Count{_Count_} { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count_ >= 0, "Number of elements to drop must be non-negative (N4971 [range.drop.view]/1)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } _NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ @@ -2559,7 +2559,7 @@ namespace ranges { _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "drop_while_view has no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *_Pred; } @@ -2567,7 +2567,7 @@ namespace ranges { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY( _Pred, "N4950 [range.drop.while.view]/3 forbids calling begin on a drop_while_view with no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif if constexpr (forward_range<_Vw>) { if (this->_Has_cache()) { return this->_Get_cache(_Range); @@ -4239,7 +4239,7 @@ namespace ranges { const iter_difference_t> _Count) _CONST_CALL_OPERATOR noexcept(_Choice<_It>._No_throw) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count >= 0, "The size passed to views::counted must be non-negative"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif constexpr _St _Strat = _Choice<_It>._Strategy; if constexpr (_Strat == _St::_Span) { @@ -5671,7 +5671,7 @@ namespace ranges { : _Range(_STD move(_Range_)), _Count{_Count_} { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count > 0, "chunk size must be greater than 0"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } _NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ @@ -5944,7 +5944,7 @@ namespace ranges { : _Range(_STD move(_Range_)), _Count{_Count_} { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count > 0, "chunk size must be greater than 0"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } _NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ @@ -6321,7 +6321,7 @@ namespace ranges { : _Range(_STD move(_Range_)), _Count{_Count_} { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count > 0, "The window size must be positive (N4950 [range.slide.view]/1)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } _NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) // strengthened @@ -6597,14 +6597,14 @@ namespace ranges { _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "chunk_by_view has no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *_Pred; } _NODISCARD constexpr _Iterator begin() { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Pred, "cannot call begin on a chunk_by_view with no predicate"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const auto _First = _RANGES begin(_Range); if (this->_Has_cache()) { @@ -6929,7 +6929,7 @@ namespace ranges { : _Range(_STD move(_Range_)), _Stride(_Stride_) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Stride > 0, "stride must be greater than 0"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif } _NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) // strengthened diff --git a/stl/inc/regex b/stl/inc/regex index 5491b129ed0..d4988266506 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -3683,10 +3683,9 @@ bool _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Match_pat(_Node_base* _Nx) { // c case _N_none: default: #if _ITERATOR_DEBUG_LEVEL != 0 - _STL_VERIFY(false, "internal data of regex node corrupted"); -#else // ^^^ _ITERATOR_DEBUG_LEVEL != 0 / _ITERATOR_DEBUG_LEVEL == 0 vvv + _STL_REPORT_ERROR("internal data of regex node corrupted"); +#endif return false; -#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } if (_Failed) { diff --git a/stl/inc/span b/stl/inc/span index bae1370bff2..4f043ea279d 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -99,7 +99,10 @@ struct _Span_iterator { } constexpr _Span_iterator& operator+=(const difference_type _Off) noexcept { +#if _ITERATOR_DEBUG_LEVEL >= 1 _Verify_offset(_Off); +#endif // _ITERATOR_DEBUG_LEVEL >= 1 + _Myptr += _Off; return *this; } @@ -116,8 +119,11 @@ struct _Span_iterator { } constexpr _Span_iterator& operator-=(const difference_type _Off) noexcept { +#if _ITERATOR_DEBUG_LEVEL >= 1 _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _Verify_offset(-_Off); +#endif // _ITERATOR_DEBUG_LEVEL >= 1 + _Myptr -= _Off; return *this; } @@ -351,32 +357,31 @@ public: template _NODISCARD constexpr auto first() const noexcept /* strengthened */ { if constexpr (_Extent != dynamic_extent) { - static_assert(_Count <= _Extent, "Count out of range in span::first()"); + static_assert(_Count <= _Extent, "Count out of range in span::first()"); } #if _CONTAINER_DEBUG_LEVEL > 0 else { - _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::first()"); + _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::first()"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 return span{_Mydata, _Count}; } - _NODISCARD constexpr auto first(const size_type _Count) const noexcept - /* strengthened */ { + _NODISCARD constexpr auto first(const size_type _Count) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::first(count)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return span{_Mydata, _Count}; } template _NODISCARD constexpr auto last() const noexcept /* strengthened */ { if constexpr (_Extent != dynamic_extent) { - static_assert(_Count <= _Extent, "Count out of range in span::last()"); + static_assert(_Count <= _Extent, "Count out of range in span::last()"); } #if _CONTAINER_DEBUG_LEVEL > 0 else { - _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::last()"); + _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::last()"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 return span{_Mydata + (_Mysize - _Count), _Count}; @@ -385,23 +390,23 @@ public: _NODISCARD constexpr auto last(const size_type _Count) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::last(count)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return span{_Mydata + (_Mysize - _Count), _Count}; } template _NODISCARD constexpr auto subspan() const noexcept /* strengthened */ { if constexpr (_Extent != dynamic_extent) { - static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()"); - static_assert( - _Count == dynamic_extent || _Count <= _Extent - _Offset, "Count out of range in span::subspan()"); + static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()"); + static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, + "Count out of range in span::subspan()"); } #if _CONTAINER_DEBUG_LEVEL > 0 else { - _STL_VERIFY(_Offset <= _Mysize, "Offset out of range in span::subspan()"); + _STL_VERIFY(_Offset <= _Mysize, "Offset out of range in span::subspan()"); if constexpr (_Count != dynamic_extent) { - _STL_VERIFY(_Count <= _Mysize - _Offset, "Count out of range in span::subspan()"); + _STL_VERIFY(_Count <= _Mysize - _Offset, "Count out of range in span::subspan()"); } } #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -432,7 +437,7 @@ public: #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize <= dynamic_extent / sizeof(element_type), "size of span in bytes exceeds std::numeric_limits::max()"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mysize * sizeof(element_type); } #pragma warning(pop) @@ -444,8 +449,8 @@ public: // [span.elem] Element access _NODISCARD constexpr reference operator[](const size_type _Off) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Off < _Mysize, "span index out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Off < _Mysize, "span subscript out of range"); +#endif return _Mydata[_Off]; } @@ -453,15 +458,15 @@ public: #pragma warning(disable : 4127) // conditional expression is constant _NODISCARD constexpr reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mysize > 0, "front of empty span"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mysize > 0, "front() called on empty span"); +#endif return _Mydata[0]; } _NODISCARD constexpr reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mysize > 0, "back of empty span"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Mysize > 0, "back() called on empty span"); +#endif return _Mydata[_Mysize - 1]; } #pragma warning(pop) diff --git a/stl/inc/valarray b/stl/inc/valarray index 3b370470e1d..5773a639e20 100644 --- a/stl/inc/valarray +++ b/stl/inc/valarray @@ -292,7 +292,7 @@ public: valarray& operator*=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] *= _Right[_Idx]; @@ -303,7 +303,7 @@ public: valarray& operator/=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] /= _Right[_Idx]; @@ -314,7 +314,7 @@ public: valarray& operator%=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] %= _Right[_Idx]; @@ -325,7 +325,7 @@ public: valarray& operator+=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] += _Right[_Idx]; @@ -336,7 +336,7 @@ public: valarray& operator-=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] -= _Right[_Idx]; @@ -347,7 +347,7 @@ public: valarray& operator^=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] ^= _Right[_Idx]; @@ -358,7 +358,7 @@ public: valarray& operator|=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] |= _Right[_Idx]; @@ -369,7 +369,7 @@ public: valarray& operator&=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] &= _Right[_Idx]; @@ -380,7 +380,7 @@ public: valarray& operator<<=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] <<= _Right[_Idx]; @@ -391,7 +391,7 @@ public: valarray& operator>>=(const valarray& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Myptr[_Idx] >>= _Right[_Idx]; @@ -406,7 +406,7 @@ public: _NODISCARD const _Ty& operator[](size_t _Off) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < _Mysize, "valarray subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Myptr[_Off]; } @@ -414,7 +414,7 @@ public: _NODISCARD _Ty& operator[](size_t _Off) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < _Mysize, "valarray subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Myptr[_Off]; } @@ -868,7 +868,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator*(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -881,7 +881,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator/(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -894,7 +894,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator%(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -907,7 +907,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator+(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -920,7 +920,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator-(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -933,7 +933,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator^(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -946,7 +946,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator&(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -959,7 +959,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator|(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -972,7 +972,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator<<(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -985,7 +985,7 @@ _EXPORT_STD template _NODISCARD valarray<_Ty> operator>>(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray<_Ty> _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -998,7 +998,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator&&(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1011,7 +1011,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator||(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1044,7 +1044,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator==(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1077,7 +1077,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator!=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1110,7 +1110,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator<(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1143,7 +1143,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator>(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1176,7 +1176,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator<=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1209,7 +1209,7 @@ _EXPORT_STD template _NODISCARD _Boolarray operator>=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const size_t _Size = _Left.size(); valarray _Ans(_Size); for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { diff --git a/stl/inc/vector b/stl/inc/vector index 27f3ad281db..ae8330bf2d2 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1737,8 +1737,8 @@ public: pointer& _Mylast = _My_data._Mylast; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_My_data._Myfirst != _Mylast, "pop_back() called on empty vector"); +#endif _Orphan_range(_Mylast - 1, _Mylast); _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); @@ -1916,7 +1916,7 @@ public: #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY( _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _My_data._Myfirst[_Pos]; } @@ -1926,7 +1926,7 @@ public: #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY( _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _My_data._Myfirst[_Pos]; } @@ -1953,7 +1953,7 @@ public: auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *_My_data._Myfirst; } @@ -1962,7 +1962,7 @@ public: auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *_My_data._Myfirst; } @@ -1971,7 +1971,7 @@ public: auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _My_data._Mylast[-1]; } @@ -1980,7 +1980,7 @@ public: auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _My_data._Mylast[-1]; } @@ -3211,7 +3211,7 @@ public: _NODISCARD _CONSTEXPR20 const_reference operator[](size_type _Off) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif const_iterator _It = begin(); _It._Advance(_Off); @@ -3221,7 +3221,7 @@ public: _NODISCARD _CONSTEXPR20 reference operator[](size_type _Off) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif iterator _It = begin(); _It._Advance(_Off); @@ -3231,7 +3231,7 @@ public: _NODISCARD _CONSTEXPR20 reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *begin(); } @@ -3239,7 +3239,7 @@ public: _NODISCARD _CONSTEXPR20 const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *begin(); } @@ -3247,7 +3247,7 @@ public: _NODISCARD _CONSTEXPR20 reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *(end() - 1); } @@ -3255,7 +3255,7 @@ public: _NODISCARD _CONSTEXPR20 const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *(end() - 1); } @@ -3422,11 +3422,13 @@ public: #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(end() > _Where, "vector erase iterator outside range"); +#endif + _STD copy(_Next_iter(_Where), end(), _Where); + +#if _ITERATOR_DEBUG_LEVEL == 2 _Orphan_range(static_cast(_Off), this->_Mysize); -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv - _STD copy(_Next_iter(_Where), end(), _Where); -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ +#endif _Trim(this->_Mysize - 1); return begin() + _Off; @@ -3441,14 +3443,16 @@ public: if (_First != _Last) { // worth doing, copy down over hole #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_Last >= _First && end() >= _Last, "vector erase iterator outside range"); +#endif + iterator _Next = _STD copy(_Last, end(), _First); const auto _Newsize = static_cast(_Next - begin()); + +#if _ITERATOR_DEBUG_LEVEL == 2 _Orphan_range(_Newsize, this->_Mysize); +#endif + _Trim(_Newsize); -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv - iterator _Next = _STD copy(_Last, end(), _First); - _Trim(static_cast(_Next - begin())); -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ } return begin() + _Off; } diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 31d0bed8c98..acac82131e1 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1786,23 +1786,31 @@ namespace ranges { requires (constructible_from, iter_rvalue_reference_t<_It>>) uninitialized_move_result<_It, _Out> _Uninitialized_move_unchecked( _It _IFirst, _Se _ILast, _Out _OFirst, _OSe _OLast) { - constexpr bool _Is_sized1 = sized_sentinel_for<_Se, _It>; - constexpr bool _Is_sized2 = sized_sentinel_for<_OSe, _Out>; - if constexpr (_Iter_move_cat<_It, _Out>::_Bitcopy_constructible && _Sized_or_unreachable_sentinel_for<_Se, _It> - && _Sized_or_unreachable_sentinel_for<_OSe, _Out>) { + constexpr bool _Is_sized1 = sized_sentinel_for<_Se, _It>; + constexpr bool _Is_sized2 = sized_sentinel_for<_OSe, _Out>; + constexpr bool _Can_memcpy = _Iter_move_cat<_It, _Out>::_Bitcopy_constructible + && _Sized_or_unreachable_sentinel_for<_Se, _It> + && _Sized_or_unreachable_sentinel_for<_OSe, _Out>; + if constexpr (_Can_memcpy && (_Is_sized1 || _Is_sized2)) { if constexpr (_Is_sized1 && _Is_sized2) { return _RANGES _Copy_memcpy_common(_IFirst, _RANGES next(_IFirst, _STD move(_ILast)), _OFirst, _RANGES next(_OFirst, _STD move(_OLast))); } else if constexpr (_Is_sized1) { return _RANGES _Copy_memcpy_distance( _IFirst, _OFirst, _IFirst, _RANGES next(_IFirst, _STD move(_ILast))); - } else if constexpr (_Is_sized2) { + } else { + _STL_INTERNAL_STATIC_ASSERT(_Is_sized2); return _RANGES _Copy_memcpy_distance( _IFirst, _OFirst, _OFirst, _RANGES next(_OFirst, _STD move(_OLast))); - } else { - _STL_ASSERT(false, "Tried to uninitialized_move two ranges with unreachable sentinels"); } } else { + if constexpr (_Can_memcpy) { + // We were eligible for the memcpy optimization above, except for both sentinels being unreachable. + // The following classic code is doomed, because no exceptions will end the infinite loop. + // Following our usual pattern, let's emit a debug assertion, then run the loop anyways. + _STL_ASSERT(false, "Tried to std::uninitialized_move() two ranges with unreachable sentinels"); + } + _Uninitialized_backout _Backout{_STD move(_OFirst)}; for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) { diff --git a/stl/inc/xstring b/stl/inc/xstring index 8bf2a0a5c08..e18772035bf 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -106,9 +106,9 @@ public: return; } - _STL_ASSERT(_Ptr, "cannot seek value-initialized string iterator"); + _STL_VERIFY(_Ptr, "cannot seek value-initialized string iterator"); const auto _Mycont = static_cast(this->_Getcont()); - _STL_ASSERT(_Mycont, "cannot seek string iterator because the iterator was " + _STL_VERIFY(_Mycont, "cannot seek string iterator because the iterator was " "invalidated (e.g. reallocation occurred, or the string was destroyed)"); const auto _Contptr = _Mycont->_Myptr(); const auto _Rawptr = _Unfancy(_Ptr); @@ -2248,7 +2248,7 @@ public: _NODISCARD _CONSTEXPR20 reference operator[](const size_type _Off) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off <= _Mypair._Myval2._Mysize, "string subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myptr()[_Off]; } @@ -2256,7 +2256,7 @@ public: /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off <= _Mypair._Myval2._Mysize, "string subscript out of range"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myptr()[_Off]; } @@ -2292,7 +2292,7 @@ public: _CONSTEXPR20 void pop_back() noexcept /* strengthened */ { const size_type _Old_size = _Mypair._Myval2._Mysize; #if _ITERATOR_DEBUG_LEVEL >= 1 - _STL_VERIFY(_Old_size != 0, "invalid to pop_back empty string"); + _STL_VERIFY(_Old_size != 0, "pop_back() called on empty string"); #endif // _ITERATOR_DEBUG_LEVEL >= 1 _Eos(_Old_size - 1); } @@ -2300,7 +2300,7 @@ public: _NODISCARD _CONSTEXPR20 reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty string"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myptr()[0]; } @@ -2308,7 +2308,7 @@ public: _NODISCARD _CONSTEXPR20 const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty string"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myptr()[0]; } @@ -2316,7 +2316,7 @@ public: _NODISCARD _CONSTEXPR20 reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty string"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myptr()[_Mypair._Myval2._Mysize - 1]; } @@ -2324,7 +2324,7 @@ public: _NODISCARD _CONSTEXPR20 const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty string"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return _Mypair._Myval2._Myptr()[_Mypair._Myval2._Mysize - 1]; } diff --git a/stl/inc/xtree b/stl/inc/xtree index 0ec8c6fce12..9738b831130 100644 --- a/stl/inc/xtree +++ b/stl/inc/xtree @@ -178,7 +178,7 @@ public: _NODISCARD reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 const auto _Mycont = static_cast(this->_Getcont()); - _STL_ASSERT(_Mycont, "cannot dereference value-initialized map/set iterator"); + _STL_VERIFY(_Mycont, "cannot dereference value-initialized map/set iterator"); _STL_VERIFY(this->_Ptr != _Mycont->_Myhead, "cannot dereference end map/set iterator"); #endif // _ITERATOR_DEBUG_LEVEL == 2 @@ -207,7 +207,7 @@ public: _Tree_const_iterator& operator--() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_ASSERT(this->_Getcont(), "cannot decrement value-initialized map/set iterator"); + _STL_VERIFY(this->_Getcont(), "cannot decrement value-initialized map/set iterator"); _Nodeptr _Ptrsav = this->_Ptr; _Mybase::operator--(); _STL_VERIFY(_Ptrsav != this->_Ptr, "cannot decrement begin map/set iterator"); diff --git a/stl/inc/xutility b/stl/inc/xutility index d31e7079341..0c5c942a29d 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -3824,8 +3824,8 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "front called on empty view_interface"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_RANGES empty(_Self), "front() called on empty ranges::view_interface"); +#endif return *_RANGES begin(_Self); } @@ -3834,8 +3834,8 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "front called on empty view_interface"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_RANGES empty(_Self), "front() called on empty ranges::view_interface"); +#endif return *_RANGES begin(_Self); } @@ -3844,8 +3844,8 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "back called on empty view_interface"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_RANGES empty(_Self), "back() called on empty ranges::view_interface"); +#endif auto _Last = _RANGES end(_Self); return *--_Last; } @@ -3855,8 +3855,8 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "back called on empty view_interface"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(!_RANGES empty(_Self), "back() called on empty ranges::view_interface"); +#endif auto _Last = _RANGES end(_Self); return *--_Last; } @@ -3868,7 +3868,7 @@ namespace ranges { if constexpr (sized_range<_Derived>) { using _U_diff = _Make_unsigned_like_t>; _STL_VERIFY(static_cast<_U_diff>(_Idx) < static_cast<_U_diff>(_RANGES size(_Self)), - "index out of range for view_interface"); + "ranges::view_interface subscript out of range"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _RANGES begin(_Self)[_Idx]; @@ -3881,7 +3881,7 @@ namespace ranges { if constexpr (sized_range<_Derived>) { using _U_diff = _Make_unsigned_like_t>; _STL_VERIFY(static_cast<_U_diff>(_Idx) < static_cast<_U_diff>(_RANGES size(_Self)), - "index out of range for view_interface"); + "ranges::view_interface subscript out of range"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _RANGES begin(_Self)[_Idx]; diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 33ac7c51203..5922af50231 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -181,35 +181,15 @@ _STL_DISABLE_CLANG_WARNINGS #endif // ^^^ !defined(_DEBUG) ^^^ #endif // !defined(_STL_CRT_SECURE_INVALID_PARAMETER) -#define _STL_REPORT_ERROR(mesg) \ - do { \ - _RPTF0(_CRT_ASSERT, mesg); \ - _STL_CRT_SECURE_INVALID_PARAMETER(mesg); \ - } while (false) - -#ifdef __clang__ -#define _STL_VERIFY(cond, mesg) \ - _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wassume\"") do { \ - if (cond) { /* contextually convertible to bool paranoia */ \ - } else { \ - _STL_REPORT_ERROR(mesg); \ - } \ - \ - _Analysis_assume_(cond); \ - } \ - while (false) \ - _Pragma("clang diagnostic pop") -#else // ^^^ Clang / MSVC vvv -#define _STL_VERIFY(cond, mesg) \ - do { \ - if (cond) { /* contextually convertible to bool paranoia */ \ - } else { \ - _STL_REPORT_ERROR(mesg); \ - } \ - \ - _Analysis_assume_(cond); \ - } while (false) -#endif // ^^^ MSVC ^^^ +#define _STL_REPORT_ERROR(mesg) \ + _RPTF0(_CRT_ASSERT, mesg); \ + _STL_CRT_SECURE_INVALID_PARAMETER(mesg) + +#define _STL_VERIFY(cond, mesg) \ + if (!(cond)) { \ + _STL_REPORT_ERROR(mesg); \ + } \ + _Analysis_assume_(cond) #ifdef _DEBUG #define _STL_ASSERT(cond, mesg) _STL_VERIFY(cond, mesg) @@ -223,20 +203,6 @@ _STL_DISABLE_CLANG_WARNINGS #define _STL_INTERNAL_CHECK(...) _Analysis_assume_(__VA_ARGS__) #endif // ^^^ !defined(_ENABLE_STL_INTERNAL_CHECK) ^^^ -#ifndef _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK -#ifdef _DEBUG -#define _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK 1 -#else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv -#define _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK 0 -#endif // ^^^ !defined(_DEBUG) ^^^ -#endif // !defined(_ENABLE_ATOMIC_REF_ALIGNMENT_CHECK) - -#if _ENABLE_ATOMIC_REF_ALIGNMENT_CHECK -#define _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg) _STL_VERIFY(cond, mesg) -#else -#define _ATOMIC_REF_CHECK_ALIGNMENT(cond, mesg) _Analysis_assume_(cond) -#endif - #include #ifdef _STATIC_CPPLIB diff --git a/tests/std/tests/P0645R10_text_formatting_death/test.cpp b/tests/std/tests/P0645R10_text_formatting_death/test.cpp index e09eba9dc28..a19bab56c5d 100644 --- a/tests/std/tests/P0645R10_text_formatting_death/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_death/test.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include #include @@ -17,17 +15,12 @@ void test_case_advance_no_range() { context.advance_to(other_format_string.begin()); } -void test_case_negative_dynamic_width() { - (void) format("{:{}}", 42, -2); -} - int main(int argc, char* argv[]) { std_testing::death_test_executive exec; #if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_case_advance_no_range, - test_case_negative_dynamic_width, }); #endif // _ITERATOR_DEBUG_LEVEL != 0 diff --git a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp index 4273f2f9909..ff1a01f2636 100644 --- a/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp +++ b/tests/std/tests/P0645R10_text_formatting_formatting/test.cpp @@ -1386,6 +1386,10 @@ void libfmt_formatter_test_runtime_width() { assert(format(STR("{0:{1}}"), reinterpret_cast(0xcafe), 10) == STR(" 0xcafe")); assert(format(STR("{0:{1}}"), 'x', 11) == STR("x ")); assert(format(STR("{0:{1}}"), STR("str"), 12) == STR("str ")); + + // Test positive and negative dynamic width: + assert(format(STR("{:{}}"), 42, 5) == STR(" 42")); + throw_helper(STR("{:{}}"), 42, -5); } template @@ -1425,6 +1429,10 @@ void libfmt_formatter_test_runtime_precision() { throw_helper(STR("{:.{}f}"), 3.14f, true); throw_helper(STR("{:.{}f}"), 3.14f, '0'); assert(format(STR("{:.{}f}"), 3.14f, static_cast(2)) == STR("3.14")); + + // Test positive and negative dynamic precision: + assert(format(STR("{:.{}}"), 3.14159265358979, 5) == STR("3.1416")); + throw_helper(STR("{:.{}}"), 3.14159265358979, -5); } template diff --git a/tests/std/tests/P0896R4_common_iterator_death/test.cpp b/tests/std/tests/P0896R4_common_iterator_death/test.cpp index 20facf56200..18bd1004ab6 100644 --- a/tests/std/tests/P0896R4_common_iterator_death/test.cpp +++ b/tests/std/tests/P0896R4_common_iterator_death/test.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include #include diff --git a/tests/std/tests/P0896R4_counted_iterator_death/test.cpp b/tests/std/tests/P0896R4_counted_iterator_death/test.cpp index dce76063cb5..92e06bb9e54 100644 --- a/tests/std/tests/P0896R4_counted_iterator_death/test.cpp +++ b/tests/std/tests/P0896R4_counted_iterator_death/test.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include #include diff --git a/tests/std/tests/P0896R4_istream_view_death/test.cpp b/tests/std/tests/P0896R4_istream_view_death/test.cpp index fbad6ceae6b..85aca7e4f48 100644 --- a/tests/std/tests/P0896R4_istream_view_death/test.cpp +++ b/tests/std/tests/P0896R4_istream_view_death/test.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include #include diff --git a/tests/std/tests/P0896R4_views_transform_death/test.cpp b/tests/std/tests/P0896R4_views_transform_death/test.cpp index 6ab18e88984..7eb908f1723 100644 --- a/tests/std/tests/P0896R4_views_transform_death/test.cpp +++ b/tests/std/tests/P0896R4_views_transform_death/test.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include #include diff --git a/tests/std/tests/VSO_0830211_container_debugging_range_checks/test.cpp b/tests/std/tests/VSO_0830211_container_debugging_range_checks/test.cpp index 0f11348804a..29b47050c76 100644 --- a/tests/std/tests/VSO_0830211_container_debugging_range_checks/test.cpp +++ b/tests/std/tests/VSO_0830211_container_debugging_range_checks/test.cpp @@ -13,6 +13,12 @@ using namespace std; +#pragma warning(disable : 4984) // 'if constexpr' is a C++17 language extension + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++17-extensions" // constexpr if is a C++17 extension +#endif + template struct TestCases { using ContainerType = typename Traits::ContainerType; @@ -26,15 +32,11 @@ struct TestCases { (void) *it; } - static void test_case_operator_arrow_value_initialized_iterator2(true_type) { - IteratorType it; - (void) it.operator->(); - } - - static void test_case_operator_arrow_value_initialized_iterator2(false_type) {} - static void test_case_operator_arrow_value_initialized_iterator() { - return test_case_operator_arrow_value_initialized_iterator2(bool_constant{}); + if constexpr (Traits::has_arrow) { + IteratorType it; + (void) it.operator->(); + } } static void test_case_operator_preincrement_value_initialized_iterator() { @@ -73,16 +75,12 @@ struct TestCases { (void) *it; } - static void test_case_operator_arrow_end_iterator2(true_type) { - ContainerType a{false, true, false, true}; - auto it = a.end(); - (void) it.operator->(); - } - - static void test_case_operator_arrow_end_iterator2(false_type) {} - static void test_case_operator_arrow_end_iterator() { - return test_case_operator_arrow_end_iterator2(bool_constant{}); + if constexpr (Traits::has_arrow) { + ContainerType a{false, true, false, true}; + auto it = a.end(); + (void) it.operator->(); + } } static void test_case_operator_preincrement_off_end() { @@ -186,8 +184,7 @@ struct TestCases { static void add_cases(std_testing::death_test_executive& exec) { #if _ITERATOR_DEBUG_LEVEL != 0 - static constexpr std_testing::death_function_t a[] = { - // TRANSITION, VSO-847348 + exec.add_death_tests({ test_case_operator_dereference_value_initialized_iterator, test_case_operator_preincrement_value_initialized_iterator, test_case_operator_predecrement_value_initialized_iterator, @@ -206,27 +203,22 @@ struct TestCases { test_case_operator_equal_incompatible_value_initialized, test_case_operator_less_incompatible_different_views, test_case_operator_less_incompatible_value_initialized, - }; - exec.add_death_tests(a); + }); - if (Traits::has_arrow) { - static constexpr std_testing::death_function_t b[] = { - // TRANSITION, VSO-847348 + if constexpr (Traits::has_arrow) { + exec.add_death_tests({ test_case_operator_arrow_value_initialized_iterator, test_case_operator_arrow_end_iterator, - }; - exec.add_death_tests(b); + }); } #endif // _ITERATOR_DEBUG_LEVEL != 0 - static constexpr std_testing::death_function_t c[] = { - // TRANSITION, VSO-847348 + exec.add_death_tests({ test_case_operator_subscript_out_of_range_empty, test_case_operator_subscript_out_of_range, test_case_front_empty, test_case_back_empty, - }; - exec.add_death_tests(c); + }); } }; diff --git a/tests/std/tests/VSO_0938757_attribute_order/env.lst b/tests/std/tests/VSO_0938757_attribute_order/env.lst index e11f90f1dfb..b73794175a9 100644 --- a/tests/std/tests/VSO_0938757_attribute_order/env.lst +++ b/tests/std/tests/VSO_0938757_attribute_order/env.lst @@ -3,4 +3,4 @@ RUNALL_INCLUDE ..\prefix.lst RUNALL_CROSSLIST -PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MTd /std:c++latest /permissive- /D_PREFAST_ -Wno-ignored-attributes" +PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MTd /std:c++latest /permissive- /D_PREFAST_ -Wno-ignored-attributes -Wno-assume"