From ab253ecf3bc67e2a820d54f171386f62e3b91871 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 24 Oct 2022 11:23:11 -0700 Subject: [PATCH 01/10] basic_string::_Move_construct_from_substr already knows the allocator --- stl/inc/xstring | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stl/inc/xstring b/stl/inc/xstring index f3d77c4cda..720b142d56 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -2648,13 +2648,13 @@ public: #if _HAS_CXX23 constexpr basic_string(basic_string&& _Right, const size_type _Roff, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { // construct from _Right [_Roff, ), potentially move - _Move_construct_from_substr(_Right, _Roff, npos, _Al); + _Move_construct_from_substr(_Right, _Roff, npos); } constexpr basic_string( basic_string&& _Right, const size_type _Roff, const size_type _Count, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { // construct from _Right [_Roff, _Roff + _Count), potentially move - _Move_construct_from_substr(_Right, _Roff, _Count, _Al); + _Move_construct_from_substr(_Right, _Roff, _Count); } #endif // _HAS_CXX23 @@ -3195,20 +3195,20 @@ private: } #if _HAS_CXX23 - constexpr void _Move_construct_from_substr( - basic_string& _Right, const size_type _Roff, const size_type _Size_max, const _Alloc& _Al) { + constexpr void _Move_construct_from_substr(basic_string& _Right, const size_type _Roff, const size_type _Size_max) { auto& _Right_data = _Right._Mypair._Myval2; _Right_data._Check_offset(_Roff); const auto _Result_size = _Right_data._Clamp_suffix_size(_Roff, _Size_max); const auto _Right_ptr = _Right_data._Myptr(); + auto& _Al = _Getal(); if (_Allocators_equal(_Al, _Right._Getal()) && _Result_size >= _BUF_SIZE) { if (_Roff != 0) { _Traits::move(_Right_ptr, _Right_ptr + _Roff, _Result_size); } _Right._Eos(_Result_size); - _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); + _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Al)); _Take_contents(_Right); } else { _Construct<_Construct_strategy::_From_ptr>(_Right_ptr + _Roff, _Result_size); From 5c01c0972a423c73cc21108ab42f5e31c42adff6 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 24 Oct 2022 11:51:58 -0700 Subject: [PATCH 02/10] Consistently guard `_Verify_offset(-n)` against `-INT_MIN` --- stl/inc/ranges | 4 ++++ stl/inc/span | 1 + 2 files changed, 5 insertions(+) diff --git a/stl/inc/ranges b/stl/inc/ranges index 1c76f60f63..0e90c91b06 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2250,6 +2250,7 @@ namespace ranges { requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _Verify_offset(-_Off); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Current -= _Off; @@ -2342,6 +2343,7 @@ namespace ranges { requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _It._Verify_offset(-_Off); #endif // _ITERATOR_DEBUG_LEVEL != 0 _It._Current -= _Off; @@ -5213,6 +5215,7 @@ namespace ranges { requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _Verify_offset(-_Off); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Current -= _Off; @@ -5313,6 +5316,7 @@ namespace ranges { requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 + _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _It._Verify_offset(-_Off); #endif // _ITERATOR_DEBUG_LEVEL != 0 auto _Copy = _It; diff --git a/stl/inc/span b/stl/inc/span index 7751b2a680..22f9f8b8c3 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -120,6 +120,7 @@ struct _Span_iterator { } constexpr _Span_iterator& operator-=(const difference_type _Off) noexcept { + _STL_VERIFY(_Off != _Min_possible_v, "integer overflow"); _Verify_offset(-_Off); _Myptr -= _Off; return *this; From 82f8f86f6c866dc4bdd9b6a3b3fda5c6ba5ce88b Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 24 Oct 2022 12:18:41 -0700 Subject: [PATCH 03/10] Cleanup _NOEXCEPT_IDL0 Make `transform_view::iterator::_Verify_offset` always `noexcept` by avoiding checks when the underlying iterator doesn't support `_Verify_offset`. Make that function and `elements_view::iterator::_Verify_offset` available only when `_IDL != 0` **fixing a bug in `elements_view::iterator`**. Remove the now unused `_NOEXCEPT_IDL0` machinery. Fixes #1269 --- stl/inc/ranges | 62 +++++++++++++------------------------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 0e90c91b06..8fbad19ea2 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2053,12 +2053,6 @@ namespace ranges { template // TRANSITION, LLVM-47414 concept _Can_const_transform = range && regular_invocable>; -#if _ITERATOR_DEBUG_LEVEL == 0 -#define _NOEXCEPT_IDL0(...) noexcept(__VA_ARGS__) -#else -#define _NOEXCEPT_IDL0(...) -#endif // _ITERATOR_DEBUG_LEVEL == 0 - _EXPORT_STD template requires view<_Vw> && regular_invocable<_Fn&, range_reference_t<_Vw>> @@ -2204,39 +2198,19 @@ namespace ranges { return _Tmp; } - constexpr void _Verify_offset(const difference_type _Off) const +#if _ITERATOR_DEBUG_LEVEL != 0 + constexpr void _Verify_offset(const difference_type _Off) const noexcept requires random_access_range<_Base> { -#if _ITERATOR_DEBUG_LEVEL == 0 - (void) _Off; -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv _STL_VERIFY(_Off == 0 || _Parent, "cannot seek value-initialized transform_view iterator"); - if constexpr (_Offset_verifiable_v>) { _Current._Verify_offset(_Off); - } else { - if (_Off < 0) { - if constexpr (sized_sentinel_for, iterator_t<_Base>>) { - _STL_VERIFY(_Off >= _RANGES begin(_Parent->_Range) - _Current, - "cannot seek transform_view iterator before begin"); - } - } else if (_Off > 0) { - if constexpr (sized_sentinel_for, iterator_t<_Base>>) { - _STL_VERIFY(_Off <= _RANGES end(_Parent->_Range) - _Current, - "cannot seek transform_view iterator after end"); - } else if constexpr (sized_sentinel_for, iterator_t<_Base>> - && sized_range<_Base>) { - const auto _Size = _RANGES distance(_Parent->_Range); - _STL_VERIFY(_Off <= _Size - (_Current - _RANGES begin(_Parent->_Range)), - "cannot seek transform_view iterator after end"); - } - } } -#endif // _ITERATOR_DEBUG_LEVEL == 0 } +#endif // _ITERATOR_DEBUG_LEVEL != 0 - constexpr _Iterator& operator+=(const difference_type _Off) - _NOEXCEPT_IDL0(noexcept(_Current += _Off)) /* strengthened */ + constexpr _Iterator& operator+=(const difference_type _Off) noexcept( + noexcept(_Current += _Off)) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -2245,8 +2219,8 @@ namespace ranges { _Current += _Off; return *this; } - constexpr _Iterator& operator-=(const difference_type _Off) - _NOEXCEPT_IDL0(noexcept(_Current -= _Off)) /* strengthened */ + constexpr _Iterator& operator-=(const difference_type _Off) noexcept( + noexcept(_Current -= _Off)) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -2258,7 +2232,7 @@ namespace ranges { } _NODISCARD constexpr decltype(auto) operator[](const difference_type _Idx) const - _NOEXCEPT_IDL0(noexcept(_STD invoke(*_Parent->_Fun, _Current[_Idx]))) /* strengthened */ + noexcept(noexcept(_STD invoke(*_Parent->_Fun, _Current[_Idx]))) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -2317,8 +2291,8 @@ namespace ranges { return _Left._Current <=> _Right._Current; } - _NODISCARD_FRIEND constexpr _Iterator operator+(_Iterator _It, difference_type _Off) - _NOEXCEPT_IDL0(noexcept(_It._Current += _Off)) /* strengthened */ + _NODISCARD_FRIEND constexpr _Iterator operator+(_Iterator _It, const difference_type _Off) noexcept( + noexcept(_It._Current += _Off)) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -2327,8 +2301,8 @@ namespace ranges { _It._Current += _Off; return _It; } - _NODISCARD_FRIEND constexpr _Iterator operator+(difference_type _Off, _Iterator _It) - _NOEXCEPT_IDL0(noexcept(_It._Current += _Off)) /* strengthened */ + _NODISCARD_FRIEND constexpr _Iterator operator+(const difference_type _Off, _Iterator _It) noexcept( + noexcept(_It._Current += _Off)) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -2338,8 +2312,8 @@ namespace ranges { return _It; } - _NODISCARD_FRIEND constexpr _Iterator operator-(_Iterator _It, difference_type _Off) - _NOEXCEPT_IDL0(noexcept(_It._Current -= _Off)) /* strengthened */ + _NODISCARD_FRIEND constexpr _Iterator operator-(_Iterator _It, const difference_type _Off) noexcept( + noexcept(_It._Current -= _Off)) /* strengthened */ requires random_access_range<_Base> { #if _ITERATOR_DEBUG_LEVEL != 0 @@ -2504,8 +2478,6 @@ namespace ranges { } }; -#undef _NOEXCEPT_IDL0 - template transform_view(_Rng&&, _Fn) -> transform_view, _Fn>; @@ -5188,17 +5160,15 @@ namespace ranges { return _Tmp; } +#if _ITERATOR_DEBUG_LEVEL != 0 constexpr void _Verify_offset(const difference_type _Off) const requires random_access_range<_Base> { -#if _ITERATOR_DEBUG_LEVEL != 0 - (void) _Off; -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv if constexpr (_Offset_verifiable_v>) { _Current._Verify_offset(_Off); } -#endif // _ITERATOR_DEBUG_LEVEL == 0 } +#endif // _ITERATOR_DEBUG_LEVEL != 0 constexpr _Iterator& operator+=(const difference_type _Off) noexcept( noexcept(_Current += _Off)) /* strengthened */ From f8a9403aad627d06f61712b243ce4348233ce747 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 24 Oct 2022 12:39:51 -0700 Subject: [PATCH 04/10] Keep type and data member definitions together in `` Fixes #330 --- stl/inc/execution | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/stl/inc/execution b/stl/inc/execution index 576e6a0a09..ab4525bf14 100644 --- a/stl/inc/execution +++ b/stl/inc/execution @@ -830,8 +830,9 @@ template struct _Static_partition_range<_RanIt, _Diff, true> { using _Target_diff = _Iter_diff_t<_RanIt>; using _URanIt = _Unwrapped_t; + using _Chunk_type = _Iterator_range<_URanIt>; + _URanIt _Start_at; - using _Chunk_type = _Iterator_range<_URanIt>; _RanIt _Populate(const _Static_partition_team<_Diff>& _Team, _RanIt _First) { // statically partition a random-access iterator range and return next(_First, _Team._Count) @@ -866,8 +867,9 @@ template struct _Static_partition_range<_FwdIt, _Diff, false> { using _Target_diff = _Iter_diff_t<_FwdIt>; using _UFwdIt = _Unwrapped_t; + using _Chunk_type = _Iterator_range<_UFwdIt>; + _Parallel_vector<_UFwdIt> _Division_points; - using _Chunk_type = _Iterator_range<_UFwdIt>; _FwdIt _Populate(const _Static_partition_team<_Diff>& _Team, _FwdIt _First) { // statically partition a forward iterator range and return next(_First, _Team._Count) @@ -949,8 +951,9 @@ struct _Static_partition_range_backward; template struct _Static_partition_range_backward<_RanIt, _Diff, true> { using _Target_diff = _Iter_diff_t<_RanIt>; + using _Chunk_type = _Iterator_range<_Unwrapped_t>; + _Unwrapped_t _Start_at; - using _Chunk_type = _Iterator_range<_Unwrapped_t>; void _Populate(const _Static_partition_team<_Diff>& _Team, _RanIt _Last) { // statically partition a random-access iterator range ending at _Last @@ -969,8 +972,9 @@ struct _Static_partition_range_backward<_RanIt, _Diff, true> { template struct _Static_partition_range_backward<_BidIt, _Diff, false> { using _Target_diff = _Iter_diff_t<_BidIt>; + using _Chunk_type = _Iterator_range<_Unwrapped_t>; + _Parallel_vector<_Unwrapped_t> _Division_points; - using _Chunk_type = _Iterator_range<_Unwrapped_t>; void _Populate(const _Static_partition_team<_Diff>& _Team, _BidIt _Last) { // statically partition a bidirectional iterator range ending at _Last From 472060469b9acc0672f8d8666014053eff6aa3db Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 24 Oct 2022 19:42:32 -0700 Subject: [PATCH 05/10] ``: Correct `if (!cond) x(); else y();` ... to `if (cond) y(); else x();` Drive-by: Let's `static_assert` only when running the test suite. --- stl/inc/system_error | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/stl/inc/system_error b/stl/inc/system_error index 77f6744e3c..333a6c1ec8 100644 --- a/stl/inc/system_error +++ b/stl/inc/system_error @@ -67,16 +67,16 @@ _EXPORT_STD _NODISCARD const error_category& system_category() noexcept; _EXPORT_STD class __declspec(novtable) error_category { // categorize an error public: -#ifndef _M_CEE_PURE +#ifdef _M_CEE_PURE + /* constexpr */ error_category() noexcept { // TRANSITION, ABI + _Addr = reinterpret_cast(this); + } +#else // ^^^ defined(_M_CEE_PURE) / !defined(_M_CEE_PURE) vvv #pragma warning(push) #pragma warning(disable : 4355) // 'this': used in base member initializer list constexpr error_category() noexcept : _Addr(this) {} #pragma warning(pop) -#else // ^^^ !defined(_M_CEE_PURE) / defined(_M_CEE_PURE) vvv - /* constexpr */ error_category() noexcept { // TRANSITION, ABI - _Addr = reinterpret_cast(this); - } -#endif // ^^^ defined(_M_CEE_PURE) ^^^ +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ _CONSTEXPR20 virtual ~error_category() noexcept = default; @@ -91,11 +91,11 @@ public: _NODISCARD virtual bool equivalent(const error_code& _Code, int _Errval) const noexcept; _NODISCARD bool operator==(const error_category& _Right) const noexcept { -#ifndef _M_CEE_PURE - return _Bit_cast(_Addr) == _Bit_cast(_Right._Addr); -#else // ^^^ !defined(_M_CEE_PURE) / defined(_M_CEE_PURE) vvv +#ifdef _M_CEE_PURE return _Addr == _Right._Addr; -#endif // ^^^ defined(_M_CEE_PURE) ^^^ +#else // ^^^ defined(_M_CEE_PURE) / !defined(_M_CEE_PURE) vvv + return _Bit_cast(_Addr) == _Bit_cast(_Right._Addr); +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ } #if !_HAS_CXX20 @@ -110,11 +110,11 @@ public: } #else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv _NODISCARD bool operator<(const error_category& _Right) const noexcept { -#ifndef _M_CEE_PURE - return _Bit_cast(_Addr) < _Bit_cast(_Right._Addr); -#else // ^^^ !defined(_M_CEE_PURE) / defined(_M_CEE_PURE) vvv +#ifdef _M_CEE_PURE return _Addr < _Right._Addr; -#endif // ^^^ defined(_M_CEE_PURE) ^^^ +#else // ^^^ defined(_M_CEE_PURE) / !defined(_M_CEE_PURE) vvv + return _Bit_cast(_Addr) < _Bit_cast(_Right._Addr); +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ } #endif // ^^^ !defined(__cpp_lib_concepts) ^^^ @@ -122,7 +122,9 @@ public: error_category& operator=(const error_category&) = delete; protected: -#ifndef _M_CEE_PURE +#ifdef _M_CEE_PURE + uintptr_t _Addr; +#else // ^^^ defined(_M_CEE_PURE) / !defined(_M_CEE_PURE) vvv union _Addr_storage { private: uintptr_t _Num; @@ -132,13 +134,12 @@ protected: constexpr explicit _Addr_storage(const uintptr_t _Addr_num) noexcept : _Num(_Addr_num) {} constexpr explicit _Addr_storage(error_category* const _Addr_ptr) noexcept : _Ptr(_Addr_ptr) {} }; - static_assert(sizeof(_Addr_storage) == sizeof(uintptr_t) && alignof(_Addr_storage) == alignof(uintptr_t), + _STL_INTERNAL_STATIC_ASSERT( + sizeof(_Addr_storage) == sizeof(uintptr_t) && alignof(_Addr_storage) == alignof(uintptr_t), "Unsupported platform"); _Addr_storage _Addr; -#else // ^^^ !defined(_M_CEE_PURE) / defined(_M_CEE_PURE) vvv - uintptr_t _Addr; -#endif // ^^^ defined(_M_CEE_PURE) ^^^ +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ constexpr explicit error_category(const uintptr_t _Addr_) noexcept : _Addr(_Addr_) {} From 20e587245cec01773f787dd3ef251ae44b98141c Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Mon, 24 Oct 2022 20:23:24 -0700 Subject: [PATCH 06/10] tests/P2278R4_basic_const_iterator nitpicks * Simplify nested requirement in `HasPeek` * Remove excess empty line --- tests/std/tests/P2278R4_basic_const_iterator/test.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp index b08f706aa6..660c201c58 100644 --- a/tests/std/tests/P2278R4_basic_const_iterator/test.cpp +++ b/tests/std/tests/P2278R4_basic_const_iterator/test.cpp @@ -11,13 +11,13 @@ using namespace std; -template +template concept Pointer = is_pointer_v; -template +template concept HasPeek = requires(const It& iter) { { iter.peek() } -> Pointer; - requires convertible_to*>; + { iter.peek() } -> convertible_to*>; }; static_assert(!HasPeek); @@ -95,7 +95,6 @@ constexpr void test_one(It iter) { assert(citer == iter); assert(*citer == *iter); - if constexpr (bidirectional_iterator) { { // Validate basic_const_iterator::operator--() same_as decltype(auto) citer2 = --citer; From 01719159f89a5db83e6758a660f370e71d07601d Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 25 Oct 2022 10:18:03 -0700 Subject: [PATCH 07/10] tests/P2322R6_ranges_alg_fold: factor out non-dependent tests ... from `instantiator::call`. Reduces compile + run time by 27%. --- .../tests/P2322R6_ranges_alg_fold/test.cpp | 174 +++++++++++------- 1 file changed, 104 insertions(+), 70 deletions(-) diff --git a/tests/std/tests/P2322R6_ranges_alg_fold/test.cpp b/tests/std/tests/P2322R6_ranges_alg_fold/test.cpp index 66e6105596..ba011e0a72 100644 --- a/tests/std/tests/P2322R6_ranges_alg_fold/test.cpp +++ b/tests/std/tests/P2322R6_ranges_alg_fold/test.cpp @@ -20,8 +20,7 @@ struct instantiator { static constexpr double left_difference = 0.1 - 0.2 - 0.3; static constexpr double right_product = 0.1 * (0.2 * 0.3); - template - static constexpr void call() { + static constexpr bool non_dependent() { using ranges::fold_left, ranges::fold_left_first, ranges::fold_left_with_iter, ranges::fold_left_first_with_iter, ranges::fold_right, ranges::fold_right_last, ranges::fold_left_with_iter_result, ranges::fold_left_first_with_iter_result, ranges::begin, ranges::end; @@ -30,10 +29,6 @@ struct instantiator { const auto vec_of_doubles = some_doubles | ranges::to(); { // Validate fold_left iterator+sentinel overload - const Rng wrapped{some_doubles}; - const same_as auto sum1 = fold_left(begin(wrapped), end(wrapped), 0.0, plus{}); - assert(sum1 == left_sum); - const same_as auto sum2 = fold_left(begin(vec_of_doubles), end(vec_of_doubles), 0.0, plus{}); assert(sum2 == left_sum); @@ -43,9 +38,6 @@ struct instantiator { } { // Validate fold_left range overload - const same_as auto sum1 = fold_left(Rng{some_doubles}, 0.0, plus{}); - assert(sum1 == left_sum); - const same_as auto sum2 = fold_left(vec_of_doubles, 0.0, plus{}); assert(sum2 == left_sum); @@ -55,10 +47,6 @@ struct instantiator { } { // Validate fold_left_first iterator+sentinel overload - const Rng wrapped{some_doubles}; - const same_as> auto diff1 = fold_left_first(begin(wrapped), end(wrapped), minus{}); - assert(diff1 == left_difference); - const same_as> auto diff2 = fold_left_first(begin(vec_of_doubles), end(vec_of_doubles), minus{}); assert(diff2 == left_difference); @@ -69,9 +57,6 @@ struct instantiator { } { // Validate fold_left_first range overload - const same_as> auto diff1 = fold_left_first(Rng{some_doubles}, minus{}); - assert(diff1 == left_difference); - const same_as> auto diff2 = fold_left_first(vec_of_doubles, minus{}); assert(diff2 == left_difference); @@ -80,12 +65,6 @@ struct instantiator { } { // Validate fold_left_with_iter iterator+sentinel overload - const Rng wrapped{some_doubles}; - const same_as, double>> auto sum1 = - fold_left_with_iter(begin(wrapped), end(wrapped), 0.0, plus{}); - assert(sum1.in == end(wrapped)); - assert(sum1.value == left_sum); - const same_as::const_iterator, double>> auto sum2 = fold_left_with_iter(begin(vec_of_doubles), end(vec_of_doubles), 0.0, plus{}); assert(sum2.in == end(vec_of_doubles)); @@ -99,12 +78,6 @@ struct instantiator { } { // Validate fold_left_with_iter range overload - const Rng wrapped{some_doubles}; - const same_as, double>> auto sum1 = - fold_left_with_iter(wrapped, 0.0, plus{}); - assert(sum1.in == end(wrapped)); - assert(sum1.value == left_sum); - const same_as::const_iterator, double>> auto sum2 = fold_left_with_iter(vec_of_doubles, 0.0, plus{}); assert(sum2.in == end(vec_of_doubles)); @@ -122,12 +95,6 @@ struct instantiator { } { // Validate fold_left_first_with_iter iterator+sentinel overload - const Rng wrapped{some_doubles}; - const same_as, optional>> auto diff1 = - fold_left_first_with_iter(begin(wrapped), end(wrapped), minus{}); - assert(diff1.in == end(wrapped)); - assert(diff1.value == left_difference); - const same_as::const_iterator, optional>> auto diff2 = fold_left_first_with_iter(begin(vec_of_doubles), end(vec_of_doubles), minus{}); assert(diff2.in == end(vec_of_doubles)); @@ -140,12 +107,6 @@ struct instantiator { } { // Validate fold_left_first_with_iter range overload - const Rng wrapped{some_doubles}; - const same_as, optional>> auto diff1 = - fold_left_first_with_iter(wrapped, minus{}); - assert(diff1.in == end(wrapped)); - assert(diff1.value == left_difference); - const same_as::const_iterator, optional>> auto diff2 = fold_left_first_with_iter(vec_of_doubles, minus{}); assert(diff2.in == end(vec_of_doubles)); @@ -161,32 +122,116 @@ struct instantiator { assert(diff4.value == left_difference); } + { // Validate fold_right iterator+sentinel overload + const same_as auto prod2 = + fold_right(begin(vec_of_doubles), end(vec_of_doubles), 1.0, multiplies{}); + assert(prod2 == right_product); + + const double single_value = 3.14; + const same_as auto prod3 = fold_right(begin(empty_rng), end(empty_rng), single_value, multiplies{}); + assert(prod3 == single_value); + } + + { // Validate fold_right range overload + const same_as auto prod2 = fold_right(vec_of_doubles, 1.0, multiplies{}); + assert(prod2 == right_product); + + const double single_value = 3.14; + const same_as auto prod3 = fold_right(empty_rng, single_value, multiplies{}); + assert(prod3 == single_value); + } + + { // Validate fold_right_last iterator+sentinel overload + const same_as> auto prod2 = + fold_right_last(begin(vec_of_doubles), end(vec_of_doubles), multiplies{}); + assert(prod2 == right_product); + + const same_as> auto prod3 = + fold_right_last(begin(empty_rng), end(empty_rng), multiplies{}); + assert(prod3 == nullopt); + } + + { // Validate fold_right_last range overload + const same_as> auto prod2 = fold_right_last(vec_of_doubles, multiplies{}); + assert(prod2 == right_product); + + const same_as> auto prod3 = fold_right_last(empty_rng, multiplies{}); + assert(prod3 == nullopt); + } + + return true; + } + + template + static constexpr void call() { + using ranges::fold_left, ranges::fold_left_first, ranges::fold_left_with_iter, + ranges::fold_left_first_with_iter, ranges::fold_right, ranges::fold_right_last, + ranges::fold_left_with_iter_result, ranges::fold_left_first_with_iter_result, ranges::begin, ranges::end; + + { // Validate fold_left iterator+sentinel overload + const Rng wrapped{some_doubles}; + const same_as auto sum1 = fold_left(begin(wrapped), end(wrapped), 0.0, plus{}); + assert(sum1 == left_sum); + } + + { // Validate fold_left range overload + const same_as auto sum1 = fold_left(Rng{some_doubles}, 0.0, plus{}); + assert(sum1 == left_sum); + } + + { // Validate fold_left_first iterator+sentinel overload + const Rng wrapped{some_doubles}; + const same_as> auto diff1 = fold_left_first(begin(wrapped), end(wrapped), minus{}); + assert(diff1 == left_difference); + } + + { // Validate fold_left_first range overload + const same_as> auto diff1 = fold_left_first(Rng{some_doubles}, minus{}); + assert(diff1 == left_difference); + } + + { // Validate fold_left_with_iter iterator+sentinel overload + const Rng wrapped{some_doubles}; + const same_as, double>> auto sum1 = + fold_left_with_iter(begin(wrapped), end(wrapped), 0.0, plus{}); + assert(sum1.in == end(wrapped)); + assert(sum1.value == left_sum); + } + + { // Validate fold_left_with_iter range overload + const Rng wrapped{some_doubles}; + const same_as, double>> auto sum1 = + fold_left_with_iter(wrapped, 0.0, plus{}); + assert(sum1.in == end(wrapped)); + assert(sum1.value == left_sum); + } + + { // Validate fold_left_first_with_iter iterator+sentinel overload + const Rng wrapped{some_doubles}; + const same_as, optional>> auto diff1 = + fold_left_first_with_iter(begin(wrapped), end(wrapped), minus{}); + assert(diff1.in == end(wrapped)); + assert(diff1.value == left_difference); + } + + { // Validate fold_left_first_with_iter range overload + const Rng wrapped{some_doubles}; + const same_as, optional>> auto diff1 = + fold_left_first_with_iter(wrapped, minus{}); + assert(diff1.in == end(wrapped)); + assert(diff1.value == left_difference); + } + if constexpr (ranges::bidirectional_range) { { // Validate fold_right iterator+sentinel overload const Rng wrapped{some_doubles}; const same_as auto prod1 = fold_right(begin(wrapped), end(wrapped), 1.0, multiplies{}); assert(prod1 == right_product); - - const same_as auto prod2 = - fold_right(begin(vec_of_doubles), end(vec_of_doubles), 1.0, multiplies{}); - assert(prod2 == right_product); - - const double single_value = 3.14; - const same_as auto prod3 = - fold_right(begin(empty_rng), end(empty_rng), single_value, multiplies{}); - assert(prod3 == single_value); } { // Validate fold_right range overload const same_as auto prod1 = fold_right(Rng{some_doubles}, 1.0, multiplies{}); assert(prod1 == right_product); - - const same_as auto prod2 = fold_right(vec_of_doubles, 1.0, multiplies{}); - assert(prod2 == right_product); - - const double single_value = 3.14; - const same_as auto prod3 = fold_right(empty_rng, single_value, multiplies{}); - assert(prod3 == single_value); } { // Validate fold_right_last iterator+sentinel overload @@ -194,25 +239,11 @@ struct instantiator { const same_as> auto prod1 = fold_right_last(begin(wrapped), end(wrapped), multiplies{}); assert(prod1 == right_product); - - const same_as> auto prod2 = - fold_right_last(begin(vec_of_doubles), end(vec_of_doubles), multiplies{}); - assert(prod2 == right_product); - - const same_as> auto prod3 = - fold_right_last(begin(empty_rng), end(empty_rng), multiplies{}); - assert(prod3 == nullopt); } { // Validate fold_right_last range overload const same_as> auto prod1 = fold_right_last(Rng{some_doubles}, multiplies{}); assert(prod1 == right_product); - - const same_as> auto prod2 = fold_right_last(vec_of_doubles, multiplies{}); - assert(prod2 == right_product); - - const same_as> auto prod3 = fold_right_last(empty_rng, multiplies{}); - assert(prod3 == nullopt); } } } @@ -252,6 +283,9 @@ int main() { STATIC_ASSERT((test_bidi(), true)); test_bidi(); + STATIC_ASSERT(instantiator::non_dependent()); + instantiator::non_dependent(); + STATIC_ASSERT(test_in_value_result()); assert(test_in_value_result()); } From 0af41f59e7a7b960e8803c97ceb324f27ae9b1b4 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 25 Oct 2022 11:10:31 -0700 Subject: [PATCH 08/10] _STL_INTERNAL_STATIC_ASSERT doesn't take a reason. Also split for clarity. --- stl/inc/system_error | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stl/inc/system_error b/stl/inc/system_error index 333a6c1ec8..3ff0657723 100644 --- a/stl/inc/system_error +++ b/stl/inc/system_error @@ -134,9 +134,8 @@ protected: constexpr explicit _Addr_storage(const uintptr_t _Addr_num) noexcept : _Num(_Addr_num) {} constexpr explicit _Addr_storage(error_category* const _Addr_ptr) noexcept : _Ptr(_Addr_ptr) {} }; - _STL_INTERNAL_STATIC_ASSERT( - sizeof(_Addr_storage) == sizeof(uintptr_t) && alignof(_Addr_storage) == alignof(uintptr_t), - "Unsupported platform"); + _STL_INTERNAL_STATIC_ASSERT(sizeof(_Addr_storage) == sizeof(uintptr_t)); + _STL_INTERNAL_STATIC_ASSERT(alignof(_Addr_storage) == alignof(uintptr_t)); _Addr_storage _Addr; #endif // ^^^ !defined(_M_CEE_PURE) ^^^ From 310daeeea7759f28016c54909703faa02fa3124c Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 25 Oct 2022 11:40:21 -0700 Subject: [PATCH 09/10] Fixup transform_view death test transform_view iterators are validated only when the underlying iterators are. --- tests/std/tests/P0896R4_views_transform_death/test.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0896R4_views_transform_death/test.cpp b/tests/std/tests/P0896R4_views_transform_death/test.cpp index c869f5f0cc..00e001aece 100644 --- a/tests/std/tests/P0896R4_views_transform_death/test.cpp +++ b/tests/std/tests/P0896R4_views_transform_death/test.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -14,7 +15,7 @@ using namespace std; static int some_ints[] = {0, 1, 2, 3}; [[maybe_unused]] constexpr auto lambda = [x = 42](int) { return x == 42; }; -using TV = decltype(ranges::transform_view{some_ints, lambda}); +using TV = decltype(ranges::transform_view{span{some_ints}, lambda}); void test_constructor_wrong_range() { vector vec0{0, 1, 2, 3}; @@ -42,8 +43,8 @@ void test_operator_preincrement_value_initialized_iterator() { } void test_operator_preincrement_after_end() { - TV r{some_ints, lambda}; - ranges::iterator_t i = ranges::next(r.begin(), r.end()); + ranges::transform_view r{span{some_ints}, lambda}; + auto i = ranges::next(r.begin(), r.end()); ++i; // cannot increment transform_view iterator past end } From 948fad13cc6a545fe21f53a3a80d9eca359162b5 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Tue, 25 Oct 2022 12:36:38 -0700 Subject: [PATCH 10/10] revert churn in views_transform_death --- tests/std/tests/P0896R4_views_transform_death/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/P0896R4_views_transform_death/test.cpp b/tests/std/tests/P0896R4_views_transform_death/test.cpp index 00e001aece..6ab18e8898 100644 --- a/tests/std/tests/P0896R4_views_transform_death/test.cpp +++ b/tests/std/tests/P0896R4_views_transform_death/test.cpp @@ -43,8 +43,8 @@ void test_operator_preincrement_value_initialized_iterator() { } void test_operator_preincrement_after_end() { - ranges::transform_view r{span{some_ints}, lambda}; - auto i = ranges::next(r.begin(), r.end()); + TV r{some_ints, lambda}; + ranges::iterator_t i = ranges::next(r.begin(), r.end()); ++i; // cannot increment transform_view iterator past end }