Skip to content

Commit a58530a

Browse files
committed
[libc++] Use __wrap_iter in string_view and array in the unstable ABI
std::string_view and std::array iterators don't have to be raw pointers, and in fact other implementations don't represent them as raw pointers. Them being raw pointers in libc++ makes it easier for users to write non-portable code. This is bad in itself, but this is even worse when considering efforts like hardening where we want an easy ability to swap for a different iterator type. If users depend on iterators being raw pointers, this becomes a build break. Hence, this patch enables the use of __wrap_iter in the unstable ABI, creating a long term path towards making this the default. This patch may break code that assumes these iterators are raw pointers for people compiling with the unstable ABI.
1 parent 6196828 commit a58530a

File tree

4 files changed

+31
-12
lines changed

4 files changed

+31
-12
lines changed

libcxx/include/__config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@
168168
// pointer from 16 to 8. This changes the output of std::string::max_size,
169169
// which makes it ABI breaking
170170
# define _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
171+
// Define std::array/std::string_view iterators to be __wrap_iters instead of raw
172+
// pointers, which prevents people from relying on a non-portable implementation
173+
// detail. This is especially useful because enabling bounded iterators hardening
174+
// requires code not to make these assumptions.
175+
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
176+
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
171177
# elif _LIBCPP_ABI_VERSION == 1
172178
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
173179
// Enable compiling copies of now inline methods into the dylib to support

libcxx/include/__iterator/wrap_iter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,14 @@ class __wrap_iter {
9797
friend class __wrap_iter;
9898
template <class _CharT, class _Traits, class _Alloc>
9999
friend class basic_string;
100+
template <class _CharT, class _Traits>
101+
friend class basic_string_view;
100102
template <class _Tp, class _Alloc>
101103
friend class _LIBCPP_TEMPLATE_VIS vector;
102104
template <class _Tp, size_t>
103105
friend class _LIBCPP_TEMPLATE_VIS span;
106+
template <class _Tp, size_t _Size>
107+
friend struct array;
104108
};
105109

106110
template <class _Iter1>

libcxx/include/array

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
120120
#include <__config>
121121
#include <__fwd/array.h>
122122
#include <__iterator/reverse_iterator.h>
123+
#include <__iterator/wrap_iter.h>
123124
#include <__tuple/sfinae_helpers.h>
124125
#include <__type_traits/conditional.h>
125126
#include <__type_traits/is_array.h>
@@ -164,14 +165,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
164165
template <class _Tp, size_t _Size>
165166
struct _LIBCPP_TEMPLATE_VIS array {
166167
// types:
167-
using __self = array;
168-
using value_type = _Tp;
169-
using reference = value_type&;
170-
using const_reference = const value_type&;
171-
using iterator = value_type*;
172-
using const_iterator = const value_type*;
173-
using pointer = value_type*;
174-
using const_pointer = const value_type*;
168+
using __self = array;
169+
using value_type = _Tp;
170+
using reference = value_type&;
171+
using const_reference = const value_type&;
172+
using pointer = value_type*;
173+
using const_pointer = const value_type*;
174+
#if defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY)
175+
using iterator = __wrap_iter<pointer>;
176+
using const_iterator = __wrap_iter<const_pointer>;
177+
#else
178+
using iterator = pointer;
179+
using const_iterator = const_pointer;
180+
#endif
175181
using size_type = size_t;
176182
using difference_type = ptrdiff_t;
177183
using reverse_iterator = std::reverse_iterator<iterator>;

libcxx/include/string_view

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,7 @@ namespace std {
215215
#include <__iterator/concepts.h>
216216
#include <__iterator/iterator_traits.h>
217217
#include <__iterator/reverse_iterator.h>
218+
#include <__iterator/wrap_iter.h>
218219
#include <__memory/pointer_traits.h>
219220
#include <__ranges/concepts.h>
220221
#include <__ranges/data.h>
@@ -278,10 +279,12 @@ public:
278279
using const_pointer = const _CharT*;
279280
using reference = _CharT&;
280281
using const_reference = const _CharT&;
281-
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
282+
#if defined(_LIBCPP_ABI_BOUNDED_ITERATORS)
282283
using const_iterator = __bounded_iter<const_pointer>;
284+
#elif defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW)
285+
using const_iterator = __wrap_iter<const_pointer>;
283286
#else
284-
using const_iterator = const_pointer; // See [string.view.iterators]
287+
using const_iterator = const_pointer;
285288
#endif
286289
using iterator = const_iterator;
287290
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@@ -350,15 +353,15 @@ public:
350353
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
351354
return std::__make_bounded_iter(data(), data(), data() + size());
352355
#else
353-
return __data_;
356+
return const_iterator(__data_);
354357
#endif
355358
}
356359

357360
_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT {
358361
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
359362
return std::__make_bounded_iter(data() + size(), data(), data() + size());
360363
#else
361-
return __data_ + __size_;
364+
return const_iterator(__data_ + __size_);
362365
#endif
363366
}
364367

0 commit comments

Comments
 (0)