[libcxx-commits] [libcxx] [libc++] Introduce _LIBCPP_ABI_BOUNDED_ITERATORS_IN_{STRING_VIEW, SPAN} (PR #143172)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jun 6 10:01:56 PDT 2025


https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/143172

For consistency with other containers, introduce per-container macros to enable bounded iterators in span and string_view. This patch also keeps the original macro around for backwards compatibility, although we probably want to deprecate and eventually remove it in a separate patch since the name can lead to confusion.

>From 43f6163063de57bba11ba34f7795be9cf4447dde Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 6 Jun 2025 12:54:48 -0400
Subject: [PATCH] [libc++] Introduce
 _LIBCPP_ABI_BOUNDED_ITERATORS_IN_{STRING_VIEW,SPAN}

For consistency with other containers, introduce per-container macros to
enable bounded iterators in span and string_view. This patch also keeps
the original macro around for backwards compatibility, although we probably
want to deprecate and eventually remove it in a separate patch since the
name can lead to confusion.
---
 ...-hardening-mode-fast-with-abi-breaks.cmake |  3 +-
 libcxx/docs/Hardening.rst                     | 26 +++++++++------
 libcxx/docs/ReleaseNotes/21.rst               |  4 +++
 libcxx/include/__configuration/abi.h          | 32 +++++++++++++------
 libcxx/include/span                           | 12 +++----
 libcxx/include/string_view                    |  6 ++--
 .../bounded-iterator-macro.compile.pass.cpp   | 22 +++++++++++++
 .../assert.iterator-indexing.pass.cpp         |  2 +-
 .../assert.iterator-indexing.pass.cpp         |  2 +-
 libcxx/utils/libcxx/test/features.py          |  3 +-
 10 files changed, 80 insertions(+), 32 deletions(-)
 create mode 100644 libcxx/test/libcxx/bounded-iterator-macro.compile.pass.cpp

diff --git a/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake b/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake
index 699d3f8866861..66b964bf27b3f 100644
--- a/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake
+++ b/libcxx/cmake/caches/Generic-hardening-mode-fast-with-abi-breaks.cmake
@@ -1,7 +1,8 @@
 set(LIBCXX_HARDENING_MODE "fast" CACHE STRING "")
 set(_defines
-    _LIBCPP_ABI_BOUNDED_ITERATORS
+    _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
     _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING
+    _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW
     _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
     _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
     _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY
diff --git a/libcxx/docs/Hardening.rst b/libcxx/docs/Hardening.rst
index 17808841bd9ec..6d4e0883f6b1a 100644
--- a/libcxx/docs/Hardening.rst
+++ b/libcxx/docs/Hardening.rst
@@ -314,22 +314,28 @@ itself) to enable additional hardening checks. This is done by passing these
 macros as ``-DLIBCXX_ABI_DEFINES="_LIBCPP_ABI_FOO;_LIBCPP_ABI_BAR;etc"`` at
 CMake configuration time. The available options are:
 
-- ``_LIBCPP_ABI_BOUNDED_ITERATORS`` -- changes the iterator type of select
-  containers (see below) to a bounded iterator that keeps track of whether it's
-  within the bounds of the original container and asserts valid bounds on every
-  dereference.
+- ``_LIBCPP_ABI_BOUNDED_ITERATORS`` -- historical equivalent to defining both
+  ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW`` and ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN``.
 
-  ABI impact: changes the iterator type of the relevant containers.
+- ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW`` -- changes the iterator type of
+  ``basic_string_view`` to a bounded iterator that keeps track of whether it's within
+  the bounds of the original container and asserts it on every dereference and
+  when performing iterator arithmetic.
+
+  ABI impact: changes the iterator type of ``basic_string_view`` and its
+  specializations, such as ``string_view`` and ``wstring_view``.
 
-  Supported containers:
+- ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN`` -- changes the iterator type of ``span``
+  to a bounded iterator that keeps track of whether it's within the bounds of the
+  original container and asserts it on every dereference and when performing iterator
+  arithmetic.
 
-  - ``span``;
-  - ``string_view``.
+  ABI impact: changes the iterator type of ``span``.
 
 - ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING`` -- changes the iterator type of
   ``basic_string`` to a bounded iterator that keeps track of whether it's within
   the bounds of the original container and asserts it on every dereference and
-  when performing iterator arithmetics.
+  when performing iterator arithmetic.
 
   ABI impact: changes the iterator type of ``basic_string`` and its
   specializations, such as ``string`` and ``wstring``.
@@ -337,7 +343,7 @@ CMake configuration time. The available options are:
 - ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR`` -- changes the iterator type of
   ``vector`` to a bounded iterator that keeps track of whether it's within the
   bounds of the original container and asserts it on every dereference and when
-  performing iterator arithmetics. Note: this doesn't yet affect
+  performing iterator arithmetic. Note: this doesn't yet affect
   ``vector<bool>``.
 
   ABI impact: changes the iterator type of ``vector`` (except ``vector<bool>``).
diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst
index 6cbc0baf29487..7d8fe07d7ca27 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -76,6 +76,10 @@ Improvements and New Features
 - The ``bitset::to_string`` function has been optimized, resulting in a performance improvement of up to 8.3x for bitsets
   with uniformly distributed zeros and ones, and up to 13.5x and 16.1x for sparse and dense bitsets, respectively.
 
+- The ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW`` and ``_LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN`` macros were added.
+  These macros control bounded iterators in ``string_view`` and ``span`` respectively. This was previously controled by
+  the single macro ``_LIBCPP_ABI_BOUNDED_ITERATORS``.
+
 Deprecations and Removals
 -------------------------
 
diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h
index cc4b930b3cf4a..f7ee77de5a786 100644
--- a/libcxx/include/__configuration/abi.h
+++ b/libcxx/include/__configuration/abi.h
@@ -145,24 +145,38 @@
 // The macro below is used for all classes whose ABI have changed as part of fixing these bugs.
 #define _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS __attribute__((__abi_tag__("llvm18_nua")))
 
-// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's
-// within the bounds of the original container and asserts it on every dereference.
+// Historical equivalent to defining `_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW` and
+// `_LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN`.
+#ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#  ifndef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW
+#    define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW
+#  endif
+#  ifndef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
+#    define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
+#  endif
+#endif
+
+// Changes the iterator type of `basic_string_view` to a bounded iterator that keeps track of whether it's within the
+// bounds of the original container and asserts it on every dereference and when performing iterator arithmetic.
 //
-// ABI impact: changes the iterator type of the relevant containers.
+// ABI impact: changes the iterator type of `basic_string_view` and its specializations, such as `string_view` and
+// `wstring_view`.
+// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW
+
+// Changes the iterator type of `span` to a bounded iterator that keeps track of whether it's within the
+// bounds of the original container and asserts it on every dereference and when performing iterator arithmetic.
 //
-// Supported containers:
-// - `span`;
-// - `string_view`.
-// #define _LIBCPP_ABI_BOUNDED_ITERATORS
+// ABI impact: changes the iterator type of `span`.
+// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
 
 // Changes the iterator type of `basic_string` to a bounded iterator that keeps track of whether it's within the bounds
-// of the original container and asserts it on every dereference and when performing iterator arithmetics.
+// of the original container and asserts it on every dereference and when performing iterator arithmetic.
 //
 // ABI impact: changes the iterator type of `basic_string` and its specializations, such as `string` and `wstring`.
 // #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING
 
 // Changes the iterator type of `vector` to a bounded iterator that keeps track of whether it's within the bounds of the
-// original container and asserts it on every dereference and when performing iterator arithmetics. Note: this doesn't
+// original container and asserts it on every dereference and when performing iterator arithmetic. Note: this doesn't
 // yet affect `vector<bool>`.
 //
 // ABI impact: changes the iterator type of `vector` (except `vector<bool>`).
diff --git a/libcxx/include/span b/libcxx/include/span
index 3d4f9e4ba7831..90afa278d0a70 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -240,7 +240,7 @@ public:
   using const_pointer   = const _Tp*;
   using reference       = _Tp&;
   using const_reference = const _Tp&;
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
   using iterator = __bounded_iter<pointer>;
 #    else
   using iterator = __wrap_iter<pointer>;
@@ -383,14 +383,14 @@ public:
 
   // [span.iter], span iterator support
   _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept {
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
     return std::__make_bounded_iter(data(), data(), data() + size());
 #    else
     return iterator(data());
 #    endif
   }
   _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept {
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
     return std::__make_bounded_iter(data() + size(), data(), data() + size());
 #    else
     return iterator(data() + size());
@@ -423,7 +423,7 @@ public:
   using const_pointer   = const _Tp*;
   using reference       = _Tp&;
   using const_reference = const _Tp&;
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
   using iterator = __bounded_iter<pointer>;
 #    else
   using iterator = __wrap_iter<pointer>;
@@ -548,14 +548,14 @@ public:
 
   // [span.iter], span iterator support
   _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept {
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
     return std::__make_bounded_iter(data(), data(), data() + size());
 #    else
     return iterator(data());
 #    endif
   }
   _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept {
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
     return std::__make_bounded_iter(data() + size(), data(), data() + size());
 #    else
     return iterator(data() + size());
diff --git a/libcxx/include/string_view b/libcxx/include/string_view
index 861187c0640e1..cad0e12538d04 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -287,7 +287,7 @@ public:
   using const_pointer   = const _CharT*;
   using reference       = _CharT&;
   using const_reference = const _CharT&;
-#  if defined(_LIBCPP_ABI_BOUNDED_ITERATORS)
+#  if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW)
   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>;
@@ -365,7 +365,7 @@ public:
   _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT { return cend(); }
 
   _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const _NOEXCEPT {
-#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW
     return std::__make_bounded_iter(data(), data(), data() + size());
 #  else
     return const_iterator(__data_);
@@ -373,7 +373,7 @@ public:
   }
 
   _LIBCPP_CONSTEXPR _LIBCPP_HIDE_FROM_ABI const_iterator cend() const _NOEXCEPT {
-#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
+#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW
     return std::__make_bounded_iter(data() + size(), data(), data() + size());
 #  else
     return const_iterator(__data_ + __size_);
diff --git a/libcxx/test/libcxx/bounded-iterator-macro.compile.pass.cpp b/libcxx/test/libcxx/bounded-iterator-macro.compile.pass.cpp
new file mode 100644
index 0000000000000..91a38d75081ca
--- /dev/null
+++ b/libcxx/test/libcxx/bounded-iterator-macro.compile.pass.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// This test ensures that setting _LIBCPP_ABI_BOUNDED_ITERATORS enabled bounded
+// iterators in std::span and std::string_view, for historical reasons.
+
+// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ABI_BOUNDED_ITERATORS
+
+#include <version>
+
+#ifndef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN
+#  error _LIBCPP_ABI_BOUNDED_ITERATORS should enable bounded iterators in std::span
+#endif
+
+#ifndef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW
+#  error _LIBCPP_ABI_BOUNDED_ITERATORS should enable bounded iterators in std::string_view
+#endif
diff --git a/libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp
index d4dacb1f2f1c7..1e4cfd3dcc096 100644
--- a/libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp
+++ b/libcxx/test/libcxx/containers/views/views.span/assert.iterator-indexing.pass.cpp
@@ -9,7 +9,7 @@
 
 // Make sure that std::span's iterators check for OOB accesses when the debug mode is enabled.
 
-// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators
+// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators-in-span
 // UNSUPPORTED: libcpp-hardening-mode=none
 
 #include <span>
diff --git a/libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp b/libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp
index 5043a88cbc3da..c9eec9cbee30b 100644
--- a/libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp
+++ b/libcxx/test/libcxx/strings/string.view/string.view.iterators/assert.iterator-indexing.pass.cpp
@@ -8,7 +8,7 @@
 
 // Make sure that std::string_view's iterators check for OOB accesses when the debug mode is enabled.
 
-// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators
+// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators-in-string-view
 // UNSUPPORTED: libcpp-hardening-mode=none
 
 #include <iterator>
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index 74746e37d3bc4..f5778fb78a898 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -365,8 +365,9 @@ def _mingwSupportsModules(cfg):
 macros = {
     "_LIBCPP_NO_VCRUNTIME": "libcpp-no-vcruntime",
     "_LIBCPP_ABI_VERSION": "libcpp-abi-version",
-    "_LIBCPP_ABI_BOUNDED_ITERATORS": "libcpp-has-abi-bounded-iterators",
     "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING": "libcpp-has-abi-bounded-iterators-in-string",
+    "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING_VIEW": "libcpp-has-abi-bounded-iterators-in-string-view",
+    "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_SPAN": "libcpp-has-abi-bounded-iterators-in-span",
     "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR": "libcpp-has-abi-bounded-iterators-in-vector",
     "_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY": "libcpp-has-abi-bounded-iterators-in-std-array",
     "_LIBCPP_ABI_BOUNDED_UNIQUE_PTR": "libcpp-has-abi-bounded-unique_ptr",



More information about the libcxx-commits mailing list