From bf1e9bdb3060acd59a432dbbcb9a1396f4ad6a22 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sat, 27 Apr 2024 07:29:29 +0800 Subject: [PATCH] ``: Consistently check preconditions for `iota_view` and `_Counted_fn` (#4616) --- stl/inc/ranges | 29 ++++++++--- .../tests/P0896R4_views_iota_death/test.cpp | 49 +++++++++++++++++++ 2 files changed, 70 insertions(+), 8 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 0c6e7db1c5..69e982e7ce 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -1381,24 +1381,35 @@ 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 constexpr (totally_ordered_with<_Wi, _Bo>) { - _STL_ASSERT(_Value_ <= _Bound, "Per N4950 [range.iota.view]/6, the first argument must not exceed the " + _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 } 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 constexpr (totally_ordered_with<_Wi, _Bo>) { - _STL_ASSERT(_Value_ <= _Bound_, "Per N4950 [range.iota.view]/8, the first argument must not exceed the " + _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 } 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))) {} + : _Value(_STD move(_First._Current)), _Bound(_STD move(_Bound_from(_Last))) { +#if _CONTAINER_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 + } _NODISCARD constexpr _It begin() const noexcept(is_nothrow_copy_constructible_v<_Wi>) /* strengthened */ { return _It{_Value}; @@ -1524,7 +1535,7 @@ namespace ranges { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Current < (numeric_limits<_Index_type>::max)(), "cannot increment repeat_view iterator past end (integer overflow)"); -#endif +#endif // _CONTAINER_DEBUG_LEVEL > 0 ++_Current; return *this; } @@ -1655,7 +1666,7 @@ namespace ranges { if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } -#endif +#endif // _CONTAINER_DEBUG_LEVEL > 0 } _NODISCARD_CTOR constexpr explicit repeat_view(_Ty&& _Value_, _Bo _Bound_ = _Bo{}) noexcept( is_nothrow_move_constructible_v<_Ty>) // strengthened @@ -1664,7 +1675,7 @@ namespace ranges { if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } -#endif +#endif // _CONTAINER_DEBUG_LEVEL > 0 } template requires constructible_from<_Ty, _TArgs...> && constructible_from<_Bo, _BArgs...> @@ -1676,7 +1687,7 @@ namespace ranges { if constexpr (_Signed_integer_like<_Bo>) { _STL_VERIFY(_Bound >= 0, "Bound must be >= 0"); } -#endif +#endif // _CONTAINER_DEBUG_LEVEL > 0 } _NODISCARD constexpr _Iterator begin() const noexcept /* strengthened */ { @@ -5251,7 +5262,9 @@ 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) { - _STL_ASSERT(_Count >= 0, "The size passed to views::counted must be non-negative"); +#if _CONTAINER_DEBUG_LEVEL > 0 + _STL_VERIFY(_Count >= 0, "The size passed to views::counted must be non-negative"); +#endif // _CONTAINER_DEBUG_LEVEL > 0 constexpr _St _Strat = _Choice<_It>._Strategy; if constexpr (_Strat == _St::_Span) { diff --git a/tests/std/tests/P0896R4_views_iota_death/test.cpp b/tests/std/tests/P0896R4_views_iota_death/test.cpp index fc606cb372..d38a5ad9a7 100644 --- a/tests/std/tests/P0896R4_views_iota_death/test.cpp +++ b/tests/std/tests/P0896R4_views_iota_death/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _CONTAINER_DEBUG_LEVEL 1 + #include #include @@ -12,6 +14,12 @@ void test_misordered_start_bound_int() { ranges::iota_view{I{42}, I{1}}; } +template +void test_misordered_iterator_sentinel_int() { + ranges::iota_view iv{I{1}, I{42}}; + decltype(iv){iv.end(), iv.begin()}; +} + template void test_misordered_start_bound_uint_value_init() { ranges::iota_view{UI{42}}; @@ -23,12 +31,26 @@ void test_misordered_start_bound_ptr() { ranges::iota_view{arr + 1, arr + 0}; } +template +void test_misordered_iterator_sentinel_ptr() { + T arr[1]{}; + ranges::iota_view iv{arr + 0, arr + 1}; + decltype(iv){iv.end(), iv.begin()}; +} + template void test_misordered_start_bound_vector_iter() { vector vec(1); ranges::iota_view{vec.end(), vec.begin()}; } +template +void test_misordered_iterator_sentinel_vector_iter() { + vector vec(1); + ranges::iota_view iv{vec.begin(), vec.end()}; + decltype(iv){iv.end(), iv.begin()}; +} + int main(int argc, char* argv[]) { std_testing::death_test_executive exec; @@ -55,6 +77,25 @@ int main(int argc, char* argv[]) { test_misordered_start_bound_int, test_misordered_start_bound_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + + test_misordered_iterator_sentinel_int, +#ifdef __cpp_char8_t + test_misordered_iterator_sentinel_int, +#endif // __cpp_char8_t + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_iterator_sentinel_int, + test_misordered_start_bound_uint_value_init, test_misordered_start_bound_uint_value_init, test_misordered_start_bound_uint_value_init, @@ -74,6 +115,14 @@ int main(int argc, char* argv[]) { test_misordered_start_bound_vector_iter, test_misordered_start_bound_vector_iter, test_misordered_start_bound_vector_iter, + + test_misordered_iterator_sentinel_ptr, + test_misordered_iterator_sentinel_ptr, + test_misordered_iterator_sentinel_ptr, + + test_misordered_iterator_sentinel_vector_iter, + test_misordered_iterator_sentinel_vector_iter, + test_misordered_iterator_sentinel_vector_iter, }); #endif // _DEBUG