https://github.com/JMazurkiewicz updated https://github.com/llvm/llvm-project/pull/66033
>From bf7096f8f435268fd830c27056e2f24564f4356b Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz <mazku...@gmail.com> Date: Fri, 8 Sep 2023 18:20:59 +0200 Subject: [PATCH 1/5] [libc++] P2770R0: "Stashing stashing iterators for proper flattening" * Parially implements P2770R0: "Stashing stashing iterators for proper flattening" * `join_with_view` hasn't been done yet since this type isn't implemented yet * Rename `test/libcxx/ranges/range.adaptors/range.adaptor.tuple` directory to `test/libcxx/ranges/range.adaptors/range.adaptor.helpers` to match the standard: http://eel.is/c++draft/range.adaptor.helpers (this change happened in P2770R0, see point 3 of wording). * Rename `libcxx\test\std\ranges\range.adaptors\range.join.view` to `libcxx\test\std\ranges\range.adaptors\range.join` to match the standard --- libcxx/docs/Status/Cxx23.rst | 1 + libcxx/docs/Status/Cxx23Papers.csv | 2 +- libcxx/docs/Status/RangesMajorFeatures.csv | 1 + libcxx/docs/Status/RangesViews.csv | 2 +- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__ranges/helpers.h | 39 ++++++ libcxx/include/__ranges/join_view.h | 131 +++++++++++------- libcxx/include/module.modulemap.in | 1 + libcxx/include/ranges | 1 + libcxx/include/regex | 8 ++ libcxx/modules/std/ranges.inc | 2 - .../as-lvalue.verify.cpp | 47 +++++++ .../tuple-for-each.pass.cpp | 0 .../segmented_iterator.compile.pass.cpp | 1 - .../alg.copy/ranges.copy.segmented.pass.cpp | 2 - .../alg.copy/ranges.copy_backward.pass.cpp | 2 - .../iterator/ctor.parent.outer.pass.cpp | 57 -------- .../adaptor.pass.cpp | 1 - .../base.pass.cpp | 1 - .../begin.pass.cpp | 31 ++++- .../ctad.compile.pass.cpp | 1 - .../ctad.verify.cpp | 1 - .../ctor.default.pass.cpp | 1 - .../ctor.view.pass.cpp | 1 - .../end.pass.cpp | 22 +-- .../general.pass.cpp | 1 - .../iterator/arrow.pass.cpp | 1 - .../iterator/ctor.default.pass.cpp | 16 +-- .../iterator/ctor.other.pass.cpp | 3 +- .../iterator/decrement.pass.cpp | 21 ++- .../iterator/eq.pass.cpp | 7 +- .../iterator/increment.pass.cpp | 18 ++- .../iterator/iter.move.pass.cpp | 1 - .../iterator/iter.swap.pass.cpp | 1 - .../iterator/member_types.compile.pass.cpp | 1 - .../iterator/star.pass.cpp | 1 - .../sentinel/ctor.default.pass.cpp | 1 - .../sentinel/ctor.other.pass.cpp | 1 - .../sentinel/ctor.parent.pass.cpp | 1 - .../sentinel/eq.pass.cpp | 19 ++- .../{range.join.view => range.join}/types.h | 66 ++++++++- ...rator_concept_conformance.compile.pass.cpp | 4 +- .../std/re/re.iter/re.regiter/types.pass.cpp | 4 + ...rator_concept_conformance.compile.pass.cpp | 4 +- .../std/re/re.iter/re.tokiter/types.pass.cpp | 4 + 45 files changed, 350 insertions(+), 182 deletions(-) create mode 100644 libcxx/include/__ranges/helpers.h create mode 100644 libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.helpers/as-lvalue.verify.cpp rename libcxx/test/libcxx/ranges/range.adaptors/{range.adaptor.tuple => range.adaptor.helpers}/tuple-for-each.pass.cpp (100%) delete mode 100644 libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.parent.outer.pass.cpp rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/adaptor.pass.cpp (99%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/base.pass.cpp (98%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/begin.pass.cpp (83%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/ctad.compile.pass.cpp (98%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/ctad.verify.cpp (97%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/ctor.default.pass.cpp (97%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/ctor.view.pass.cpp (97%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/end.pass.cpp (95%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/general.pass.cpp (98%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/arrow.pass.cpp (99%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/ctor.default.pass.cpp (70%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/ctor.other.pass.cpp (97%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/decrement.pass.cpp (85%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/eq.pass.cpp (89%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/increment.pass.cpp (94%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/iter.move.pass.cpp (98%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/iter.swap.pass.cpp (98%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/member_types.compile.pass.cpp (99%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/iterator/star.pass.cpp (97%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/sentinel/ctor.default.pass.cpp (95%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/sentinel/ctor.other.pass.cpp (99%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/sentinel/ctor.parent.pass.cpp (97%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/sentinel/eq.pass.cpp (81%) rename libcxx/test/std/ranges/range.adaptors/{range.join.view => range.join}/types.h (88%) diff --git a/libcxx/docs/Status/Cxx23.rst b/libcxx/docs/Status/Cxx23.rst index 5b4d9a6fe943d45..bc71670fe33fe49 100644 --- a/libcxx/docs/Status/Cxx23.rst +++ b/libcxx/docs/Status/Cxx23.rst @@ -46,6 +46,7 @@ Paper Status clang doesn't issue a diagnostic for deprecated using template declarations. .. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well. .. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet. + .. [#note-P2770R0] P2770R0: Same as the above. .. [#note-P2693R1] P2693R1: The formatter for ``std::thread::id`` is implemented. The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is not implemented yet. diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv index 9cb49fd5176ea5f..3ac7a3b5e8a6b25 100644 --- a/libcxx/docs/Status/Cxx23Papers.csv +++ b/libcxx/docs/Status/Cxx23Papers.csv @@ -104,7 +104,7 @@ "`P2708R1 <https://wg21.link/P2708R1>`__","LWG", "No Further Fundamentals TSes", "November 2022","|Nothing to do|","","" "","","","","","","" "`P0290R4 <https://wg21.link/P0290R4>`__","LWG", "``apply()`` for ``synchronized_value<T>``","February 2023","","","|concurrency TS|" -"`P2770R0 <https://wg21.link/P2770R0>`__","LWG", "Stashing stashing ``iterators`` for proper flattening","February 2023","","","|ranges|" +"`P2770R0 <https://wg21.link/P2770R0>`__","LWG", "Stashing stashing ``iterators`` for proper flattening","February 2023","|Partial| [#note-P2770R0]_","","|ranges|" "`P2164R9 <https://wg21.link/P2164R9>`__","LWG", "``views::enumerate``","February 2023","","","|ranges|" "`P2711R1 <https://wg21.link/P2711R1>`__","LWG", "Making multi-param constructors of ``views`` ``explicit``","February 2023","|Partial| [#note-P2711R1]_","","|ranges|" "`P2609R3 <https://wg21.link/P2609R3>`__","LWG", "Relaxing Ranges Just A Smidge","February 2023","","","|ranges|" diff --git a/libcxx/docs/Status/RangesMajorFeatures.csv b/libcxx/docs/Status/RangesMajorFeatures.csv index 259a0218ce15e32..c0bec8d924e8a9b 100644 --- a/libcxx/docs/Status/RangesMajorFeatures.csv +++ b/libcxx/docs/Status/RangesMajorFeatures.csv @@ -2,3 +2,4 @@ Standard,Name,Assignee,CL,Status C++23,`ranges::to <https://wg21.link/P1206R7>`_,Konstantin Varlamov,`D142335 <https://reviews.llvm.org/D142335>`_,Complete C++23,`Pipe support for user-defined range adaptors <https://wg21.link/P2387R3>`_,Unassigned,No patch yet,Not started C++23,`Formatting Ranges <https://wg21.link/P2286R8>`_,Mark de Wever,Various,Complete +C++20,`Stashing stashing iterators for proper flattening <https://wg21.link/P2770R0>`_,Jakub Mazurkiewicz,Various,In progress diff --git a/libcxx/docs/Status/RangesViews.csv b/libcxx/docs/Status/RangesViews.csv index 371b01ae6920f64..b635187000252bb 100644 --- a/libcxx/docs/Status/RangesViews.csv +++ b/libcxx/docs/Status/RangesViews.csv @@ -28,7 +28,7 @@ C++23,`zip <https://wg21.link/P2321R2>`_,Hui Xie,`D122806 <https://llvm.org/D122 C++23,`zip_transform <https://wg21.link/P2321R2>`_,Hui Xie,No patch yet,Not started C++23,`adjacent <https://wg21.link/P2321R2>`_,Hui Xie,No patch yet,Not started C++23,`adjacent_transform <https://wg21.link/P2321R2>`_,Hui Xie,No patch yet,Not started -C++23,`join_with <https://wg21.link/P2441R2>`_,Unassigned,No patch yet,Not started +C++23,`join_with <https://wg21.link/P2441R2>`_,Jakub Mazurkiewicz,`GitHub #65536 <https://github.com/llvm/llvm-project/pull/65536>`_,In progress C++23,`slide <https://wg21.link/P2442R1>`_,Unassigned,No patch yet,Not started C++23,`chunk <https://wg21.link/P2442R1>`_,Unassigned,No patch yet,Not started C++23,`chunk_by <https://wg21.link/P2443R1>`_,Jakub Mazurkiewicz,`D144767 <https://llvm.org/D144767>`_,✅ diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 2ec755236dbaee2..84489fac2b0217c 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -621,6 +621,7 @@ set(files __ranges/enable_view.h __ranges/filter_view.h __ranges/from_range.h + __ranges/helpers.h __ranges/iota_view.h __ranges/istream_view.h __ranges/join_view.h diff --git a/libcxx/include/__ranges/helpers.h b/libcxx/include/__ranges/helpers.h new file mode 100644 index 000000000000000..6ea8eae022bc448 --- /dev/null +++ b/libcxx/include/__ranges/helpers.h @@ -0,0 +1,39 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_HELPERS_H +#define _LIBCPP___RANGES_HELPERS_H + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 20 + +namespace ranges { +template <class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp& __as_lvalue(_LIBCPP_LIFETIMEBOUND _Tp&& __t) { + return static_cast<_Tp&>(__t); +} +} // namespace ranges + +#endif // _LIBCPP_STD_VER >= 20 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_HELPERS_H diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h index e6240dfd2580dc7..aa361ab30e6393d 100644 --- a/libcxx/include/__ranges/join_view.h +++ b/libcxx/include/__ranges/join_view.h @@ -27,6 +27,7 @@ #include <__ranges/all.h> #include <__ranges/concepts.h> #include <__ranges/empty.h> +#include <__ranges/helpers.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> @@ -41,10 +42,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD -// Note: `join_view` is still marked experimental because there is an ABI-breaking change that affects `join_view` in -// the pipeline (https://isocpp.org/files/papers/D2770R0.html). -// TODO: make `join_view` non-experimental once D2770 is implemented. -#if _LIBCPP_STD_VER >= 20 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#if _LIBCPP_STD_VER >= 20 namespace ranges { template<class> @@ -84,11 +82,16 @@ namespace ranges { template <class> friend struct std::__segmented_iterator_traits; - static constexpr bool _UseCache = !is_reference_v<_InnerRange>; - using _Cache = _If<_UseCache, __non_propagating_cache<remove_cvref_t<_InnerRange>>, __empty_cache>; - _LIBCPP_NO_UNIQUE_ADDRESS _Cache __cache_; _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); + static constexpr bool _UseOuterCache = !forward_range<_View>; + using _OuterCache = _If<_UseOuterCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>; + _LIBCPP_NO_UNIQUE_ADDRESS _OuterCache __outer_; + + static constexpr bool _UseInnerCache = !is_reference_v<_InnerRange>; + using _InnerCache = _If<_UseInnerCache, __non_propagating_cache<remove_cvref_t<_InnerRange>>, __empty_cache>; + _LIBCPP_NO_UNIQUE_ADDRESS _InnerCache __inner_; + public: _LIBCPP_HIDE_FROM_ABI join_view() requires default_initializable<_View> = default; @@ -105,16 +108,22 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr auto begin() { - constexpr bool __use_const = __simple_view<_View> && - is_reference_v<range_reference_t<_View>>; - return __iterator<__use_const>{*this, ranges::begin(__base_)}; + if constexpr (forward_range<_View>) { + constexpr bool __use_const = __simple_view<_View> && + is_reference_v<range_reference_t<_View>>; + return __iterator<__use_const>{*this, ranges::begin(__base_)}; + } else { + __outer_.__emplace(ranges::begin(__base_)); + return __iterator<false>{*this}; + } } template<class _V2 = _View> _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const - requires input_range<const _V2> && - is_reference_v<range_reference_t<const _V2>> + requires forward_range<const _V2> && + is_reference_v<range_reference_t<const _V2>> && + input_range<range_reference_t<const _V2>> { return __iterator<true>{*this, ranges::begin(__base_)}; } @@ -134,13 +143,12 @@ namespace ranges { template<class _V2 = _View> _LIBCPP_HIDE_FROM_ABI constexpr auto end() const - requires input_range<const _V2> && - is_reference_v<range_reference_t<const _V2>> + requires forward_range<const _V2> && + is_reference_v<range_reference_t<const _V2>> && + input_range<range_reference_t<const _V2>> { using _ConstInnerRange = range_reference_t<const _View>; - if constexpr (forward_range<const _View> && - is_reference_v<_ConstInnerRange> && - forward_range<_ConstInnerRange> && + if constexpr (forward_range<_ConstInnerRange> && common_range<const _View> && common_range<_ConstInnerRange>) { return __iterator<true>{*this, ranges::end(__base_)}; @@ -154,11 +162,10 @@ namespace ranges { requires view<_View> && input_range<range_reference_t<_View>> template<bool _Const> struct join_view<_View>::__sentinel { - template<bool> - friend struct __sentinel; - private: - using _Parent = __maybe_const<_Const, join_view<_View>>; + friend join_view; + + using _Parent = __maybe_const<_Const, join_view>; using _Base = __maybe_const<_Const, _View>; sentinel_t<_Base> __end_ = sentinel_t<_Base>(); @@ -179,7 +186,7 @@ namespace ranges { requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { - return __x.__outer_ == __y.__end_; + return __x.__get_outer() == __y.__end_; } }; @@ -191,9 +198,7 @@ namespace ranges { template<bool _Const> struct join_view<_View>::__iterator final : public __join_view_iterator_category<__maybe_const<_Const, _View>> { - - template<bool> - friend struct __iterator; + friend join_view; template <class> friend struct std::__segmented_iterator_traits; @@ -209,8 +214,11 @@ namespace ranges { static constexpr bool __ref_is_glvalue = is_reference_v<range_reference_t<_Base>>; + static constexpr bool _OuterPresent = forward_range<_Base>; + using _OuterType = _If<_OuterPresent, _Outer, __empty_cache>; // TODO Use `__empty` from D154238 + public: - _Outer __outer_ = _Outer(); + _LIBCPP_NO_UNIQUE_ADDRESS _OuterType __outer_ = _OuterType(); private: optional<_Inner> __inner_; @@ -218,12 +226,12 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr void __satisfy() { - for (; __outer_ != ranges::end(__parent_->__base_); ++__outer_) { - auto&& __inner = [&]() -> auto&& { + for (; __get_outer() != ranges::end(__parent_->__base_); ++__get_outer()) { + auto&& __inner = [this]() -> auto&& { if constexpr (__ref_is_glvalue) - return *__outer_; + return *__get_outer(); else - return __parent_->__cache_.__emplace_from([&]() -> decltype(auto) { return *__outer_; }); + return __parent_->__inner_.__emplace_from([&]() -> decltype(auto) { return *__get_outer(); }); }(); __inner_ = ranges::begin(__inner); if (*__inner_ != ranges::end(__inner)) @@ -234,8 +242,37 @@ namespace ranges { __inner_.reset(); } + _LIBCPP_HIDE_FROM_ABI constexpr _Outer& __get_outer() { + if constexpr (forward_range<_Base>) { + return __outer_; + } else { + return *__parent_->__outer_; + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr const _Outer& __get_outer() const { + if constexpr (forward_range<_Base>) { + return __outer_; + } else { + return *__parent_->__outer_; + } + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, _Outer __outer) + requires forward_range<_Base> + : __outer_(std::move(__outer)), __parent_(std::addressof(__parent)) { + __satisfy(); + } + + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent) + requires(!forward_range<_Base>) + : __parent_(std::addressof(__parent)) { + __satisfy(); + } + _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent* __parent, _Outer __outer, _Inner __inner) - : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} + requires forward_range<_Base> + : __outer_(std::move(__outer)), __inner_(std::move(__inner)), __parent_(__parent) {} public: using iterator_concept = _If< @@ -254,15 +291,7 @@ namespace ranges { using difference_type = common_type_t< range_difference_t<_Base>, range_difference_t<range_reference_t<_Base>>>; - _LIBCPP_HIDE_FROM_ABI - __iterator() requires default_initializable<_Outer> = default; - - _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(_Parent& __parent, _Outer __outer) - : __outer_(std::move(__outer)) - , __parent_(std::addressof(__parent)) { - __satisfy(); - } + _LIBCPP_HIDE_FROM_ABI __iterator() = default; _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) @@ -287,14 +316,14 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { - auto&& __inner = [&]() -> auto&& { + auto __get_inner_range = [&]() -> decltype(auto) { if constexpr (__ref_is_glvalue) - return *__outer_; + return *__get_outer(); else - return *__parent_->__cache_; - }(); - if (++*__inner_ == ranges::end(__inner)) { - ++__outer_; + return *__parent_->__inner_; + }; + if (++*__inner_ == ranges::end(ranges::__as_lvalue(__get_inner_range()))) { + ++__get_outer(); __satisfy(); } return *this; @@ -324,11 +353,11 @@ namespace ranges { common_range<range_reference_t<_Base>> { if (__outer_ == ranges::end(__parent_->__base_)) - __inner_ = ranges::end(*--__outer_); + __inner_ = ranges::end(ranges::__as_lvalue(*--__outer_)); // Skip empty inner ranges when going backwards. - while (*__inner_ == ranges::begin(*__outer_)) { - __inner_ = ranges::end(*--__outer_); + while (*__inner_ == ranges::begin(ranges::__as_lvalue(*__outer_))) { + __inner_ = ranges::end(ranges::__as_lvalue(*--__outer_)); } --*__inner_; @@ -350,7 +379,7 @@ namespace ranges { _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) requires __ref_is_glvalue && - equality_comparable<iterator_t<_Base>> && + forward_range<_Base> && equality_comparable<iterator_t<range_reference_t<_Base>>> { return __x.__outer_ == __y.__outer_ && __x.__inner_ == __y.__inner_; @@ -436,7 +465,7 @@ struct __segmented_iterator_traits<_JoinViewIterator> { } }; -#endif // #if _LIBCPP_STD_VER >= 20 && defined(_LIBCPP_ENABLE_EXPERIMENTAL) +#endif // #if _LIBCPP_STD_VER >= 20 _LIBCPP_END_NAMESPACE_STD diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 6d9bb8653fcb5e9..691b1ee5a493851 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1692,6 +1692,7 @@ module std_private_ranges_filter_view [system] { export std_private_ranges_range_adaptor } module std_private_ranges_from_range [system] { header "__ranges/from_range.h" } +module std_private_ranges_helpers [system] { header "__ranges/helpers.h" } module std_private_ranges_iota_view [system] { header "__ranges/iota_view.h" } module std_private_ranges_istream_view [system] { header "__ranges/istream_view.h" diff --git a/libcxx/include/ranges b/libcxx/include/ranges index db592fd5cb360c4..4af8ec8c63eaed0 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -395,6 +395,7 @@ namespace std { #include <__ranges/enable_view.h> #include <__ranges/filter_view.h> #include <__ranges/from_range.h> +#include <__ranges/helpers.h> #include <__ranges/iota_view.h> #include <__ranges/join_view.h> #include <__ranges/lazy_split_view.h> diff --git a/libcxx/include/regex b/libcxx/include/regex index e8865ac1089d6f4..59d3af2a4bcb32a 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -697,6 +697,7 @@ public: typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; + typedef input_iterator_tag iterator_concept; // since C++20 regex_iterator(); regex_iterator(BidirectionalIterator a, BidirectionalIterator b, @@ -737,6 +738,7 @@ public: typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; + typedef input_iterator_tag iterator_concept; // since C++20 regex_token_iterator(); regex_token_iterator(BidirectionalIterator a, BidirectionalIterator b, @@ -6407,6 +6409,9 @@ public: typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; +#if _LIBCPP_STD_VER >= 20 + typedef input_iterator_tag iterator_concept; +#endif private: _BidirectionalIterator __begin_; @@ -6542,6 +6547,9 @@ public: typedef const value_type* pointer; typedef const value_type& reference; typedef forward_iterator_tag iterator_category; +#if _LIBCPP_STD_VER >= 20 + typedef input_iterator_tag iterator_concept; +#endif private: typedef regex_iterator<_BidirectionalIterator, _CharT, _Traits> _Position; diff --git a/libcxx/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc index a883103d812588b..82c7d99f8979a82 100644 --- a/libcxx/modules/std/ranges.inc +++ b/libcxx/modules/std/ranges.inc @@ -204,13 +204,11 @@ export namespace std { using std::ranges::views::drop_while; } // namespace views -#ifdef _LIBCPP_ENABLE_EXPERIMENTAL using std::ranges::join_view; namespace views { using std::ranges::views::join; } // namespace views -#endif // _LIBCPP_ENABLE_EXPERIMENTAL #if 0 using std::ranges::join_with_view; diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.helpers/as-lvalue.verify.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.helpers/as-lvalue.verify.cpp new file mode 100644 index 000000000000000..32c64020dde33ad --- /dev/null +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.helpers/as-lvalue.verify.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// <ranges> + +// template<class T> +// constexpr T& as-lvalue(T&& t) { // exposition only + +#include <ranges> + +#include <concepts> +#include <utility> + +constexpr bool test() { + // Check glvalue + { + int lvalue{}; + [[maybe_unused]] std::same_as<int&> decltype(auto) check = std::ranges::__as_lvalue(lvalue); + } + + // Check prvalue + { + [[maybe_unused]] std::same_as<int&> decltype(auto) check = std::ranges::__as_lvalue(0); // expected-warning {{temporary bound to local reference 'check' will be destroyed at the end of the full-expression}} + } + + // Check xvalue + { + int xvalue{}; + [[maybe_unused]] std::same_as<int&> decltype(auto) check = std::ranges::__as_lvalue(std::move(xvalue)); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.tuple/tuple-for-each.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.helpers/tuple-for-each.pass.cpp similarity index 100% rename from libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.tuple/tuple-for-each.pass.cpp rename to libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.helpers/tuple-for-each.pass.cpp diff --git a/libcxx/test/libcxx/ranges/range.adaptors/range.join/segmented_iterator.compile.pass.cpp b/libcxx/test/libcxx/ranges/range.adaptors/range.join/segmented_iterator.compile.pass.cpp index 82e8cab503a2750..6cd17c2b3f3533b 100644 --- a/libcxx/test/libcxx/ranges/range.adaptors/range.join/segmented_iterator.compile.pass.cpp +++ b/libcxx/test/libcxx/ranges/range.adaptors/range.join/segmented_iterator.compile.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental #include <ranges> #include <utility> diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp index 9291c0aa1f43404..19ef30436a5a04c 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy.segmented.pass.cpp @@ -7,8 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// TODO: make `join_view` non-experimental once D2770 is implemented. -// UNSUPPORTED: !c++experimental #include <algorithm> #include <array> diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp index 184008c3e2fd0ff..301fbcbc533c260 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.copy/ranges.copy_backward.pass.cpp @@ -9,8 +9,6 @@ // <algorithm> // UNSUPPORTED: c++03, c++11, c++14, c++17 -// TODO: make `join_view` non-experimental once D2770 is implemented. -// UNSUPPORTED: !c++experimental // UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME // template<bidirectional_iterator I1, sentinel_for<I1> S1, bidirectional_iterator I2> diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.parent.outer.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.parent.outer.pass.cpp deleted file mode 100644 index 215318f15cad0db..000000000000000 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.parent.outer.pass.cpp +++ /dev/null @@ -1,57 +0,0 @@ -//===----------------------------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental - -// constexpr iterator(Parent& parent, OuterIter outer); - -#include <cassert> -#include <ranges> - -#include "../types.h" - -using NonDefaultCtrIter = cpp20_input_iterator<int*>; -static_assert(!std::default_initializable<NonDefaultCtrIter>); - -using NonDefaultCtrIterView = BufferView<NonDefaultCtrIter, sentinel_wrapper<NonDefaultCtrIter>>; -static_assert(std::ranges::input_range<NonDefaultCtrIterView>); - -constexpr bool test() { - int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}; - { - CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), - CopyableChild(buffer[3])}; - CopyableParent parent{children}; - std::ranges::join_view jv(parent); - std::ranges::iterator_t<decltype(jv)> iter(jv, std::ranges::begin(parent)); - assert(*iter == 1); - } - - { - // LWG3569 Inner iterator not default_initializable - // With the current spec, the constructor under test invokes Inner iterator's default constructor - // even if it is not default constructible - // This test is checking that this constructor can be invoked with an inner range with non default - // constructible iterator - NonDefaultCtrIterView inners[] = {buffer[0], buffer[1]}; - auto outer = std::views::all(inners); - std::ranges::join_view jv(outer); - std::ranges::iterator_t<decltype(jv)> iter(jv, std::ranges::begin(outer)); - assert(*iter == 1); - } - - return true; -} - -int main(int, char**) { - test(); - static_assert(test()); - - return 0; -} diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/adaptor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/adaptor.pass.cpp similarity index 99% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/adaptor.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/adaptor.pass.cpp index afaf32272109963..9beb3d282a27cc9 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/adaptor.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/adaptor.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // std::views::join diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/base.pass.cpp similarity index 98% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/base.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/base.pass.cpp index 13883e894ac7bf9..caf018b582263a5 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/base.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/base.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr V base() const& requires copy_constructible<V>; // constexpr V base() &&; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/begin.pass.cpp similarity index 83% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/begin.pass.cpp index 9e4fa5f8c59a44a..005d0d1d2d5cb75 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/begin.pass.cpp @@ -7,15 +7,17 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr auto begin(); // constexpr auto begin() const -// requires input_range<const V> && -// is_reference_v<range_reference_t<const V>>; +// requires forward_range<const V> && +// is_reference_v<range_reference_t<const V>> && +// input_range<range_reference_t<const V>>; +#include <algorithm> #include <cassert> #include <ranges> +#include <string_view> #include "types.h" @@ -120,7 +122,7 @@ constexpr bool test() { static_assert(HasConstBegin<decltype(jv)>); } - // !input_range<const V> + // !forward_range<const V> { std::ranges::join_view jv{ConstNotRange{}}; static_assert(!HasConstBegin<decltype(jv)>); @@ -146,6 +148,27 @@ constexpr bool test() { static_assert(std::same_as<decltype(jv.begin()), decltype(std::as_const(jv).begin())>); } + // Check stashing iterators (LWG3698: regex_iterator and join_view don't work together very well) + { + std::ranges::join_view<StashingRange> jv; + assert(std::ranges::equal(std::views::counted(jv.begin(), 10), std::string_view{"aababcabcd"})); + } + + // LWG3700: The `const begin` of the `join_view` family does not require `InnerRng` to be a range + { + std::ranges::join_view<ConstNonJoinableRange> jv; + static_assert(!HasConstBegin<decltype(jv)>); + } + + // Check example from LWG3700 + { + auto r = std::views::iota(0, 5) | std::views::split(1); + auto s = std::views::single(r); + auto j = s | std::views::join; + auto f = j.front(); + assert(std::ranges::equal(f, std::views::single(0))); + } + return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/ctad.compile.pass.cpp similarity index 98% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/ctad.compile.pass.cpp index 2c470991be0b6bc..a8eafc5a9c02111 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/ctad.compile.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // template<class R> // explicit join_view(R&&) -> join_view<views::all_t<R>>; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/ctad.verify.cpp similarity index 97% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/ctad.verify.cpp index eddc950747ba768..2c6eea500580d6b 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/ctad.verify.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // template<class R> // explicit join_view(R&&) -> join_view<views::all_t<R>>; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/ctor.default.pass.cpp similarity index 97% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.default.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/ctor.default.pass.cpp index 26206e32c358cec..0daff7d3b3c98ab 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.default.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/ctor.default.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // join_view() requires default_initializable<V> = default; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/ctor.view.pass.cpp similarity index 97% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.view.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/ctor.view.pass.cpp index ce5393062d77814..75d4c7e5916b0a5 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.view.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/ctor.view.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr explicit join_view(V base); diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/end.pass.cpp similarity index 95% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/end.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/end.pass.cpp index 7e225202cc23127..516ba25a0e8596d 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/end.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/end.pass.cpp @@ -7,10 +7,12 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr auto end(); // constexpr auto end() const; +// requires forward_range<const V> && +// is_reference_v<range_reference_t<const V>> && +// input_range<range_reference_t<const V>> #include <cassert> #include <ranges> @@ -33,13 +35,13 @@ concept HasConstEnd = requires (const T& t){ // | 3 | Y | Y | Y | Y | N | Y |sentinel<true> |sentinel<true>| // | 4 | Y | Y | Y | N | Y | Y |sentinel<true> | - | // | 5 | Y | Y | N | Y | Y | Y |sentinel<true> |sentinel<true>| -// | 6 | Y | N | Y | Y | Y | Y |sentinel<true> |sentinel<true>| +// | 6 | Y | N | Y | Y | Y | Y |sentinel<true> | - | // | 7 | N | Y | Y | Y | Y | Y |iterator<false>|iterator<true>| // | 8 | N | Y | Y | Y | Y | N |sentinel<false>|sentinel<true>| // | 9 | N | Y | Y | Y | N | Y |sentinel<false>|sentinel<true>| // | 10 | N | Y | Y | N | Y | Y |sentinel<false>| - | // | 11 | N | Y | N | Y | Y | Y |sentinel<false>|sentinel<true>| -// | 12 | N | N | Y | Y | Y | Y |sentinel<false>|sentinel<true>| +// | 12 | N | N | Y | Y | Y | Y |sentinel<false>| - | // // @@ -131,10 +133,8 @@ constexpr bool test() { std::ranges::join_view jv(outer); assert(jv.end() == std::ranges::next(jv.begin(), 16)); - assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16)); - static_assert(HasConstEnd<decltype(jv)>); - static_assert(std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>); + static_assert(!HasConstEnd<decltype(jv)>); static_assert(!std::ranges::common_range<decltype(jv)>); static_assert(!std::ranges::common_range<const decltype(jv)>); } @@ -219,10 +219,8 @@ constexpr bool test() { std::ranges::join_view jv(outer); assert(jv.end() == std::ranges::next(jv.begin(), 16)); - assert(std::as_const(jv).end() == std::ranges::next(std::as_const(jv).begin(), 16)); - static_assert(HasConstEnd<decltype(jv)>); - static_assert(!std::same_as<decltype(jv.end()), decltype(std::as_const(jv).end())>); + static_assert(!HasConstEnd<decltype(jv)>); static_assert(!std::ranges::common_range<decltype(jv)>); static_assert(!std::ranges::common_range<const decltype(jv)>); } @@ -288,6 +286,12 @@ constexpr bool test() { assert(jv.end() == std::ranges::next(jv.begin(), 12)); } + // LWG3700: The `const begin` of the `join_view` family does not require `InnerRng` to be a range + { + std::ranges::join_view<ConstNonJoinableRange> jv; + static_assert(!HasConstEnd<decltype(jv)>); + } + return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/general.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/general.pass.cpp similarity index 98% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/general.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/general.pass.cpp index e9eab585260cdc9..f92eb418fac77c8 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/general.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/general.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // General tests for join_view. This file does not test anything specifically. diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/arrow.pass.cpp similarity index 99% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/arrow.pass.cpp index e610cde2c3b5bec..ddcf66bfe775e7d 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/arrow.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr InnerIter operator->() const // requires has-arrow<InnerIter> && copyable<InnerIter>; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.default.pass.cpp similarity index 70% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.default.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.default.pass.cpp index e4f193e4e606421..82fe824fad1b2a4 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.default.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.default.pass.cpp @@ -7,9 +7,8 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental -// iterator() requires default_initializable<OuterIter> = default; +// iterator() = default; #include <ranges> @@ -29,19 +28,12 @@ constexpr void test_default_constructible() { using JoinView = std::ranges::join_view<view<It>>; using JoinIterator = std::ranges::iterator_t<JoinView>; static_assert(std::is_default_constructible_v<JoinIterator>); - JoinIterator it; (void)it; -} - -template <class It> -constexpr void test_non_default_constructible() { - using JoinView = std::ranges::join_view<view<It>>; - using JoinIterator = std::ranges::iterator_t<JoinView>; - static_assert(!std::is_default_constructible_v<JoinIterator>); + [[maybe_unused]] JoinIterator it; } constexpr bool test() { - test_non_default_constructible<cpp17_input_iterator<ChildView*>>(); - // NOTE: cpp20_input_iterator can't be used with join_view because it is not copyable. + test_default_constructible<cpp17_input_iterator<ChildView*>>(); + test_default_constructible<cpp20_input_iterator<ChildView*>>(); test_default_constructible<forward_iterator<ChildView*>>(); test_default_constructible<bidirectional_iterator<ChildView*>>(); test_default_constructible<random_access_iterator<ChildView*>>(); diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.other.pass.cpp similarity index 97% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.other.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.other.pass.cpp index a0406f90c88c639..e220b2cfeac84aa 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.other.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.other.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr iterator(iterator<!Const> i) // requires Const && @@ -37,7 +36,7 @@ constexpr bool test() { { CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])}; - std::ranges::join_view jv(CopyableParent{children}); + std::ranges::join_view jv(ForwardCopyableParent{children}); auto iter1 = jv.begin(); using iterator = decltype(iter1); using const_iterator = decltype(std::as_const(jv).begin()); diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/decrement.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/decrement.pass.cpp similarity index 85% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/decrement.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/decrement.pass.cpp index 4363fb0e330c3b9..c07bf4cc2adfe1c 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/decrement.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/decrement.pass.cpp @@ -7,7 +7,14 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental + +// This causes ICE on powerpc(64)-ibm-aix: +// Assertion failed: Offset >= Size, +// file clang/lib/CodeGen/CGRecordLayoutBuilder.cpp, +// line 802, +// void (anonymous namespace)::CGRecordLowering::insertPadding()() +// TODO: investigation needed +// XFAIL: target=powerpc{{.*}}-ibm-aix // constexpr iterator& operator--(); // requires ref-is-glvalue && bidirectional_range<Base> && @@ -18,9 +25,12 @@ // bidirectional_range<range_reference_t<Base>> && // common_range<range_reference_t<Base>>; +#include <algorithm> +#include <array> #include <cassert> #include <ranges> #include <type_traits> +#include <vector> #include "../types.h" @@ -150,6 +160,15 @@ constexpr bool test() { static_assert(!CanPostDecrement<decltype(iter)>); } + { + // LWG3791: `join_view::iterator::operator--` may be ill-formed + std::vector<std::vector<int>> vec = {{1, 2}, {3, 4}, {5, 6}}; + auto r = vec | std::views::transform([](auto& x) -> auto&& { return std::move(x); }) | std::views::join; + auto e = --r.end(); + assert(*e == 6); + assert(std::ranges::equal(std::views::reverse(r), std::array{6, 5, 4, 3, 2, 1})); + } + return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/eq.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/eq.pass.cpp similarity index 89% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/eq.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/eq.pass.cpp index 327cc82b06b085b..8b7e694b080f47f 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/eq.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/eq.pass.cpp @@ -7,10 +7,9 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // friend constexpr bool operator==(const iterator& x, const iterator& y); -// requires ref-is-glvalue && equality_comparable<iterator_t<Base>> && +// requires ref-is-glvalue && forward_range<Base> && // equality_comparable<iterator_t<range_reference_t<Base>>>; #include <cassert> @@ -43,7 +42,7 @@ constexpr bool test() { } { - // !equality_comparable<iterator_t<Base>> + // !forward_range<iterator_t<Base>> using Inner = BufferView<int*>; using Outer = BufferView<cpp20_input_iterator<Inner*>, sentinel_wrapper<cpp20_input_iterator<Inner*>>>; static_assert(!std::equality_comparable<std::ranges::iterator_t<Outer>>); @@ -51,8 +50,6 @@ constexpr bool test() { std::ranges::join_view jv(Outer{inners}); auto iter = jv.begin(); static_assert(!std::equality_comparable<decltype(iter)>); - auto const_iter = std::as_const(jv).begin(); - static_assert(!std::equality_comparable<decltype(const_iter)>); } { diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/increment.pass.cpp similarity index 94% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/increment.pass.cpp index 4bcb4de7e9c8868..dada91462a73fff 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/increment.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr iterator& operator++(); // constexpr void operator++(int); @@ -205,6 +204,23 @@ constexpr bool test() { static_assert(std::is_void_v<decltype(iter++)>); } + { + // Check stashing iterators (LWG3698: regex_iterator and join_view don't work together very well) + std::ranges::join_view<StashingRange> jv; + auto it = jv.begin(); + assert(*it == 'a'); + ++it; + assert(*it == 'a'); + ++it; + assert(*it == 'b'); + it++; + assert(*it == 'a'); + it++; + assert(*it == 'b'); + ++it; + assert(*it == 'c'); + } + return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/iter.move.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/iter.move.pass.cpp similarity index 98% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/iter.move.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/iter.move.pass.cpp index 0bf6aa3d926146e..917e72dc858545c 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/iter.move.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/iter.move.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // friend constexpr decltype(auto) iter_move(const iterator& i); diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/iter.swap.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/iter.swap.pass.cpp similarity index 98% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/iter.swap.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/iter.swap.pass.cpp index e9b73f1a415966a..28e1bf75726f639 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/iter.swap.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/iter.swap.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // friend constexpr void iter_swap(const iterator& x, const iterator& y); diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/member_types.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/member_types.compile.pass.cpp similarity index 99% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/member_types.compile.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/member_types.compile.pass.cpp index 17b98facd65081d..b9b9d73d77e2655 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/member_types.compile.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/member_types.compile.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // Iterator traits and member typedefs in join_view::<iterator>. diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/star.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/star.pass.cpp similarity index 97% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/star.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/iterator/star.pass.cpp index fa6f7bb031207a3..73457b826df0b04 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/star.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/iterator/star.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr decltype(auto) operator*() const; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.default.pass.cpp similarity index 95% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.default.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.default.pass.cpp index 0eebe14af3fcba3..42fcc733e181f4f 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.default.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.default.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // sentinel() = default; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.other.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.other.pass.cpp similarity index 99% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.other.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.other.pass.cpp index c2d7058746d758b..4bd8025efb5c1b3 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.other.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.other.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr sentinel(sentinel<!Const> s); // requires Const && convertible_to<sentinel_t<V>, sentinel_t<Base>>; diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.parent.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.parent.pass.cpp similarity index 97% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.parent.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.parent.pass.cpp index a9df7c3881ba8f9..1ac68277338fee2 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.parent.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.parent.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // constexpr explicit sentinel(Parent& parent); diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/eq.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/eq.pass.cpp similarity index 81% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/eq.pass.cpp rename to libcxx/test/std/ranges/range.adaptors/range.join/sentinel/eq.pass.cpp index cbd03b84f208b9f..bc7d4bec94d3e63 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/eq.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.join/sentinel/eq.pass.cpp @@ -7,7 +7,6 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: !c++experimental // template<bool OtherConst> // requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>> @@ -17,6 +16,7 @@ #include <concepts> #include <functional> #include <ranges> +#include <type_traits> #include "../types.h" @@ -61,18 +61,27 @@ static_assert(EqualityComparable<std::ranges::iterator_t<const ConstComparableVi constexpr bool test() { int buffer[4][4] = {{1111, 2222, 3333, 4444}, {555, 666, 777, 888}, {99, 1010, 1111, 1212}, {13, 14, 15, 16}}; + // test iterator<false> == sentinel<false> { ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])}; - auto jv = std::ranges::join_view(ParentView(children)); + auto jv = std::ranges::join_view(ParentView(children)); assert(jv.end() == std::ranges::next(jv.begin(), 16)); - static_assert(!EqualityComparable<decltype(std::as_const(jv).begin()), decltype(jv.end())>); - static_assert(!EqualityComparable<decltype(jv.begin()), decltype(std::as_const(jv).end())>); } + // test iterator<false> == sentinel<true> + { + ChildView children[4] = {ChildView(buffer[0]), ChildView(buffer[1]), ChildView(buffer[2]), ChildView(buffer[3])}; + using ParentT = std::remove_all_extents_t<decltype(children)>; + auto jv = std::ranges::join_view(ForwardParentView<ParentT>(children)); + assert(std::as_const(jv).end() == std::ranges::next(jv.begin(), 16)); + } + + // test iterator<true> == sentinel<true> { CopyableChild children[4] = {CopyableChild(buffer[0]), CopyableChild(buffer[1]), CopyableChild(buffer[2]), CopyableChild(buffer[3])}; - const auto jv = std::ranges::join_view(ParentView(children)); + using ParentT = std::remove_all_extents_t<decltype(children)>; + const auto jv = std::ranges::join_view(ForwardParentView<ParentT>(children)); assert(jv.end() == std::ranges::next(jv.begin(), 16)); } diff --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/types.h b/libcxx/test/std/ranges/range.adaptors/range.join/types.h similarity index 88% rename from libcxx/test/std/ranges/range.adaptors/range.join.view/types.h rename to libcxx/test/std/ranges/range.adaptors/range.join/types.h index b2ef5f090b5731d..c1378dc1144b403 100644 --- a/libcxx/test/std/ranges/range.adaptors/range.join.view/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.join/types.h @@ -11,6 +11,7 @@ #include <concepts> #include <cstdint> +#include <string> #include <tuple> #include "test_macros.h" @@ -52,13 +53,13 @@ inline ChildView globalChildren[4] = { ChildView(globalBuffer[3]), }; -template <class T> +template <class T, template<class...> class Iter = cpp17_input_iterator> struct ParentView : std::ranges::view_base { T* ptr_; unsigned size_; - using iterator = cpp20_input_iterator<T*>; - using const_iterator = cpp20_input_iterator<const T*>; + using iterator = Iter<T*>; + using const_iterator = Iter<const T*>; using sentinel = sentinel_wrapper<iterator>; using const_sentinel = sentinel_wrapper<const_iterator>; @@ -80,6 +81,9 @@ struct ParentView : std::ranges::view_base { template <class T> ParentView(T*) -> ParentView<T>; +template<class T> +using ForwardParentView = ParentView<T, forward_iterator>; + struct CopyableChild : std::ranges::view_base { int* ptr_; unsigned size_; @@ -97,15 +101,16 @@ struct CopyableChild : std::ranges::view_base { constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); } }; -struct CopyableParent : std::ranges::view_base { +template<template<class...> class Iter> +struct CopyableParentTemplate : std::ranges::view_base { CopyableChild* ptr_; - using iterator = cpp17_input_iterator<CopyableChild*>; - using const_iterator = cpp17_input_iterator<const CopyableChild*>; + using iterator = Iter<CopyableChild*>; + using const_iterator = Iter<const CopyableChild*>; using sentinel = sentinel_wrapper<iterator>; using const_sentinel = sentinel_wrapper<const_iterator>; - constexpr CopyableParent(CopyableChild* ptr) : ptr_(ptr) {} + constexpr CopyableParentTemplate(CopyableChild* ptr) : ptr_(ptr) {} constexpr iterator begin() { return iterator(ptr_); } constexpr const_iterator begin() const { return const_iterator(ptr_); } @@ -113,6 +118,9 @@ struct CopyableParent : std::ranges::view_base { constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + 4)); } }; +using CopyableParent = CopyableParentTemplate<cpp17_input_iterator>; +using ForwardCopyableParent = CopyableParentTemplate<forward_iterator>; + struct Box { int x; }; @@ -392,4 +400,48 @@ struct IterMoveSwapAwareView : BufferView<int*> { }; static_assert(std::ranges::input_range<IterMoveSwapAwareView>); +class StashingIterator { +public: + using difference_type = std::ptrdiff_t; + using value_type = std::string; + + constexpr StashingIterator() : letter_('a') {} + + constexpr StashingIterator& operator++() { + str_ += letter_; + ++letter_; + return *this; + } + + constexpr void operator++(int) { ++*this; } + + constexpr value_type operator*() const { return str_; } + + constexpr bool operator==(std::default_sentinel_t) const { return letter_ > 'z'; } + +private: + char letter_; + value_type str_; +}; + +using StashingRange = std::ranges::subrange<StashingIterator, std::default_sentinel_t>; +static_assert(std::ranges::input_range<StashingRange>); +static_assert(!std::ranges::forward_range<StashingRange>); + +class ConstNonJoinableRange : public std::ranges::view_base { +public: + constexpr StashingIterator begin() { return {}; } + constexpr std::default_sentinel_t end() { return {}; } + + constexpr const int* begin() const { return &val_; } + constexpr const int* end() const { return &val_ + 1; } + +private: + int val_ = 1; +}; +static_assert(std::ranges::input_range<ConstNonJoinableRange>); +static_assert(std::ranges::input_range<const ConstNonJoinableRange>); +static_assert(std::ranges::input_range<std::ranges::range_reference_t<ConstNonJoinableRange>>); +static_assert(!std::ranges::input_range<std::ranges::range_reference_t<const ConstNonJoinableRange>>); + #endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_JOIN_TYPES_H diff --git a/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp index 6f2da091c3709b3..ad61baa76018da8 100644 --- a/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/re/re.iter/re.regiter/iterator_concept_conformance.compile.pass.cpp @@ -14,8 +14,8 @@ #include <iterator> -static_assert(std::forward_iterator<std::cregex_iterator>); -static_assert(!std::bidirectional_iterator<std::cregex_iterator>); +static_assert(std::input_iterator<std::cregex_iterator>); +static_assert(!std::forward_iterator<std::cregex_iterator>); static_assert(!std::indirectly_writable<std::cregex_iterator, char>); static_assert(std::sentinel_for<std::cregex_iterator, std::cregex_iterator>); static_assert(!std::sized_sentinel_for<std::cregex_iterator, std::cregex_iterator>); diff --git a/libcxx/test/std/re/re.iter/re.regiter/types.pass.cpp b/libcxx/test/std/re/re.iter/re.regiter/types.pass.cpp index 7d30b0adcc234c3..8ee2c5006d31c4a 100644 --- a/libcxx/test/std/re/re.iter/re.regiter/types.pass.cpp +++ b/libcxx/test/std/re/re.iter/re.regiter/types.pass.cpp @@ -20,6 +20,7 @@ // typedef const value_type* pointer; // typedef const value_type& reference; // typedef forward_iterator_tag iterator_category; +// typedef input_iterator_tag iterator_concept; // since C++20 #include <regex> #include <type_traits> @@ -36,6 +37,9 @@ test() static_assert((std::is_same<typename I::pointer, const std::match_results<const CharT*>*>::value), ""); static_assert((std::is_same<typename I::reference, const std::match_results<const CharT*>&>::value), ""); static_assert((std::is_same<typename I::iterator_category, std::forward_iterator_tag>::value), ""); +#if TEST_STD_VER >= 20 + static_assert(std::is_same_v<typename I::iterator_concept, std::input_iterator_tag>); +#endif } int main(int, char**) diff --git a/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp index 397226552edee07..23eea7f369c170d 100644 --- a/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp +++ b/libcxx/test/std/re/re.iter/re.tokiter/iterator_concept_conformance.compile.pass.cpp @@ -14,8 +14,8 @@ #include <iterator> -static_assert(std::forward_iterator<std::cregex_token_iterator>); -static_assert(!std::bidirectional_iterator<std::cregex_token_iterator>); +static_assert(std::input_iterator<std::cregex_token_iterator>); +static_assert(!std::forward_iterator<std::cregex_token_iterator>); static_assert(!std::indirectly_writable<std::cregex_token_iterator, char>); static_assert(std::sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>); static_assert(!std::sized_sentinel_for<std::cregex_token_iterator, std::cregex_token_iterator>); diff --git a/libcxx/test/std/re/re.iter/re.tokiter/types.pass.cpp b/libcxx/test/std/re/re.iter/re.tokiter/types.pass.cpp index 73ad58f4eecfb6a..a9c18e8a1b77a16 100644 --- a/libcxx/test/std/re/re.iter/re.tokiter/types.pass.cpp +++ b/libcxx/test/std/re/re.iter/re.tokiter/types.pass.cpp @@ -20,6 +20,7 @@ // typedef const value_type* pointer; // typedef const value_type& reference; // typedef forward_iterator_tag iterator_category; +// typedef input_iterator_tag iterator_concept; // since C++20 #include <regex> #include <type_traits> @@ -36,6 +37,9 @@ test() static_assert((std::is_same<typename I::pointer, const std::sub_match<const CharT*>*>::value), ""); static_assert((std::is_same<typename I::reference, const std::sub_match<const CharT*>&>::value), ""); static_assert((std::is_same<typename I::iterator_category, std::forward_iterator_tag>::value), ""); +#if TEST_STD_VER >= 20 + static_assert(std::is_same_v<typename I::iterator_concept, std::input_iterator_tag>); +#endif } int main(int, char**) >From abea114319aa07f8f722ff5d7778bb8c0c2b19d3 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz <mazku...@gmail.com> Date: Sat, 23 Sep 2023 23:34:12 +0200 Subject: [PATCH 2/5] Address https://github.com/llvm/llvm-project/pull/66033#discussion_r1326048325 > Not attached to the diff. We should update `libcxx/docs/UsingLibcxx.rst` to > stop mentioning that `std::ranges::join_view` is experimental. Remove note. --- libcxx/docs/UsingLibcxx.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/libcxx/docs/UsingLibcxx.rst b/libcxx/docs/UsingLibcxx.rst index ee4cd31a93526e9..d1a9a906d58051d 100644 --- a/libcxx/docs/UsingLibcxx.rst +++ b/libcxx/docs/UsingLibcxx.rst @@ -50,7 +50,6 @@ when ``-fexperimental-library`` is passed: * ``std::stop_token``, ``std::stop_source`` and ``std::stop_callback`` * ``std::jthread`` * ``std::chrono::tzdb`` and related time zone functionality -* ``std::ranges::join_view`` .. warning:: Experimental libraries are experimental. >From c8ff0e6e7d9eff414c7aab784f58203a98322cc5 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz <mazku...@gmail.com> Date: Sat, 23 Sep 2023 23:51:46 +0200 Subject: [PATCH 3/5] Address https://github.com/llvm/llvm-project/pull/66033#discussion_r1326042902 > As a general guideline, we try not to add headers with generic names like > `helpers.h`. If this utility is needed and it is needed relatively widely, it > should be in something like `__utility/as_lvalue.h`. Otherwise it could just > live in `join_view.h`. Move `as-lvalue` to `__utility/as_lvalue.h`. --- libcxx/include/CMakeLists.txt | 2 +- libcxx/include/__ranges/join_view.h | 2 +- .../include/{__ranges/helpers.h => __utility/as_lvalue.h} | 6 +++--- libcxx/include/module.modulemap.in | 2 +- libcxx/include/ranges | 1 - libcxx/include/utility | 1 + 6 files changed, 7 insertions(+), 7 deletions(-) rename libcxx/include/{__ranges/helpers.h => __utility/as_lvalue.h} (88%) diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 84489fac2b0217c..4e9ad2d09149e05 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -621,7 +621,6 @@ set(files __ranges/enable_view.h __ranges/filter_view.h __ranges/from_range.h - __ranges/helpers.h __ranges/iota_view.h __ranges/istream_view.h __ranges/join_view.h @@ -835,6 +834,7 @@ set(files __type_traits/void_t.h __undef_macros __utility/as_const.h + __utility/as_lvalue.h __utility/auto_cast.h __utility/cmp.h __utility/convert_to_integral.h diff --git a/libcxx/include/__ranges/join_view.h b/libcxx/include/__ranges/join_view.h index aa361ab30e6393d..dd8a8dc627eaed6 100644 --- a/libcxx/include/__ranges/join_view.h +++ b/libcxx/include/__ranges/join_view.h @@ -27,12 +27,12 @@ #include <__ranges/all.h> #include <__ranges/concepts.h> #include <__ranges/empty.h> -#include <__ranges/helpers.h> #include <__ranges/non_propagating_cache.h> #include <__ranges/range_adaptor.h> #include <__ranges/view_interface.h> #include <__type_traits/common_type.h> #include <__type_traits/maybe_const.h> +#include <__utility/as_lvalue.h> #include <__utility/forward.h> #include <optional> diff --git a/libcxx/include/__ranges/helpers.h b/libcxx/include/__utility/as_lvalue.h similarity index 88% rename from libcxx/include/__ranges/helpers.h rename to libcxx/include/__utility/as_lvalue.h index 6ea8eae022bc448..b4df650edbf65ef 100644 --- a/libcxx/include/__ranges/helpers.h +++ b/libcxx/include/__utility/as_lvalue.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef _LIBCPP___RANGES_HELPERS_H -#define _LIBCPP___RANGES_HELPERS_H +#ifndef _LIBCPP___UTILITY_AS_LVALUE_H +#define _LIBCPP___UTILITY_AS_LVALUE_H #include <__config> @@ -36,4 +36,4 @@ _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // _LIBCPP___RANGES_HELPERS_H +#endif // _LIBCPP___UTILITY_AS_LVALUE_H diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 691b1ee5a493851..21450eb7999868d 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1692,7 +1692,6 @@ module std_private_ranges_filter_view [system] { export std_private_ranges_range_adaptor } module std_private_ranges_from_range [system] { header "__ranges/from_range.h" } -module std_private_ranges_helpers [system] { header "__ranges/helpers.h" } module std_private_ranges_iota_view [system] { header "__ranges/iota_view.h" } module std_private_ranges_istream_view [system] { header "__ranges/istream_view.h" @@ -2044,6 +2043,7 @@ module std_private_type_traits_unwrap_ref [system module std_private_type_traits_void_t [system] { header "__type_traits/void_t.h" } module std_private_utility_as_const [system] { header "__utility/as_const.h" } +module std_private_utility_as_lvalue [system] { header "__utility/as_lvalue.h" } module std_private_utility_auto_cast [system] { header "__utility/auto_cast.h" export std_private_type_traits_decay diff --git a/libcxx/include/ranges b/libcxx/include/ranges index 4af8ec8c63eaed0..db592fd5cb360c4 100644 --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -395,7 +395,6 @@ namespace std { #include <__ranges/enable_view.h> #include <__ranges/filter_view.h> #include <__ranges/from_range.h> -#include <__ranges/helpers.h> #include <__ranges/iota_view.h> #include <__ranges/join_view.h> #include <__ranges/lazy_split_view.h> diff --git a/libcxx/include/utility b/libcxx/include/utility index c5581d55e79bbb3..1deef3db204107f 100644 --- a/libcxx/include/utility +++ b/libcxx/include/utility @@ -249,6 +249,7 @@ template <class T> #include <__assert> // all public C++ headers provide the assertion handler #include <__config> #include <__utility/as_const.h> +#include <__utility/as_lvalue.h> #include <__utility/auto_cast.h> #include <__utility/cmp.h> #include <__utility/declval.h> >From 23357b51c17ae74c0b2d6f6f7f014b7e2ac3ab3d Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz <mazku...@gmail.com> Date: Sun, 24 Sep 2023 00:09:02 +0200 Subject: [PATCH 4/5] Address https://github.com/llvm/llvm-project/pull/66033#discussion_r1326046571 > I don't understand this note. I'm not sure the note will make sense once this > is rendered as HTML? Fix note. --- libcxx/docs/Status/Cxx23.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/Status/Cxx23.rst b/libcxx/docs/Status/Cxx23.rst index bc71670fe33fe49..28eadc558da206d 100644 --- a/libcxx/docs/Status/Cxx23.rst +++ b/libcxx/docs/Status/Cxx23.rst @@ -46,7 +46,7 @@ Paper Status clang doesn't issue a diagnostic for deprecated using template declarations. .. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well. .. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet. - .. [#note-P2770R0] P2770R0: Same as the above. + .. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet. .. [#note-P2693R1] P2693R1: The formatter for ``std::thread::id`` is implemented. The formatter for ``stacktrace`` is not implemented, since ``stacktrace`` is not implemented yet. >From 2658dfb20f2dc575fe6ca23d5fd1c5e7b3651e60 Mon Sep 17 00:00:00 2001 From: Jakub Mazurkiewicz <mazku...@gmail.com> Date: Tue, 26 Sep 2023 14:48:45 +0200 Subject: [PATCH 5/5] Update `ignore_format.txt` file --- libcxx/utils/data/ignore_format.txt | 47 +++++++++++++++-------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/libcxx/utils/data/ignore_format.txt b/libcxx/utils/data/ignore_format.txt index 0efbe4c78b5490c..4a788cb4741e336 100644 --- a/libcxx/utils/data/ignore_format.txt +++ b/libcxx/utils/data/ignore_format.txt @@ -887,6 +887,7 @@ libcxx/test/libcxx/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.int/bad_en libcxx/test/libcxx/numerics/rand/rand.dis/rand.dist.uni/rand.dist.uni.real/bad_engine.verify.cpp libcxx/test/libcxx/numerics/rand/rand.req.urng/valid_int_type.verify.cpp libcxx/test/libcxx/ranges/range.access/end.incomplete_type.pass.cpp +libcxx/test/libcxx/ranges/range.adaptors/range.adaptor.helpers/as-lvalue.verify.cpp libcxx/test/libcxx/ranges/range.adaptors/range.all/all.nodiscard.verify.cpp libcxx/test/libcxx/ranges/range.adaptors/range.chunk.by/adaptor.nodiscard.verify.cpp libcxx/test/libcxx/ranges/range.adaptors/range.common.view/adaptor.nodiscard.verify.cpp @@ -5233,29 +5234,29 @@ libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/compare.pass.cpp libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.default.pass.cpp libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.pass.cpp libcxx/test/std/ranges/range.adaptors/range.filter/types.h -libcxx/test/std/ranges/range.adaptors/range.join.view/adaptor.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/base.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/begin.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.compile.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/ctad.verify.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.default.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/ctor.view.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/end.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/general.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.default.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.other.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/ctor.parent.outer.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/decrement.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/eq.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/member_types.compile.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/star.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.default.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.other.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/ctor.parent.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/sentinel/eq.pass.cpp -libcxx/test/std/ranges/range.adaptors/range.join.view/types.h +libcxx/test/std/ranges/range.adaptors/range.join/adaptor.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/base.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/begin.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/ctad.compile.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/ctad.verify.cpp +libcxx/test/std/ranges/range.adaptors/range.join/ctor.default.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/ctor.view.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/end.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/general.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/arrow.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.default.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.other.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/ctor.parent.outer.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/decrement.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/eq.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/increment.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/member_types.compile.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/iterator/star.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.default.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.other.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/sentinel/ctor.parent.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/sentinel/eq.pass.cpp +libcxx/test/std/ranges/range.adaptors/range.join/types.h libcxx/test/std/ranges/range.adaptors/range.lazy.split/adaptor.pass.cpp libcxx/test/std/ranges/range.adaptors/range.lazy.split/base.pass.cpp libcxx/test/std/ranges/range.adaptors/range.lazy.split/begin.pass.cpp _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits