Skip to content

Commit

Permalink
[libc++] Use __wrap_iter in string_view and array in the unstable ABI
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ldionne committed Mar 1, 2024
1 parent 962f3e4 commit ba38951
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 12 deletions.
6 changes: 6 additions & 0 deletions libcxx/include/__config
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@
// The implementation moved to the header, but we still export the symbols from
// the dylib for backwards compatibility.
# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
// Define std::array/std::string_view iterators to be __wrap_iters instead of raw
// pointers, which prevents people from relying on a non-portable implementation
// detail. This is especially useful because enabling bounded iterators hardening
// requires code not to make these assumptions.
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
# elif _LIBCPP_ABI_VERSION == 1
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
// Enable compiling copies of now inline methods into the dylib to support
Expand Down
4 changes: 4 additions & 0 deletions libcxx/include/__iterator/wrap_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,14 @@ class __wrap_iter {
friend class __wrap_iter;
template <class _CharT, class _Traits, class _Alloc>
friend class basic_string;
template <class _CharT, class _Traits>
friend class basic_string_view;
template <class _Tp, class _Alloc>
friend class _LIBCPP_TEMPLATE_VIS vector;
template <class _Tp, size_t>
friend class _LIBCPP_TEMPLATE_VIS span;
template <class _Tp, size_t _Size>
friend struct array;
};

template <class _Iter1>
Expand Down
22 changes: 14 additions & 8 deletions libcxx/include/array
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
#include <__config>
#include <__fwd/array.h>
#include <__iterator/reverse_iterator.h>
#include <__iterator/wrap_iter.h>
#include <__tuple/sfinae_helpers.h>
#include <__type_traits/conditional.h>
#include <__type_traits/is_array.h>
Expand Down Expand Up @@ -167,14 +168,19 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp, size_t _Size>
struct _LIBCPP_TEMPLATE_VIS array {
// types:
using __self = array;
using value_type = _Tp;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = value_type*;
using const_iterator = const value_type*;
using pointer = value_type*;
using const_pointer = const value_type*;
using __self = array;
using value_type = _Tp;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = value_type*;
using const_pointer = const value_type*;
#if defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY)
using iterator = __wrap_iter<pointer>;
using const_iterator = __wrap_iter<const_pointer>;
#else
using iterator = pointer;
using const_iterator = const_pointer;
#endif
using size_type = size_t;
using difference_type = ptrdiff_t;
using reverse_iterator = std::reverse_iterator<iterator>;
Expand Down
11 changes: 7 additions & 4 deletions libcxx/include/string_view
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ namespace std {
#include <__iterator/concepts.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/reverse_iterator.h>
#include <__iterator/wrap_iter.h>
#include <__memory/pointer_traits.h>
#include <__ranges/concepts.h>
#include <__ranges/data.h>
Expand Down Expand Up @@ -278,10 +279,12 @@ public:
using const_pointer = const _CharT*;
using reference = _CharT&;
using const_reference = const _CharT&;
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
#if defined(_LIBCPP_ABI_BOUNDED_ITERATORS)
using const_iterator = __bounded_iter<const_pointer>;
#elif defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW)
using const_iterator = __wrap_iter<const_pointer>;
#else
using const_iterator = const_pointer; // See [string.view.iterators]
using const_iterator = const_pointer;
#endif
using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
Expand Down Expand Up @@ -353,15 +356,15 @@ public:
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
return std::__make_bounded_iter(data(), data(), data() + size());
#else
return __data_;
return const_iterator(__data_);
#endif
}

_LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT {
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
return std::__make_bounded_iter(data() + size(), data(), data() + size());
#else
return __data_ + __size_;
return const_iterator(__data_ + __size_);
#endif
}

Expand Down

0 comments on commit ba38951

Please sign in to comment.