Skip to content

Commit a35629c

Browse files
authored
[libc++] Remove assumptions that std::array::iterator is a raw pointer (#74624)
This patch removes assumptions that std::array's iterators are raw pointers in the source code and in our test suite. While this is true right now, this doesn't have to be true and ion the future we might want to enable bounded iterators in std::array, which would require this change. This is a pre-requisite for landing #74482
1 parent d0605e2 commit a35629c

File tree

9 files changed

+407
-306
lines changed

9 files changed

+407
-306
lines changed

libcxx/include/__format/buffer.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,10 @@ class _LIBCPP_TEMPLATE_VIS __output_buffer {
130130
/// A std::transform wrapper.
131131
///
132132
/// Like @ref __copy it may need to do type conversion.
133-
template <__fmt_char_type _InCharT, class _UnaryOperation>
134-
_LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) {
133+
template <contiguous_iterator _Iterator,
134+
class _UnaryOperation,
135+
__fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
136+
_LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
135137
_LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range");
136138

137139
size_t __n = static_cast<size_t>(__last - __first);
@@ -590,8 +592,10 @@ class _LIBCPP_TEMPLATE_VIS __retarget_buffer {
590592
__size_ += __n;
591593
}
592594

593-
template <__fmt_char_type _InCharT, class _UnaryOperation>
594-
_LIBCPP_HIDE_FROM_ABI void __transform(const _InCharT* __first, const _InCharT* __last, _UnaryOperation __operation) {
595+
template <contiguous_iterator _Iterator,
596+
class _UnaryOperation,
597+
__fmt_char_type _InCharT = typename iterator_traits<_Iterator>::value_type>
598+
_LIBCPP_HIDE_FROM_ABI void __transform(_Iterator __first, _Iterator __last, _UnaryOperation __operation) {
595599
_LIBCPP_ASSERT_UNCATEGORIZED(__first <= __last, "not a valid range");
596600

597601
size_t __n = static_cast<size_t>(__last - __first);

libcxx/include/__format/formatter_integral.h

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
#include <__format/format_error.h>
2121
#include <__format/formatter_output.h>
2222
#include <__format/parser_std_format_spec.h>
23+
#include <__iterator/concepts.h>
24+
#include <__iterator/iterator_traits.h>
25+
#include <__memory/pointer_traits.h>
2326
#include <__system_error/errc.h>
2427
#include <__type_traits/make_unsigned.h>
2528
#include <__utility/unreachable.h>
@@ -49,7 +52,9 @@ namespace __formatter {
4952
// Generic
5053
//
5154

52-
_LIBCPP_HIDE_FROM_ABI inline char* __insert_sign(char* __buf, bool __negative, __format_spec::__sign __sign) {
55+
template <contiguous_iterator _Iterator>
56+
requires same_as<char, iter_value_t<_Iterator>>
57+
_LIBCPP_HIDE_FROM_ABI inline _Iterator __insert_sign(_Iterator __buf, bool __negative, __format_spec::__sign __sign) {
5358
if (__negative)
5459
*__buf++ = '-';
5560
else
@@ -148,14 +153,16 @@ _LIBCPP_HIDE_FROM_ABI auto __format_char(
148153
// Integer
149154
//
150155

151-
/** Wrapper around @ref to_chars, returning the output pointer. */
152-
template <integral _Tp>
153-
_LIBCPP_HIDE_FROM_ABI char* __to_buffer(char* __first, char* __last, _Tp __value, int __base) {
156+
/** Wrapper around @ref to_chars, returning the output iterator. */
157+
template <contiguous_iterator _Iterator, integral _Tp>
158+
requires same_as<char, iter_value_t<_Iterator>>
159+
_LIBCPP_HIDE_FROM_ABI _Iterator __to_buffer(_Iterator __first, _Iterator __last, _Tp __value, int __base) {
154160
// TODO FMT Evaluate code overhead due to not calling the internal function
155161
// directly. (Should be zero overhead.)
156-
to_chars_result __r = std::to_chars(__first, __last, __value, __base);
162+
to_chars_result __r = std::to_chars(std::to_address(__first), std::to_address(__last), __value, __base);
157163
_LIBCPP_ASSERT_UNCATEGORIZED(__r.ec == errc(0), "Internal buffer too small");
158-
return __r.ptr;
164+
auto __diff = __r.ptr - std::to_address(__first);
165+
return __first + __diff;
159166
}
160167

161168
/**
@@ -203,9 +210,10 @@ consteval size_t __buffer_size() noexcept
203210
+ 1; // Reserve space for the sign.
204211
}
205212

206-
template <class _OutIt, class _CharT>
207-
_LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, const char* __begin, const char* __first,
208-
const char* __last, string&& __grouping, _CharT __sep,
213+
template <class _OutIt, contiguous_iterator _Iterator, class _CharT>
214+
requires same_as<char, iter_value_t<_Iterator>>
215+
_LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, _Iterator __begin, _Iterator __first,
216+
_Iterator __last, string&& __grouping, _CharT __sep,
209217
__format_spec::__parsed_specifications<_CharT> __specs) {
210218
int __size = (__first - __begin) + // [sign][prefix]
211219
(__last - __first) + // data
@@ -269,22 +277,23 @@ _LIBCPP_HIDE_FROM_ABI _OutIt __write_using_decimal_separators(_OutIt __out_it, c
269277

270278

271279

272-
template <unsigned_integral _Tp, class _CharT, class _FormatContext>
280+
template <unsigned_integral _Tp, contiguous_iterator _Iterator, class _CharT, class _FormatContext>
281+
requires same_as<char, iter_value_t<_Iterator>>
273282
_LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator __format_integer(
274283
_Tp __value,
275284
_FormatContext& __ctx,
276285
__format_spec::__parsed_specifications<_CharT> __specs,
277286
bool __negative,
278-
char* __begin,
279-
char* __end,
287+
_Iterator __begin,
288+
_Iterator __end,
280289
const char* __prefix,
281290
int __base) {
282-
char* __first = __formatter::__insert_sign(__begin, __negative, __specs.__std_.__sign_);
291+
_Iterator __first = __formatter::__insert_sign(__begin, __negative, __specs.__std_.__sign_);
283292
if (__specs.__std_.__alternate_form_ && __prefix)
284293
while (*__prefix)
285294
*__first++ = *__prefix++;
286295

287-
char* __last = __formatter::__to_buffer(__first, __end, __value, __base);
296+
_Iterator __last = __formatter::__to_buffer(__first, __end, __value, __base);
288297

289298
# ifndef _LIBCPP_HAS_NO_LOCALIZATION
290299
if (__specs.__std_.__locale_specific_form_) {

libcxx/include/__format/formatter_output.h

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@
2323
#include <__format/unicode.h>
2424
#include <__iterator/back_insert_iterator.h>
2525
#include <__iterator/concepts.h>
26-
#include <__iterator/iterator_traits.h> // iter_value_t
26+
#include <__iterator/iterator_traits.h>
2727
#include <__memory/addressof.h>
28+
#include <__memory/pointer_traits.h>
2829
#include <__utility/move.h>
2930
#include <__utility/unreachable.h>
3031
#include <cstddef>
@@ -110,26 +111,32 @@ _LIBCPP_HIDE_FROM_ABI auto __copy(basic_string_view<_CharT> __str, output_iterat
110111
}
111112
}
112113

113-
template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT>
114-
_LIBCPP_HIDE_FROM_ABI auto
115-
__copy(const _CharT* __first, const _CharT* __last, output_iterator<const _OutCharT&> auto __out_it)
114+
template <contiguous_iterator _Iterator,
115+
__fmt_char_type _CharT = typename iterator_traits<_Iterator>::value_type,
116+
__fmt_char_type _OutCharT = _CharT>
117+
_LIBCPP_HIDE_FROM_ABI auto __copy(_Iterator __first, _Iterator __last, output_iterator<const _OutCharT&> auto __out_it)
116118
-> decltype(__out_it) {
117119
return __formatter::__copy(basic_string_view{__first, __last}, std::move(__out_it));
118120
}
119121

120-
template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT>
121-
_LIBCPP_HIDE_FROM_ABI auto __copy(const _CharT* __first, size_t __n, output_iterator<const _OutCharT&> auto __out_it)
122+
template <contiguous_iterator _Iterator,
123+
__fmt_char_type _CharT = typename iterator_traits<_Iterator>::value_type,
124+
__fmt_char_type _OutCharT = _CharT>
125+
_LIBCPP_HIDE_FROM_ABI auto __copy(_Iterator __first, size_t __n, output_iterator<const _OutCharT&> auto __out_it)
122126
-> decltype(__out_it) {
123-
return __formatter::__copy(basic_string_view{__first, __n}, std::move(__out_it));
127+
return __formatter::__copy(basic_string_view{std::to_address(__first), __n}, std::move(__out_it));
124128
}
125129

126130
/// Transform wrapper.
127131
///
128132
/// This uses a "mass output function" of __format::__output_buffer when possible.
129-
template <__fmt_char_type _CharT, __fmt_char_type _OutCharT = _CharT, class _UnaryOperation>
133+
template <contiguous_iterator _Iterator,
134+
__fmt_char_type _CharT = typename iterator_traits<_Iterator>::value_type,
135+
__fmt_char_type _OutCharT = _CharT,
136+
class _UnaryOperation>
130137
_LIBCPP_HIDE_FROM_ABI auto
131-
__transform(const _CharT* __first,
132-
const _CharT* __last,
138+
__transform(_Iterator __first,
139+
_Iterator __last,
133140
output_iterator<const _OutCharT&> auto __out_it,
134141
_UnaryOperation __operation) -> decltype(__out_it) {
135142
if constexpr (std::same_as<decltype(__out_it), std::back_insert_iterator<__format::__output_buffer<_OutCharT>>>) {
@@ -260,8 +267,11 @@ __write(_Iterator __first,
260267
return __formatter::__write(__first, __last, std::move(__out_it), __specs, __last - __first);
261268
}
262269

263-
template <class _CharT, class _ParserCharT, class _UnaryOperation>
264-
_LIBCPP_HIDE_FROM_ABI auto __write_transformed(const _CharT* __first, const _CharT* __last,
270+
template <contiguous_iterator _Iterator,
271+
class _CharT = typename iterator_traits<_Iterator>::value_type,
272+
class _ParserCharT,
273+
class _UnaryOperation>
274+
_LIBCPP_HIDE_FROM_ABI auto __write_transformed(_Iterator __first, _Iterator __last,
265275
output_iterator<const _CharT&> auto __out_it,
266276
__format_spec::__parsed_specifications<_ParserCharT> __specs,
267277
_UnaryOperation __op) -> decltype(__out_it) {

libcxx/test/libcxx/input.output/iostream.format/print.fun/transcoding.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
99
// UNSUPPORTED: no-filesystem
1010
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
11+
// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=2000000
1112

1213
// <print>
1314

@@ -32,9 +33,9 @@ constexpr void test(std::basic_string_view<CharT> expected, std::string_view inp
3233
std::array<CharT, 1024> buffer;
3334
std::ranges::fill(buffer, CharT('*'));
3435

35-
CharT* out = std::__unicode::__transcode(input.begin(), input.end(), buffer.data());
36+
auto out = std::__unicode::__transcode(input.begin(), input.end(), buffer.begin());
3637

37-
assert(std::basic_string_view<CharT>(buffer.data(), out) == expected);
38+
assert(std::basic_string_view<CharT>(buffer.begin(), out) == expected);
3839

3940
out = std::find_if(out, buffer.end(), [](CharT c) { return c != CharT('*'); });
4041
assert(out == buffer.end());

libcxx/test/std/algorithms/robust_against_proxy_iterators_lifetime_bugs.pass.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -547,24 +547,22 @@ class ConstexprIterator {
547547

548548
#endif // TEST_STD_VER > 17
549549

550-
template <class T, std::size_t N = 32>
550+
template <class T, std::size_t StorageSize = 32>
551551
class Input {
552-
using Array = std::array<T, N>;
553-
554552
std::size_t size_ = 0;
555-
Array values_ = {};
553+
T values_[StorageSize] = {};
556554

557555
public:
558-
template <std::size_t N2>
559-
TEST_CONSTEXPR_CXX20 Input(std::array<T, N2> from) {
560-
static_assert(N2 <= N, "");
556+
template <std::size_t N>
557+
TEST_CONSTEXPR_CXX20 Input(std::array<T, N> from) {
558+
static_assert(N <= StorageSize, "");
561559

562560
std::copy(from.begin(), from.end(), begin());
563-
size_ = N2;
561+
size_ = N;
564562
}
565563

566-
TEST_CONSTEXPR_CXX20 typename Array::iterator begin() { return values_.begin(); }
567-
TEST_CONSTEXPR_CXX20 typename Array::iterator end() { return values_.begin() + size_; }
564+
TEST_CONSTEXPR_CXX20 T* begin() { return values_; }
565+
TEST_CONSTEXPR_CXX20 T* end() { return values_ + size_; }
568566
TEST_CONSTEXPR_CXX20 std::size_t size() const { return size_; }
569567
};
570568

libcxx/test/std/containers/sequences/array/types.pass.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,6 @@ int main(int, char**)
5454
typedef std::array<T, 10> C;
5555
static_assert((std::is_same<C::reference, T&>::value), "");
5656
static_assert((std::is_same<C::const_reference, const T&>::value), "");
57-
LIBCPP_STATIC_ASSERT((std::is_same<C::iterator, T*>::value), "");
58-
LIBCPP_STATIC_ASSERT((std::is_same<C::const_iterator, const T*>::value), "");
5957
test_iterators<C>();
6058
static_assert((std::is_same<C::pointer, T*>::value), "");
6159
static_assert((std::is_same<C::const_pointer, const T*>::value), "");
@@ -76,8 +74,6 @@ int main(int, char**)
7674
typedef std::array<T, 0> C;
7775
static_assert((std::is_same<C::reference, T&>::value), "");
7876
static_assert((std::is_same<C::const_reference, const T&>::value), "");
79-
LIBCPP_STATIC_ASSERT((std::is_same<C::iterator, T*>::value), "");
80-
LIBCPP_STATIC_ASSERT((std::is_same<C::const_iterator, const T*>::value), "");
8177
test_iterators<C>();
8278
static_assert((std::is_same<C::pointer, T*>::value), "");
8379
static_assert((std::is_same<C::const_pointer, const T*>::value), "");

libcxx/test/std/containers/views/views.span/span.cons/iterator_sentinel.pass.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,10 @@ class throw_operator_minus {
114114
friend difference_type operator-(throw_operator_minus, throw_operator_minus) { throw 42; };
115115

116116
friend bool operator==(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ == y.it_; }
117-
friend auto operator<=>(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ <=> y.it_; }
117+
friend bool operator<(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ < y.it_; }
118+
friend bool operator>(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ > y.it_; }
119+
friend bool operator<=(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ <= y.it_; }
120+
friend bool operator>=(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ >= y.it_; }
118121
};
119122

120123
template <class It>

0 commit comments

Comments
 (0)