[libcxx-commits] [libcxx] a845b5b - [libc++] Use bounded iterators in std::string_view when the debug mode is enabled
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jan 31 15:23:53 PST 2023
Author: Louis Dionne
Date: 2023-01-31T18:23:46-05:00
New Revision: a845b5b4fb8a0070a6e296c462fd62bb17d74bff
URL: https://github.com/llvm/llvm-project/commit/a845b5b4fb8a0070a6e296c462fd62bb17d74bff
DIFF: https://github.com/llvm/llvm-project/commit/a845b5b4fb8a0070a6e296c462fd62bb17d74bff.diff
LOG: [libc++] Use bounded iterators in std::string_view when the debug mode is enabled
Differential Revision: https://reviews.llvm.org/D142903
Added:
libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp
Modified:
libcxx/docs/ReleaseNotes.rst
libcxx/include/__chrono/formatter.h
libcxx/include/__chrono/parser_std_format_spec.h
libcxx/include/__format/formatter_output.h
libcxx/include/__format/formatter_tuple.h
libcxx/include/__format/range_formatter.h
libcxx/include/string_view
libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp
libcxx/test/std/ranges/range.adaptors/range.lazy.split/base.pass.cpp
libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp
libcxx/test/std/ranges/range.adaptors/range.lazy.split/types.h
Removed:
################################################################################
diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst
index 268df3aebf308..8a04afb1a1459 100644
--- a/libcxx/docs/ReleaseNotes.rst
+++ b/libcxx/docs/ReleaseNotes.rst
@@ -41,6 +41,9 @@ Implemented Papers
Improvements and New Features
-----------------------------
+- ``std::string_view`` now provides iterators that check for out-of-bounds accesses when the safe
+ libc++ mode is enabled.
+
Deprecations and Removals
-------------------------
diff --git a/libcxx/include/__chrono/formatter.h b/libcxx/include/__chrono/formatter.h
index 2015783acbbbe..f3748bc730528 100644
--- a/libcxx/include/__chrono/formatter.h
+++ b/libcxx/include/__chrono/formatter.h
@@ -169,7 +169,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
if (__year < 1000 || __year > 9999)
__formatter::__format_century(__year, __sstr);
else
- __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
+ __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
} break;
case _CharT('j'):
@@ -180,7 +180,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
// an intemediate step.
__sstr << chrono::duration_cast<chrono::days>(chrono::duration_cast<chrono::seconds>(__value)).count();
else
- __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
+ __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
break;
case _CharT('q'):
@@ -208,7 +208,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
case _CharT('S'):
case _CharT('T'):
- __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
+ __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
if constexpr (__use_fraction<_Tp>())
__formatter::__format_sub_seconds(__value, __sstr);
break;
@@ -252,7 +252,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
if (__year < 1000)
__formatter::__format_year(__year, __sstr);
else
- __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
+ __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
} break;
case _CharT('F'): {
@@ -261,7 +261,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
__formatter::__format_year(__year, __sstr);
__sstr << std::format(_LIBCPP_STATICALLY_WIDEN(_CharT, "-{:02}-{:02}"), __t.tm_mon + 1, __t.tm_mday);
} else
- __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
+ __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
} break;
case _CharT('O'):
@@ -271,7 +271,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
// fractional part should be formatted.
if (*(__it + 1) == 'S') {
++__it;
- __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
+ __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
__formatter::__format_sub_seconds(__value, __sstr);
break;
}
@@ -281,7 +281,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
++__it;
[[fallthrough]];
default:
- __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), __s, __it + 1);
+ __facet.put({__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
break;
}
} else {
diff --git a/libcxx/include/__chrono/parser_std_format_spec.h b/libcxx/include/__chrono/parser_std_format_spec.h
index dbcfe6da608a8..f4f2b079b6bb1 100644
--- a/libcxx/include/__chrono/parser_std_format_spec.h
+++ b/libcxx/include/__chrono/parser_std_format_spec.h
@@ -137,17 +137,19 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) {
template <class _CharT>
class _LIBCPP_TEMPLATE_VIS __parser_chrono {
+ using _ConstIterator = typename basic_format_parse_context<_CharT>::const_iterator;
+
public:
_LIBCPP_HIDE_FROM_ABI constexpr auto
__parse(basic_format_parse_context<_CharT>& __parse_ctx, __fields __fields, __flags __flags)
-> decltype(__parse_ctx.begin()) {
- const _CharT* __begin = __parser_.__parse(__parse_ctx, __fields);
- const _CharT* __end = __parse_ctx.end();
+ _ConstIterator __begin = __parser_.__parse(__parse_ctx, __fields);
+ _ConstIterator __end = __parse_ctx.end();
if (__begin == __end)
return __begin;
- const _CharT* __last = __parse_chrono_specs(__begin, __end, __flags);
- __chrono_specs_ = basic_string_view<_CharT>{__begin, __last};
+ _ConstIterator __last = __parse_chrono_specs(__begin, __end, __flags);
+ __chrono_specs_ = basic_string_view<_CharT>{__begin, __last};
return __last;
}
@@ -156,8 +158,8 @@ class _LIBCPP_TEMPLATE_VIS __parser_chrono {
basic_string_view<_CharT> __chrono_specs_;
private:
- _LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
- __parse_chrono_specs(const _CharT* __begin, const _CharT* __end, __flags __flags) {
+ _LIBCPP_HIDE_FROM_ABI constexpr _ConstIterator
+ __parse_chrono_specs(_ConstIterator __begin, _ConstIterator __end, __flags __flags) {
_LIBCPP_ASSERT(__begin != __end,
"When called with an empty input the function will cause "
"undefined behavior by evaluating data not in the input");
@@ -190,7 +192,7 @@ class _LIBCPP_TEMPLATE_VIS __parser_chrono {
/// \pre *__begin == '%'
/// \post __begin points at the end parsed conversion-spec
_LIBCPP_HIDE_FROM_ABI constexpr void
- __parse_conversion_spec(const _CharT*& __begin, const _CharT* __end, __flags __flags) {
+ __parse_conversion_spec(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
++__begin;
if (__begin == __end)
std::__throw_format_error("End of input while parsing the modifier chrono conversion-spec");
@@ -304,7 +306,7 @@ class _LIBCPP_TEMPLATE_VIS __parser_chrono {
/// \pre *__begin == 'E'
/// \post __begin is incremented by one.
_LIBCPP_HIDE_FROM_ABI constexpr void
- __parse_modifier_E(const _CharT*& __begin, const _CharT* __end, __flags __flags) {
+ __parse_modifier_E(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
++__begin;
if (__begin == __end)
std::__throw_format_error("End of input while parsing the modifier E");
@@ -343,7 +345,7 @@ class _LIBCPP_TEMPLATE_VIS __parser_chrono {
/// \pre *__begin == 'O'
/// \post __begin is incremented by one.
_LIBCPP_HIDE_FROM_ABI constexpr void
- __parse_modifier_O(const _CharT*& __begin, const _CharT* __end, __flags __flags) {
+ __parse_modifier_O(_ConstIterator& __begin, _ConstIterator __end, __flags __flags) {
++__begin;
if (__begin == __end)
std::__throw_format_error("End of input while parsing the modifier O");
diff --git a/libcxx/include/__format/formatter_output.h b/libcxx/include/__format/formatter_output.h
index 82d619e3d2403..33a5144588542 100644
--- a/libcxx/include/__format/formatter_output.h
+++ b/libcxx/include/__format/formatter_output.h
@@ -503,7 +503,7 @@ __escape(basic_string<_CharT>& __str, basic_string_view<_CharT> __values, __esca
__unicode::__code_point_view<_CharT> __view{__values.begin(), __values.end()};
while (!__view.__at_end()) {
- const _CharT* __first = __view.__position();
+ auto __first = __view.__position();
typename __unicode::__consume_p2286_result __result = __view.__consume_p2286();
if (__result.__ill_formed_size == 0) {
if (!__formatter::__is_escaped_sequence_written(__str, __result.__value, __mark))
diff --git a/libcxx/include/__format/formatter_tuple.h b/libcxx/include/__format/formatter_tuple.h
index 6769fe47d51dc..662b7f86cfb36 100644
--- a/libcxx/include/__format/formatter_tuple.h
+++ b/libcxx/include/__format/formatter_tuple.h
@@ -51,7 +51,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple {
template <class _ParseContext>
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) {
- const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_tuple);
+ auto __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_tuple);
// [format.tuple]/7
// ... For each element e in underlying_, if e.set_debug_format()
@@ -61,7 +61,7 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_tuple {
std::__set_debug_format(std::get<_Index>(__underlying_));
});
- const _CharT* __end = __parse_ctx.end();
+ auto __end = __parse_ctx.end();
if (__begin == __end)
return __begin;
diff --git a/libcxx/include/__format/range_formatter.h b/libcxx/include/__format/range_formatter.h
index 9ea61a70350a7..5fea7b434deca 100644
--- a/libcxx/include/__format/range_formatter.h
+++ b/libcxx/include/__format/range_formatter.h
@@ -55,8 +55,8 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter {
template <class _ParseContext>
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __parse_ctx) {
- const _CharT* __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_range);
- const _CharT* __end = __parse_ctx.end();
+ auto __begin = __parser_.__parse(__parse_ctx, __format_spec::__fields_range);
+ auto __end = __parse_ctx.end();
if (__begin == __end)
return __begin;
@@ -211,7 +211,8 @@ struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT range_formatter {
__format_spec::__parser<_CharT> __parser_{.__alignment_ = __format_spec::__alignment::__left};
private:
- _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(const _CharT*& __begin, const _CharT* __end) {
+ template <contiguous_iterator _Iterator>
+ _LIBCPP_HIDE_FROM_ABI constexpr void __parse_type(_Iterator& __begin, _Iterator __end) {
switch (*__begin) {
case _CharT('m'):
if constexpr (__fmt_pair_like<_Tp>) {
diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index ea98e38de8719..5de0075dba2f9 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -208,6 +208,7 @@ namespace std {
#include <__functional/hash.h>
#include <__functional/unary_function.h>
#include <__fwd/string_view.h>
+#include <__iterator/bounded_iter.h>
#include <__iterator/concepts.h>
#include <__iterator/readable_traits.h>
#include <__iterator/reverse_iterator.h>
@@ -265,7 +266,11 @@ public:
using const_pointer = const _CharT*;
using reference = _CharT&;
using const_reference = const _CharT&;
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
+ using const_iterator = __bounded_iter<const_pointer>;
+#else
using const_iterator = const_pointer; // See [string.view.iterators]
+#endif
using iterator = const_iterator;
using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator;
@@ -343,10 +348,22 @@ public:
const_iterator end() const _NOEXCEPT { return cend(); }
_LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
- const_iterator cbegin() const _NOEXCEPT { return __data_; }
+ const_iterator cbegin() const _NOEXCEPT {
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
+ return std::__make_bounded_iter(data(), data(), data() + size());
+#else
+ return __data_;
+#endif
+ }
_LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
- const_iterator cend() const _NOEXCEPT { return __data_ + __size_; }
+ const_iterator cend() const _NOEXCEPT {
+#ifdef _LIBCPP_DEBUG_ITERATOR_BOUNDS_CHECKING
+ return std::__make_bounded_iter(data() + size(), data(), data() + size());
+#else
+ return __data_ + __size_;
+#endif
+ }
_LIBCPP_CONSTEXPR_SINCE_CXX17 _LIBCPP_INLINE_VISIBILITY
const_reverse_iterator rbegin() const _NOEXCEPT { return const_reverse_iterator(cend()); }
diff --git a/libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp b/libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp
new file mode 100644
index 0000000000000..f6b16ebd34331
--- /dev/null
+++ b/libcxx/test/libcxx/strings/string.view/string.view.iterators/debug.iterator-indexing.pass.cpp
@@ -0,0 +1,88 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Make sure that std::string_view's iterators check for OOB accesses when the debug mode is enabled.
+
+// REQUIRES: has-unix-headers
+// UNSUPPORTED: !libcpp-has-debug-mode
+
+#include <string_view>
+
+#include "check_assertion.h"
+
+int main(int, char**) {
+ // string_view::iterator
+ {
+ std::string_view const str("hello world");
+ {
+ auto it = str.end();
+ TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.end();
+ TEST_LIBCPP_ASSERT_FAILURE(it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.begin();
+ TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range");
+ }
+ }
+
+ // string_view::const_iterator
+ {
+ std::string_view const str("hello world");
+ {
+ auto it = str.cend();
+ TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.cend();
+ TEST_LIBCPP_ASSERT_FAILURE(it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.cbegin();
+ TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator[]: Attempt to index an iterator out-of-range");
+ }
+ }
+
+ // string_view::reverse_iterator
+ {
+ std::string_view const str("hello world");
+ {
+ auto it = str.rend();
+ TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.rend();
+ TEST_LIBCPP_ASSERT_FAILURE(it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.rbegin();
+ TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator");
+ }
+ }
+
+ // string_view::const_reverse_iterator
+ {
+ std::string_view const str("hello world");
+ {
+ auto it = str.crend();
+ TEST_LIBCPP_ASSERT_FAILURE(*it, "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.crend();
+ TEST_LIBCPP_ASSERT_FAILURE(it.operator->(), "__bounded_iter::operator->: Attempt to dereference an out-of-range iterator");
+ }
+ {
+ auto it = str.crbegin();
+ TEST_LIBCPP_ASSERT_FAILURE(it[99], "__bounded_iter::operator*: Attempt to dereference an out-of-range iterator");
+ }
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp
index 0592c08799ebe..9039ed051b612 100644
--- a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp
+++ b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/extended_grapheme_cluster.pass.cpp
@@ -62,11 +62,11 @@ constexpr void test(const Data& data) {
for (const auto& d : data) {
assert(d.code_points.size() == d.breaks.size());
- std::__unicode::__extended_grapheme_cluster_view view{d.input.data(), d.input.data() + d.input.size()};
+ std::__unicode::__extended_grapheme_cluster_view view{d.input.begin(), d.input.end()};
for (size_t i = 0; i < d.breaks.size(); ++i) {
auto r = view.__consume();
assert(r.__code_point_ == d.code_points[i]);
- assert(r.__last_ == d.input.data() + d.breaks[i]);
+ assert(r.__last_ == d.input.begin() + d.breaks[i]);
}
}
}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/base.pass.cpp
index b9f2ac2ddd159..c08e996a37ee4 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/base.pass.cpp
@@ -25,8 +25,8 @@ struct MoveOnlyView : std::ranges::view_base {
constexpr MoveOnlyView(std::string_view v) : view_(v) {}
constexpr MoveOnlyView(MoveOnlyView&&) = default;
constexpr MoveOnlyView& operator=(MoveOnlyView&&) = default;
- constexpr const char* begin() const { return view_.begin(); }
- constexpr const char* end() const { return view_.end(); }
+ constexpr std::string_view::const_iterator begin() const { return view_.begin(); }
+ constexpr std::string_view::const_iterator end() const { return view_.end(); }
constexpr bool operator==(MoveOnlyView rhs) const { return view_ == rhs.view_; }
};
static_assert( std::ranges::view<MoveOnlyView>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
index a82217564ecdc..ebf1356afff60 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/ctor.range.pass.cpp
@@ -80,8 +80,8 @@ struct StrView : std::ranges::view_base {
// C++23 and later.
template <std::ranges::range R>
constexpr StrView(R&& r) : buffer_(r.begin(), r.end()) {}
- constexpr const char* begin() const { return buffer_.begin(); }
- constexpr const char* end() const { return buffer_.end(); }
+ constexpr std::string_view::const_iterator begin() const { return buffer_.begin(); }
+ constexpr std::string_view::const_iterator end() const { return buffer_.end(); }
constexpr bool operator==(const StrView& rhs) const { return buffer_ == rhs.buffer_; }
};
static_assert( std::ranges::random_access_range<StrView>);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp
index 690ac7c904a76..0f5ab62650429 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/end.pass.cpp
@@ -29,8 +29,8 @@ struct ForwardViewCommonIfConst : std::ranges::view_base {
constexpr ForwardViewCommonIfConst& operator=(const ForwardViewCommonIfConst&) = default;
constexpr forward_iterator<char*> begin() { return forward_iterator<char*>(nullptr); }
constexpr std::default_sentinel_t end() { return std::default_sentinel; }
- constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(view_.begin()); }
- constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(view_.end()); }
+ constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); }
+ constexpr forward_iterator<std::string_view::const_iterator> end() const { return forward_iterator<std::string_view::const_iterator>(view_.end()); }
};
bool operator==(forward_iterator<char*>, std::default_sentinel_t) { return false; }
@@ -45,10 +45,10 @@ struct ForwardViewNonCommonRange : std::ranges::view_base {
constexpr ForwardViewNonCommonRange& operator=(const ForwardViewNonCommonRange&) = default;
constexpr forward_iterator<char*> begin() { return forward_iterator<char*>(nullptr); }
constexpr std::default_sentinel_t end() { return std::default_sentinel; }
- constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(view_.begin()); }
+ constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); }
constexpr std::default_sentinel_t end() const { return std::default_sentinel; }
};
-bool operator==(forward_iterator<const char*>, std::default_sentinel_t) { return false; }
+bool operator==(forward_iterator<std::string_view::const_iterator>, std::default_sentinel_t) { return false; }
constexpr bool test() {
// non-const: forward_range<V> && simple_view<V> && simple_view<P> -> outer-iterator<Const = true>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/types.h b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/types.h
index a606e915f04df..2eedc4c91d414 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.lazy.split/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.lazy.split/types.h
@@ -24,8 +24,8 @@ struct CopyableView : std::ranges::view_base {
constexpr explicit CopyableView() = default;
constexpr CopyableView(const char* ptr) : view_(ptr) {}
constexpr CopyableView(std::string_view v) : view_(v) {}
- constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(view_.begin()); }
- constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(view_.end()); }
+ constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); }
+ constexpr forward_iterator<std::string_view::const_iterator> end() const { return forward_iterator<std::string_view::const_iterator>(view_.end()); }
constexpr bool operator==(const CopyableView& rhs) const { return view_ == rhs.view_; }
};
static_assert( std::ranges::forward_range<CopyableView>);
@@ -42,8 +42,8 @@ struct ForwardView : std::ranges::view_base {
constexpr ForwardView(std::string_view v) : view_(v) {}
constexpr ForwardView(ForwardView&&) = default;
constexpr ForwardView& operator=(ForwardView&&) = default;
- constexpr forward_iterator<const char*> begin() const { return forward_iterator<const char*>(view_.begin()); }
- constexpr forward_iterator<const char*> end() const { return forward_iterator<const char*>(view_.end()); }
+ constexpr forward_iterator<std::string_view::const_iterator> begin() const { return forward_iterator<std::string_view::const_iterator>(view_.begin()); }
+ constexpr forward_iterator<std::string_view::const_iterator> end() const { return forward_iterator<std::string_view::const_iterator>(view_.end()); }
};
static_assert( std::ranges::forward_range<ForwardView>);
static_assert( std::ranges::forward_range<const ForwardView>);
@@ -122,13 +122,13 @@ struct ForwardOnlyIfNonConstView : std::ranges::view_base {
constexpr ForwardOnlyIfNonConstView(ForwardOnlyIfNonConstView&&) = default;
constexpr ForwardOnlyIfNonConstView& operator=(ForwardOnlyIfNonConstView&&) = default;
- constexpr forward_iterator<const char*> begin() { return forward_iterator<const char*>(view_.begin()); }
- constexpr forward_iterator<const char*> end() { return forward_iterator<const char*>(view_.end()); }
- constexpr almost_forward_iterator<const char*> begin() const {
- return almost_forward_iterator<const char*>(view_.begin());
+ constexpr forward_iterator<std::string_view::const_iterator> begin() { return forward_iterator<std::string_view::const_iterator>(view_.begin()); }
+ constexpr forward_iterator<std::string_view::const_iterator> end() { return forward_iterator<std::string_view::const_iterator>(view_.end()); }
+ constexpr almost_forward_iterator<std::string_view::const_iterator> begin() const {
+ return almost_forward_iterator<std::string_view::const_iterator>(view_.begin());
}
- constexpr almost_forward_iterator<const char*> end() const {
- return almost_forward_iterator<const char*>(view_.end());
+ constexpr almost_forward_iterator<std::string_view::const_iterator> end() const {
+ return almost_forward_iterator<std::string_view::const_iterator>(view_.end());
}
};
static_assert( std::ranges::forward_range<ForwardOnlyIfNonConstView>);
More information about the libcxx-commits
mailing list