From 7d01c7c5b5b51542a0a4bcd2406172a37c04846d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 14:12:54 -0800 Subject: [PATCH 01/42] Exclude valarray's 28 binary ops, no test impact. --- stl/inc/valarray | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/stl/inc/valarray b/stl/inc/valarray index 5773a639e2..9de6bd8d80 100644 --- a/stl/inc/valarray +++ b/stl/inc/valarray @@ -290,7 +290,7 @@ public: } valarray& operator*=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -301,7 +301,7 @@ public: } valarray& operator/=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -312,7 +312,7 @@ public: } valarray& operator%=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -323,7 +323,7 @@ public: } valarray& operator+=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -334,7 +334,7 @@ public: } valarray& operator-=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -345,7 +345,7 @@ public: } valarray& operator^=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -356,7 +356,7 @@ public: } valarray& operator|=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -367,7 +367,7 @@ public: } valarray& operator&=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -378,7 +378,7 @@ public: } valarray& operator<<=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -389,7 +389,7 @@ public: } valarray& operator>>=(const valarray& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize == _Right._Mysize, "valarrays of different lengths"); #endif const size_t _Size = _Mysize; // eliminating indirection helps vectorization @@ -866,7 +866,7 @@ _NODISCARD _Boolarray operator||(const typename valarray<_Ty>::value_type& _Left _EXPORT_STD template _NODISCARD valarray<_Ty> operator*(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -879,7 +879,7 @@ _NODISCARD valarray<_Ty> operator*(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator/(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -892,7 +892,7 @@ _NODISCARD valarray<_Ty> operator/(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator%(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -905,7 +905,7 @@ _NODISCARD valarray<_Ty> operator%(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator+(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -918,7 +918,7 @@ _NODISCARD valarray<_Ty> operator+(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator-(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -931,7 +931,7 @@ _NODISCARD valarray<_Ty> operator-(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator^(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -944,7 +944,7 @@ _NODISCARD valarray<_Ty> operator^(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator&(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -957,7 +957,7 @@ _NODISCARD valarray<_Ty> operator&(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator|(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -970,7 +970,7 @@ _NODISCARD valarray<_Ty> operator|(const valarray<_Ty>& _Left, const valarray<_T _EXPORT_STD template _NODISCARD valarray<_Ty> operator<<(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -983,7 +983,7 @@ _NODISCARD valarray<_Ty> operator<<(const valarray<_Ty>& _Left, const valarray<_ _EXPORT_STD template _NODISCARD valarray<_Ty> operator>>(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -996,7 +996,7 @@ _NODISCARD valarray<_Ty> operator>>(const valarray<_Ty>& _Left, const valarray<_ _EXPORT_STD template _NODISCARD _Boolarray operator&&(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -1009,7 +1009,7 @@ _NODISCARD _Boolarray operator&&(const valarray<_Ty>& _Left, const valarray<_Ty> _EXPORT_STD template _NODISCARD _Boolarray operator||(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -1042,7 +1042,7 @@ _NODISCARD _Boolarray operator==(const typename valarray<_Ty>::value_type& _Left _EXPORT_STD template _NODISCARD _Boolarray operator==(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -1075,7 +1075,7 @@ _NODISCARD _Boolarray operator!=(const typename valarray<_Ty>::value_type& _Left _EXPORT_STD template _NODISCARD _Boolarray operator!=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -1108,7 +1108,7 @@ _NODISCARD _Boolarray operator<(const typename valarray<_Ty>::value_type& _Left, _EXPORT_STD template _NODISCARD _Boolarray operator<(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -1141,7 +1141,7 @@ _NODISCARD _Boolarray operator>(const typename valarray<_Ty>::value_type& _Left, _EXPORT_STD template _NODISCARD _Boolarray operator>(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -1174,7 +1174,7 @@ _NODISCARD _Boolarray operator<=(const typename valarray<_Ty>::value_type& _Left _EXPORT_STD template _NODISCARD _Boolarray operator<=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); @@ -1207,7 +1207,7 @@ _NODISCARD _Boolarray operator>=(const typename valarray<_Ty>::value_type& _Left _EXPORT_STD template _NODISCARD _Boolarray operator>=(const valarray<_Ty>& _Left, const valarray<_Ty>& _Right) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Left.size() == _Right.size(), "valarrays of different lengths"); #endif const size_t _Size = _Left.size(); From 96471c5969ce4f1e50d90303ebc3f5f506ca2bd3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 14:19:23 -0800 Subject: [PATCH 02/42] Exclude condition_variable::wait_until, no test impact. --- stl/inc/mutex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/mutex b/stl/inc/mutex index 0daa8314b5..3f5ab3d1b7 100644 --- a/stl/inc/mutex +++ b/stl/inc/mutex @@ -584,12 +584,12 @@ public: cv_status wait_until(unique_lock& _Lck, const chrono::time_point<_Clock, _Duration>& _Abs_time) { // wait until time point static_assert(chrono::_Is_clock_v<_Clock>, "Clock type required"); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY( _Lck.owns_lock(), "wait_until's caller must own the lock argument (N4958 [thread.condition.condvar]/17)"); _STL_VERIFY(_Mtx_current_owns(_Lck.mutex()->_Mymtx()), "wait_until's calling thread must hold the lock argument's mutex (N4958 [thread.condition.condvar]/17)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 for (;;) { const auto _Now = _Clock::now(); if (_Abs_time <= _Now) { From 809bbeee2b925a7b59bd5d69239dc4930ee108ff Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 14:49:16 -0800 Subject: [PATCH 03/42] Exclude basic_string::resize_and_overwrite, no test impact. --- stl/inc/xstring | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index e18772035b..d8c8884660 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -2391,10 +2391,10 @@ public: auto _Arg_size = _New_size; const auto _Result_size = _STD move(_Op)(_Arg_ptr, _Arg_size); const auto _Result_as_size_type = static_cast(_Result_size); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Result_size >= 0, "the returned size can't be smaller than 0"); _STL_VERIFY(_Result_as_size_type <= _New_size, "the returned size can't be greater than the passed size"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 _Eos(_Result_as_size_type); } From bd4e2badd479e9a706ae810851d8a84ff9a24168 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 14:55:30 -0800 Subject: [PATCH 04/42] Exclude basic_string_view's ctor, update test coverage. --- stl/inc/__msvc_string_view.hpp | 2 +- tests/std/tests/VSO_0000000_string_view_idl/test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 5e973ade48..7c1043143f 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -1379,7 +1379,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer constexpr basic_string_view( _In_reads_(_Count) const const_pointer _Cts, const size_type _Count) noexcept // strengthened : _Mydata(_Cts), _Mysize(_Count) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count == 0 || _Cts, "non-zero size null string_view"); #endif } diff --git a/tests/std/tests/VSO_0000000_string_view_idl/test.cpp b/tests/std/tests/VSO_0000000_string_view_idl/test.cpp index 7b52fcb5c1..9f18f1a11e 100644 --- a/tests/std/tests/VSO_0000000_string_view_idl/test.cpp +++ b/tests/std/tests/VSO_0000000_string_view_idl/test.cpp @@ -239,6 +239,7 @@ int main(int argc, char* argv[]) { test_case_operator_less_incompatible_value_initialized, test_case_remove_prefix_incompatible, test_case_remove_suffix_incompatible, + test_case_null_constructor, }); #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -251,7 +252,6 @@ int main(int argc, char* argv[]) { test_case_remove_prefix_too_large, test_case_remove_suffix_too_large, test_case_Copy_s, - test_case_null_constructor, }); return exec.run(argc, argv); From 1f933a7a9f0613b23728fa00a404f3f317fe16fd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 14:43:02 -0800 Subject: [PATCH 05/42] Exclude span::size_bytes, update test coverage. --- stl/inc/span | 2 +- tests/std/tests/P0122R7_span_death/test.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/span b/stl/inc/span index 4f043ea279..3099483be5 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -434,7 +434,7 @@ public: #pragma warning(push) #pragma warning(disable : 4127) // conditional expression is constant _NODISCARD constexpr size_type size_bytes() const noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize <= dynamic_extent / sizeof(element_type), "size of span in bytes exceeds std::numeric_limits::max()"); #endif diff --git a/tests/std/tests/P0122R7_span_death/test.cpp b/tests/std/tests/P0122R7_span_death/test.cpp index 545b6729de..1b4c668117 100644 --- a/tests/std/tests/P0122R7_span_death/test.cpp +++ b/tests/std/tests/P0122R7_span_death/test.cpp @@ -330,6 +330,7 @@ int main(int argc, char* argv[]) { test_case_algorithm_incompatible_different_size, test_case_algorithm_incompatible_value_initialized, test_case_algorithm_incompatible_transposed, + test_case_size_bytes_overflow, }); #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -351,7 +352,6 @@ int main(int argc, char* argv[]) { test_case_subspan_excessive_runtime_count_dynamic_extent, test_case_subspan_excessive_runtime_offset_static_extent, test_case_subspan_excessive_runtime_count_static_extent, - test_case_size_bytes_overflow, test_case_operator_subscript_out_of_range_dynamic_extent, test_case_operator_subscript_out_of_range_static_extent, test_case_front_empty_dynamic_extent, From a96d50ba56e96351de9258d101630336ba423395 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 19:48:05 -0800 Subject: [PATCH 06/42] Exclude most of ``, update test coverage. Need to silence Clang -Wunused-variable warnings in the tests. --- stl/inc/mdspan | 100 +++++++++--------- .../P0009R18_mdspan_extents_death/test.cpp | 6 +- .../test.cpp | 8 +- .../test.cpp | 8 +- .../test.cpp | 6 +- .../P0009R18_mdspan_mdspan_death/test.cpp | 15 ++- 6 files changed, 80 insertions(+), 63 deletions(-) diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 714c6120c7..94d19ef370 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -100,7 +100,7 @@ private: _STL_INTERNAL_STATIC_ASSERT(sizeof...(_OtherExtents) == _Rank); _STL_INTERNAL_STATIC_ASSERT( ((_OtherExtents == dynamic_extent || _Extents == dynamic_extent || _OtherExtents == _Extents) && ...)); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (rank() > 0) { for (rank_type _Idx = 0; _Idx < _Rank; ++_Idx) { if constexpr (rank() != rank_dynamic()) { @@ -114,7 +114,7 @@ private: "r (N4950 [mdspan.extents.cons]/2.2)"); } } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } template @@ -126,7 +126,7 @@ private: requires (tuple_size_v<_ExtsTuple> != _Rank_dynamic) constexpr explicit extents(_Extents_from_tuple, _ExtsTuple _Tpl, index_sequence<_DynIndices...>) noexcept : _Base{static_cast(_STD move(_STD get<_Dynamic_indices_inv[_DynIndices]>(_Tpl)))...} { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 [&](index_sequence<_MixedIndices...>) { _STL_VERIFY(((_Static_extents[_MixedIndices] == dynamic_extent || _STD cmp_equal(_Static_extents[_MixedIndices], @@ -135,7 +135,7 @@ private: "Value of exts_arr[r] must be equal to extent(r) for each r for which extent(r) is a static extent " "(N4950 [mdspan.extents.cons]/7.1)"); }(make_index_sequence{}); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } template @@ -143,13 +143,13 @@ private: : _Base{static_cast(_STD as_const(_Dynamic_exts[_Indices]))...} { _STL_INTERNAL_STATIC_ASSERT(is_convertible_v && is_nothrow_constructible_v); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Is_standard_integer<_OtherIndexType> && _Rank_dynamic != 0) { _STL_VERIFY(((_Dynamic_exts[_Indices] >= 0 && _STD in_range(_Dynamic_exts[_Indices])) && ...), "exts[r] must be representable as a nonnegative value of type index_type for every rank index r " "(N4950 [mdspan.extents.cons]/10.2)"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } template @@ -158,7 +158,7 @@ private: _STL_INTERNAL_STATIC_ASSERT(_Size != _Rank_dynamic); _STL_INTERNAL_STATIC_ASSERT(is_convertible_v && is_nothrow_constructible_v); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Is_standard_integer<_OtherIndexType>) { for (rank_type _Idx = 0; _Idx < _Rank; ++_Idx) { _STL_VERIFY( @@ -170,7 +170,7 @@ private: "(N4950 [mdspan.extents.cons]/10.2)"); } } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } public: @@ -183,14 +183,14 @@ public: } _NODISCARD static constexpr size_t static_extent(_In_range_(<, _Rank) const rank_type _Idx) noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Idx < _Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/1)"); #endif return _Static_extents[_Idx]; } _NODISCARD constexpr index_type extent(_In_range_(<, _Rank) const rank_type _Idx) const noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Idx < _Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/3)"); #endif if constexpr (rank_dynamic() == 0) { @@ -222,7 +222,7 @@ public: && (sizeof...(_OtherIndexTypes) == rank_dynamic() || sizeof...(_OtherIndexTypes) == rank()) constexpr explicit extents(_OtherIndexTypes... _Exts) noexcept : extents(_Extents_from_tuple{}, _STD tie(_Exts...), make_index_sequence{}) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 auto _Check_extent = [](const _Ty& _Ext) { if constexpr (_Is_standard_integer<_Ty>) { return _Ext >= 0 && _STD in_range(_Ext); @@ -235,7 +235,7 @@ public: }; _STL_VERIFY((_Check_extent(_Exts) && ...), "Each argument must be representable as a nonnegative value of type " "index_type (N4950 [mdspan.extents.cons]/7.2)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } template @@ -463,7 +463,7 @@ struct _Maybe_fully_static_extents<_Extents> { template constexpr explicit _Maybe_fully_static_extents([[maybe_unused]] const _OtherExtents& _Exts_) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 (void) _Extents{_Exts_}; // NB: temporary created for preconditions check #endif } @@ -495,13 +495,13 @@ public: constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type& _Exts_) noexcept : _Base(_Exts_) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (extents_type::rank_dynamic() != 0) { _STL_VERIFY(_Exts_._Is_dynamic_multidim_index_space_size_representable(), "The size of the multidimensional index space e must be representable as a value of type index_type " "(N4950 [mdspan.layout.left.cons]/1)."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } template @@ -509,7 +509,7 @@ public: constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) mapping(const mapping<_OtherExtents>& _Other) noexcept : _Base(_Other.extents()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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)."); @@ -521,7 +521,7 @@ public: constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) mapping(const layout_right::mapping<_OtherExtents>& _Other) noexcept : _Base(_Other.extents()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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)."); @@ -533,7 +533,7 @@ public: constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<_OtherExtents>& _Other) noexcept // strengthened : _Base(_Other.extents()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (extents_type::rank() > 0) { index_type _Prod = 1; for (size_t _Idx = 0; _Idx < extents_type::_Rank; ++_Idx) { @@ -546,7 +546,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]/10.2)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } constexpr mapping& operator=(const mapping&) noexcept = default; @@ -594,7 +594,7 @@ public: _NODISCARD constexpr index_type stride(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept requires (extents_type::rank() > 0) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_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 @@ -612,7 +612,7 @@ private: _NODISCARD constexpr index_type _Index_impl( [[maybe_unused]] index_sequence<_Seq...> _Index_seq, _IndexTypes... _Indices) const noexcept { _STL_INTERNAL_STATIC_ASSERT(conjunction_v...>); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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)."); @@ -649,13 +649,13 @@ public: constexpr mapping(const mapping&) noexcept = default; constexpr mapping(const extents_type& _Exts_) noexcept : _Base(_Exts_) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (extents_type::rank_dynamic() != 0) { _STL_VERIFY(_Exts_._Is_dynamic_multidim_index_space_size_representable(), "The size of the multidimensional index space e must be representable as a value of type index_type " "(N4950 [mdspan.layout.right.cons]/1)."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } template @@ -663,7 +663,7 @@ public: constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) mapping(const mapping<_OtherExtents>& _Other) noexcept : _Base(_Other.extents()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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)."); @@ -675,7 +675,7 @@ public: constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>) mapping(const layout_left::mapping<_OtherExtents>& _Other) noexcept : _Base(_Other.extents()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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)."); @@ -686,7 +686,7 @@ public: requires is_constructible_v constexpr explicit(extents_type::rank() > 0) mapping(const layout_stride::mapping<_OtherExtents>& _Other) noexcept : _Base(_Other.extents()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (extents_type::rank() > 0) { index_type _Prod = 1; for (size_t _Idx = extents_type::_Rank; _Idx-- > 0;) { @@ -699,7 +699,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]/10.2)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } constexpr mapping& operator=(const mapping&) noexcept = default; @@ -747,7 +747,7 @@ public: _NODISCARD constexpr index_type stride(_In_range_(<, extents_type::_Rank) const rank_type _Idx) const noexcept requires (extents_type::rank() > 0) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_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 @@ -765,7 +765,7 @@ private: _NODISCARD constexpr index_type _Index_impl( [[maybe_unused]] index_sequence<_Seq...> _Index_seq, _IndexTypes... _Indices) const noexcept { _STL_INTERNAL_STATIC_ASSERT(conjunction_v...>); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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)."); @@ -815,7 +815,7 @@ private: : _Extents_base(_Exts_), _Strides_base{static_cast(_STD as_const(_Strides_[_Indices]))...} { _STL_INTERNAL_STATIC_ASSERT(is_convertible_v && is_nothrow_constructible_v); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (extents_type::rank() != 0) { bool _Found_zero = false; bool _Overflow = false; @@ -838,7 +838,7 @@ private: _STL_VERIFY(_Found_zero || !_Overflow, "REQUIRED-SPAN-SIZE(e, s) must be representable as a value of type " "index_type (N4950 [mdspan.layout.stride.cons]/4.2)."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } public: @@ -846,7 +846,7 @@ public: if constexpr (extents_type::rank() != 0) { this->_Array.back() = 1; for (rank_type _Idx = extents_type::_Rank - 1; _Idx-- > 0;) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 const bool _Overflow = _Mul_overflow(this->_Array[_Idx + 1], this->_Exts.extent(_Idx + 1), this->_Array[_Idx]); // NB: N4950 requires value of 'layout_right::mapping().required_span_size()' to be @@ -855,9 +855,9 @@ public: _STL_VERIFY(!_Overflow, "Value of layout_right::mapping().required_span_size() must be " "representable as a value of type index_type (N4950 [mdspan.layout.stride.cons]/1)."); -#else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL == 0 vvv +#else // ^^^ _ITERATOR_DEBUG_LEVEL != 0 / _ITERATOR_DEBUG_LEVEL == 0 vvv this->_Array[_Idx] = static_cast(this->_Array[_Idx + 1] * this->_Exts.extent(_Idx + 1)); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } } } @@ -887,17 +887,17 @@ public: || _Is_mapping_of) )) mapping(const _StridedLayoutMapping& _Other) noexcept : _Extents_base(_Other.extents()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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.stride.cons]/7.3)."); _STL_VERIFY( _Offset(_Other) == 0, "Value of OFFSET(other) must be equal to 0 (N4950 [mdspan.layout.stride.cons]/7.4)."); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 if constexpr (extents_type::_Rank != 0) { for (rank_type _Idx = 0; _Idx < extents_type::_Rank; ++_Idx) { const auto _Stride = _Other.stride(_Idx); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_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 @@ -980,7 +980,7 @@ public: _STL_REPORT_ERROR("The argument to stride must be nonnegative and less than extents_type::rank()."); return 1; } else { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Idx < extents_type::_Rank, "The argument to stride must be nonnegative and less than extents_type::rank()."); #endif @@ -1028,7 +1028,7 @@ private: _NODISCARD constexpr index_type _Index_impl( [[maybe_unused]] index_sequence<_Seq...> _Index_seq, _IndexTypes... _Indices) const noexcept { _STL_INTERNAL_STATIC_ASSERT(conjunction_v...>); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _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)."); @@ -1142,7 +1142,7 @@ struct _Mdspan_accessor_base<_AccessorPolicy> { static constexpr _AccessorPolicy _Acc{}; }; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 template _NODISCARD constexpr _IndexType _Mdspan_checked_index_cast(_OtherIndexType&& _Idx) noexcept(is_nothrow_constructible_v<_IndexType, _OtherIndexType>) { @@ -1156,7 +1156,7 @@ _NODISCARD constexpr _IndexType _Mdspan_checked_index_cast(_OtherIndexType&& _Id } return static_cast<_IndexType>(_STD forward<_OtherIndexType>(_Idx)); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 _EXPORT_STD template > @@ -1201,7 +1201,7 @@ public: } _NODISCARD static constexpr size_t static_extent(_In_range_(<, extents_type::_Rank) const rank_type _Idx) noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Idx < extents_type::_Rank, "Index must be less than rank() (N4950 [mdspan.extents.obs]/1)"); #endif return extents_type::_Static_extents[_Idx]; @@ -1306,11 +1306,11 @@ public: && (sizeof...(_OtherIndexTypes) == rank()) _NODISCARD constexpr reference operator[](_OtherIndexTypes... _Indices) const noexcept(noexcept(_Access_impl(static_cast(_STD move(_Indices))...))) /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 return _Access_impl(_STD _Mdspan_checked_index_cast(_STD move(_Indices))...); -#else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL <= 0 vvv +#else // ^^^ _ITERATOR_DEBUG_LEVEL != 0 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Access_impl(static_cast(_STD move(_Indices))...); -#endif // ^^^ _CONTAINER_DEBUG_LEVEL <= 0 ^^^ +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } #endif // ^^^ defined(__cpp_multidimensional_subscript) ^^^ @@ -1319,11 +1319,11 @@ private: _NODISCARD constexpr reference _Multidimensional_subscript( span<_OtherIndexType, rank()> _Indices, index_sequence<_Seq...>) const noexcept(noexcept(_Access_impl(static_cast(_STD as_const(_Indices[_Seq]))...))) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 return _Access_impl(_STD _Mdspan_checked_index_cast(_STD as_const(_Indices[_Seq]))...); -#else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL <= 0 vvv +#else // ^^^ _ITERATOR_DEBUG_LEVEL != 0 / _ITERATOR_DEBUG_LEVEL == 0 vvv return _Access_impl(static_cast(_STD as_const(_Indices[_Seq]))...); -#endif // ^^^ _CONTAINER_DEBUG_LEVEL <= 0 ^^^ +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } public: @@ -1344,13 +1344,13 @@ public: } _NODISCARD constexpr size_type size() const noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (rank_dynamic() != 0) { _STL_VERIFY(this->_Map.extents().template _Is_dynamic_multidim_index_space_size_representable(), "The size of the multidimensional index space extents() must be representable as a value of type " "size_type (N4950 [mdspan.mdspan.members]/7)."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 return static_cast( _Fwd_prod_of_extents::_Calculate(this->_Map.extents(), extents_type::_Rank)); } diff --git a/tests/std/tests/P0009R18_mdspan_extents_death/test.cpp b/tests/std/tests/P0009R18_mdspan_extents_death/test.cpp index bdb9279c6a..2ef5d3fc05 100644 --- a/tests/std/tests/P0009R18_mdspan_extents_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_extents_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 @@ -97,6 +95,8 @@ void test_construction_from_array_with_unrepresentable_as_index_type_values() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; + +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_static_extent_function_with_invalid_index, test_extent_function_with_invalid_index, @@ -111,5 +111,7 @@ int main(int argc, char* argv[]) { test_construction_from_array_with_invalid_values, test_construction_from_array_with_unrepresentable_as_index_type_values, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + return exec.run(argc, argv); } diff --git a/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp index b0b5f031e7..ce0fb91171 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_left_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_left_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 @@ -41,7 +39,7 @@ void test_construction_from_other_stride_mapping_1() { layout_stride::mapping m1{Ext{}, array{4, 1}}; // For all r in the range [0, extents_type::rank()), other.stride(r) must be equal to // extents().fwd-prod-of-extents(r) - layout_left::mapping m2{m1}; + [[maybe_unused]] layout_left::mapping m2{m1}; } void test_construction_from_other_stride_mapping_2() { @@ -67,6 +65,8 @@ void test_stride_function() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; + +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_construction_from_extents_type_with_signed_index_type, test_construction_from_extents_type_with_unsigned_index_type, @@ -77,5 +77,7 @@ int main(int argc, char* argv[]) { test_call_operator, test_stride_function, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + return exec.run(argc, argv); } diff --git a/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp index ef72ed7be3..4de267099f 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_right_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_right_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 @@ -41,7 +39,7 @@ void test_construction_from_other_stride_mapping_1() { layout_stride::mapping m1{Ext{}, array{1, 2}}; // For all r in the range [0, extents_type::rank()), other.stride(r) must be equal to // extents().rev-prod-of-extents(r) - layout_right::mapping m2{m1}; + [[maybe_unused]] layout_right::mapping m2{m1}; } void test_construction_from_other_stride_mapping_2() { @@ -67,6 +65,8 @@ void test_stride_function() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; + +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_construction_from_extents_type_with_signed_index_type, test_construction_from_extents_type_with_unsigned_index_type, @@ -77,5 +77,7 @@ int main(int argc, char* argv[]) { test_call_operator, test_stride_function, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + return exec.run(argc, argv); } diff --git a/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp b/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp index 4668facbd2..2c1cb19e7d 100644 --- a/tests/std/tests/P0009R18_mdspan_layout_stride_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_layout_stride_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 @@ -69,6 +67,8 @@ void test_stride_with_empty_extents() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; + +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_default_construction, test_construction_from_extents_and_array_1, @@ -79,5 +79,7 @@ int main(int argc, char* argv[]) { test_call_operator, test_stride_with_empty_extents, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + return exec.run(argc, argv); } diff --git a/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp b/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp index e1c3bba1a9..4100d93948 100644 --- a/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp @@ -57,16 +57,25 @@ void test_size_when_index_type_is_unsigned() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; + +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ - test_construction_from_other_mdspan, #ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 - test_access_with_invalid_multidimensional_index_1, test_access_with_nonrepresentable_index_1, #endif // __cpp_multidimensional_subscript - test_access_with_invalid_multidimensional_index_2, test_access_with_nonrepresentable_index_2, test_size_when_index_type_is_signed, test_size_when_index_type_is_unsigned, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + exec.add_death_tests({ + test_construction_from_other_mdspan, +#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 + test_access_with_invalid_multidimensional_index_1, +#endif // __cpp_multidimensional_subscript + test_access_with_invalid_multidimensional_index_2, + }); + return exec.run(argc, argv); } From 4da1340e4cb419fc81d9761032d13d7eeeffc3ed Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 14:27:32 -0800 Subject: [PATCH 07/42] Exclude ``, update test coverage. --- stl/inc/generator | 6 +++--- tests/std/tests/P2502R2_generator_death/test.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stl/inc/generator b/stl/inc/generator index 09c16afc33..69aa0d5b81 100644 --- a/stl/inc/generator +++ b/stl/inc/generator @@ -477,14 +477,14 @@ namespace _Gen_detail { _NODISCARD _Ref operator*() const noexcept(noexcept(static_cast<_Ref>(*_Coro.promise()._Get_top().promise()._Ptr))) /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Coro.done(), "Can't dereference generator end iterator"); #endif return static_cast<_Ref>(*_Coro.promise()._Get_top().promise()._Ptr); } _Iterator& operator++() { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Coro.done(), "Can't increment generator end iterator"); #endif _Coro.promise()._Get_top().resume(); @@ -565,7 +565,7 @@ public: _NODISCARD _Gen_detail::_Iter_provider<_Value, _Ref>::_Iterator begin() { // Pre: _Coro is suspended at its initial suspend point -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Coro, "Can't call begin on moved-from generator"); #endif _Coro.resume(); diff --git a/tests/std/tests/P2502R2_generator_death/test.cpp b/tests/std/tests/P2502R2_generator_death/test.cpp index edf602a32c..990f5639e7 100644 --- a/tests/std/tests/P2502R2_generator_death/test.cpp +++ b/tests/std/tests/P2502R2_generator_death/test.cpp @@ -5,8 +5,6 @@ int main() {} #else // ^^^ workaround / no workaround vvv -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include @@ -43,12 +41,14 @@ void test_end_iterator_incrementation() { int main(int argc, char** argv) { std_testing::death_test_executive exec; +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_begin_after_initial_suspend_point, test_begin_after_moving_from, test_end_iterator_dereference, test_end_iterator_incrementation, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From 1acddc8ec9259f7d044236002f994fc57bafb0fb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:44:42 -0800 Subject: [PATCH 08/42] Exclude iota_view, update test coverage. --- stl/inc/ranges | 12 ++++++------ tests/std/tests/P0896R4_views_iota_death/test.cpp | 6 ++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 3af972f884..6ef58c5676 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -959,34 +959,34 @@ namespace ranges { constexpr explicit iota_view(_Wi _Value_) noexcept(is_nothrow_move_constructible_v<_Wi> && is_nothrow_default_constructible_v<_Bo>) // strengthened : _Value(_STD move(_Value_)) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (totally_ordered_with<_Wi, _Bo>) { _STL_VERIFY(_Value_ <= _Bound, "Per N4981 [range.iota.view]/6, the first argument must not exceed the " "value-initialized bound when their types are totally ordered."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } constexpr explicit iota_view(type_identity_t<_Wi> _Value_, type_identity_t<_Bo> _Bound_) noexcept(is_nothrow_move_constructible_v<_Wi> && is_nothrow_move_constructible_v<_Bo>) // strengthened : _Value(_STD move(_Value_)), _Bound(_STD move(_Bound_)) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (totally_ordered_with<_Wi, _Bo>) { _STL_VERIFY(_Value_ <= _Bound_, "Per N4981 [range.iota.view]/8, the first argument must not exceed the " "second when their types are totally ordered."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } constexpr explicit iota_view(_It _First, _Se _Last) noexcept(is_nothrow_move_constructible_v<_Wi> && is_nothrow_move_constructible_v<_Bo>) // strengthened : _Value(_STD move(_First._Current)), _Bound(_STD move(_Bound_from(_Last))) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (totally_ordered_with<_Wi, _Bo>) { _STL_VERIFY(_Value <= _Bound, "Per N4981 [range.iota.view]/8 and /10, the iterator must not exceed the " "sentinel when their types are totally ordered."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } _NODISCARD constexpr _It begin() const noexcept(is_nothrow_copy_constructible_v<_Wi>) /* strengthened */ { diff --git a/tests/std/tests/P0896R4_views_iota_death/test.cpp b/tests/std/tests/P0896R4_views_iota_death/test.cpp index d38a5ad9a7..43ea1041ed 100644 --- a/tests/std/tests/P0896R4_views_iota_death/test.cpp +++ b/tests/std/tests/P0896R4_views_iota_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 @@ -54,7 +52,7 @@ void test_misordered_iterator_sentinel_vector_iter() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; -#ifdef _DEBUG +#if _ITERATOR_DEBUG_LEVEL != 0 struct S {}; exec.add_death_tests({ @@ -124,7 +122,7 @@ int main(int argc, char* argv[]) { test_misordered_iterator_sentinel_vector_iter, test_misordered_iterator_sentinel_vector_iter, }); -#endif // _DEBUG +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From 818163a490359ddeb0f9782903524f7badb03419 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:47:50 -0800 Subject: [PATCH 09/42] Exclude repeat_view, update test coverage. --- stl/inc/ranges | 26 +++++++++---------- .../tests/P2474R2_views_repeat_death/test.cpp | 5 ++-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 6ef58c5676..3f0a2ced25 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1109,7 +1109,7 @@ namespace ranges { } constexpr _Iterator& operator++() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Current < (numeric_limits<_Index_type>::max)(), "cannot increment repeat_view iterator past end (integer overflow)"); #endif @@ -1123,14 +1123,14 @@ namespace ranges { } constexpr _Iterator& operator--() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (is_same_v<_Bo, unreachable_sentinel_t>) { _STL_VERIFY(_Current > (numeric_limits<_Index_type>::min)(), "cannot decrement repeat_view iterator before begin (integer overflow)"); } else { _STL_VERIFY(_Current > 0, "cannot decrement below 0"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 --_Current; return *this; } @@ -1141,7 +1141,7 @@ namespace ranges { } constexpr _Iterator& operator+=(difference_type _Off) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (sizeof(difference_type) > sizeof(_Index_type)) { _STL_VERIFY(static_cast<_Index_type>(_Off) == _Off, _Off > 0 ? "cannot advance repeat_view iterator past end (integer overflow)" @@ -1159,12 +1159,12 @@ namespace ranges { if constexpr (!is_same_v<_Bo, unreachable_sentinel_t>) { _STL_VERIFY(_Current + _Off >= 0, "cannot subtract below 0"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 _Current += static_cast<_Index_type>(_Off); return *this; } constexpr _Iterator& operator-=(difference_type _Off) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (sizeof(difference_type) > sizeof(_Index_type)) { _STL_VERIFY(static_cast<_Index_type>(_Off) == _Off, _Off < 0 ? "cannot advance repeat_view iterator past end (integer overflow)" @@ -1182,7 +1182,7 @@ namespace ranges { if constexpr (!is_same_v<_Bo, unreachable_sentinel_t>) { _STL_VERIFY(_Current - _Off >= 0, "cannot subtract below 0"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 _Current -= static_cast<_Index_type>(_Off); return *this; } @@ -1239,20 +1239,20 @@ namespace ranges { noexcept(is_nothrow_copy_constructible_v<_Ty>) // strengthened requires copy_constructible<_Ty> : _Value(in_place, _Value_), _Bound(_STD move(_Bound_)) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } _NODISCARD_CTOR constexpr explicit repeat_view(_Ty&& _Value_, _Bo _Bound_ = _Bo{}) noexcept(is_nothrow_move_constructible_v<_Ty>) // strengthened : _Value(in_place, _STD move(_Value_)), _Bound(_STD move(_Bound_)) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } template requires constructible_from<_Ty, _TArgs...> && constructible_from<_Bo, _BArgs...> @@ -1261,11 +1261,11 @@ namespace ranges { noexcept(is_nothrow_constructible_v<_Ty, _TArgs...> && noexcept(_STD make_from_tuple<_Bo>(_Bound_args))) // strengthened : repeat_view(_Val_args, index_sequence_for<_TArgs...>{}, _STD make_from_tuple<_Bo>(_Bound_args)) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 } _NODISCARD constexpr _Iterator begin() const noexcept /* strengthened */ { diff --git a/tests/std/tests/P2474R2_views_repeat_death/test.cpp b/tests/std/tests/P2474R2_views_repeat_death/test.cpp index 77ea4d0290..920a926135 100644 --- a/tests/std/tests/P2474R2_views_repeat_death/test.cpp +++ b/tests/std/tests/P2474R2_views_repeat_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 @@ -129,6 +127,7 @@ void test_iter_sub_neg_huge() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_view_lvalue_negative, test_view_rvalue_negative, @@ -155,5 +154,7 @@ int main(int argc, char* argv[]) { test_iter_sub_neg_huge, test_iter_sub_neg_huge, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + return exec.run(argc, argv); } From 03d1405f8946bdc8b416135e3db2c4926533d1d2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:48:30 -0800 Subject: [PATCH 10/42] Exclude filter_view, update test coverage. --- stl/inc/ranges | 4 ++-- tests/std/tests/P0896R4_views_filter_death/test.cpp | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 3f0a2ced25..fe883da1d7 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1759,14 +1759,14 @@ namespace ranges { } _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "filter_view has no predicate"); #endif return *_Pred; } _NODISCARD constexpr _Iterator begin() { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY( _Pred, "N4950 [range.filter.view]/3 forbids calling begin on a filter_view that holds no predicate"); #endif diff --git a/tests/std/tests/P0896R4_views_filter_death/test.cpp b/tests/std/tests/P0896R4_views_filter_death/test.cpp index 6a79aa699a..d6f119b6ea 100644 --- a/tests/std/tests/P0896R4_views_filter_death/test.cpp +++ b/tests/std/tests/P0896R4_views_filter_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 @@ -180,11 +178,6 @@ int main(int argc, char* argv[]) { test_iter_swap_value_initialized_iterator_left, test_iter_swap_value_initialized_iterator_right, }); -#else // ^^^ test everything / test only _CONTAINER_DEBUG_LEVEL cases vvv - exec.add_death_tests({ - test_view_predicate, - test_view_begin, - }); #endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); From 7d52a2305f0f9362fdb08a855a2d7be851b91c3a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:48:51 -0800 Subject: [PATCH 11/42] Exclude take_view, update test coverage. --- stl/inc/ranges | 2 +- tests/std/tests/P0896R4_views_take_death/test.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index fe883da1d7..eefcfbadc3 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1915,7 +1915,7 @@ namespace ranges { constexpr explicit take_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)), _Count{_Count_} { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count_ >= 0, "Number of elements to take must be non-negative (N4971 [range.take.view]/1)"); #endif } diff --git a/tests/std/tests/P0896R4_views_take_death/test.cpp b/tests/std/tests/P0896R4_views_take_death/test.cpp index 54c26053f5..325100b547 100644 --- a/tests/std/tests/P0896R4_views_take_death/test.cpp +++ b/tests/std/tests/P0896R4_views_take_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 @@ -17,11 +15,11 @@ void test_constructor_negative_size() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; -#ifdef _DEBUG +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_constructor_negative_size, }); -#endif // _DEBUG +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From 6c79b36fe464136a8be22ecaae21b65e1ceb98a4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:49:25 -0800 Subject: [PATCH 12/42] Exclude take_while_view, update test coverage. --- stl/inc/ranges | 6 +++--- tests/std/tests/P0896R4_views_take_while_death/test.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index eefcfbadc3..298a384f08 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2223,7 +2223,7 @@ namespace ranges { } _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "take_while_view has no predicate"); #endif return *_Pred; @@ -2245,7 +2245,7 @@ namespace ranges { noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel>) /* strengthened */ requires (!_Simple_view<_Vw>) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate"); #endif return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; @@ -2255,7 +2255,7 @@ namespace ranges { noexcept(_RANGES end(_Range)) && is_nothrow_move_constructible_v<_Sentinel>) /* strengthened */ requires range && indirect_unary_predicate> { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate"); #endif return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; diff --git a/tests/std/tests/P0896R4_views_take_while_death/test.cpp b/tests/std/tests/P0896R4_views_take_while_death/test.cpp index 3ebc5d93dd..34e3da9769 100644 --- a/tests/std/tests/P0896R4_views_take_while_death/test.cpp +++ b/tests/std/tests/P0896R4_views_take_while_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 @@ -51,11 +49,13 @@ void test_view_const_end() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_view_predicate, test_view_end, test_view_const_end, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From ad023f9dc8928ee181f8619db8131e0d7884ef45 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:49:55 -0800 Subject: [PATCH 13/42] Exclude drop_view, update test coverage. --- stl/inc/ranges | 2 +- tests/std/tests/P0896R4_views_drop_death/test.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 298a384f08..9dd6cd9580 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2335,7 +2335,7 @@ namespace ranges { constexpr explicit drop_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)), _Count{_Count_} { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count_ >= 0, "Number of elements to drop must be non-negative (N4971 [range.drop.view]/1)"); #endif } diff --git a/tests/std/tests/P0896R4_views_drop_death/test.cpp b/tests/std/tests/P0896R4_views_drop_death/test.cpp index 9205b10aa7..5d3996e6f7 100644 --- a/tests/std/tests/P0896R4_views_drop_death/test.cpp +++ b/tests/std/tests/P0896R4_views_drop_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 @@ -17,11 +15,11 @@ void test_constructor_negative_size() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; -#ifdef _DEBUG +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_constructor_negative_size, }); -#endif // _DEBUG +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From 4a87616216187258c14b784e6bbada9d8f05f8e8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:50:20 -0800 Subject: [PATCH 14/42] Exclude drop_while_view, update test coverage. --- stl/inc/ranges | 4 ++-- tests/std/tests/P0896R4_views_drop_while_death/test.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 9dd6cd9580..8e2b7776e1 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2557,14 +2557,14 @@ namespace ranges { } _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "drop_while_view has no predicate"); #endif return *_Pred; } _NODISCARD constexpr auto begin() { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY( _Pred, "N4950 [range.drop.while.view]/3 forbids calling begin on a drop_while_view with no predicate"); #endif diff --git a/tests/std/tests/P0896R4_views_drop_while_death/test.cpp b/tests/std/tests/P0896R4_views_drop_while_death/test.cpp index 9cce078838..e145c6e017 100644 --- a/tests/std/tests/P0896R4_views_drop_while_death/test.cpp +++ b/tests/std/tests/P0896R4_views_drop_while_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 @@ -48,10 +46,12 @@ void test_view_begin() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_view_predicate, test_view_begin, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From 9ef4d6228861daae5c945b22c6bb259cf9a4232f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:50:47 -0800 Subject: [PATCH 15/42] Exclude views::counted, update test coverage. --- stl/inc/ranges | 2 +- tests/std/tests/P0896R4_views_counted_death/test.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 8e2b7776e1..0e3d5de567 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -4237,7 +4237,7 @@ namespace ranges { requires (input_or_output_iterator> && _Choice<_It>._Strategy != _St::_None) _NODISCARD _STATIC_CALL_OPERATOR constexpr auto operator()(_It&& _First, const iter_difference_t> _Count) _CONST_CALL_OPERATOR noexcept(_Choice<_It>._No_throw) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count >= 0, "The size passed to views::counted must be non-negative"); #endif constexpr _St _Strat = _Choice<_It>._Strategy; diff --git a/tests/std/tests/P0896R4_views_counted_death/test.cpp b/tests/std/tests/P0896R4_views_counted_death/test.cpp index 1ec2d648cd..8bb5fdba4b 100644 --- a/tests/std/tests/P0896R4_views_counted_death/test.cpp +++ b/tests/std/tests/P0896R4_views_counted_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 @@ -17,11 +15,11 @@ void test_constructor_negative_size() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; -#ifdef _DEBUG +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_constructor_negative_size, }); -#endif // _DEBUG +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From 65d99ecb2cf46924e2589e287e24b661e5680fa4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:51:10 -0800 Subject: [PATCH 16/42] Exclude chunk_view, update test coverage. --- stl/inc/ranges | 4 ++-- tests/std/tests/P2442R1_views_chunk_death/test.cpp | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 0e3d5de567..96543f62c2 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -5669,7 +5669,7 @@ namespace ranges { constexpr explicit chunk_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ : _Range(_STD move(_Range_)), _Count{_Count_} { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count > 0, "chunk size must be greater than 0"); #endif } @@ -5942,7 +5942,7 @@ namespace ranges { constexpr explicit chunk_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ : _Range(_STD move(_Range_)), _Count{_Count_} { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count > 0, "chunk size must be greater than 0"); #endif } diff --git a/tests/std/tests/P2442R1_views_chunk_death/test.cpp b/tests/std/tests/P2442R1_views_chunk_death/test.cpp index a62cfdfac6..026e166131 100644 --- a/tests/std/tests/P2442R1_views_chunk_death/test.cpp +++ b/tests/std/tests/P2442R1_views_chunk_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 @@ -110,11 +108,6 @@ int main(int argc, char* argv[]) { test_fwd_iterator_advance_past_end_with_integer_overflow, test_fwd_iterator_advance_negative_min, }); -#else // ^^^ test everything / test only _CONTAINER_DEBUG_LEVEL cases vvv - exec.add_death_tests({ - test_view_negative_size_forward_range, - test_view_negative_size_input_range, - }); #endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); From 311d1742c86e0bb52e83688f25272efbf083714b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:51:32 -0800 Subject: [PATCH 17/42] Exclude slide_view, update test coverage. --- stl/inc/ranges | 2 +- tests/std/tests/P2442R1_views_slide_death/test.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 96543f62c2..ef2da610bc 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -6319,7 +6319,7 @@ namespace ranges { constexpr explicit slide_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ : _Range(_STD move(_Range_)), _Count{_Count_} { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count > 0, "The window size must be positive (N4950 [range.slide.view]/1)"); #endif } diff --git a/tests/std/tests/P2442R1_views_slide_death/test.cpp b/tests/std/tests/P2442R1_views_slide_death/test.cpp index 794f1e6907..fc2b1dc11b 100644 --- a/tests/std/tests/P2442R1_views_slide_death/test.cpp +++ b/tests/std/tests/P2442R1_views_slide_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 @@ -23,10 +21,12 @@ void test_view_zero_window_size() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_view_negative_window_size, test_view_zero_window_size, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } From 40ea373edfacd034bb7c2ca4194784b515b871d3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:51:57 -0800 Subject: [PATCH 18/42] Exclude chunk_by_view, update test coverage. --- stl/inc/ranges | 4 ++-- tests/std/tests/P2443R1_views_chunk_by_death/test.cpp | 7 ------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index ef2da610bc..7586ffacc8 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -6595,14 +6595,14 @@ namespace ranges { } _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "chunk_by_view has no predicate"); #endif return *_Pred; } _NODISCARD constexpr _Iterator begin() { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pred, "cannot call begin on a chunk_by_view with no predicate"); #endif diff --git a/tests/std/tests/P2443R1_views_chunk_by_death/test.cpp b/tests/std/tests/P2443R1_views_chunk_by_death/test.cpp index 0796597520..f414c1ac07 100644 --- a/tests/std/tests/P2443R1_views_chunk_by_death/test.cpp +++ b/tests/std/tests/P2443R1_views_chunk_by_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 @@ -106,11 +104,6 @@ int main(int argc, char* argv[]) { test_operator_postdecrement_value_initialized_iterator, test_operator_postdecrement_before_begin, }); -#else // ^^^ test everything / test only _CONTAINER_DEBUG_LEVEL cases vvv - exec.add_death_tests({ - test_view_predicate, - test_view_begin, - }); #endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); From 705b09626bc62c7582e432f95cba85788fb217f2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:52:22 -0800 Subject: [PATCH 19/42] Exclude stride_view, update test coverage. --- stl/inc/ranges | 2 +- tests/std/tests/P1899R3_views_stride_death/test.cpp | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 7586ffacc8..1b6517b70a 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -6927,7 +6927,7 @@ namespace ranges { constexpr explicit stride_view(_Vw _Range_, range_difference_t<_Vw> _Stride_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)), _Stride(_Stride_) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Stride > 0, "stride must be greater than 0"); #endif } diff --git a/tests/std/tests/P1899R3_views_stride_death/test.cpp b/tests/std/tests/P1899R3_views_stride_death/test.cpp index ffe1afd65e..0cebca9f4b 100644 --- a/tests/std/tests/P1899R3_views_stride_death/test.cpp +++ b/tests/std/tests/P1899R3_views_stride_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 @@ -66,10 +64,6 @@ int main(int argc, char* argv[]) { test_iterator_advance_past_end_with_integer_overflow, test_iterator_advance_negative_min, }); -#else // ^^^ test everything / test only _CONTAINER_DEBUG_LEVEL case vvv - exec.add_death_tests({ - test_view_negative_stride, - }); #endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); From e21a1ae5f39693d3db3f73d582406836ac59383e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 15:52:49 -0800 Subject: [PATCH 20/42] Exclude cartesian_product_view, update test coverage. --- stl/inc/ranges | 12 ++++++------ .../P2374R4_views_cartesian_product_death/test.cpp | 7 ------- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 1b6517b70a..4ded5ba5f5 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -9153,7 +9153,7 @@ namespace ranges { requires _Cartesian_product_is_sized<_First, _Rest...> { return [&](index_sequence<_Indices...>) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 const array _Sizes = {static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases)))...}; const bool _Any_zero = ((_Sizes[_Indices] == 0) || ...); if (_Any_zero) { @@ -9165,9 +9165,9 @@ namespace ranges { _STL_VERIFY(!_Overflow, "Size of cartesian product cannot be represented by size type (N4950 " "[range.cartesian.view]/10)."); return _Product; -#else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL == 0 vvv +#else // ^^^ _ITERATOR_DEBUG_LEVEL != 0 / _ITERATOR_DEBUG_LEVEL == 0 vvv return (static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases))) * ...); -#endif // ^^^ _CONTAINER_DEBUG_LEVEL == 0 ^^^ +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ }(make_index_sequence<1 + sizeof...(_Rest)>{}); } @@ -9175,7 +9175,7 @@ namespace ranges { requires _Cartesian_product_is_sized { return [&](index_sequence<_Indices...>) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 const array _Sizes = {static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases)))...}; const bool _Any_zero = ((_Sizes[_Indices] == 0) || ...); if (_Any_zero) { @@ -9187,9 +9187,9 @@ namespace ranges { _STL_VERIFY(!_Overflow, "Size of cartesian product cannot be represented by size type (N4950 " "[range.cartesian.view]/10)."); return _Product; -#else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL == 0 vvv +#else // ^^^ _ITERATOR_DEBUG_LEVEL != 0 / _ITERATOR_DEBUG_LEVEL == 0 vvv return (static_cast<_Size_type>(_RANGES size(_STD get<_Indices>(_Bases))) * ...); -#endif // ^^^ _CONTAINER_DEBUG_LEVEL == 0 ^^^ +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ }(make_index_sequence<1 + sizeof...(_Rest)>{}); } }; diff --git a/tests/std/tests/P2374R4_views_cartesian_product_death/test.cpp b/tests/std/tests/P2374R4_views_cartesian_product_death/test.cpp index 65b850caaf..9becd5d078 100644 --- a/tests/std/tests/P2374R4_views_cartesian_product_death/test.cpp +++ b/tests/std/tests/P2374R4_views_cartesian_product_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 @@ -79,11 +77,6 @@ int main(int argc, char* argv[]) { test_iterator_differencing, test_iterator_and_default_sentinel_differencing, }); -#else // ^^^ test everything / test only _CONTAINER_DEBUG_LEVEL cases vvv - exec.add_death_tests({ - test_view_size, - test_view_const_size, - }); #endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); From 19e84069d8e24b06b33e693875d43beb1e893131 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 27 Jan 2025 11:21:02 -0800 Subject: [PATCH 21/42] Add `_MSVC_STL_HARDENING` control macros, initially off-by-default. --- stl/inc/yvals.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 5922af5023..727f1edb55 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -169,6 +169,66 @@ _STL_DISABLE_CLANG_WARNINGS #error _ITERATOR_DEBUG_LEVEL != 0 must imply _CONTAINER_DEBUG_LEVEL == 1. #endif // _ITERATOR_DEBUG_LEVEL != 0 && _CONTAINER_DEBUG_LEVEL == 0 +#ifndef _MSVC_STL_HARDENING +#define _MSVC_STL_HARDENING 0 +#endif + +#ifndef _MSVC_STL_HARDENING_ARRAY +#define _MSVC_STL_HARDENING_ARRAY _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_BASIC_STRING +#define _MSVC_STL_HARDENING_BASIC_STRING _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_BASIC_STRING_VIEW +#define _MSVC_STL_HARDENING_BASIC_STRING_VIEW _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_BITSET +#define _MSVC_STL_HARDENING_BITSET _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_DEQUE +#define _MSVC_STL_HARDENING_DEQUE _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_EXPECTED +#define _MSVC_STL_HARDENING_EXPECTED _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_FORWARD_LIST +#define _MSVC_STL_HARDENING_FORWARD_LIST _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_LIST +#define _MSVC_STL_HARDENING_LIST _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_MDSPAN +#define _MSVC_STL_HARDENING_MDSPAN _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_OPTIONAL +#define _MSVC_STL_HARDENING_OPTIONAL _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE +#define _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_SPAN +#define _MSVC_STL_HARDENING_SPAN _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_VALARRAY +#define _MSVC_STL_HARDENING_VALARRAY _MSVC_STL_HARDENING +#endif + +#ifndef _MSVC_STL_HARDENING_VECTOR +#define _MSVC_STL_HARDENING_VECTOR _MSVC_STL_HARDENING +#endif + #ifndef _STL_CRT_SECURE_INVALID_PARAMETER #ifdef _STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER #define _STL_CRT_SECURE_INVALID_PARAMETER(expr) _CSTD abort() From 777f8eefa3533e781e2fa2eea12e9dcc7c765181 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 28 Jan 2025 20:45:04 -0800 Subject: [PATCH 22/42] Harden array. --- stl/inc/array | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/array b/stl/inc/array index 77bf40f14f..5be4b29622 100644 --- a/stl/inc/array +++ b/stl/inc/array @@ -531,7 +531,7 @@ public: } _NODISCARD _CONSTEXPR17 reference operator[](_In_range_(<, _Size) size_type _Pos) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pos < _Size, "array subscript out of range"); #endif @@ -540,7 +540,7 @@ public: _NODISCARD constexpr const_reference operator[](_In_range_(<, _Size) size_type _Pos) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pos < _Size, "array subscript out of range"); #endif @@ -707,7 +707,7 @@ public: } _NODISCARD reference operator[](size_type) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_REPORT_ERROR("array subscript is invalid"); #endif @@ -715,7 +715,7 @@ public: } _NODISCARD const_reference operator[](size_type) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_REPORT_ERROR("array subscript is invalid"); #endif @@ -723,7 +723,7 @@ public: } _NODISCARD reference front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_REPORT_ERROR("array::front() is invalid"); #endif @@ -731,7 +731,7 @@ public: } _NODISCARD const_reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_REPORT_ERROR("array::front() is invalid"); #endif @@ -739,7 +739,7 @@ public: } _NODISCARD reference back() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_REPORT_ERROR("array::back() is invalid"); #endif @@ -747,7 +747,7 @@ public: } _NODISCARD const_reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_REPORT_ERROR("array::back() is invalid"); #endif From 8b7ba646534717381c5e5421719ea2f72644f317 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 00:32:23 -0800 Subject: [PATCH 23/42] Harden deque, overhaul pop_front/pop_back. --- stl/inc/deque | 51 +++++++++++++++++++-------------------------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/stl/inc/deque b/stl/inc/deque index cab1a2a804..b6fcee81c3 100644 --- a/stl/inc/deque +++ b/stl/inc/deque @@ -1063,7 +1063,7 @@ public: } _NODISCARD const_reference operator[](size_type _Pos) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); #endif @@ -1071,7 +1071,7 @@ public: } _NODISCARD reference operator[](size_type _Pos) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range"); #endif @@ -1095,7 +1095,7 @@ public: } _NODISCARD reference front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!empty(), "front() called on empty deque"); #endif @@ -1103,7 +1103,7 @@ public: } _NODISCARD const_reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!empty(), "front() called on empty deque"); #endif @@ -1111,7 +1111,7 @@ public: } _NODISCARD reference back() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!empty(), "back() called on empty deque"); #endif @@ -1119,7 +1119,7 @@ public: } _NODISCARD const_reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!empty(), "back() called on empty deque"); #endif @@ -1473,47 +1473,34 @@ private: public: void pop_front() noexcept /* strengthened */ { +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(!empty(), "pop_front() called on empty deque"); +#endif + #if _ITERATOR_DEBUG_LEVEL == 2 - if (empty()) { - _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())); - if (--_Mysize() == 0) { - _Myoff() = 0; - } else { - ++_Myoff(); - } - } -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv + _Orphan_off(_Myoff()); +#endif _Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Myoff())); if (--_Mysize() == 0) { _Myoff() = 0; } else { ++_Myoff(); } -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ } void pop_back() noexcept /* strengthened */ { -#if _ITERATOR_DEBUG_LEVEL == 2 - if (empty()) { - _STL_REPORT_ERROR("pop_back() called on empty deque"); - } else { // something to erase, do it - size_type _Newoff = _Myoff() + _Mysize() - 1; - _Orphan_off(_Newoff); - _Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Newoff)); - if (--_Mysize() == 0) { - _Myoff() = 0; - } - } -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv +#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(!empty(), "pop_back() called on empty deque"); +#endif + size_type _Newoff = _Myoff() + _Mysize() - 1; +#if _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_off(_Newoff); +#endif _Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Newoff)); if (--_Mysize() == 0) { _Myoff() = 0; } -#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^ } iterator erase(const_iterator _Where) noexcept(is_nothrow_move_assignable_v) /* strengthened */ { From f1d8fe70ffcbc4921f10ffb402279352e2567aaa Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 01:10:17 -0800 Subject: [PATCH 24/42] Harden forward_list, add pop_front. --- stl/inc/forward_list | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/stl/inc/forward_list b/stl/inc/forward_list index 3e801e48e2..f0fb5398ef 100644 --- a/stl/inc/forward_list +++ b/stl/inc/forward_list @@ -900,7 +900,7 @@ public: } _NODISCARD reference front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_FORWARD_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Myhead != nullptr, "front() called on empty forward_list"); #endif @@ -908,7 +908,7 @@ public: } _NODISCARD const_reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_FORWARD_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Myhead != nullptr, "front() called on empty forward_list"); #endif @@ -927,6 +927,10 @@ public: #endif // _HAS_CXX23 void pop_front() noexcept /* strengthened */ { +#if _MSVC_STL_HARDENING_FORWARD_LIST || _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(_Mypair._Myval2._Myhead != nullptr, "pop_front() called on empty forward_list"); +#endif + _Erase_after(_Mypair._Myval2._Before_head()); } From c9ceb7ee2e64be77006fc92c0656c780edb81958 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 01:14:07 -0800 Subject: [PATCH 25/42] Harden list. --- stl/inc/list | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stl/inc/list b/stl/inc/list index fc5093dca8..1d67c2e481 100644 --- a/stl/inc/list +++ b/stl/inc/list @@ -1208,7 +1208,7 @@ public: } _NODISCARD reference front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty list"); #endif @@ -1216,7 +1216,7 @@ public: } _NODISCARD const_reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty list"); #endif @@ -1224,7 +1224,7 @@ public: } _NODISCARD reference back() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty list"); #endif @@ -1232,7 +1232,7 @@ public: } _NODISCARD const_reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty list"); #endif @@ -1253,7 +1253,7 @@ public: #endif // _HAS_CXX23 void pop_front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_front() called on empty list"); #endif @@ -1274,7 +1274,7 @@ public: #endif // _HAS_CXX23 void pop_back() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_LIST || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "pop_back() called on empty list"); #endif From d5a39a119fadb3386c6e2ae7de2a5387779cd28f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 13:13:02 -0800 Subject: [PATCH 26/42] Harden vector, add vector::pop_back. --- stl/inc/vector | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index ae8330bf2d..1450120f06 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -1736,7 +1736,7 @@ public: auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_My_data._Myfirst != _Mylast, "pop_back() called on empty vector"); #endif @@ -1913,7 +1913,7 @@ public: _NODISCARD _CONSTEXPR20 _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY( _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); #endif @@ -1923,7 +1923,7 @@ public: _NODISCARD _CONSTEXPR20 const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY( _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); #endif @@ -1951,7 +1951,7 @@ public: _NODISCARD _CONSTEXPR20 _Ty& front() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); #endif @@ -1960,7 +1960,7 @@ public: _NODISCARD _CONSTEXPR20 const _Ty& front() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); #endif @@ -1969,7 +1969,7 @@ public: _NODISCARD _CONSTEXPR20 _Ty& back() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); #endif @@ -1978,7 +1978,7 @@ public: _NODISCARD _CONSTEXPR20 const _Ty& back() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); #endif @@ -3209,7 +3209,7 @@ public: } _NODISCARD _CONSTEXPR20 const_reference operator[](size_type _Off) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); #endif @@ -3219,7 +3219,7 @@ public: } _NODISCARD _CONSTEXPR20 reference operator[](size_type _Off) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); #endif @@ -3229,7 +3229,7 @@ public: } _NODISCARD _CONSTEXPR20 reference front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); #endif @@ -3237,7 +3237,7 @@ public: } _NODISCARD _CONSTEXPR20 const_reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); #endif @@ -3245,7 +3245,7 @@ public: } _NODISCARD _CONSTEXPR20 reference back() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); #endif @@ -3253,7 +3253,7 @@ public: } _NODISCARD _CONSTEXPR20 const_reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); #endif @@ -3272,6 +3272,10 @@ public: #endif // _HAS_CXX23 _CONSTEXPR20 void pop_back() noexcept /* strengthened */ { +#if _MSVC_STL_HARDENING_VECTOR || _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(this->_Mysize != 0, "pop_back() called on empty vector"); +#endif + erase(end() - 1); } From 2c2a79e3e4f4c72f9ce802a60a95fc6782684b12 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 13:27:04 -0800 Subject: [PATCH 27/42] Harden basic_string, add pop_back. --- stl/inc/xstring | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index d8c8884660..6763eecdb2 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -2246,17 +2246,19 @@ public: } _NODISCARD _CONSTEXPR20 reference operator[](const size_type _Off) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off <= _Mypair._Myval2._Mysize, "string subscript out of range"); #endif + return _Mypair._Myval2._Myptr()[_Off]; } _NODISCARD _CONSTEXPR20 const_reference operator[](const size_type _Off) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off <= _Mypair._Myval2._Mysize, "string subscript out of range"); #endif + return _Mypair._Myval2._Myptr()[_Off]; } @@ -2291,14 +2293,16 @@ public: _CONSTEXPR20 void pop_back() noexcept /* strengthened */ { const size_type _Old_size = _Mypair._Myval2._Mysize; -#if _ITERATOR_DEBUG_LEVEL >= 1 + +#if _MSVC_STL_HARDENING_BASIC_STRING || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Old_size != 0, "pop_back() called on empty string"); -#endif // _ITERATOR_DEBUG_LEVEL >= 1 +#endif + _Eos(_Old_size - 1); } _NODISCARD _CONSTEXPR20 reference front() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty string"); #endif @@ -2306,7 +2310,7 @@ public: } _NODISCARD _CONSTEXPR20 const_reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "front() called on empty string"); #endif @@ -2314,7 +2318,7 @@ public: } _NODISCARD _CONSTEXPR20 reference back() noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty string"); #endif @@ -2322,7 +2326,7 @@ public: } _NODISCARD _CONSTEXPR20 const_reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mypair._Myval2._Mysize != 0, "back() called on empty string"); #endif From c65c68b7b6241a8d4900b367374055442c579b69 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 13:33:45 -0800 Subject: [PATCH 28/42] Harden basic_string_view. --- stl/inc/__msvc_string_view.hpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 7c1043143f..4ccfeabf32 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -1474,7 +1474,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 +#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off < _Mysize, "string_view subscript out of range"); #endif @@ -1489,31 +1489,35 @@ 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 +#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize != 0, "front() called on empty string_view"); #endif + return _Mydata[0]; } _NODISCARD constexpr const_reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize != 0, "back() called on empty string_view"); #endif + return _Mydata[_Mysize - 1]; } constexpr void remove_prefix(const size_type _Count) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize >= _Count, "cannot remove_prefix() larger than string_view size"); #endif + _Mydata += _Count; _Mysize -= _Count; } constexpr void remove_suffix(const size_type _Count) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize >= _Count, "cannot remove_suffix() larger than string_view size"); #endif + _Mysize -= _Count; } From 0a799fba7f8909404519fe22f18b135e4bfc1f02 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 19:32:56 -0800 Subject: [PATCH 29/42] Harden span. --- stl/inc/span | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/stl/inc/span b/stl/inc/span index 3099483be5..e94b0d55ca 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -294,12 +294,12 @@ public: template <_Span_compatible_iterator _It> constexpr explicit(_Extent != dynamic_extent) span(_It _First, size_type _Count) noexcept // strengthened : _Mybase(_STD to_address(_STD _Get_unwrapped_n(_First, _Count)), _Count) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Extent != dynamic_extent) { _STL_VERIFY(_Count == _Extent, "Cannot construct span with static extent from range [first, first + count) as count != extent"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 } template <_Span_compatible_iterator _It, _Span_compatible_sentinel<_It> _Sentinel> @@ -307,12 +307,12 @@ public: noexcept(noexcept(_Last - _First)) // strengthened : _Mybase(_STD to_address(_First), static_cast(_Last - _First)) { _STD _Adl_verify_range(_First, _Last); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Extent != dynamic_extent) { _STL_VERIFY(_Last - _First == _Extent, "Cannot construct span with static extent from range [first, last) as last - first != extent"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 } template @@ -331,12 +331,12 @@ public: template <_Span_compatible_range _Rng> constexpr explicit(_Extent != dynamic_extent) span(_Rng&& _Range) : _Mybase(_RANGES data(_Range), static_cast(_RANGES size(_Range))) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Extent != dynamic_extent) { _STL_VERIFY(_RANGES size(_Range) == _Extent, "Cannot construct span with static extent from range r as std::ranges::size(r) != extent"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 } template @@ -345,12 +345,12 @@ public: constexpr explicit(_Extent != dynamic_extent && _OtherExtent == dynamic_extent) span(const span<_OtherTy, _OtherExtent>& _Other) noexcept : _Mybase(_Other.data(), _Other.size()) { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 if constexpr (_Extent != dynamic_extent) { _STL_VERIFY(_Other.size() == _Extent, "Cannot construct span with static extent from other span as other.size() != extent"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 } // [span.sub] Subviews @@ -359,18 +359,20 @@ public: if constexpr (_Extent != dynamic_extent) { static_assert(_Count <= _Extent, "Count out of range in span::first()"); } -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 else { _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::first()"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 + return span{_Mydata, _Count}; } _NODISCARD constexpr auto first(const size_type _Count) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::first(count)"); #endif + return span{_Mydata, _Count}; } @@ -379,18 +381,20 @@ public: if constexpr (_Extent != dynamic_extent) { static_assert(_Count <= _Extent, "Count out of range in span::last()"); } -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 else { _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::last()"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 + return span{_Mydata + (_Mysize - _Count), _Count}; } _NODISCARD constexpr auto last(const size_type _Count) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Count <= _Mysize, "Count out of range in span::last(count)"); #endif + return span{_Mydata + (_Mysize - _Count), _Count}; } @@ -401,7 +405,7 @@ public: static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Count out of range in span::subspan()"); } -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 else { _STL_VERIFY(_Offset <= _Mysize, "Offset out of range in span::subspan()"); @@ -409,7 +413,8 @@ public: _STL_VERIFY(_Count <= _Mysize - _Offset, "Count out of range in span::subspan()"); } } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 + using _ReturnType = span; return _ReturnType{_Mydata + _Offset, _Count == dynamic_extent ? _Mysize - _Offset : _Count}; @@ -417,11 +422,12 @@ public: _NODISCARD constexpr auto subspan(const size_type _Offset, const size_type _Count = dynamic_extent) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Offset <= _Mysize, "Offset out of range in span::subspan(offset, count)"); _STL_VERIFY(_Count == dynamic_extent || _Count <= _Mysize - _Offset, "Count out of range in span::subspan(offset, count)"); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 + using _ReturnType = span; return _ReturnType{_Mydata + _Offset, _Count == dynamic_extent ? _Mysize - _Offset : _Count}; } @@ -448,25 +454,28 @@ public: // [span.elem] Element access _NODISCARD constexpr reference operator[](const size_type _Off) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off < _Mysize, "span subscript out of range"); #endif + return _Mydata[_Off]; } #pragma warning(push) #pragma warning(disable : 4127) // conditional expression is constant _NODISCARD constexpr reference front() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize > 0, "front() called on empty span"); #endif + return _Mydata[0]; } _NODISCARD constexpr reference back() const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_SPAN || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Mysize > 0, "back() called on empty span"); #endif + return _Mydata[_Mysize - 1]; } #pragma warning(pop) From 78e097b9e14ec9c67c87b7370f16a95d4d4708cf Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 29 Jan 2025 20:06:42 -0800 Subject: [PATCH 30/42] Harden mdspan. --- stl/inc/mdspan | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 94d19ef370..bedc604603 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -1286,14 +1286,14 @@ public: "[mdspan.mdspan.cons]/20.1)."); static_assert(is_constructible_v, "The extents_type must be constructible from OtherExtents (N4950 [mdspan.mdspan.cons]/20.2)."); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_MDSPAN || _ITERATOR_DEBUG_LEVEL != 0 for (rank_type _Idx = 0; _Idx < extents_type::_Rank; ++_Idx) { const auto _Static_ext = extents_type::_Static_extents[_Idx]; _STL_VERIFY(_STD cmp_equal(_Static_ext, dynamic_extent) || _STD cmp_equal(_Static_ext, _Other.extent(_Idx)), "For each rank index r of extents_type, static_extent(r) == dynamic_extent || static_extent(r) == " "other.extent(r) must be true (N4950 [mdspan.mdspan.cons]/21.1)."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_MDSPAN || _ITERATOR_DEBUG_LEVEL != 0 } constexpr mdspan& operator=(const mdspan&) = default; @@ -1434,7 +1434,7 @@ private: _NODISCARD constexpr reference _Access_impl(_OtherIndexTypes... _Indices) const noexcept(noexcept(this->_Acc.access(_Ptr, static_cast(this->_Map(_Indices...))))) { _STL_INTERNAL_STATIC_ASSERT(conjunction_v...>); -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_MDSPAN || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Map.extents()._Contains_multidimensional_index(make_index_sequence{}, _Indices...), "mdspan subscript out of range; extents_type::index-cast(std::move(indices)) must be " "a multidimensional index in extents() (N5001 [mdspan.mdspan.members]/3)."); From 92759435ede8303fe087a5d94157f39f74e16de5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 30 Jan 2025 00:10:30 -0800 Subject: [PATCH 31/42] Harden expected. --- stl/inc/expected | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/stl/inc/expected b/stl/inc/expected index 45eb51a5fb..4080ad8b5e 100644 --- a/stl/inc/expected +++ b/stl/inc/expected @@ -620,40 +620,46 @@ public: // [expected.object.obs] _NODISCARD constexpr const _Ty* operator->() const noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Has_value, "operator->() called on a std::expected that contains an error, not a value"); #endif + return _STD addressof(_Value); } _NODISCARD constexpr _Ty* operator->() noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Has_value, "operator->() called on a std::expected that contains an error, not a value"); #endif + return _STD addressof(_Value); } _NODISCARD constexpr const _Ty& operator*() const& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); #endif + return _Value; } _NODISCARD constexpr _Ty& operator*() & noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); #endif + return _Value; } _NODISCARD constexpr const _Ty&& operator*() const&& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); #endif + return _STD move(_Value); } _NODISCARD constexpr _Ty&& operator*() && noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); #endif + return _STD move(_Value); } @@ -706,27 +712,31 @@ public: } _NODISCARD constexpr const _Err& error() const& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _Unexpected; } _NODISCARD constexpr _Err& error() & noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _Unexpected; } _NODISCARD constexpr const _Err&& error() const&& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _STD move(_Unexpected); } _NODISCARD constexpr _Err&& error() && noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _STD move(_Unexpected); } @@ -1468,7 +1478,7 @@ public: } constexpr void operator*() const noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Has_value, "operator*() called on a std::expected that contains an error, not a value"); #endif } @@ -1489,27 +1499,31 @@ public: } _NODISCARD constexpr const _Err& error() const& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _Unexpected; } _NODISCARD constexpr _Err& error() & noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _Unexpected; } _NODISCARD constexpr const _Err&& error() const&& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _STD move(_Unexpected); } _NODISCARD constexpr _Err&& error() && noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_EXPECTED || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_Has_value, "error() called on a std::expected that contains a value, not an error"); #endif + return _STD move(_Unexpected); } From 95355d47e6d454a6b880e459fa50cc57d2772203 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 30 Jan 2025 00:14:09 -0800 Subject: [PATCH 32/42] Harden optional. --- stl/inc/optional | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/stl/inc/optional b/stl/inc/optional index 7a527fff61..196374892e 100644 --- a/stl/inc/optional +++ b/stl/inc/optional @@ -181,30 +181,34 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> { } _NODISCARD constexpr _Ty& operator*() & noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_OPTIONAL || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); #endif + return this->_Value; } _NODISCARD constexpr const _Ty& operator*() const& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_OPTIONAL || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); #endif + return this->_Value; } _NODISCARD constexpr _Ty&& operator*() && noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_OPTIONAL || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); #endif + return _STD move(this->_Value); } _NODISCARD constexpr const _Ty&& operator*() const&& noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_OPTIONAL || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Has_value, "operator*() called on empty optional"); #endif + return _STD move(this->_Value); } }; @@ -376,15 +380,17 @@ public: } _NODISCARD constexpr const _Ty* operator->() const noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_OPTIONAL || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Has_value, "operator->() called on empty optional"); #endif + return _STD addressof(this->_Value); } _NODISCARD constexpr _Ty* operator->() noexcept { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_OPTIONAL || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(this->_Has_value, "operator->() called on empty optional"); #endif + return _STD addressof(this->_Value); } From 0b6c64126c8c398078119aa287f96b1eff5aabaf Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 30 Jan 2025 00:25:17 -0800 Subject: [PATCH 33/42] Harden valarray. --- stl/inc/valarray | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/valarray b/stl/inc/valarray index 9de6bd8d80..bb30c01648 100644 --- a/stl/inc/valarray +++ b/stl/inc/valarray @@ -404,7 +404,7 @@ public: } _NODISCARD const _Ty& operator[](size_t _Off) const noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VALARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off < _Mysize, "valarray subscript out of range"); #endif @@ -412,7 +412,7 @@ public: } _NODISCARD _Ty& operator[](size_t _Off) noexcept /* strengthened */ { -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _MSVC_STL_HARDENING_VALARRAY || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(_Off < _Mysize, "valarray subscript out of range"); #endif From 274a0bd1aa570e2e4fbe619842f57ac2c831fd92 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 30 Jan 2025 00:28:43 -0800 Subject: [PATCH 34/42] Harden ranges::view_interface. --- stl/inc/xutility | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index 0c5c942a29..cd3abe887b 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -3823,9 +3823,11 @@ namespace ranges { requires forward_range<_Derived> { auto& _Self = _Cast(); -#if _CONTAINER_DEBUG_LEVEL > 0 + +#if _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_RANGES empty(_Self), "front() called on empty ranges::view_interface"); #endif + return *_RANGES begin(_Self); } @@ -3833,9 +3835,11 @@ namespace ranges { requires forward_range { auto& _Self = _Cast(); -#if _CONTAINER_DEBUG_LEVEL > 0 + +#if _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_RANGES empty(_Self), "front() called on empty ranges::view_interface"); #endif + return *_RANGES begin(_Self); } @@ -3843,9 +3847,11 @@ namespace ranges { requires bidirectional_range<_Derived> && common_range<_Derived> { auto& _Self = _Cast(); -#if _CONTAINER_DEBUG_LEVEL > 0 + +#if _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_RANGES empty(_Self), "back() called on empty ranges::view_interface"); #endif + auto _Last = _RANGES end(_Self); return *--_Last; } @@ -3854,9 +3860,11 @@ namespace ranges { requires bidirectional_range && common_range { auto& _Self = _Cast(); -#if _CONTAINER_DEBUG_LEVEL > 0 + +#if _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 _STL_VERIFY(!_RANGES empty(_Self), "back() called on empty ranges::view_interface"); #endif + auto _Last = _RANGES end(_Self); return *--_Last; } @@ -3864,26 +3872,30 @@ namespace ranges { template _NODISCARD constexpr decltype(auto) operator[](const range_difference_t<_Rng> _Idx) { auto& _Self = _Cast(); -#if _CONTAINER_DEBUG_LEVEL > 0 + +#if _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 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)), "ranges::view_interface subscript out of range"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 + return _RANGES begin(_Self)[_Idx]; } template _NODISCARD constexpr decltype(auto) operator[](const range_difference_t<_Rng> _Idx) const { auto& _Self = _Cast(); -#if _CONTAINER_DEBUG_LEVEL > 0 + +#if _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 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)), "ranges::view_interface subscript out of range"); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _MSVC_STL_HARDENING_RANGES_VIEW_INTERFACE || _ITERATOR_DEBUG_LEVEL != 0 + return _RANGES begin(_Self)[_Idx]; } }; From e26df58a44a52a40510e0d87a79fba1e907289c4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 30 Jan 2025 00:37:43 -0800 Subject: [PATCH 35/42] Harden bitset, overhauling operator[]. Filed GH 5262 "``: `operator[]` could be SAL annotated with `_In_range_(<, _Bits)`" for followup. Fusing _Validate() into operator[] fixes some libcxx bitset tests that were failing due to constexpr step limits. --- stl/inc/bitset | 18 ++++++++---------- tests/libcxx/expected_results.txt | 5 ++--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/stl/inc/bitset b/stl/inc/bitset index 7374ea0676..7792605af4 100644 --- a/stl/inc/bitset +++ b/stl/inc/bitset @@ -116,14 +116,6 @@ public: }; private: - static constexpr void _Validate(const size_t _Pos) noexcept { // verify that _Pos is within bounds -#if _ITERATOR_DEBUG_LEVEL == 0 - (void) _Pos; -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv - _STL_VERIFY(_Pos < _Bits, "bitset subscript out of range"); -#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^ - } - constexpr bool _Subscript(size_t _Pos) const noexcept { return (_Array[_Pos / _Bitsperword] & (_Ty{1} << _Pos % _Bitsperword)) != 0; } @@ -133,12 +125,18 @@ private: public: _NODISCARD constexpr bool operator[](const size_t _Pos) const noexcept /* strengthened */ { - _Validate(_Pos); +#if _MSVC_STL_HARDENING_BITSET || _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(_Pos < _Bits, "bitset subscript out of range"); +#endif + return _Subscript(_Pos); } _NODISCARD _CONSTEXPR23 reference operator[](const size_t _Pos) noexcept /* strengthened */ { - _Validate(_Pos); +#if _MSVC_STL_HARDENING_BITSET || _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(_Pos < _Bits, "bitset subscript out of range"); +#endif + return reference(*this, _Pos); } diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 52c4877f62..1187eadbe9 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -996,10 +996,9 @@ std/containers/sequences/vector/vector.modifiers/destroy_elements.pass.cpp FAIL std/containers/sequences/vector/vector.modifiers/insert_range.pass.cpp FAIL std/strings/basic.string/string.modifiers/string_replace/replace_with_range.pass.cpp FAIL std/utilities/charconv/charconv.to.chars/integral.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/left_shift_eq.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp FAIL +std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp:2 FAIL std/utilities/template.bitset/bitset.members/op_or_eq.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/right_shift_eq.pass.cpp FAIL +std/utilities/template.bitset/bitset.members/right_shift_eq.pass.cpp:2 FAIL # Not analyzed. In debug mode, looks like a proxy object unexpectedly exhausts an 80-byte buffer. # In release mode, fails in a later assertion that appears to be testing libc++-specific behavior. From 77b6fc5435390a23239591352486b98384c4df13 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 4 Feb 2025 22:01:24 -0800 Subject: [PATCH 36/42] Update test coverage for CDL removal. In VSO_0677157_flist_merge_edge_cases, avoid duplicate coverage of front(). In VSO_0000000_string_view_idl, remove comment citing VSO-830211, the bug that requested CDL (added by MSVC-PR-174936 on 2019-04-15). --- .../tests/P0009R18_mdspan_mdspan_death/test.cpp | 13 +++---------- tests/std/tests/P0122R7_span_death/test.cpp | 10 ++-------- tests/std/tests/P0220R1_optional_death/test.cpp | 4 ++-- tests/std/tests/P0323R12_expected/test.cpp | 2 -- .../test.cpp | 4 ++-- .../tests/VSO_0000000_string_view_idl/test.cpp | 15 ++++++--------- .../VSO_0677157_flist_merge_edge_cases/test.cpp | 6 ++---- .../test.cpp | 17 +++++++---------- 8 files changed, 24 insertions(+), 47 deletions(-) diff --git a/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp b/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp index 4100d93948..2e225ae4fa 100644 --- a/tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_mdspan_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 @@ -60,22 +58,17 @@ int main(int argc, char* argv[]) { #if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ + test_construction_from_other_mdspan, #ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 + test_access_with_invalid_multidimensional_index_1, test_access_with_nonrepresentable_index_1, #endif // __cpp_multidimensional_subscript + test_access_with_invalid_multidimensional_index_2, test_access_with_nonrepresentable_index_2, test_size_when_index_type_is_signed, test_size_when_index_type_is_unsigned, }); #endif // _ITERATOR_DEBUG_LEVEL != 0 - exec.add_death_tests({ - test_construction_from_other_mdspan, -#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 - test_access_with_invalid_multidimensional_index_1, -#endif // __cpp_multidimensional_subscript - test_access_with_invalid_multidimensional_index_2, - }); - return exec.run(argc, argv); } diff --git a/tests/std/tests/P0122R7_span_death/test.cpp b/tests/std/tests/P0122R7_span_death/test.cpp index 1b4c668117..42fdb8123b 100644 --- a/tests/std/tests/P0122R7_span_death/test.cpp +++ b/tests/std/tests/P0122R7_span_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 @@ -330,12 +328,6 @@ int main(int argc, char* argv[]) { test_case_algorithm_incompatible_different_size, test_case_algorithm_incompatible_value_initialized, test_case_algorithm_incompatible_transposed, - test_case_size_bytes_overflow, - }); -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - // _CONTAINER_DEBUG_LEVEL tests - exec.add_death_tests({ test_case_constructor_first_count_incompatible_extent, test_case_constructor_first_last_incompatible_extent, test_case_constructor_range_incompatible_extent, @@ -352,6 +344,7 @@ int main(int argc, char* argv[]) { test_case_subspan_excessive_runtime_count_dynamic_extent, test_case_subspan_excessive_runtime_offset_static_extent, test_case_subspan_excessive_runtime_count_static_extent, + test_case_size_bytes_overflow, test_case_operator_subscript_out_of_range_dynamic_extent, test_case_operator_subscript_out_of_range_static_extent, test_case_front_empty_dynamic_extent, @@ -359,6 +352,7 @@ int main(int argc, char* argv[]) { test_case_front_empty_static_extent, test_case_back_empty_static_extent, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } diff --git a/tests/std/tests/P0220R1_optional_death/test.cpp b/tests/std/tests/P0220R1_optional_death/test.cpp index bdc284f002..b55a59b292 100644 --- a/tests/std/tests/P0220R1_optional_death/test.cpp +++ b/tests/std/tests/P0220R1_optional_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 @@ -47,6 +45,7 @@ void test_nullopt_operator_star_const_rvalue() { int main(int argc, char* argv[]) { std_testing::death_test_executive exec; +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_nullopt_operator_arrow, test_nullopt_operator_arrow_const, @@ -55,6 +54,7 @@ int main(int argc, char* argv[]) { test_nullopt_operator_star_rvalue, test_nullopt_operator_star_const_rvalue, }); +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } diff --git a/tests/std/tests/P0323R12_expected/test.cpp b/tests/std/tests/P0323R12_expected/test.cpp index 37476de98b..ce2eccd161 100644 --- a/tests/std/tests/P0323R12_expected/test.cpp +++ b/tests/std/tests/P0323R12_expected/test.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include #include diff --git a/tests/std/tests/VSO_0000000_list_iterator_debugging/test.cpp b/tests/std/tests/VSO_0000000_list_iterator_debugging/test.cpp index fae346f53c..cd9730af06 100644 --- a/tests/std/tests/VSO_0000000_list_iterator_debugging/test.cpp +++ b/tests/std/tests/VSO_0000000_list_iterator_debugging/test.cpp @@ -532,7 +532,7 @@ int main(int argc, char* argv[]) { }); #endif // _ITERATOR_DEBUG_LEVEL == 2 -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_case_empty_front_bad, test_case_empty_cfront_bad, @@ -541,7 +541,7 @@ int main(int argc, char* argv[]) { test_case_pop_front_bad, test_case_pop_back_bad, }); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } diff --git a/tests/std/tests/VSO_0000000_string_view_idl/test.cpp b/tests/std/tests/VSO_0000000_string_view_idl/test.cpp index 9f18f1a11e..e9aad83d10 100644 --- a/tests/std/tests/VSO_0000000_string_view_idl/test.cpp +++ b/tests/std/tests/VSO_0000000_string_view_idl/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 @@ -237,20 +235,19 @@ int main(int argc, char* argv[]) { test_case_operator_equal_incompatible_value_initialized, test_case_operator_less_incompatible_different_views, test_case_operator_less_incompatible_value_initialized, + test_case_operator_subscript_out_of_range, + test_case_front_empty, + test_case_back_empty, + test_case_remove_prefix_too_large, + test_case_remove_suffix_too_large, test_case_remove_prefix_incompatible, test_case_remove_suffix_incompatible, test_case_null_constructor, }); #endif // _ITERATOR_DEBUG_LEVEL != 0 + // basic_string_view::_Copy_s is unconditionally checked. exec.add_death_tests({ - // These tests are turned on for _ITERATOR_DEBUG_LEVEL == 0 as part of - // VSO-830211 "Macro to enable runtime bounds checking for subscript operator for STL containers" - test_case_operator_subscript_out_of_range, - test_case_front_empty, - test_case_back_empty, - test_case_remove_prefix_too_large, - test_case_remove_suffix_too_large, test_case_Copy_s, }); diff --git a/tests/std/tests/VSO_0677157_flist_merge_edge_cases/test.cpp b/tests/std/tests/VSO_0677157_flist_merge_edge_cases/test.cpp index 70a508eb94..dbc4cfbfac 100644 --- a/tests/std/tests/VSO_0677157_flist_merge_edge_cases/test.cpp +++ b/tests/std/tests/VSO_0677157_flist_merge_edge_cases/test.cpp @@ -267,18 +267,16 @@ int main(int argc, char* argv[]) { test_case_empty_source_bad>, test_case_empty_target_bad, test_case_empty_target_bad>, - test_case_front_bad, - test_case_cfront_bad, }); #endif // _ITERATOR_DEBUG_LEVEL == 2 -#if _CONTAINER_DEBUG_LEVEL > 0 +#if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ test_case_front_bad, test_case_cfront_bad, test_case_pop_front_bad, }); -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // _ITERATOR_DEBUG_LEVEL != 0 return exec.run(argc, argv); } 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 29b47050c7..9b9643b198 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 @@ -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 @@ -203,6 +201,10 @@ struct TestCases { test_case_operator_equal_incompatible_value_initialized, test_case_operator_less_incompatible_different_views, test_case_operator_less_incompatible_value_initialized, + test_case_operator_subscript_out_of_range_empty, + test_case_operator_subscript_out_of_range, + test_case_front_empty, + test_case_back_empty, }); if constexpr (Traits::has_arrow) { @@ -211,14 +213,9 @@ struct TestCases { test_case_operator_arrow_end_iterator, }); } -#endif // _ITERATOR_DEBUG_LEVEL != 0 - - 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, - }); +#else // ^^^ _ITERATOR_DEBUG_LEVEL != 0 / _ITERATOR_DEBUG_LEVEL == 0 vvv + (void) exec; +#endif // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ } }; From 9c8a7b1ca58852c495a9cdf98e66c290c45aae3f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 31 Jan 2025 17:03:25 -0800 Subject: [PATCH 37/42] Remove CDL's default definition and emit an error if users define it. --- stl/inc/yvals.h | 14 +++----------- stl/inc/yvals_core.h | 2 +- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 727f1edb55..06f1658c2e 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -157,17 +157,9 @@ _STL_DISABLE_CLANG_WARNINGS #endif // defined(_DLL) etc. #endif // !defined(_ALLOW_RUNTIME_LIBRARY_MISMATCH) -#ifndef _CONTAINER_DEBUG_LEVEL -#if _ITERATOR_DEBUG_LEVEL == 0 -#define _CONTAINER_DEBUG_LEVEL 0 -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv -#define _CONTAINER_DEBUG_LEVEL 1 -#endif // _ITERATOR_DEBUG_LEVEL == 0 -#endif // !defined(_CONTAINER_DEBUG_LEVEL) - -#if _ITERATOR_DEBUG_LEVEL != 0 && _CONTAINER_DEBUG_LEVEL == 0 -#error _ITERATOR_DEBUG_LEVEL != 0 must imply _CONTAINER_DEBUG_LEVEL == 1. -#endif // _ITERATOR_DEBUG_LEVEL != 0 && _CONTAINER_DEBUG_LEVEL == 0 +#ifdef _CONTAINER_DEBUG_LEVEL +_EMIT_STL_ERROR(STL1006, "_CONTAINER_DEBUG_LEVEL has been removed. It was superseded by _MSVC_STL_HARDENING."); +#endif #ifndef _MSVC_STL_HARDENING #define _MSVC_STL_HARDENING 0 diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 2bd67b707b..2a8a7a098a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1519,7 +1519,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // next warning number: STL4049 -// next error number: STL1006 +// next error number: STL1007 // P0619R4 Removing C++17-Deprecated Features #ifndef _HAS_FEATURES_REMOVED_IN_CXX20 From 33c69b10dc6811c69a78b848fecce62d580b556f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Sun, 2 Feb 2025 00:15:26 -0800 Subject: [PATCH 38/42] Add test coverage: GH_005090_stl_hardening --- tests/std/test.lst | 1 + .../std/tests/GH_005090_stl_hardening/env.lst | 6 + .../tests/GH_005090_stl_hardening/test.cpp | 711 ++++++++++++++++++ 3 files changed, 718 insertions(+) create mode 100644 tests/std/tests/GH_005090_stl_hardening/env.lst create mode 100644 tests/std/tests/GH_005090_stl_hardening/test.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index 7093936102..e188823bfc 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -253,6 +253,7 @@ tests\GH_004657_expected_constraints_permissive tests\GH_004845_logical_operator_traits_with_non_bool_constant tests\GH_004929_internal_tag_constructors tests\GH_004930_char_traits_user_specialization +tests\GH_005090_stl_hardening tests\LWG2381_num_get_floating_point tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function diff --git a/tests/std/tests/GH_005090_stl_hardening/env.lst b/tests/std/tests/GH_005090_stl_hardening/env.lst new file mode 100644 index 0000000000..606d5f8417 --- /dev/null +++ b/tests/std/tests/GH_005090_stl_hardening/env.lst @@ -0,0 +1,6 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst +RUNALL_CROSSLIST +* PM_CL="/D_MSVC_STL_HARDENING=1" diff --git a/tests/std/tests/GH_005090_stl_hardening/test.cpp b/tests/std/tests/GH_005090_stl_hardening/test.cpp new file mode 100644 index 0000000000..9fc8b475a9 --- /dev/null +++ b/tests/std/tests/GH_005090_stl_hardening/test.cpp @@ -0,0 +1,711 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// env.lst defines _MSVC_STL_HARDENING to 1. + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if _HAS_CXX17 +#include +#include +#endif // _HAS_CXX17 + +#if _HAS_CXX20 +#include +#include +#endif // _HAS_CXX20 + +#if _HAS_CXX23 +#include +#include +#endif // _HAS_CXX23 + +#include + +using namespace std; + +// +void test_array_subscript() { + array a{}; +#pragma warning(push) +#pragma warning(disable : 28020) // /analyze correctly warns: The expression '_Param_(1)<3' is not true at this call. + (void) a[3]; +#pragma warning(pop) +} + +void test_array_subscript_const() { + const array a{}; +#pragma warning(push) +#pragma warning(disable : 28020) // /analyze correctly warns: The expression '_Param_(1)<3' is not true at this call. + (void) a[3]; +#pragma warning(pop) +} + +void test_array_zero_subscript() { + array az{}; + (void) az[0]; +} + +void test_array_zero_subscript_const() { + const array az{}; + (void) az[0]; +} + +void test_array_zero_front() { + array az{}; + (void) az.front(); +} + +void test_array_zero_front_const() { + const array az{}; + (void) az.front(); +} + +void test_array_zero_back() { + array az{}; + (void) az.back(); +} + +void test_array_zero_back_const() { + const array az{}; + (void) az.back(); +} + +// +void test_bitset_subscript() { + bitset<100> b{}; + (void) b[100]; +} + +void test_bitset_subscript_const() { + const bitset<100> b{}; + (void) b[100]; +} + +// +void test_deque_subscript() { + deque d(3); + (void) d[3]; +} + +void test_deque_subscript_const() { + const deque d(3); + (void) d[3]; +} + +void test_deque_front() { + deque d{}; + (void) d.front(); +} + +void test_deque_front_const() { + const deque d{}; + (void) d.front(); +} + +void test_deque_back() { + deque d{}; + (void) d.back(); +} + +void test_deque_back_const() { + const deque d{}; + (void) d.back(); +} + +void test_deque_pop_front() { + deque d{}; + d.pop_front(); +} + +void test_deque_pop_back() { + deque d{}; + d.pop_back(); +} + +// +void test_forward_list_front() { + forward_list fl{}; + (void) fl.front(); +} + +void test_forward_list_front_const() { + const forward_list fl{}; + (void) fl.front(); +} + +void test_forward_list_pop_front() { + forward_list fl{}; + fl.pop_front(); +} + +// +void test_list_front() { + list l{}; + (void) l.front(); +} + +void test_list_front_const() { + const list l{}; + (void) l.front(); +} + +void test_list_back() { + list l{}; + (void) l.back(); +} + +void test_list_back_const() { + const list l{}; + (void) l.back(); +} + +void test_list_pop_front() { + list l{}; + l.pop_front(); +} + +void test_list_pop_back() { + list l{}; + l.pop_back(); +} + +// +void test_string_subscript() { + string s(3, '*'); + (void) s[4]; // beyond null terminator +} + +void test_string_subscript_const() { + const string s(3, '*'); + (void) s[4]; // beyond null terminator +} + +void test_string_front() { + string s{}; + (void) s.front(); +} + +void test_string_front_const() { + const string s{}; + (void) s.front(); +} + +void test_string_back() { + string s{}; + (void) s.back(); +} + +void test_string_back_const() { + const string s{}; + (void) s.back(); +} + +void test_string_pop_back() { + string s{}; + s.pop_back(); +} + +// +void test_valarray_subscript() { + valarray va(3); + (void) va[3]; +} + +void test_valarray_subscript_const() { + const valarray va(3); + (void) va[3]; +} + +// +void test_vector_subscript() { + vector v(3); + (void) v[3]; +} + +void test_vector_subscript_const() { + const vector v(3); + (void) v[3]; +} + +void test_vector_front() { + vector v{}; + (void) v.front(); +} + +void test_vector_front_const() { + const vector v{}; + (void) v.front(); +} + +void test_vector_back() { + vector v{}; + (void) v.back(); +} + +void test_vector_back_const() { + const vector v{}; + (void) v.back(); +} + +void test_vector_pop_back() { + vector v{}; + v.pop_back(); +} + +void test_vector_bool_subscript() { + vector vb(3); + (void) vb[3]; +} + +void test_vector_bool_subscript_const() { + const vector vb(3); + (void) vb[3]; +} + +void test_vector_bool_front() { + vector vb{}; + (void) vb.front(); +} + +void test_vector_bool_front_const() { + const vector vb{}; + (void) vb.front(); +} + +void test_vector_bool_back() { + vector vb{}; + (void) vb.back(); +} + +void test_vector_bool_back_const() { + const vector vb{}; + (void) vb.back(); +} + +void test_vector_bool_pop_back() { + vector vb{}; + vb.pop_back(); +} + +#if _HAS_CXX17 +// +void test_optional_deref_lvalue() { + optional o{}; + (void) *o; +} + +void test_optional_deref_lvalue_const() { + const optional o{}; + (void) *o; +} + +void test_optional_deref_rvalue() { + optional o{}; + (void) *move(o); +} + +void test_optional_deref_rvalue_const() { + const optional o{}; + (void) *move(o); +} + +void test_optional_arrow() { + optional o{}; + (void) o.operator->(); +} + +void test_optional_arrow_const() { + const optional o{}; + (void) o.operator->(); +} + +// +void test_string_view_subscript() { + const string_view sv{"Toki"}; + (void) sv[4]; +} + +void test_string_view_front() { + const string_view sv{}; + (void) sv.front(); +} + +void test_string_view_back() { + const string_view sv{}; + (void) sv.back(); +} + +void test_string_view_remove_prefix() { + string_view sv{"Cosmos"}; + sv.remove_prefix(7); +} + +void test_string_view_remove_suffix() { + string_view sv{"Meadow"}; + sv.remove_suffix(7); +} +#endif // _HAS_CXX17 + +#if _HAS_CXX20 +// +// ranges::subrange derives from ranges::view_interface, which is hardened. +void test_ranges_view_interface_subscript() { + int arr[10]{}; + ranges::subrange sr{arr + 5, arr + 8}; + (void) sr[3]; +} + +void test_ranges_view_interface_subscript_const() { + int arr[10]{}; + const ranges::subrange sr{arr + 5, arr + 8}; + (void) sr[3]; +} + +void test_ranges_view_interface_front() { + int arr[10]{}; + ranges::subrange sr{arr + 5, arr + 5}; + (void) sr.front(); +} + +void test_ranges_view_interface_front_const() { + int arr[10]{}; + const ranges::subrange sr{arr + 5, arr + 5}; + (void) sr.front(); +} + +void test_ranges_view_interface_back() { + int arr[10]{}; + ranges::subrange sr{arr + 5, arr + 5}; + (void) sr.back(); +} + +void test_ranges_view_interface_back_const() { + int arr[10]{}; + const ranges::subrange sr{arr + 5, arr + 5}; + (void) sr.back(); +} + +// +void test_span_ctor_first_count() { + int arr[10]{}; + span sp_static{arr, 10}; +} + +void test_span_ctor_first_last() { + int arr[10]{}; + span sp_static{arr, arr + 10}; +} + +void test_span_ctor_range() { + vector v(10); + span sp_static{v}; +} + +void test_span_ctor_other() { + int arr[10]{}; + span other{arr}; + span sp_static{other}; +} + +void test_span_first_compiletime() { + int arr[10]{}; + const span sp{arr}; + (void) sp.first<11>(); +} + +void test_span_first_runtime() { + int arr[10]{}; + const span sp{arr}; + (void) sp.first(11); +} + +void test_span_last_compiletime() { + int arr[10]{}; + const span sp{arr}; + (void) sp.last<11>(); +} + +void test_span_last_runtime() { + int arr[10]{}; + const span sp{arr}; + (void) sp.last(11); +} + +void test_span_subspan_compiletime_bad_offset() { + int arr[10]{}; + const span sp{arr}; + (void) sp.subspan<11>(); +} + +void test_span_subspan_compiletime_bad_count() { + int arr[10]{}; + const span sp{arr}; + (void) sp.subspan<3, 8>(); +} + +void test_span_subspan_runtime_bad_offset() { + int arr[10]{}; + const span sp{arr}; + (void) sp.subspan(11); +} + +void test_span_subspan_runtime_bad_count() { + int arr[10]{}; + const span sp{arr}; + (void) sp.subspan(3, 8); +} + +void test_span_subscript() { + int arr[10]{}; + const span sp{arr}; + (void) sp[10]; +} + +void test_span_front() { + const span sp{}; + (void) sp.front(); +} + +void test_span_back() { + const span sp{}; + (void) sp.back(); +} +#endif // _HAS_CXX20 + +#if _HAS_CXX23 +// +void test_expected_arrow() { + expected e{unexpect, "woof"}; + (void) e.operator->(); +} + +void test_expected_arrow_const() { + const expected e{unexpect, "woof"}; + (void) e.operator->(); +} + +void test_expected_deref_lvalue() { + expected e{unexpect, "woof"}; + (void) *e; +} + +void test_expected_deref_lvalue_const() { + const expected e{unexpect, "woof"}; + (void) *e; +} + +void test_expected_deref_rvalue() { + expected e{unexpect, "woof"}; + (void) *move(e); +} + +void test_expected_deref_rvalue_const() { + const expected e{unexpect, "woof"}; + (void) *move(e); +} + +void test_expected_error_lvalue() { + expected e{1729}; + (void) e.error(); +} + +void test_expected_error_lvalue_const() { + const expected e{1729}; + (void) e.error(); +} + +void test_expected_error_rvalue() { + expected e{1729}; + (void) move(e).error(); +} + +void test_expected_error_rvalue_const() { + const expected e{1729}; + (void) move(e).error(); +} + +void test_expected_void_deref() { + const expected ev{unexpect, "woof"}; + (void) *ev; +} + +void test_expected_void_error_lvalue() { + expected ev{}; + (void) ev.error(); +} + +void test_expected_void_error_lvalue_const() { + const expected ev{}; + (void) ev.error(); +} + +void test_expected_void_error_rvalue() { + expected ev{}; + (void) move(ev).error(); +} + +void test_expected_void_error_rvalue_const() { + const expected ev{}; + (void) move(ev).error(); +} + +// +void test_mdspan_ctor_other() { + char arr[12]{}; + mdspan> other{arr, 4, 3}; + mdspan> md{other}; +} + +#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 +void test_mdspan_subscript_multidim() { + const auto str{"HissMeowPurr"}; + const mdspan> md{str, 3, 4}; + (void) md[1, 4]; +} +#endif // ^^^ defined(__cpp_multidimensional_subscript) ^^^ + +void test_mdspan_subscript_array() { + const auto str{"HissMeowPurr"}; + const mdspan> md{str, 3, 4}; + const array a_idx{1, 4}; + (void) md[a_idx]; +} + +void test_mdspan_subscript_span() { + const auto str{"HissMeowPurr"}; + const mdspan> md{str, 3, 4}; + const array a_idx{1, 4}; + const span sp_idx{a_idx}; + (void) md[sp_idx]; +} +#endif // _HAS_CXX23 + +int main(int argc, char* argv[]) { + std_testing::death_test_executive exec; + + exec.add_death_tests({ + test_array_subscript, + test_array_subscript_const, + test_array_zero_subscript, + test_array_zero_subscript_const, + test_array_zero_front, + test_array_zero_front_const, + test_array_zero_back, + test_array_zero_back_const, + test_bitset_subscript, + test_bitset_subscript_const, + test_deque_subscript, + test_deque_subscript_const, + test_deque_front, + test_deque_front_const, + test_deque_back, + test_deque_back_const, + test_deque_pop_front, + test_deque_pop_back, + test_forward_list_front, + test_forward_list_front_const, + test_forward_list_pop_front, + test_list_front, + test_list_front_const, + test_list_back, + test_list_back_const, + test_list_pop_front, + test_list_pop_back, + test_string_subscript, + test_string_subscript_const, + test_string_front, + test_string_front_const, + test_string_back, + test_string_back_const, + test_string_pop_back, + test_valarray_subscript, + test_valarray_subscript_const, + test_vector_subscript, + test_vector_subscript_const, + test_vector_front, + test_vector_front_const, + test_vector_back, + test_vector_back_const, + test_vector_pop_back, + test_vector_bool_subscript, + test_vector_bool_subscript_const, + test_vector_bool_front, + test_vector_bool_front_const, + test_vector_bool_back, + test_vector_bool_back_const, + test_vector_bool_pop_back, + +#if _HAS_CXX17 + test_optional_deref_lvalue, + test_optional_deref_lvalue_const, + test_optional_deref_rvalue, + test_optional_deref_rvalue_const, + test_optional_arrow, + test_optional_arrow_const, + test_string_view_subscript, + test_string_view_front, + test_string_view_back, + test_string_view_remove_prefix, + test_string_view_remove_suffix, +#endif // _HAS_CXX17 + +#if _HAS_CXX20 + test_ranges_view_interface_subscript, + test_ranges_view_interface_subscript_const, + test_ranges_view_interface_front, + test_ranges_view_interface_front_const, + test_ranges_view_interface_back, + test_ranges_view_interface_back_const, + test_span_ctor_first_count, + test_span_ctor_first_last, + test_span_ctor_range, + test_span_ctor_other, + test_span_first_compiletime, + test_span_first_runtime, + test_span_last_compiletime, + test_span_last_runtime, + test_span_subspan_compiletime_bad_offset, + test_span_subspan_compiletime_bad_count, + test_span_subspan_runtime_bad_offset, + test_span_subspan_runtime_bad_count, + test_span_subscript, + test_span_front, + test_span_back, +#endif // _HAS_CXX20 + +#if _HAS_CXX23 + test_expected_arrow, + test_expected_arrow_const, + test_expected_deref_lvalue, + test_expected_deref_lvalue_const, + test_expected_deref_rvalue, + test_expected_deref_rvalue_const, + test_expected_error_lvalue, + test_expected_error_lvalue_const, + test_expected_error_rvalue, + test_expected_error_rvalue_const, + test_expected_void_deref, + test_expected_void_error_lvalue, + test_expected_void_error_lvalue_const, + test_expected_void_error_rvalue, + test_expected_void_error_rvalue_const, + test_mdspan_ctor_other, +#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6 + test_mdspan_subscript_multidim, +#endif // ^^^ defined(__cpp_multidimensional_subscript) ^^^ + test_mdspan_subscript_array, + test_mdspan_subscript_span, +#endif // _HAS_CXX23 + }); + + return exec.run(argc, argv); +} From fae0a977f0ffe0fa501b920ae35cf0d7e49afd28 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 5 Feb 2025 21:18:30 -0800 Subject: [PATCH 39/42] Enhancement: Move span::size_bytes() debug checks into span's ctors. We don't need to push-disable-pop warning C4127 "conditional expression is constant" because we're going to separately handle static vs. dynamic extents. Add a comment to size_bytes() explaining that we've already checked. (Having constructor checks is sufficient because spans can't grow.) The checks are moving into `_Span_extent_type`, which has different cases for static vs. dynamic extents. We need to say `sizeof(_Ty)` because we don't have the `element_type` typedef. In the debug messages, drop qualification from "std::numeric_limits"; the name is obvious, and if we can mention `span` unqualified, surely `numeric_limits` is fine. For static extents, we can unconditionally `static_assert`, as the throughput cost is trivial. I'm doing this in the constructor, (1) for consistency with dynamic extents below, and (2) because I could imagine pathological code (in STL test suites?) claiming that `span(-2)>` isn't forbidden to simply instantiate as a type - but the moment that an object of such a type is constructed, the constructor arguments must surely be lying, so we're justified in performing a debug check then. For dynamic extents, `_Span_extent_type` construction performs the runtime check. This is IDL != 0 (as opposed to hardening), so it's okay if we check more frequently than absolutely necessary. (For example, when constructing from a built-in array or a `std::array`, we don't need to worry about overflow.) --- stl/inc/span | 20 +++++++++++--------- tests/std/tests/P0122R7_span_death/test.cpp | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/stl/inc/span b/stl/inc/span index e94b0d55ca..fff19050f9 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -206,7 +206,10 @@ struct _Span_extent_type { constexpr _Span_extent_type() noexcept = default; - constexpr explicit _Span_extent_type(const pointer _Data, size_t) noexcept : _Mydata{_Data} {} + constexpr explicit _Span_extent_type(const pointer _Data, size_t) noexcept : _Mydata{_Data} { + static_assert( + _Mysize <= dynamic_extent / sizeof(_Ty), "size of span in bytes exceeds numeric_limits::max()"); + } pointer _Mydata{nullptr}; static constexpr size_t _Mysize = _Extent; @@ -219,7 +222,12 @@ struct _Span_extent_type<_Ty, dynamic_extent> { constexpr _Span_extent_type() noexcept = default; constexpr explicit _Span_extent_type(const pointer _Data, const size_t _Size) noexcept - : _Mydata{_Data}, _Mysize{_Size} {} + : _Mydata{_Data}, _Mysize{_Size} { +#if _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY( + _Mysize <= dynamic_extent / sizeof(_Ty), "size of span in bytes exceeds numeric_limits::max()"); +#endif + } pointer _Mydata{nullptr}; size_t _Mysize{0}; @@ -437,16 +445,10 @@ public: return _Mysize; } -#pragma warning(push) -#pragma warning(disable : 4127) // conditional expression is constant _NODISCARD constexpr size_type size_bytes() const noexcept { -#if _ITERATOR_DEBUG_LEVEL != 0 - _STL_VERIFY(_Mysize <= dynamic_extent / sizeof(element_type), - "size of span in bytes exceeds std::numeric_limits::max()"); -#endif + // Under _ITERATOR_DEBUG_LEVEL != 0, span's constructors verify that this multiplication won't overflow. return _Mysize * sizeof(element_type); } -#pragma warning(pop) _NODISCARD constexpr bool empty() const noexcept { return _Mysize == 0; diff --git a/tests/std/tests/P0122R7_span_death/test.cpp b/tests/std/tests/P0122R7_span_death/test.cpp index 42fdb8123b..48baa31a2f 100644 --- a/tests/std/tests/P0122R7_span_death/test.cpp +++ b/tests/std/tests/P0122R7_span_death/test.cpp @@ -259,7 +259,7 @@ void test_case_subspan_excessive_runtime_count_static_extent() { } void test_case_size_bytes_overflow() { - span sp(begin(globalArray), static_cast(-2)); // undefined behavior, not detected here + span sp(begin(globalArray), static_cast(-2)); // undefined behavior is detected here (void) sp.size_bytes(); // size of span in bytes exceeds std::numeric_limits::max() } From 199fffdadba95b9795481a8005ae01b0d4e37cb6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 6 Feb 2025 15:52:48 -0800 Subject: [PATCH 40/42] Enhancement: Overhaul the STL's "doom function". Emit errors if the old macros are defined. `_MSVC_STL_DOOM_FUNCTION` is so named because it could expand to many things: a user-customized function, abort(), _invoke_watson(), or (in the future) __fastfail(). Add comments explaining how the doom function can be replaced. Provide `_MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION` as users have specifically requested abort(). Change the `_STL_CRT_SECURE_INVALID_PARAMETER(expr)` parameter to `_MSVC_STL_DOOM_FUNCTION(mesg)`. We always call it with a `mesg` string, so stringizing it again with `#expr` is a mistake. Calling _invoke_watson() will immediately call __fastfail(), without calling any user-customized invalid parameter handlers. This gives attackers fewer opportunities to exploit running code. (When we can drop Win7 support in Dev18, we should be able to directly call __fastfail(), resulting in less codegen.) Cleanup: Add global scope qualification to _invoke_watson in the no-exceptions definition of _RAISE, for consistency. Remove /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER from the test suites. --- stl/inc/yvals.h | 35 ++++++++++++------- stl/inc/yvals_core.h | 2 +- tests/libcxx/usual_matrix.lst | 2 +- .../env.lst | 2 +- tests/std/tests/modules_20_matrix.lst | 2 +- tests/std/tests/prefix.lst | 2 +- tests/tr1/prefix.lst | 2 +- 7 files changed, 29 insertions(+), 18 deletions(-) diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index 06f1658c2e..d316c7cd40 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -221,21 +221,32 @@ _EMIT_STL_ERROR(STL1006, "_CONTAINER_DEBUG_LEVEL has been removed. It was supers #define _MSVC_STL_HARDENING_VECTOR _MSVC_STL_HARDENING #endif -#ifndef _STL_CRT_SECURE_INVALID_PARAMETER +#ifdef _STL_CRT_SECURE_INVALID_PARAMETER +_EMIT_STL_ERROR(STL1007, "_STL_CRT_SECURE_INVALID_PARAMETER has been removed. " + "It was superseded by _MSVC_STL_DOOM_FUNCTION."); +#endif + #ifdef _STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER -#define _STL_CRT_SECURE_INVALID_PARAMETER(expr) _CSTD abort() -#elif defined(_DEBUG) // Avoid emitting unused long strings for function names; see GH-1956. -// static_cast(__LINE__) avoids warning C4365 (signed/unsigned mismatch) with the /ZI compiler option. -#define _STL_CRT_SECURE_INVALID_PARAMETER(expr) \ - ::_invalid_parameter(_CRT_WIDE(#expr), L"", __FILEW__, static_cast(__LINE__), 0) -#else // ^^^ defined(_DEBUG) / !defined(_DEBUG) vvv -#define _STL_CRT_SECURE_INVALID_PARAMETER(expr) _CRT_SECURE_INVALID_PARAMETER(expr) -#endif // ^^^ !defined(_DEBUG) ^^^ -#endif // !defined(_STL_CRT_SECURE_INVALID_PARAMETER) +_EMIT_STL_ERROR(STL1008, "_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER has been removed. " + "It was superseded by _MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION."); +#endif + +// The STL's "doom function" can be replaced. Notes: +// * It must not throw. (Attempting to throw would slam into noexcept.) +// * Common case: If it doesn't return, it should be marked as `[[noreturn]]`. +// * Uncommon case: If it returns, the STL will attempt to "continue on error", behaving as if no checking was done. +#ifndef _MSVC_STL_DOOM_FUNCTION +#ifdef _MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION +#define _MSVC_STL_DOOM_FUNCTION(mesg) _CSTD abort() +#else // ^^^ defined(_MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION) / !defined(_MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION) vvv +// TRANSITION, GH-4858: after dropping Win7 support, we can directly call __fastfail(FAST_FAIL_INVALID_ARG). +#define _MSVC_STL_DOOM_FUNCTION(mesg) ::_invoke_watson(nullptr, nullptr, nullptr, 0, 0) +#endif // ^^^ !defined(_MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION) ^^^ +#endif // ^^^ !defined(_MSVC_STL_DOOM_FUNCTION) ^^^ #define _STL_REPORT_ERROR(mesg) \ _RPTF0(_CRT_ASSERT, mesg); \ - _STL_CRT_SECURE_INVALID_PARAMETER(mesg) + _MSVC_STL_DOOM_FUNCTION(mesg) #define _STL_VERIFY(cond, mesg) \ if (!(cond)) { \ @@ -469,7 +480,7 @@ class _CRTIMP2_PURE_IMPORT _EmptyLockit { // empty lock class used for bin compa } \ } -#define _RAISE(x) _invoke_watson(nullptr, nullptr, nullptr, 0, 0) +#define _RAISE(x) ::_invoke_watson(nullptr, nullptr, nullptr, 0, 0) #define _RERAISE #define _THROW(...) (__VA_ARGS__)._Raise() diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 2a8a7a098a..4adc435e9b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1519,7 +1519,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect // next warning number: STL4049 -// next error number: STL1007 +// next error number: STL1009 // P0619R4 Removing C++17-Deprecated Features #ifndef _HAS_FEATURES_REMOVED_IN_CXX20 diff --git a/tests/libcxx/usual_matrix.lst b/tests/libcxx/usual_matrix.lst index a6642320f3..72969ef33c 100644 --- a/tests/libcxx/usual_matrix.lst +++ b/tests/libcxx/usual_matrix.lst @@ -3,7 +3,7 @@ RUNALL_INCLUDE ..\universal_prefix.lst RUNALL_CROSSLIST -* PM_CL="/EHsc /MTd /std:c++latest /permissive- /utf-8 /FImsvc_stdlib_force_include.h /wd4643 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER" +* PM_CL="/EHsc /MTd /std:c++latest /permissive- /utf-8 /FImsvc_stdlib_force_include.h /wd4643" RUNALL_CROSSLIST PM_CL="/analyze:autolog- /Zc:preprocessor /wd6262" ASAN PM_CL="-fsanitize=address /Zi" PM_LINK="/debug" diff --git a/tests/std/tests/P1502R1_standard_library_header_units/env.lst b/tests/std/tests/P1502R1_standard_library_header_units/env.lst index 90f83ac9b6..3fc0a727c7 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/env.lst +++ b/tests/std/tests/P1502R1_standard_library_header_units/env.lst @@ -3,7 +3,7 @@ RUNALL_INCLUDE ..\..\..\universal_prefix.lst RUNALL_CROSSLIST -* PM_CL="/w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER /Zc:preprocessor" +* PM_CL="/w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /Zc:preprocessor" RUNALL_CROSSLIST * PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=20 /std:c++20" * PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=23 /std:c++latest" diff --git a/tests/std/tests/modules_20_matrix.lst b/tests/std/tests/modules_20_matrix.lst index 22a3a5ea9d..6ccb872fd8 100644 --- a/tests/std/tests/modules_20_matrix.lst +++ b/tests/std/tests/modules_20_matrix.lst @@ -3,7 +3,7 @@ RUNALL_INCLUDE ..\..\universal_prefix.lst RUNALL_CROSSLIST -* PM_CL="/w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER /Zc:preprocessor" +* PM_CL="/w14365 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /Zc:preprocessor" RUNALL_CROSSLIST * PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=20 /std:c++20" * PM_CL="/w14640 /Zc:threadSafeInit- /EHsc /DTEST_STANDARD=23 /std:c++latest" diff --git a/tests/std/tests/prefix.lst b/tests/std/tests/prefix.lst index ca509bbe8f..167a64e537 100644 --- a/tests/std/tests/prefix.lst +++ b/tests/std/tests/prefix.lst @@ -3,4 +3,4 @@ RUNALL_INCLUDE ..\..\universal_prefix.lst RUNALL_CROSSLIST -* PM_CL="/FIforce_include.hpp /w14365 /w14668 /w15267 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER" +* PM_CL="/FIforce_include.hpp /w14365 /w14668 /w15267 /D_ENFORCE_FACET_SPECIALIZATIONS=1" diff --git a/tests/tr1/prefix.lst b/tests/tr1/prefix.lst index 5d1ecb45c8..09eacd9984 100644 --- a/tests/tr1/prefix.lst +++ b/tests/tr1/prefix.lst @@ -3,4 +3,4 @@ RUNALL_INCLUDE ..\universal_prefix.lst RUNALL_CROSSLIST -* PM_CL="/FIforce_include.hpp /w14668 /w15267 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_CRT_SECURE_NO_WARNINGS /D_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER" +* PM_CL="/FIforce_include.hpp /w14668 /w15267 /D_ENFORCE_FACET_SPECIALIZATIONS=1 /D_CRT_SECURE_NO_WARNINGS" From cc35a7bf790cae921305f53b46ccbef4218f37dc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 13 Feb 2025 01:39:45 -0800 Subject: [PATCH 41/42] Code review feedback: Improve comments and debug messages. --- stl/inc/__msvc_string_view.hpp | 2 +- stl/inc/span | 2 ++ stl/inc/yvals.h | 6 ++++++ tests/std/tests/VSO_0000000_string_view_idl/test.cpp | 3 ++- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/stl/inc/__msvc_string_view.hpp b/stl/inc/__msvc_string_view.hpp index 4ccfeabf32..c078de097f 100644 --- a/stl/inc/__msvc_string_view.hpp +++ b/stl/inc/__msvc_string_view.hpp @@ -1380,7 +1380,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer _In_reads_(_Count) const const_pointer _Cts, const size_type _Count) noexcept // strengthened : _Mydata(_Cts), _Mysize(_Count) { #if _ITERATOR_DEBUG_LEVEL != 0 - _STL_VERIFY(_Count == 0 || _Cts, "non-zero size null string_view"); + _STL_VERIFY(_Count == 0 || _Cts, "cannot construct a string_view from a null pointer and a non-zero size"); #endif } diff --git a/stl/inc/span b/stl/inc/span index fff19050f9..ec504c9877 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -207,6 +207,7 @@ struct _Span_extent_type { constexpr _Span_extent_type() noexcept = default; constexpr explicit _Span_extent_type(const pointer _Data, size_t) noexcept : _Mydata{_Data} { + // Verify that later calls to size_bytes() won't overflow: static_assert( _Mysize <= dynamic_extent / sizeof(_Ty), "size of span in bytes exceeds numeric_limits::max()"); } @@ -224,6 +225,7 @@ struct _Span_extent_type<_Ty, dynamic_extent> { constexpr explicit _Span_extent_type(const pointer _Data, const size_t _Size) noexcept : _Mydata{_Data}, _Mysize{_Size} { #if _ITERATOR_DEBUG_LEVEL != 0 + // Verify that later calls to size_bytes() won't overflow: _STL_VERIFY( _Mysize <= dynamic_extent / sizeof(_Ty), "size of span in bytes exceeds numeric_limits::max()"); #endif diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index d316c7cd40..bae84f1e6b 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -235,6 +235,12 @@ _EMIT_STL_ERROR(STL1008, "_STL_CALL_ABORT_INSTEAD_OF_INVALID_PARAMETER has been // * It must not throw. (Attempting to throw would slam into noexcept.) // * Common case: If it doesn't return, it should be marked as `[[noreturn]]`. // * Uncommon case: If it returns, the STL will attempt to "continue on error", behaving as if no checking was done. +// + For example, a legacy codebase with a long startup time might want to log errors for investigation later. +// + WARNING: If you replace the STL's "doom function" to "continue on error", you do so at your own risk! +// After the STL has detected a precondition violation, undefined behavior is imminent. The STL will support +// "continue on error" by proceeding to do what it would have done anyways (instead of falling off the end of +// a non-void function, etc.), but it will not attempt to replace undefined behavior with implementation-defined +// behavior. (For example, we will not transform `pop_back()` of an empty `vector` to be a no-op.) #ifndef _MSVC_STL_DOOM_FUNCTION #ifdef _MSVC_STL_USE_ABORT_AS_DOOM_FUNCTION #define _MSVC_STL_DOOM_FUNCTION(mesg) _CSTD abort() diff --git a/tests/std/tests/VSO_0000000_string_view_idl/test.cpp b/tests/std/tests/VSO_0000000_string_view_idl/test.cpp index e9aad83d10..d96ce9cf42 100644 --- a/tests/std/tests/VSO_0000000_string_view_idl/test.cpp +++ b/tests/std/tests/VSO_0000000_string_view_idl/test.cpp @@ -246,7 +246,8 @@ int main(int argc, char* argv[]) { }); #endif // _ITERATOR_DEBUG_LEVEL != 0 - // basic_string_view::_Copy_s is unconditionally checked. + // basic_string_view::_Copy_s() is a non-Standard extension that's unconditionally checked. + // See: https://learn.microsoft.com/en-us/cpp/standard-library/basic-string-view-class?view=msvc-170#_copy_s exec.add_death_tests({ test_case_Copy_s, }); From 175f14d044d2f7e314f14b4732de3e80b669b7c4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 18 Feb 2025 22:09:44 -0800 Subject: [PATCH 42/42] Pre-emptively resolve conflict with GH 5274 by marking bitset.members tests as SKIPPED. --- tests/libcxx/expected_results.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 1187eadbe9..8c55f59e92 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -996,9 +996,12 @@ std/containers/sequences/vector/vector.modifiers/destroy_elements.pass.cpp FAIL std/containers/sequences/vector/vector.modifiers/insert_range.pass.cpp FAIL std/strings/basic.string/string.modifiers/string_replace/replace_with_range.pass.cpp FAIL std/utilities/charconv/charconv.to.chars/integral.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp:2 FAIL -std/utilities/template.bitset/bitset.members/op_or_eq.pass.cpp FAIL -std/utilities/template.bitset/bitset.members/right_shift_eq.pass.cpp:2 FAIL + +# Not analyzed, failing due to constexpr step limits. SKIPPED because they occasionally pass in certain configurations. +std/utilities/template.bitset/bitset.members/left_shift_eq.pass.cpp SKIPPED +std/utilities/template.bitset/bitset.members/op_and_eq.pass.cpp SKIPPED +std/utilities/template.bitset/bitset.members/op_or_eq.pass.cpp SKIPPED +std/utilities/template.bitset/bitset.members/right_shift_eq.pass.cpp SKIPPED # Not analyzed. In debug mode, looks like a proxy object unexpectedly exhausts an 80-byte buffer. # In release mode, fails in a later assertion that appears to be testing libc++-specific behavior.