From 28d739f407128a5b08c96919d4dea6e68dc616aa Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Tue, 21 Feb 2023 23:48:37 +0100 Subject: [PATCH 1/9] Add extra testing machinery --- tests/std/include/range_algorithm_support.hpp | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/std/include/range_algorithm_support.hpp b/tests/std/include/range_algorithm_support.hpp index 36597c5160c..2b9e254a480 100644 --- a/tests/std/include/range_algorithm_support.hpp +++ b/tests/std/include/range_algorithm_support.hpp @@ -383,6 +383,37 @@ struct std::basic_common_reference<::test::proxy_reference, ::test: }; namespace test { + template + struct init_list_not_constructible_sentinel { + init_list_not_constructible_sentinel() = default; + init_list_not_constructible_sentinel(T*) {} + + template + init_list_not_constructible_sentinel(std::initializer_list) = delete; + }; + + template + struct init_list_not_constructible_iterator { + using difference_type = int; + using value_type = T; + + init_list_not_constructible_iterator() = default; + init_list_not_constructible_iterator(T*) {} + + template + init_list_not_constructible_iterator(std::initializer_list) = delete; + + T operator*() const; // not defined + init_list_not_constructible_iterator& operator++(); // not defined + init_list_not_constructible_iterator operator++(int); // not defined + + bool operator==(init_list_not_constructible_sentinel) const; // not defined + }; + + static_assert(std::input_iterator>); + static_assert( + std::sentinel_for, init_list_not_constructible_iterator>); + template }, From 5303c0093c1f81a5dcdaa0a8a1a9501c606f38fa Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Tue, 21 Feb 2023 23:49:07 +0100 Subject: [PATCH 2/9] Fix `move_sentinel` --- stl/inc/iterator | 4 ++-- .../P0896R4_ranges_iterator_machinery/test.cpp | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/stl/inc/iterator b/stl/inc/iterator index 6af048c0988..5eeb541f246 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -187,13 +187,13 @@ public: constexpr move_sentinel() = default; constexpr explicit move_sentinel(_Se _Val) noexcept(is_nothrow_move_constructible_v<_Se>) // strengthened - : _Last{_STD move(_Val)} {} + : _Last(_STD move(_Val)) {} template requires convertible_to constexpr move_sentinel(const move_sentinel<_Se2>& _Val) noexcept( is_nothrow_constructible_v<_Se, const _Se2&>) // strengthened - : _Last{_Val._Get_last()} {} + : _Last(_Val._Get_last()) {} template requires assignable_from<_Se&, const _Se2&> diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 09e34c98304..4de3989d99a 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -11,13 +11,12 @@ #include #include +#include + #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) namespace ranges = std::ranges; -template -inline constexpr bool always_false = false; - template using reference_to = T&; template @@ -3448,6 +3447,15 @@ namespace move_iterator_test { STATIC_ASSERT(!three_way_comparable>, move_sentinel>); + void test_gh_3014() { // COMPILE-ONLY + using S = test::init_list_not_constructible_sentinel; + S s; + [[maybe_unused]] move_sentinel y{s}; // Check 'move_sentinel(S s)' + + move_sentinel s2; + [[maybe_unused]] move_sentinel z{s2}; // Check 'move_sentinel(const move_sentinel& s2)' + } + constexpr bool test() { // Validate iter_move int count = 0; From c4b83ab8f8656e2de95acf1baf89db7250f9c897 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Wed, 22 Feb 2023 12:07:39 +0100 Subject: [PATCH 3/9] Fix `iterator_t` --- stl/inc/ranges | 8 +++----- .../tests/P0896R4_views_transform/test.cpp | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 78b1c04e432..0f8a00d980d 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2380,12 +2380,10 @@ namespace ranges { #endif // _ITERATOR_DEBUG_LEVEL != 0 } - // clang-format off - constexpr _Iterator(_Iterator _It) - noexcept(is_nothrow_constructible_v, iterator_t<_Vw>>) // strengthened + constexpr _Iterator(_Iterator _It) noexcept( + is_nothrow_constructible_v, iterator_t<_Vw>>) // strengthened requires _Const && convertible_to, iterator_t<_Base>> - : _Current{_STD move(_It._Current)}, _Parent{_It._Parent} {} - // clang-format on + : _Current(_STD move(_It._Current)), _Parent(_It._Parent) {} _NODISCARD constexpr const iterator_t<_Base>& base() const& noexcept { return _Current; diff --git a/tests/std/tests/P0896R4_views_transform/test.cpp b/tests/std/tests/P0896R4_views_transform/test.cpp index 887884c942d..e314e7e6a33 100644 --- a/tests/std/tests/P0896R4_views_transform/test.cpp +++ b/tests/std/tests/P0896R4_views_transform/test.cpp @@ -811,6 +811,26 @@ void test_gh_1709() { } } +// GH-3014 ": list-initialization is misused" +void test_gh_3014() { // COMPILE-ONLY + struct InRange { + int* begin() { + return nullptr; + } + + test::init_list_not_constructible_iterator begin() const { + return nullptr; + } + + unreachable_sentinel_t end() const { + return {}; + } + }; + + auto r = InRange{} | views::transform(identity{}); + [[maybe_unused]] decltype(as_const(r).begin()) i = r.begin(); // Check 'iterator(iterator i)' +} + int main() { { // Validate copyable views constexpr span s{some_ints}; From 494545b1ae03f963b5521ed25b20271b4d08c9ee Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Wed, 22 Feb 2023 12:19:26 +0100 Subject: [PATCH 4/9] Fix `iterator_t` --- stl/inc/ranges | 2 +- tests/std/include/range_algorithm_support.hpp | 2 +- tests/std/tests/P0896R4_views_join/test.cpp | 20 +++++++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 0f8a00d980d..9d70ba9ddb1 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -3692,7 +3692,7 @@ namespace ranges { constexpr _Iterator(_Iterator _It) requires _Const && convertible_to, _OuterIter> && convertible_to>, _InnerIter> - : _Outer{_STD move(_It._Outer)}, _Inner{_STD move(_It._Inner)}, _Parent{_It._Parent} {} + : _Outer(_STD move(_It._Outer)), _Inner(_STD move(_It._Inner)), _Parent(_It._Parent) {} _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(**_Inner)) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 diff --git a/tests/std/include/range_algorithm_support.hpp b/tests/std/include/range_algorithm_support.hpp index 2b9e254a480..e6b629025b2 100644 --- a/tests/std/include/range_algorithm_support.hpp +++ b/tests/std/include/range_algorithm_support.hpp @@ -403,7 +403,7 @@ namespace test { template init_list_not_constructible_iterator(std::initializer_list) = delete; - T operator*() const; // not defined + T& operator*() const; // not defined init_list_not_constructible_iterator& operator++(); // not defined init_list_not_constructible_iterator operator++(int); // not defined diff --git a/tests/std/tests/P0896R4_views_join/test.cpp b/tests/std/tests/P0896R4_views_join/test.cpp index 7da95ce34bc..919ce6afa2f 100644 --- a/tests/std/tests/P0896R4_views_join/test.cpp +++ b/tests/std/tests/P0896R4_views_join/test.cpp @@ -503,6 +503,26 @@ void test_non_trivially_destructible_type() { // COMPILE-ONLY auto r2 = views::empty | views::transform([](Inner& r) { return r; }) | views::join; } +// GH-3014 ": list-initialization is misused" +void test_gh_3014() { // COMPILE-ONLY + struct InRange { + string* begin() { + return nullptr; + } + + test::init_list_not_constructible_iterator begin() const { + return nullptr; + } + + unreachable_sentinel_t end() const { + return {}; + } + }; + + auto r = InRange{} | views::join; + [[maybe_unused]] decltype(as_const(r).begin()) i = r.begin(); // Check 'iterator(iterator i)' +} + int main() { // Validate views constexpr string_view expected = "Hello World!"sv; From 28e0d74341daf44b5a2fc1d2f191d2a936ab27df Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Wed, 22 Feb 2023 12:26:09 +0100 Subject: [PATCH 5/9] Fix `iterator_t` --- stl/inc/ranges | 2 +- .../std/tests/P0896R4_views_elements/test.cpp | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 9d70ba9ddb1..95e0bcc0863 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -5539,7 +5539,7 @@ namespace ranges { constexpr _Iterator(_Iterator _It) noexcept( is_nothrow_constructible_v, iterator_t<_Vw>>) // strengthened requires _Const && convertible_to, iterator_t<_Base>> - : _Current{_STD move(_It._Current)} {} + : _Current(_STD move(_It._Current)) {} _NODISCARD constexpr const iterator_t<_Base>& base() const& noexcept { return _Current; diff --git a/tests/std/tests/P0896R4_views_elements/test.cpp b/tests/std/tests/P0896R4_views_elements/test.cpp index f19e4a09adc..6d8a52a5e82 100644 --- a/tests/std/tests/P0896R4_views_elements/test.cpp +++ b/tests/std/tests/P0896R4_views_elements/test.cpp @@ -394,6 +394,27 @@ constexpr void instantiation_test() { #endif // TEST_EVERYTHING } +// GH-3014 ": list-initialization is misused" +void test_gh_3014() { // COMPILE-ONLY + using P = pair; + struct InRange { + P* begin() { + return nullptr; + } + + test::init_list_not_constructible_iterator

begin() const { + return nullptr; + } + + unreachable_sentinel_t end() const { + return {}; + } + }; + + auto r = InRange{} | views::elements<0>; + [[maybe_unused]] decltype(as_const(r).begin()) i = r.begin(); // Check 'iterator(iterator i)' +} + int main() { { // Validate copyable views constexpr span s{some_pairs}; From 093d34917eddc7299618df62ff9b9f800f6382c3 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Wed, 22 Feb 2023 15:37:59 +0100 Subject: [PATCH 6/9] Fix `iterator_t` and `sentinel_t` --- stl/inc/ranges | 4 +-- .../tests/P2441R2_views_join_with/test.cpp | 35 +++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 95e0bcc0863..7c9fc6aa54f 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -4102,7 +4102,7 @@ namespace ranges { && convertible_to, _OuterIter> // && convertible_to>, _InnerIter> // && convertible_to, _PatternIter> // - : _Outer_it{_STD move(_It._Outer_it)}, _Parent{_It._Parent} { + : _Outer_it(_STD move(_It._Outer_it)), _Parent(_It._Parent) { switch (_It._Inner_it._Contains) { case _Variantish_state::_Holds_first: _Inner_it._Emplace_first(_STD move(_It._Inner_it._First)); @@ -4292,7 +4292,7 @@ namespace ranges { constexpr _Sentinel(_Sentinel _Se) noexcept( is_nothrow_constructible_v, sentinel_t<_Vw>>) // strengthened requires _Const && convertible_to, sentinel_t<_Base>> - : _Last{_STD move(_Se._Last)} {} + : _Last(_STD move(_Se._Last)) {} template requires sentinel_for, iterator_t<_Maybe_const<_OtherConst, _Vw>>> diff --git a/tests/std/tests/P2441R2_views_join_with/test.cpp b/tests/std/tests/P2441R2_views_join_with/test.cpp index d5b965a47cc..852d78745ce 100644 --- a/tests/std/tests/P2441R2_views_join_with/test.cpp +++ b/tests/std/tests/P2441R2_views_join_with/test.cpp @@ -558,6 +558,41 @@ void test_valueless_iterator() { } } +// GH-3014 ": list-initialization is misused" +struct FakeStr { + const char* begin() { + return nullptr; + } + + unreachable_sentinel_t end() { + return {}; + } +}; + +void test_gh_3014() { // COMPILE-ONLY + struct InRange { + FakeStr* begin() { + return nullptr; + } + + test::init_list_not_constructible_iterator begin() const { + return nullptr; + } + + FakeStr* end() { + return nullptr; + } + + test::init_list_not_constructible_sentinel end() const { + return nullptr; + } + }; + + auto r = InRange{} | views::join_with('-'); + [[maybe_unused]] decltype(as_const(r).begin()) i = r.begin(); // Check 'iterator(iterator i)' + [[maybe_unused]] decltype(as_const(r).end()) s = r.end(); // Check 'sentinel(sentinel s)' +} + int main() { { auto filtered_and_joined = From 4652ebd8e02c60cd312fb16c4169f246b4b1dfc4 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Wed, 22 Feb 2023 15:41:00 +0100 Subject: [PATCH 7/9] Extra comment for `move_sentinel` test --- tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 4de3989d99a..8417836a073 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -3447,6 +3447,7 @@ namespace move_iterator_test { STATIC_ASSERT(!three_way_comparable>, move_sentinel>); + // GH-3014 ": list-initialization is misused" void test_gh_3014() { // COMPILE-ONLY using S = test::init_list_not_constructible_sentinel; S s; From 857c3aa91c5d9afa2c0b815376f64ffc533af97b Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz Date: Wed, 22 Feb 2023 16:53:44 +0100 Subject: [PATCH 8/9] Fix initialization order and one more constructor (`join_with_view`) --- stl/inc/ranges | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 7c9fc6aa54f..ff0bdda974a 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -4018,7 +4018,7 @@ namespace ranges { _Variantish<_PatternIter, _InnerIter> _Inner_it{}; constexpr _Iterator(_Parent_t& _Parent_, iterator_t<_Base> _Outer_) - : _Parent{_STD addressof(_Parent_)}, _Outer_it{_STD move(_Outer_)} { + : _Parent(_STD addressof(_Parent_)), _Outer_it(_STD move(_Outer_)) { if (_Outer_it != _RANGES end(_Parent->_Range)) { auto&& _Inner = _Update_inner(); _Inner_it._Emplace_second(_RANGES begin(_Inner)); @@ -4102,7 +4102,7 @@ namespace ranges { && convertible_to, _OuterIter> // && convertible_to>, _InnerIter> // && convertible_to, _PatternIter> // - : _Outer_it(_STD move(_It._Outer_it)), _Parent(_It._Parent) { + : _Parent(_It._Parent), _Outer_it(_STD move(_It._Outer_it)) { switch (_It._Inner_it._Contains) { case _Variantish_state::_Holds_first: _Inner_it._Emplace_first(_STD move(_It._Inner_it._First)); From 9a585cee08f2302ee6f7908175bdffd1c7cf8254 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 22 Feb 2023 11:17:30 -0800 Subject: [PATCH 9/9] Code review feedback. --- tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp | 4 ---- tests/std/tests/P0896R4_views_elements/test.cpp | 1 - 2 files changed, 5 deletions(-) diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 8417836a073..4335bf5cc40 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -13,10 +13,6 @@ #include -#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) - -namespace ranges = std::ranges; - template using reference_to = T&; template diff --git a/tests/std/tests/P0896R4_views_elements/test.cpp b/tests/std/tests/P0896R4_views_elements/test.cpp index 6d8a52a5e82..1bff24a240a 100644 --- a/tests/std/tests/P0896R4_views_elements/test.cpp +++ b/tests/std/tests/P0896R4_views_elements/test.cpp @@ -396,7 +396,6 @@ constexpr void instantiation_test() { // GH-3014 ": list-initialization is misused" void test_gh_3014() { // COMPILE-ONLY - using P = pair; struct InRange { P* begin() { return nullptr;