From 0962eb1677ba53de59c51c87e0b0f02f7f91f4d0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 11:57:02 -0800 Subject: [PATCH 01/35] Remove CDL preprocessor comments after a single line. --- stl/inc/__msvc_string_view.hpp | 12 +++---- stl/inc/array | 16 ++++----- stl/inc/deque | 12 +++---- stl/inc/expected | 30 ++++++++--------- stl/inc/forward_list | 4 +-- stl/inc/generator | 6 ++-- stl/inc/list | 12 +++---- stl/inc/mdspan | 8 ++--- stl/inc/optional | 12 +++---- stl/inc/ranges | 28 ++++++++-------- stl/inc/span | 10 +++--- stl/inc/valarray | 60 +++++++++++++++++----------------- stl/inc/vector | 22 ++++++------- stl/inc/xstring | 12 +++---- stl/inc/xutility | 8 ++--- 15 files changed, 126 insertions(+), 126 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 14198cbdf6b..7315083bbb0 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]; @@ -1491,21 +1491,21 @@ 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 +#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 +#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 +#endif _Mydata += _Count; _Mysize -= _Count; } @@ -1513,7 +1513,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer 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 +#endif _Mysize -= _Count; } diff --git a/stl/inc/array b/stl/inc/array index b8eef281ba1..30a3bfde6a7 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]; } @@ -709,7 +709,7 @@ 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 +#endif return *data(); } @@ -717,7 +717,7 @@ public: _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 +#endif return *data(); } @@ -725,7 +725,7 @@ public: _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_REPORT_ERROR("array::front() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *data(); } @@ -733,7 +733,7 @@ public: _NODISCARD const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_REPORT_ERROR("array::front() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *data(); } @@ -741,7 +741,7 @@ public: _NODISCARD reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_REPORT_ERROR("array::back() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *data(); } @@ -749,7 +749,7 @@ public: _NODISCARD const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_REPORT_ERROR("array::back() invalid"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif return *data(); } diff --git a/stl/inc/deque b/stl/inc/deque index 9bba528c614..7b20c927366 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); } diff --git a/stl/inc/expected b/stl/inc/expected index f27e3fc7007..ce6f3f4ef7e 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -622,38 +622,38 @@ public: _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 +#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 +#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 +#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 +#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 +#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 +#endif return _STD move(_Value); } @@ -708,25 +708,25 @@ 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 +#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 +#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 +#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 +#endif return _STD move(_Unexpected); } @@ -1470,7 +1470,7 @@ 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 +#endif } constexpr void value() const& { @@ -1491,25 +1491,25 @@ 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 +#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 +#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 +#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 +#endif return _STD move(_Unexpected); } diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 0d556e5639a..7dab698a46e 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -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..a16d4f74322 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -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; } @@ -1255,7 +1255,7 @@ 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 +#endif _Unchecked_erase(_Mypair._Myval2._Myhead->_Next); } @@ -1276,7 +1276,7 @@ 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 +#endif _Unchecked_erase(_Mypair._Myval2._Myhead->_Prev); } diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 99b6b7333bf..c777fc66e91 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{}; @@ -1202,7 +1202,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]; } diff --git a/stl/inc/optional b/stl/inc/optional index 28e41c46abf..def67f9bbc9 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -183,28 +183,28 @@ 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 +#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 +#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 +#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 +#endif return _STD move(this->_Value); } }; @@ -378,13 +378,13 @@ 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 +#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 +#endif return _STD addressof(this->_Value); } diff --git a/stl/inc/ranges b/stl/inc/ranges index 53da3d6daa2..8b4ef384a0f 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -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; } @@ -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; } @@ -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/span b/stl/inc/span index bae1370bff2..b83ccb39278 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -365,7 +365,7 @@ public: /* 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}; } @@ -385,7 +385,7 @@ 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}; } @@ -445,7 +445,7 @@ public: _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 +#endif return _Mydata[_Off]; } @@ -454,14 +454,14 @@ public: _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 +#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 +#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..a2ff0f37e32 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1738,7 +1738,7 @@ public: #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif _Orphan_range(_Mylast - 1, _Mylast); _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); @@ -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); } diff --git a/stl/inc/xstring b/stl/inc/xstring index 8bf2a0a5c08..869162ca296 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -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]; } @@ -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/xutility b/stl/inc/xutility index d31e7079341..f5158ecad96 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -3825,7 +3825,7 @@ 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 +#endif return *_RANGES begin(_Self); } @@ -3835,7 +3835,7 @@ 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 +#endif return *_RANGES begin(_Self); } @@ -3845,7 +3845,7 @@ 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 +#endif auto _Last = _RANGES end(_Self); return *--_Last; } @@ -3856,7 +3856,7 @@ 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 +#endif auto _Last = _RANGES end(_Self); return *--_Last; } From acc4f3487967a9b1d1d01c81303ef6b957d9b7fc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 12:08:29 -0800 Subject: [PATCH 02/35] Remove CDL preprocessor comments after a single `_STL_VERIFY` over multiple lines. --- stl/inc/mdspan | 24 ++++++++++++------------ stl/inc/ranges | 6 +++--- stl/inc/span | 2 +- stl/inc/vector | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/stl/inc/mdspan b/stl/inc/mdspan index c777fc66e91..4722cb7481a 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -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); } } @@ -982,7 +982,7 @@ public: #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 +1031,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)); } @@ -1436,7 +1436,7 @@ private: #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 +#endif return this->_Acc.access(_Ptr, static_cast(this->_Map(_Indices...))); } diff --git a/stl/inc/ranges b/stl/inc/ranges index 8b4ef384a0f..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; } @@ -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)}; @@ -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); diff --git a/stl/inc/span b/stl/inc/span index b83ccb39278..a110a856d28 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -432,7 +432,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) diff --git a/stl/inc/vector b/stl/inc/vector index a2ff0f37e32..ffab255b3a7 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -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]; } From c20b369d936b36c16aa53e9debad6d7c955815b9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 12:13:23 -0800 Subject: [PATCH 03/35] docs/import_library.md: Don't mention CDL - it doesn't affect ABI, and will be removed. --- docs/import_library.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 2cb3a35263ed0abaed90383aacb154dba75111c8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 31 Jan 2025 02:27:07 -0800 Subject: [PATCH 04/35] Improve debug messages: "array subscript invalid" This identifies that we're dealing with array, and that the call is permanently bogus, following the example of "array::front() invalid". --- stl/inc/array | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/array b/stl/inc/array index 30a3bfde6a7..71c2b94e3ef 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -708,7 +708,7 @@ public: _NODISCARD reference operator[](size_type) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array subscript out of range"); + _STL_REPORT_ERROR("array subscript invalid"); #endif return *data(); @@ -716,7 +716,7 @@ public: _NODISCARD const_reference operator[](size_type) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array subscript out of range"); + _STL_REPORT_ERROR("array subscript invalid"); #endif return *data(); From 06a1361f5c307fd488a7e043cfc0b0f3a521cb48 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 31 Jan 2025 02:43:20 -0800 Subject: [PATCH 05/35] Improve debug messages: "MEOW subscript out of range" This is consistent with vector. mdspan's message was very opaque; starting with "mdspan subscript out of range" provides clarity. Additionally, "I" was previously used without being defined; I've replaced it with its definition from /2. ranges::view_interface now refers to itself with qualification. --- stl/inc/bitset | 2 +- stl/inc/mdspan | 3 ++- stl/inc/span | 2 +- stl/inc/xutility | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/stl/inc/bitset b/stl/inc/bitset index b6e493d957c..cbd91bbb342 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 ^^^ } diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 4722cb7481a..5e8b6ff8af1 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -1435,7 +1435,8 @@ 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)."); + "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/span b/stl/inc/span index a110a856d28..1f75db9fb2b 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -444,7 +444,7 @@ 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"); + _STL_VERIFY(_Off < _Mysize, "span subscript out of range"); #endif return _Mydata[_Off]; } diff --git a/stl/inc/xutility b/stl/inc/xutility index f5158ecad96..3de8c100627 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -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]; From 97d2acb2d9acc97e43cc2bc566ce28782e5ee54b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 31 Jan 2025 03:02:01 -0800 Subject: [PATCH 06/35] Improve debug messages: "MEOW() called on empty WOOF" deque now mentions whether pop_front() or pop_back() was called. optional now mentions whether operator*() or operator->() was called. ranges::view_interface now refers to itself with qualification. --- stl/inc/__msvc_string_view.hpp | 4 ++-- stl/inc/deque | 4 ++-- stl/inc/list | 4 ++-- stl/inc/optional | 12 ++++++------ stl/inc/span | 4 ++-- stl/inc/vector | 2 +- stl/inc/xstring | 2 +- stl/inc/xutility | 8 ++++---- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 7315083bbb0..b953621e40a 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -1490,14 +1490,14 @@ 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"); + _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"); + _STL_VERIFY(_Mysize != 0, "back() called on empty string_view"); #endif return _Mydata[_Mysize - 1]; } diff --git a/stl/inc/deque b/stl/inc/deque index 7b20c927366..26ef8a573aa 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -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); diff --git a/stl/inc/list b/stl/inc/list index a16d4f74322..0c0dd2438d5 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -1254,7 +1254,7 @@ public: void pop_front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_front called on empty list"); + _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_front() called on empty list"); #endif _Unchecked_erase(_Mypair._Myval2._Myhead->_Next); @@ -1275,7 +1275,7 @@ public: void pop_back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_back called on empty list"); + _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_back() called on empty list"); #endif _Unchecked_erase(_Mypair._Myval2._Myhead->_Prev); diff --git a/stl/inc/optional b/stl/inc/optional index def67f9bbc9..7a527fff616 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -182,28 +182,28 @@ 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"); + _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"); + _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"); + _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"); + _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); #endif return _STD move(this->_Value); } @@ -377,13 +377,13 @@ public: _NODISCARD constexpr const _Ty* operator->() const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(this->_Has_value, "Cannot access value of empty optional"); + _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"); + _STL_VERIFY(this->_Has_value, "operator->() called on empty optional"); #endif return _STD addressof(this->_Value); } diff --git a/stl/inc/span b/stl/inc/span index 1f75db9fb2b..ab2bdfd2d0a 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -453,14 +453,14 @@ 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"); + _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"); + _STL_VERIFY(_Mysize > 0, "back() called on empty span"); #endif return _Mydata[_Mysize - 1]; } diff --git a/stl/inc/vector b/stl/inc/vector index ffab255b3a7..9fdba165fe4 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1737,7 +1737,7 @@ public: pointer& _Mylast = _My_data._Mylast; #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); + _STL_VERIFY(_My_data._Myfirst != _Mylast, "pop_back() called on empty vector"); #endif _Orphan_range(_Mylast - 1, _Mylast); diff --git a/stl/inc/xstring b/stl/inc/xstring index 869162ca296..53896acd62a 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -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); } diff --git a/stl/inc/xutility b/stl/inc/xutility index 3de8c100627..0c5c942a29d 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -3824,7 +3824,7 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "front called on empty view_interface"); + _STL_VERIFY(!_RANGES empty(_Self), "front() called on empty ranges::view_interface"); #endif return *_RANGES begin(_Self); } @@ -3834,7 +3834,7 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "front called on empty view_interface"); + _STL_VERIFY(!_RANGES empty(_Self), "front() called on empty ranges::view_interface"); #endif return *_RANGES begin(_Self); } @@ -3844,7 +3844,7 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "back called on empty view_interface"); + _STL_VERIFY(!_RANGES empty(_Self), "back() called on empty ranges::view_interface"); #endif auto _Last = _RANGES end(_Self); return *--_Last; @@ -3855,7 +3855,7 @@ namespace ranges { { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_RANGES empty(_Self), "back called on empty view_interface"); + _STL_VERIFY(!_RANGES empty(_Self), "back() called on empty ranges::view_interface"); #endif auto _Last = _RANGES end(_Self); return *--_Last; From a7ce525f44f145378e58029027aaca50cd5d8cf1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 31 Jan 2025 03:16:30 -0800 Subject: [PATCH 07/35] Improve debug messages: Clarify span's first(), last(), subspan(). --- stl/inc/span | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stl/inc/span b/stl/inc/span index ab2bdfd2d0a..646ae2f7295 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -351,11 +351,11 @@ 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}; @@ -372,11 +372,11 @@ public: 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}; @@ -392,16 +392,16 @@ public: 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 From f325132caf9d413c3c4f3c48713539c0f0ab6c3a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 31 Jan 2025 03:27:08 -0800 Subject: [PATCH 08/35] Improve debug messages: Clarify string_view remove_prefix(), remove_suffix(). Spell the function names literally for improved searchability. Mention the short version of the class name too. Adjust "longer" to "larger" for style. --- stl/inc/__msvc_string_view.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index b953621e40a..5e973ade480 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -1504,7 +1504,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer 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"); + _STL_VERIFY(_Mysize >= _Count, "cannot remove_prefix() larger than string_view size"); #endif _Mydata += _Count; _Mysize -= _Count; @@ -1512,7 +1512,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer 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"); + _STL_VERIFY(_Mysize >= _Count, "cannot remove_suffix() larger than string_view size"); #endif _Mysize -= _Count; } From a3de2848b9a1ca589178dfcd377593ad786667e5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 31 Jan 2025 03:34:58 -0800 Subject: [PATCH 09/35] Improve debug messages: std::expected. This splits "expected stores an error, not a value" into: "operator->() called on a std::expected that stores an error, not a value" "operator*() called on a std::expected that stores an error, not a value" And changes "expected stores a value, not an error" into: "error() called on a std::expected that stores a value, not an error" This mentions which member function is being called. Because "expected" doesn't really sound like a noun, I've added "std::" qualification and made the phrases less terse. --- stl/inc/expected | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index ce6f3f4ef7e..4edea7d9d21 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -621,38 +621,38 @@ 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"); + _STL_VERIFY(_Has_value, "operator->() called on a std::expected that stores 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"); + _STL_VERIFY(_Has_value, "operator->() called on a std::expected that stores 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"); + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that stores 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"); + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that stores 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"); + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that stores 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"); + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that stores an error, not a value"); #endif return _STD move(_Value); } @@ -707,25 +707,25 @@ public: _NODISCARD constexpr const _Err& error() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores 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"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores 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"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores 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"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores a value, not an error"); #endif return _STD move(_Unexpected); } @@ -1469,7 +1469,7 @@ public: constexpr void operator*() const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "expected stores an error, not a value"); + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that stores an error, not a value"); #endif } @@ -1490,25 +1490,25 @@ public: _NODISCARD constexpr const _Err& error() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "expected stores a value, not an error"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores 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"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores 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"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores 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"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores a value, not an error"); #endif return _STD move(_Unexpected); } From a5ab1f5535f9814dc7e69a2069aa3e349dcc528e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Feb 2025 21:23:43 -0800 Subject: [PATCH 10/35] Improve debug messages: Grammar. --- stl/inc/__msvc_ranges_tuple_formatter.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index 9b4595db7a3..b9d752c26d1 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_VERIFY(false, "basic_format_arg is in an impossible state"); int _Dummy{}; return _STD forward<_Visitor>(_Vis)(_Dummy); } From eca9c57fb504ecb42a3e65db7e269e273750cbdb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 18:11:03 -0800 Subject: [PATCH 11/35] Test cleanup: Remove CDL definitions from some `` tests. These weren't CDL-sensitive at all, and were properly guarded with `IDL != 0`. --- tests/std/tests/P0896R4_common_iterator_death/test.cpp | 2 -- tests/std/tests/P0896R4_counted_iterator_death/test.cpp | 2 -- tests/std/tests/P0896R4_istream_view_death/test.cpp | 2 -- tests/std/tests/P0896R4_views_transform_death/test.cpp | 2 -- 4 files changed, 8 deletions(-) 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 From fd0c6f1467aabe2d0193ec4e3a77df7b3d21a82a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 18:45:20 -0800 Subject: [PATCH 12/35] Test cleanup: Drop CDL from `` test, properly test negative dynamic width/precision. `` isn't CDL-sensitive. Negative dynamic width/precision are required to throw format_error; we don't use "death tests" for exceptions. For clarity and consistency, add positive and negative test cases for both. This may slightly duplicate existing coverage, but negative dynamic precision wasn't being properly tested AFAICT. --- tests/std/tests/P0645R10_text_formatting_death/test.cpp | 7 ------- .../tests/P0645R10_text_formatting_formatting/test.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) 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 From 2007c12824b7eac05756ef3b20b643fffe3aa5f6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 22:04:58 -0800 Subject: [PATCH 13/35] Test cleanup: Remove VSO-847348 workarounds. VSO-847348 "c1xx ICEs deducing array size inside a temploid" was fixed at some point during the last 6 years (verified with prod/fe x86chk). --- .../test.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) 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..8e1bf47a26c 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 @@ -186,8 +186,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 +205,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 + 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); + }); } }; From ed90fb162eeec5b0c8a529c50879da64c0f8394d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 22:07:56 -0800 Subject: [PATCH 14/35] Test cleanup: Use `if constexpr` instead of tag dispatch and plain `if`. --- .../test.cpp | 34 +++++++++---------- 1 file changed, 16 insertions(+), 18 deletions(-) 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 8e1bf47a26c..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() { @@ -207,7 +205,7 @@ struct TestCases { test_case_operator_less_incompatible_value_initialized, }); - if (Traits::has_arrow) { + if constexpr (Traits::has_arrow) { exec.add_death_tests({ test_case_operator_arrow_value_initialized_iterator, test_case_operator_arrow_end_iterator, From 6554e97cb1331393f80a5afb4404e19e937afa66 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 22:25:24 -0800 Subject: [PATCH 15/35] Code cleanups: Add const, unwrap "strengthened". --- stl/inc/bitset | 2 +- stl/inc/span | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/stl/inc/bitset b/stl/inc/bitset index cbd91bbb342..7374ea0676b 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -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/span b/stl/inc/span index 646ae2f7295..d698310c0db 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -361,8 +361,7 @@ public: 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 From a78ff8d0934026e89f1ae7913ddd47014c0f3b5f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 1 Feb 2025 06:44:00 -0800 Subject: [PATCH 16/35] Code cleanup: Conditional `_STL_REPORT_ERROR` => `_STL_VERIFY` or `_STL_ASSERT` In ``, we always call `_Prepare_oversized`, but the `_STL_REPORT_ERROR` was guarded by `#ifdef _DEBUG`. Convert this to `_STL_ASSERT`, which is consistent with the `_STL_ASSERT` that appears immediately below. In `` lcm(), extract `const bool _Overflow` so the `_STL_VERIFY` has no side effects. --- stl/inc/algorithm | 4 +--- stl/inc/list | 4 +--- stl/inc/memory_resource | 10 ++++------ stl/inc/numeric | 14 ++++++-------- 4 files changed, 12 insertions(+), 20 deletions(-) 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/list b/stl/inc/list index 0c0dd2438d5..996b111a379 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -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/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); } From 88a59ba7b1260d67d9da0aa1df9c5f39fc0fc0ad Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sat, 1 Feb 2025 07:00:12 -0800 Subject: [PATCH 17/35] Code cleanup: `_STL_VERIFY(false)` => `_STL_REPORT_ERROR` In ``, add `return 1;` in `stride()` to support upcoming changes for continue-on-error. In ``, unconditionally `return false;` for the same reason. --- stl/inc/__msvc_ranges_tuple_formatter.hpp | 2 +- stl/inc/format | 2 +- stl/inc/mdspan | 3 ++- stl/inc/regex | 5 ++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index b9d752c26d1..34feaed5f93 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 an impossible state"); + _STL_REPORT_ERROR("basic_format_arg is in an impossible state"); int _Dummy{}; return _STD forward<_Visitor>(_Vis)(_Dummy); } 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/mdspan b/stl/inc/mdspan index 5e8b6ff8af1..714c6120c71 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -977,7 +977,8 @@ 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, 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) { From 71dcd4f4bf0b7cea10335d40c7ca23fa8baddd0c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Feb 2025 21:42:18 -0800 Subject: [PATCH 18/35] Code cleanup: Consistently order `case` before `default`. --- stl/inc/atomic | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/atomic b/stl/inc/atomic index e69bb281481..be16668bb8f 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -177,10 +177,10 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { 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: \ + default: \ _INVALID_MEMORY_ORDER; \ _FALLTHROUGH; @@ -1180,9 +1180,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: From 25960e56f5936afcb36bee57c37e3e37fea23179 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Feb 2025 21:51:24 -0800 Subject: [PATCH 19/35] Code cleanup: Fuse _Check_alignment into atomic_ref ctor. --- stl/inc/atomic | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/stl/inc/atomic b/stl/inc/atomic index be16668bb8f..4bd089de886 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -2328,7 +2328,9 @@ public: explicit atomic_ref(_Ty& _Value) noexcept /* strengthened */ : _Base(_Value) { if constexpr (is_always_lock_free) { - _Check_alignment(_Value); + _ATOMIC_REF_CHECK_ALIGNMENT( + (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 +2438,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 From 85f29dcfacda61d0876e73f2de26a6fbce2cfda3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Feb 2025 21:55:07 -0800 Subject: [PATCH 20/35] Code cleanup: Collapse _ATOMIC_REF_CHECK_ALIGNMENT into _STL_ASSERT. This doesn't change behavior (it remains a debug-only check), it just removes an escape hatch that was never used. --- stl/inc/atomic | 3 +-- stl/inc/yvals.h | 14 -------------- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/stl/inc/atomic b/stl/inc/atomic index 4bd089de886..0545d54a405 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -2328,8 +2328,7 @@ public: explicit atomic_ref(_Ty& _Value) noexcept /* strengthened */ : _Base(_Value) { if constexpr (is_always_lock_free) { - _ATOMIC_REF_CHECK_ALIGNMENT( - (reinterpret_cast(_STD addressof(_Value)) & (required_alignment - 1)) == 0, + _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(); diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 33ac7c51203..99cb832ed3d 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -223,20 +223,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 From 57e3cca3dd09bddc1d5dca0ff75e077b14da6ed9 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Feb 2025 23:42:57 -0800 Subject: [PATCH 21/35] Code cleanup: Avoid duplicating _Off and _Count. Add const to _Moved. --- stl/inc/deque | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stl/inc/deque b/stl/inc/deque index 26ef8a573aa..cab1a2a804e 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -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; From 22a4cbb33170cfc41423378aa06a8e8634be3f44 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 00:09:00 -0800 Subject: [PATCH 22/35] Code cleanup: Avoid duplicating _STD copy() call. --- stl/inc/vector | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 9fdba165fe4..73c02a626b5 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -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; From 59512b9881ed687420bdfc2a8bf51bb27de6015a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 00:12:31 -0800 Subject: [PATCH 23/35] Code cleanup: Avoid more duplication. We can always extract _Newsize for clarity. --- stl/inc/vector | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 73c02a626b5..ae8330bf2d2 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -3443,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; } From 62ce28dc004d5c6d7d49aa5feaf8bad4efd52ba7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 00:30:01 -0800 Subject: [PATCH 24/35] Code cleanup: IDL == 2 implies debug, so _STL_ASSERT should be _STL_VERIFY. This is especially noticeable when _STL_VERIFY already follows. --- stl/inc/forward_list | 2 +- stl/inc/list | 6 +++--- stl/inc/xtree | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 7dab698a46e..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 diff --git a/stl/inc/list b/stl/inc/list index 996b111a379..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 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"); From 8c69d19bff2e279fe600465501e481ef3600a53f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 01:19:20 -0800 Subject: [PATCH 25/35] Code cleanup: Extract _Can_memcpy for clarity, simplifying following CoE fix. --- stl/inc/memory | 11 ++++++----- stl/inc/xmemory | 10 ++++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 49d0e0af838..f8232fea424 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -92,11 +92,12 @@ 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) { 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))); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 31d0bed8c98..4d381ab20a7 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1786,10 +1786,12 @@ 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) { 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))); From 451c7ba695be858396d7cb4746c817f3004581ee Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 01:44:21 -0800 Subject: [PATCH 26/35] Enhancement (for CoE): Adjust uninitialized_meow's logic. We'll continue right into an infinite loop, but at least we won't fall off the end of a non-void function. --- stl/inc/memory | 14 ++++++++++---- stl/inc/xmemory | 14 ++++++++++---- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index f8232fea424..6b90ea01e05 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -97,20 +97,26 @@ namespace ranges { 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) { + 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 uninitialized_copy two ranges with unreachable sentinels"); + } + _Uninitialized_backout _Backout{_STD move(_OFirst)}; for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) { diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 4d381ab20a7..2c9e09d2a68 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1791,20 +1791,26 @@ namespace ranges { 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) { + 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 uninitialized_move two ranges with unreachable sentinels"); + } + _Uninitialized_backout _Backout{_STD move(_OFirst)}; for (; _IFirst != _ILast && _Backout._Last != _OLast; ++_IFirst) { From 33df5861fa0223caa609cf5d6eaf5af16f121c3f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Feb 2025 21:41:17 -0800 Subject: [PATCH 27/35] Enhancement (for CoE): After _INVALID_MEMORY_ORDER, consistently fallthrough to seq_cst. We were already doing this in other places. --- stl/inc/atomic | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/stl/inc/atomic b/stl/inc/atomic index 0545d54a405..3bab8dbc58f 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -138,18 +138,17 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { case _Atomic_memory_order_relaxed: \ _Result = __iso_volatile_load##_Width(_Ptr); \ break; \ + case _Atomic_memory_order_release: \ + case _Atomic_memory_order_acq_rel: \ + default: \ + _INVALID_MEMORY_ORDER; \ + _FALLTHROUGH; \ case _Atomic_memory_order_consume: \ case _Atomic_memory_order_acquire: \ case _Atomic_memory_order_seq_cst: \ _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 @@ -158,15 +157,15 @@ extern "C" inline void _Check_memory_order(const unsigned int _Order) noexcept { switch (_Order_var) { \ case _Atomic_memory_order_relaxed: \ break; \ - case _Atomic_memory_order_consume: \ - case _Atomic_memory_order_acquire: \ - case _Atomic_memory_order_seq_cst: \ - _Compiler_or_memory_barrier(); \ - break; \ case _Atomic_memory_order_release: \ case _Atomic_memory_order_acq_rel: \ default: \ _INVALID_MEMORY_ORDER; \ + _FALLTHROUGH; \ + case _Atomic_memory_order_consume: \ + case _Atomic_memory_order_acquire: \ + case _Atomic_memory_order_seq_cst: \ + _Compiler_or_memory_barrier(); \ break; \ } From 81776a0bcf3ff4255e38f9b595550c29579c884c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 00:41:13 -0800 Subject: [PATCH 28/35] Enhancement: _STL_ASSERT => _STL_VERIFY for checks within IDL >= 1. We don't really care about IDL exactly equal to 1, but these should clearly be checked in IDL=1 release, consistent with the following checks. --- stl/inc/xstring | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index 53896acd62a..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); From 0f562b8ab2621b16727ed63e7c0790c9dac7ba9f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 01:04:56 -0800 Subject: [PATCH 29/35] Enhancement: Replace _STL_ASSERT with _STL_INTERNAL_STATIC_ASSERT. These conditions are already guaranteed by `duration` and `ratio`. They don't need to be checked for users, especially at runtime. --- stl/inc/chrono | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/stl/inc/chrono b/stl/inc/chrono index c017d6b5068..ff9081e1dc5 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1608,8 +1608,12 @@ 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. + + _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; - _STL_ASSERT(_Duration::period::num > 0 && _Den > 0, "Numerator and denominator can't be less than 1."); + 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) { From 925cd6ad51cc5614e44d19506e9f71d55687f1a0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Feb 2025 23:55:48 -0800 Subject: [PATCH 30/35] Enhancement: Remove IDL=2 null asserts from auto_ptr deref/arrow. It's silly to assert that _Myptr is non-null when we're about to dereference it (or return it for imminent dereferencing). We purged this category of asserts from the STL aeons ago, but must have missed auto_ptr. The idea is that null dereferences are just as obvious in the debugger. Note that this makes the code consistent with unique_ptr and shared_ptr. --- stl/inc/memory | 8 -------- 1 file changed, 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 6b90ea01e05..0d789cfcebc 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1049,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(); } From a6ea00a89924581a63d2e3a523c7b5fb2d092ac5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 04:47:38 -0800 Subject: [PATCH 31/35] Enhancement: _Span_iterator::operator-= was unconditionally checking. First, a cleanup: _Verify_offset does something for IDL >= 1 only, so we can guard the callsite in operator+=. In operator-=, the pathological "integer overflow" check was being performed unconditionally. Guard it for IDL >= 1, and the following _Verify_offset call. --- stl/inc/span | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stl/inc/span b/stl/inc/span index d698310c0db..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; } From b1f76b8d7dfab67661a776aca52d437fbdc45cec Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 23:50:34 -0800 Subject: [PATCH 32/35] Enhancement: Improve `_STL_REPORT_ERROR`, `_STL_VERIFY` codegen. See: https://godbolt.org/z/b95sjPPGo And: https://github.com/microsoft/STL/blob/fc15609a0f2ae2a134c34e7c9a13977994f37367/stl/inc/atomic#L103-L105 `do { ... } while (false)` has debug codegen costs. We don't need this because we ALWAYS use braces for control flow. `if (cond) { } else { ... }` also has debug codegen costs. We control the conditions, and the Standard's specification for boolean-testable has improved, so we shouldn't need this. We can drop `-Wassume` ("assumption is ignored because it contains (potential) side-effects") suppression for Clang in `_STL_VERIFY`. Clang doesn't support `/analyze`, but VSO_0938757_attribute_order is special - it runs Clang with `/D_PREFAST_` to verify that we're ordering standard attributes before non-standard attributes. Because this is the only test that's activating `_Analysis_assume_` for Clang, compiling it with `-Wno-assume` is better than modifying the product code. --- stl/inc/yvals.h | 38 +++++-------------- .../tests/VSO_0938757_attribute_order/env.lst | 2 +- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 99cb832ed3d..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) 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" From 05fdc63af81736ecedc1a770c5c9a812f0dfec34 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Feb 2025 02:57:13 -0800 Subject: [PATCH 33/35] Code cleanup: Use `_Check_MEOW_memory_order` to avoid some `_FALLTHROUGH` in ``. For `_ATOMIC_LOAD_ARM64` and `_ATOMIC_POST_LOAD_BARRIER_AS_NEEDED`, use `_Check_load_memory_order` and arrange the control flow to preserve the fallthrough behavior. Because `_Check_load_memory_order` takes a real enum, we need to compare against the enumerators and avoid `static_cast(_Order)`. For `_ATOMIC_STORE_PREFIX`, expand this **absolutely hideous** macro at each point of usage, then perform a similar transformation. As a bonus, we get to drop a bunch of early `return;`s. --- stl/inc/atomic | 110 +++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 64 deletions(-) diff --git a/stl/inc/atomic b/stl/inc/atomic index 3bab8dbc58f..000559221f9 100644 --- a/stl/inc/atomic +++ b/stl/inc/atomic @@ -134,54 +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_release: \ - case _Atomic_memory_order_acq_rel: \ - default: \ - _INVALID_MEMORY_ORDER; \ - _FALLTHROUGH; \ - 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; \ } #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_release: \ - case _Atomic_memory_order_acq_rel: \ - default: \ - _INVALID_MEMORY_ORDER; \ - _FALLTHROUGH; \ - 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; \ - } - -#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; \ - case _Atomic_memory_order_consume: \ - case _Atomic_memory_order_acquire: \ - case _Atomic_memory_order_acq_rel: \ - default: \ - _INVALID_MEMORY_ORDER; \ - _FALLTHROUGH; + } #define _ATOMIC_STORE_SEQ_CST_ARM(_Width, _Ptr, _Desired) \ _Memory_barrier(); \ @@ -730,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; } } @@ -743,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); } @@ -833,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; } } @@ -846,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); } @@ -935,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; } } @@ -948,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); } @@ -1037,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; } } @@ -1050,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 @@ -1059,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); } @@ -3035,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 From 7f6b11b59442407e896eeb10d79bedaa68d0aeb2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Feb 2025 16:28:12 -0800 Subject: [PATCH 34/35] Improve debug messages: "stores" => "contains" --- stl/inc/expected | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 4edea7d9d21..45eb51a5fb6 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -621,38 +621,38 @@ public: // [expected.object.obs] _NODISCARD constexpr const _Ty* operator->() const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "operator->() called on a std::expected that stores an error, not a value"); + _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, "operator->() called on a std::expected that stores an error, not a value"); + _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, "operator*() called on a std::expected that stores an error, not a value"); + _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, "operator*() called on a std::expected that stores an error, not a value"); + _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, "operator*() called on a std::expected that stores an error, not a value"); + _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, "operator*() called on a std::expected that stores an error, not a value"); + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); #endif return _STD move(_Value); } @@ -707,25 +707,25 @@ public: _NODISCARD constexpr const _Err& error() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores a value, not an error"); + _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, "error() called on a std::expected that stores a value, not an error"); + _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, "error() called on a std::expected that stores a value, not an error"); + _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, "error() called on a std::expected that stores a value, not an error"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif return _STD move(_Unexpected); } @@ -1469,7 +1469,7 @@ public: constexpr void operator*() const noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Has_value, "operator*() called on a std::expected that stores an error, not a value"); + _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); #endif } @@ -1490,25 +1490,25 @@ public: _NODISCARD constexpr const _Err& error() const& noexcept { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(!_Has_value, "error() called on a std::expected that stores a value, not an error"); + _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, "error() called on a std::expected that stores a value, not an error"); + _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, "error() called on a std::expected that stores a value, not an error"); + _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, "error() called on a std::expected that stores a value, not an error"); + _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif return _STD move(_Unexpected); } From 5fee29e02d8ada87bac04703404f95c234b3ebe2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 6 Feb 2025 21:29:15 -0800 Subject: [PATCH 35/35] Code review feedback: Improve debug messages and whitespace. --- stl/inc/__msvc_ranges_tuple_formatter.hpp | 2 +- stl/inc/array | 12 ++++++------ stl/inc/chrono | 3 +-- stl/inc/memory | 2 +- stl/inc/xmemory | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/stl/inc/__msvc_ranges_tuple_formatter.hpp b/stl/inc/__msvc_ranges_tuple_formatter.hpp index 34feaed5f93..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_REPORT_ERROR("basic_format_arg is in an 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/array b/stl/inc/array index 71c2b94e3ef..77bf40f14f1 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -708,7 +708,7 @@ public: _NODISCARD reference operator[](size_type) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array subscript invalid"); + _STL_REPORT_ERROR("array subscript is invalid"); #endif return *data(); @@ -716,7 +716,7 @@ public: _NODISCARD const_reference operator[](size_type) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array subscript invalid"); + _STL_REPORT_ERROR("array subscript is invalid"); #endif return *data(); @@ -724,7 +724,7 @@ public: _NODISCARD reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::front() invalid"); + _STL_REPORT_ERROR("array::front() is invalid"); #endif return *data(); @@ -732,7 +732,7 @@ public: _NODISCARD const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::front() invalid"); + _STL_REPORT_ERROR("array::front() is invalid"); #endif return *data(); @@ -740,7 +740,7 @@ public: _NODISCARD reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::back() invalid"); + _STL_REPORT_ERROR("array::back() is invalid"); #endif return *data(); @@ -748,7 +748,7 @@ public: _NODISCARD const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_REPORT_ERROR("array::back() invalid"); + _STL_REPORT_ERROR("array::back() is invalid"); #endif return *data(); diff --git a/stl/inc/chrono b/stl/inc/chrono index ff9081e1dc5..b71235f710d 100644 --- a/stl/inc/chrono +++ b/stl/inc/chrono @@ -1612,8 +1612,7 @@ namespace chrono { _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; - + 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/memory b/stl/inc/memory index 0d789cfcebc..3770d48706d 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -114,7 +114,7 @@ namespace ranges { // 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 uninitialized_copy two ranges with unreachable sentinels"); + _STL_ASSERT(false, "Tried to std::uninitialized_copy() two ranges with unreachable sentinels"); } _Uninitialized_backout _Backout{_STD move(_OFirst)}; diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 2c9e09d2a68..acac82131e1 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1808,7 +1808,7 @@ namespace ranges { // 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 uninitialized_move two ranges with unreachable sentinels"); + _STL_ASSERT(false, "Tried to std::uninitialized_move() two ranges with unreachable sentinels"); } _Uninitialized_backout _Backout{_STD move(_OFirst)};