aboutsummaryrefslogtreecommitdiff
path: root/libcxx
diff options
context:
space:
mode:
authorLouis Dionne <ldionne.2@gmail.com>2024-03-04 18:23:53 -0500
committerGitHub <noreply@github.com>2024-03-04 18:23:53 -0500
commit5174b3802575425dcbc58680ccce10961fdb8b67 (patch)
tree0cf98cdf97ad4583d2e4cb096f7a8cfe546fe0df /libcxx
parent4d80df0922ef7e48d53d4ae382977d8a2ff34ce0 (diff)
downloadllvm-5174b3802575425dcbc58680ccce10961fdb8b67.zip
llvm-5174b3802575425dcbc58680ccce10961fdb8b67.tar.gz
llvm-5174b3802575425dcbc58680ccce10961fdb8b67.tar.bz2
[libc++] Use __wrap_iter in string_view and array in the unstable ABI (#74482)
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. This patch also removes several assumptions that array iterators are raw pointers in the code base and in the test suite.
Diffstat (limited to 'libcxx')
-rw-r--r--libcxx/include/__config6
-rw-r--r--libcxx/include/__iterator/wrap_iter.h4
-rw-r--r--libcxx/include/array22
-rw-r--r--libcxx/include/string_view11
4 files changed, 31 insertions, 12 deletions
diff --git a/libcxx/include/__config b/libcxx/include/__config
index 8d4d173..3a438e8 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -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
diff --git a/libcxx/include/__iterator/wrap_iter.h b/libcxx/include/__iterator/wrap_iter.h
index 3827241..3124826 100644
--- a/libcxx/include/__iterator/wrap_iter.h
+++ b/libcxx/include/__iterator/wrap_iter.h
@@ -97,10 +97,14 @@ private:
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 961b620..7fa5dc1 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>
@@ -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>;
diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index 48bbcd8..e0dd5c5 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>
@@ -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>;
@@ -353,7 +356,7 @@ public:
#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
return std::__make_bounded_iter(data(), data(), data() + size());
#else
- return __data_;
+ return const_iterator(__data_);
#endif
}
@@ -361,7 +364,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
}