[libcxx-commits] [libcxx] [libc++] Use __wrap_iter in string_view and array in the unstable ABI (PR #74482)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Dec 18 07:02:26 PST 2023
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/74482
>From 596c73ddfa84501cb8c6a20f4d4c9baada15d967 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 5 Dec 2023 09:57:07 -0500
Subject: [PATCH] [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.
---
libcxx/include/__config | 6 ++++++
libcxx/include/__iterator/wrap_iter.h | 2 ++
libcxx/include/array | 22 ++++++++++++++--------
libcxx/include/string_view | 11 +++++++----
4 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 7f66042f90256d..7352e57c2de657 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -168,6 +168,12 @@
// pointer from 16 to 8. This changes the output of std::string::max_size,
// which makes it ABI breaking
# define _LIBCPP_ABI_STRING_8_BYTE_ALIGNMENT
+// 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
diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h
index d028d7b3c33c7f..b9cb69dfd799a7 100644
--- a/libcxx/include/__iterator/wrap_iter.h
+++ b/libcxx/include/__iterator/wrap_iter.h
@@ -99,8 +99,10 @@ class __wrap_iter
template <class _Up> 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>
diff --git a/libcxx/include/array b/libcxx/include/array
index d00bf278e63545..b318c78b49a2be 100644
--- a/libcxx/include/array
+++ b/libcxx/include/array
@@ -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>
@@ -165,14 +166,19 @@ 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>;
diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index 3712584a6666da..282ddbc0be9ca6 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -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>
@@ -279,10 +280,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>;
@@ -367,7 +370,7 @@ public:
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
return std::__make_bounded_iter(data(), data(), data() + size());
#else
- return __data_;
+ return const_iterator(__data_);
#endif
}
@@ -376,7 +379,7 @@ public:
#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
}
More information about the libcxx-commits
mailing list