[libcxx-commits] [libcxx] [libc++] Remove `optional::iterator` from experimental mode (PR #203782)

William Tran-Viet via libcxx-commits libcxx-commits at lists.llvm.org
Fri Oct 2 18:30:09 PDT 2026


https://github.com/smallp-o-p updated https://github.com/llvm/llvm-project/pull/203782

>From 0daa357edac4824cb4d025e7e2a3c780e461080b Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 14 Jun 2026 14:49:29 -0400
Subject: [PATCH 1/9] Remove `optional::iterator` from experimental mode

---
 libcxx/docs/ReleaseNotes/23.rst               |  1 +
 libcxx/include/__configuration/experimental.h |  1 -
 libcxx/include/optional                       | 37 +++++++++----------
 libcxx/include/version                        |  4 +-
 libcxx/modules/std/optional.inc               |  4 +-
 .../fexperimental-library.compile.pass.cpp    |  4 --
 .../utilities/optional/nodiscard.verify.cpp   |  4 +-
 .../optional.version.compile.pass.cpp         | 16 +++-----
 .../version.version.compile.pass.cpp          | 16 +++-----
 .../generate_feature_test_macro_components.py |  2 -
 10 files changed, 32 insertions(+), 57 deletions(-)

diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index 7823c2db39867c4..726e576ef403824 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -65,6 +65,7 @@ Improvements and New Features
   ``"std::visit: variant is valueless"``, ``"std::get: variant is valueless"``, or
   ``"std::get: wrong alternative for variant"``. The standard only requires ``what()`` to return an
   unspecified non-null string, so user code that does not match on the exact message remains correct.
+- ``optional::iterator`` is no longer experimental.
 
 Deprecations and Removals
 -------------------------
diff --git a/libcxx/include/__configuration/experimental.h b/libcxx/include/__configuration/experimental.h
index bb38d8297c63db1..d14df3e5175f351 100644
--- a/libcxx/include/__configuration/experimental.h
+++ b/libcxx/include/__configuration/experimental.h
@@ -33,6 +33,5 @@
 #define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
 #define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
 #define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
-#define _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
 
 #endif // _LIBCPP___CONFIGURATION_EXPERIMENTAL_H
diff --git a/libcxx/include/optional b/libcxx/include/optional
index 66995435b5109b0..43e8511a957894d 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -737,7 +737,7 @@ using __optional_sfinae_assign_base_t _LIBCPP_NODEBUG =
 template <class _Tp>
 class optional;
 
-#    if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#    if _LIBCPP_STD_VER >= 26
 template <class _Tp>
 constexpr bool ranges::enable_view<optional<_Tp>> = true;
 
@@ -780,8 +780,6 @@ struct __optional_iterator_base<_Tp&> : __optional_storage_base<_Tp&> {
   using __optional_storage_base<_Tp&>::__optional_storage_base;
 };
 
-#      if _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-
 template <class _Tp>
   requires is_object_v<_Tp>
 struct __optional_iterator_base<_Tp> : __optional_move_assign_base<_Tp> {
@@ -792,33 +790,33 @@ private:
 public:
   using __optional_move_assign_base<_Tp>::__optional_move_assign_base;
 
-#        ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
   using iterator       = __bounded_iter<__pointer>;
   using const_iterator = __bounded_iter<__const_pointer>;
-#        else
+#      else
   using iterator       = __capacity_aware_iterator<__pointer, optional<_Tp>, 1>;
   using const_iterator = __capacity_aware_iterator<__const_pointer, optional<_Tp>, 1>;
-#        endif
+#      endif
 
   // [optional.iterators], iterator support
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() noexcept {
     auto* __ptr = std::addressof(this->__get());
 
-#        ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
     return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
-#        else
+#      else
     return std::__make_capacity_aware_iterator<__pointer, optional<_Tp>, 1>(__ptr);
-#        endif
+#      endif
   }
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept {
     auto* __ptr = std::addressof(this->__get());
 
-#        ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
     return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
-#        else
+#      else
     return std::__make_capacity_aware_iterator<__const_pointer, optional<_Tp>, 1>(__ptr);
-#        endif
+#      endif
   }
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator end() noexcept {
@@ -838,22 +836,22 @@ private:
 public:
   using __optional_storage_base<_Tp&>::__optional_storage_base;
 
-#        ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
   using iterator = __bounded_iter<__pointer>;
-#        else
+#      else
   using iterator = __capacity_aware_iterator<__pointer, optional<_Tp&>, 1>;
-#        endif
+#      endif
 
   // [optional.ref.iterators], iterator support
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const noexcept {
     auto* __ptr = this->has_value() ? std::addressof(this->__get()) : nullptr;
 
-#        ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+#      ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
     return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
-#        else
+#      else
     return std::__make_capacity_aware_iterator<__pointer, optional<_Tp&>, 1>(__ptr);
-#        endif
+#      endif
   }
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const noexcept {
@@ -861,8 +859,7 @@ public:
   }
 };
 
-#      endif // _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-#    endif   // _LIBCPP_STD_VER >= 26
+#    endif // _LIBCPP_STD_VER >= 26
 
 template <class _Tp>
 class _LIBCPP_DECLSPEC_EMPTY_BASES optional
diff --git a/libcxx/include/version b/libcxx/include/version
index 7f2dc9e4b72ab1c..9d3d7395f98e59d 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -611,9 +611,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # define __cpp_lib_not_fn                               202306L
 # undef  __cpp_lib_optional
 # define __cpp_lib_optional                             202506L
-# if _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-#   define __cpp_lib_optional_range_support             202406L
-# endif
+# define __cpp_lib_optional_range_support               202406L
 # undef  __cpp_lib_out_ptr
 # define __cpp_lib_out_ptr                              202311L
 // # define __cpp_lib_philox_engine                        202406L
diff --git a/libcxx/modules/std/optional.inc b/libcxx/modules/std/optional.inc
index 8196a8dde577cea..88de0bb4db12b9d 100644
--- a/libcxx/modules/std/optional.inc
+++ b/libcxx/modules/std/optional.inc
@@ -10,7 +10,7 @@
 export namespace std {
   // [optional.optional], class template optional
   using std::optional;
-#if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#if _LIBCPP_STD_VER >= 26
   // [optional.iterators], iterator support
   namespace ranges {
     using std::ranges::enable_borrowed_range;
@@ -24,7 +24,7 @@ export namespace std {
   // [optional.bad.access], class bad_optional_access
   using std::bad_optional_access;
 
-#if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#if _LIBCPP_STD_VER >= 26
   using std::format_kind;
 #endif
 
diff --git a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp
index 82fd1ad4d9a16b7..479b46a39e963ce 100644
--- a/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp
+++ b/libcxx/test/libcxx/experimental/fexperimental-library.compile.pass.cpp
@@ -16,10 +16,6 @@
 
 #include <version>
 
-#if !_LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-#  error "-fexperimental-library should enable optional::iterator"
-#endif
-
 #if !_LIBCPP_HAS_EXPERIMENTAL_PSTL
 #  error "-fexperimental-library should enable the PSTL"
 #endif
diff --git a/libcxx/test/libcxx/utilities/optional/nodiscard.verify.cpp b/libcxx/test/libcxx/utilities/optional/nodiscard.verify.cpp
index 0ae368b4f87ce60..c49546cfdf4adb1 100644
--- a/libcxx/test/libcxx/utilities/optional/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/utilities/optional/nodiscard.verify.cpp
@@ -32,7 +32,7 @@ void test() {
 
   opt.has_value(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
 
-#if TEST_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#if TEST_STD_VER >= 26
   opt.begin();  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
   cOpt.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
   opt.end();    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
@@ -92,10 +92,8 @@ void test() {
 
   optRef.has_value(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
 
-#  if _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
   optRef.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
   optRef.end();   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
-#  endif
 
   *optRef;  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
   *cOptRef; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
index 9850c20afec872f..c4e652979a4e667 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
@@ -146,17 +146,11 @@
 #    error "__cpp_lib_optional should have the value 202506L in c++26"
 #  endif
 
-#  if !defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-#    ifndef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should be defined in c++26"
-#    endif
-#    if __cpp_lib_optional_range_support != 202406L
-#      error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
-#    endif
-#  else
-#    ifdef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should not be defined when the requirement '!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR' is not met!"
-#    endif
+#  ifndef __cpp_lib_optional_range_support
+#    error "__cpp_lib_optional_range_support should be defined in c++26"
+#  endif
+#  if __cpp_lib_optional_range_support != 202406L
+#    error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
 #  endif
 
 #endif // TEST_STD_VER > 23
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index d9c78b73f7e237f..ac4e0003347a646 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -7586,17 +7586,11 @@
 #    error "__cpp_lib_optional should have the value 202506L in c++26"
 #  endif
 
-#  if !defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-#    ifndef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should be defined in c++26"
-#    endif
-#    if __cpp_lib_optional_range_support != 202406L
-#      error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
-#    endif
-#  else
-#    ifdef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should not be defined when the requirement '!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR' is not met!"
-#    endif
+#  ifndef __cpp_lib_optional_range_support
+#    error "__cpp_lib_optional_range_support should be defined in c++26"
+#  endif
+#  if __cpp_lib_optional_range_support != 202406L
+#    error "__cpp_lib_optional_range_support should have the value 202406L in c++26"
 #  endif
 
 #  ifndef __cpp_lib_out_ptr
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index d764a1f677ba6a4..02e79ad7ca38ff3 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1039,8 +1039,6 @@ def add_version_header(tc):
             "name": "__cpp_lib_optional_range_support",
             "values": {"c++26": 202406},  # P3168R2 Give std::optional Range Support
             "headers": ["optional"],
-            "test_suite_guard": "!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR",
-            "libcxx_guard": "_LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR",
         },
         {
             "name": "__cpp_lib_out_ptr",

>From 3aff5a1dd1a74abe4ec54d669df3de0a72eedb36 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Sun, 14 Jun 2026 14:54:46 -0400
Subject: [PATCH 2/9] Tests

---
 .../libcxx/utilities/optional/nodiscard.iterator.verify.cpp     | 2 --
 .../optional/optional.iterator/iterator.compile.pass.cpp        | 2 +-
 .../std/utilities/optional/optional.iterator/begin.pass.cpp     | 2 --
 .../optional/optional.iterator/borrowed_range.compile.pass.cpp  | 2 --
 .../std/utilities/optional/optional.iterator/compare.pass.cpp   | 1 -
 .../test/std/utilities/optional/optional.iterator/end.pass.cpp  | 2 --
 .../std/utilities/optional/optional.iterator/iterator.pass.cpp  | 2 --
 libcxx/utils/libcxx/test/params.py                              | 1 -
 8 files changed, 1 insertion(+), 13 deletions(-)

diff --git a/libcxx/test/libcxx/utilities/optional/nodiscard.iterator.verify.cpp b/libcxx/test/libcxx/utilities/optional/nodiscard.iterator.verify.cpp
index a3945000cbb77d8..7fd96498870121c 100644
--- a/libcxx/test/libcxx/utilities/optional/nodiscard.iterator.verify.cpp
+++ b/libcxx/test/libcxx/utilities/optional/nodiscard.iterator.verify.cpp
@@ -8,8 +8,6 @@
 
 // REQUIRES: std-at-least-c++26
 
-// UNSUPPORTED: libcpp-has-no-experimental-optional-iterator
-
 // <optional>
 
 // Check that functions are marked [[nodiscard]]
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
index 265d39c97cb3917..b12d421adef7db7 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/iterator.compile.pass.cpp
@@ -10,7 +10,7 @@
 
 // <optional>
 
-// UNSUPPORTED: libcpp-has-abi-bounded-iterators-in-optional, libcpp-has-no-experimental-optional-iterator
+// UNSUPPORTED: libcpp-has-abi-bounded-iterators-in-optional
 
 // Ensure that a std::optional<T>::iterator can only be converted to a std::optional<T>::iterator.
 
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp
index 7c75fe8b4507692..81234525923a109 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp
@@ -8,8 +8,6 @@
 
 // REQUIRES: std-at-least-c++26
 
-// UNSUPPORTED: libcpp-has-no-experimental-optional-iterator
-
 // <optional>
 
 // constexpr iterator optional::begin() noexcept;
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp
index 65edbd54ff5b8b7..a79d1d51a5b11ca 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp
@@ -8,8 +8,6 @@
 
 // REQUIRES: std-at-least-c++26
 
-// UNSUPPORTED: libcpp-has-no-experimental-optional-iterator
-
 // <optional>
 
 // template <class T> class optional<T&>::iterator;
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
index 4c48c54df325776..b3f778328c0cc97 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // REQUIRES: std-at-least-c++26
-// UNSUPPORTED: libcpp-has-no-experimental-optional-iterator
 
 // <optional>
 
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp
index 563f160092a3823..c62c9fc7746d6a8 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp
@@ -8,8 +8,6 @@
 
 // REQUIRES: std-at-least-c++26
 
-// UNSUPPORTED: libcpp-has-no-experimental-optional-iterator
-
 // <optional>
 
 // constexpr iterator optional::end() noexcept;
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
index 05b8b3572ef53ec..996811d078b8699 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
@@ -8,8 +8,6 @@
 
 // REQUIRES: std-at-least-c++26
 
-// UNSUPPORTED: libcpp-has-no-experimental-optional-iterator
-
 // <optional>
 
 // template <class T> class optional::iterator;
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index d0bb38ab84df496..b0e0c48873eb339 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -362,7 +362,6 @@ def getSuitableClangTidy(cfg):
         if experimental
         else [
             AddFeature("libcpp-has-no-incomplete-pstl"),
-            AddFeature("libcpp-has-no-experimental-optional-iterator"),
             AddFeature("libcpp-has-no-experimental-tzdb"),
             AddFeature("libcpp-has-no-experimental-syncstream"),
             AddFeature("libcpp-has-no-experimental-hardening-observe-semantic"),

>From c498aadfb57c8f76707a04b7ad181137129f4139 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 2 Oct 2026 14:02:23 -0400
Subject: [PATCH 3/9] Reimplement optional::iterator for potentially 3 iterator
 types

---
 libcxx/docs/ReleaseNotes/24.rst               |  1 +
 libcxx/include/__optional/common.h            |  4 +-
 libcxx/include/__optional/optional.h          | 67 ++++++++-----
 libcxx/include/__optional/optional_ref.h      | 51 ++++++----
 .../assert.arithmetic.pass.cpp                | 81 +++++++++++++++-
 .../assert.bounded_iterator.pass.cpp          | 95 +++++++++++++++++--
 .../optional/optional.iterator/begin.pass.cpp |  7 +-
 .../borrowed_range.compile.pass.cpp           |  2 +
 .../optional.iterator/compare.pass.cpp        |  3 +-
 .../optional/optional.iterator/end.pass.cpp   |  8 +-
 .../optional.iterator/iterator.pass.cpp       |  6 +-
 11 files changed, 268 insertions(+), 57 deletions(-)

diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index 38d31eea96e4cff..d2fc16bcbef022b 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -60,6 +60,7 @@ Improvements and New Features
 -----------------------------
 
 - ``basic_filebuf`` now supports files larger than 2GB on 32-bit AIX and 32-bit glibc targets.
+- ``optional::iterator`` is no longer experimental.
 
 Deprecations and Removals
 -------------------------
diff --git a/libcxx/include/__optional/common.h b/libcxx/include/__optional/common.h
index 26031f658a90428..8c759ab005cd865 100644
--- a/libcxx/include/__optional/common.h
+++ b/libcxx/include/__optional/common.h
@@ -72,7 +72,7 @@ template <class _Tp>
 inline constexpr bool __is_valid_optional_contained_type = is_object_v<_Tp> || is_lvalue_reference_v<_Tp>;
 #  endif
 
-#  if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#  if _LIBCPP_STD_VER >= 26
 
 template <class _Tp>
 constexpr bool ranges::enable_view<optional<_Tp>> = true;
@@ -83,7 +83,7 @@ constexpr range_format format_kind<optional<_Tp>> = range_format::disabled;
 template <class _Tp>
 constexpr bool ranges::enable_borrowed_range<optional<_Tp&>> = true;
 
-#  endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#  endif // _LIBCPP_STD_VER >= 26
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/__optional/optional.h b/libcxx/include/__optional/optional.h
index 52f3bde864f9054..bbd53528ccdd5c3 100644
--- a/libcxx/include/__optional/optional.h
+++ b/libcxx/include/__optional/optional.h
@@ -16,6 +16,7 @@
 #include <__fwd/optional.h>
 #include <__iterator/bounded_iter.h>
 #include <__iterator/capacity_aware_iterator.h>
+#include <__iterator/static_packed_bounded_iter.h>
 #include <__memory/addressof.h>
 #include <__memory/construct_at.h>
 #include <__optional/common.h>
@@ -681,50 +682,68 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
 
   using __base::reset;
 
-#  if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#  if _LIBCPP_STD_VER >= 26
 
 private:
   using __pointer _LIBCPP_NODEBUG       = add_pointer_t<_Tp>;
   using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
 
-public:
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-  using iterator       = __bounded_iter<__pointer>;
-  using const_iterator = __bounded_iter<__const_pointer>;
+  template <bool = std::__range_fits_in_alignment(alignof(_Tp), 1)>
+  struct _LIBCPP_NODEBUG __iterator {
+    using __type _LIBCPP_NODEBUG       = std::__static_packed_bounded_iterator<__pointer, 1>;
+    using __const_type _LIBCPP_NODEBUG = std::__static_packed_bounded_iterator<__const_pointer, 1>;
+
+    template <class _PtrType>
+    static auto __make(_PtrType __p, unsigned) noexcept {
+      return std::__make_static_packed_bounded_iter<_PtrType, 1>(__p, 0);
+    }
+  };
+
+  template <>
+  struct _LIBCPP_NODEBUG __iterator<false> {
+#    if _LIBCPP_ABI_BOUNDED_ITERATORS
+    using __type _LIBCPP_NODEBUG       = std::__bounded_iter<__pointer>;
+    using __const_type _LIBCPP_NODEBUG = std::__bounded_iter<__const_pointer>;
 #    else
-  using iterator       = __capacity_aware_iterator<__pointer, 1>;
-  using const_iterator = __capacity_aware_iterator<__const_pointer, 1>;
+    using __type _LIBCPP_NODEBUG       = std::__capacity_aware_iterator<__pointer, 1>;
+    using __const_type _LIBCPP_NODEBUG = std::__capacity_aware_iterator<__const_pointer, 1>;
 #    endif
 
+    template <class _PtrType>
+    static auto __make(_PtrType __p, [[__maybe_unused__]] unsigned __end_offset) noexcept {
+#    if _LIBCPP_ABI_BOUNDED_ITERATORS
+      return std::__make_bounded_iter<_PtrType>(__p, __p, __p + __end_offset)
+#    else
+      return std::__make_capacity_aware_iterator<_PtrType, 1>(__p);
+#    endif
+    }
+  };
+
+  using __iter _LIBCPP_NODEBUG = __iterator<>;
+
+public:
+  using iterator       = __iter::__type;
+  using const_iterator = __iter::__const_type;
+
   // [optional.iterators], iterator support
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept {
     auto* __ptr = std::addressof(this->__val_);
 
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
-#    else
-    return std::__make_capacity_aware_iterator<__pointer, 1>(__ptr);
-#    endif
+    return __iter::__make(__ptr, this->has_value() ? 1 : 0);
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator begin() const noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept {
     auto* __ptr = std::addressof(this->__val_);
 
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    return std::__make_bounded_iter(__ptr, __ptr, __ptr + (this->has_value() ? 1 : 0));
-#    else
-    return std::__make_capacity_aware_iterator<__const_pointer, 1>(__ptr);
-#    endif
+    return __iter::__make(__ptr, this->has_value() ? 1 : 0);
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator end() noexcept {
-    return begin() + (this->has_value() ? 1 : 0);
-  }
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const_iterator end() const noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return begin() + (this->has_value() ? 1 : 0); }
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept {
     return begin() + (this->has_value() ? 1 : 0);
   }
 
-#  endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
+#  endif // _LIBCPP_STD_VER >= 26
 };
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__optional/optional_ref.h b/libcxx/include/__optional/optional_ref.h
index 93ce0a9fa6746d3..8b411475ae25229 100644
--- a/libcxx/include/__optional/optional_ref.h
+++ b/libcxx/include/__optional/optional_ref.h
@@ -16,6 +16,7 @@
 #include <__fwd/optional.h>
 #include <__iterator/bounded_iter.h>
 #include <__iterator/capacity_aware_iterator.h>
+#include <__iterator/static_packed_bounded_iter.h>
 #include <__memory/addressof.h>
 #include <__optional/common.h>
 #include <__optional/comparison.h>
@@ -55,19 +56,41 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 template <class _Tp>
 struct __optional_ref_iterator_base {};
 
-#  if _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-
 template <class _Tp>
   requires(is_object_v<_Tp> && !__is_unbounded_array_v<_Tp>)
 struct __optional_ref_iterator_base<_Tp&> {
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-  using iterator = __bounded_iter<_Tp*>;
-#    else
-  using iterator = __capacity_aware_iterator<_Tp*, 1>;
-#    endif
-};
+protected:
+  using __pointer = add_pointer_t<_Tp>;
+
+  template <bool = std::__range_fits_in_alignment(alignof(_Tp), 1)>
+  struct _LIBCPP_NODEBUG __iterator {
+    using __type = std::__static_packed_bounded_iterator<__pointer, 1>;
+
+    static __type __make(__pointer __p, unsigned) noexcept {
+      return std::__make_static_packed_bounded_iter<__pointer, 1>(__p, 0);
+    }
+  };
+
+  template <>
+  struct _LIBCPP_NODEBUG __iterator<false> {
+#  if _LIBCPP_ABI_BOUNDED_ITERATORS
+    using __type = std::__bounded_iter<__pointer>;
+#  else
+    using __type = std::__capacity_aware_iterator<__pointer, 1>;
+#  endif
 
+    static __type __make(__pointer __p, [[__maybe_unused__]] unsigned __end_offset) noexcept {
+#  if _LIBCPP_ABI_BOUNDED_ITERATORS
+      return std::__make_bounded_iter<__pointer>(__p, __p, __p + __end_offset);
+#  else
+      return std::__make_capacity_aware_iterator<__pointer, 1>(__p);
 #  endif
+    }
+  };
+
+public:
+  using iterator = __iterator<>::__type;
+};
 
 template <class _Tp>
 class optional<_Tp&> : public __optional_ref_iterator_base<_Tp&> {
@@ -275,24 +298,18 @@ class optional<_Tp&> : public __optional_ref_iterator_base<_Tp&> {
   _LIBCPP_HIDE_FROM_ABI constexpr void reset() noexcept { __value_ = nullptr; }
 
   // [optional.ref.iterators], iterator support
-#  if _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const noexcept
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto begin() const noexcept
     requires __has_iterator_
   {
-#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    return std::__make_bounded_iter(__value_, __value_, __value_ + (this->has_value() ? 1 : 0));
-#    else
-    return std::__make_capacity_aware_iterator<_Tp*, 1>(__value_);
-#    endif
+    return __optional_ref_iterator_base<_Tp&>::template __iterator<>::__make(__value_, this->has_value() ? 1 : 0);
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto end() const noexcept
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto end() const noexcept
     requires __has_iterator_
   {
     return begin() + (this->has_value() ? 1 : 0);
   }
-#  endif
 };
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
index fe348a12962bad1..7f7e593cfc6a6a3 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.iterator/assert.arithmetic.pass.cpp
@@ -18,9 +18,82 @@
 
 #include "check_assertion.h"
 
-int main(int, char**) {
+// If T fits the requirements for __static_packed_bounded_iterator, optional<T>'s iterator will always be that,
+// regardless of if the ABI switch is on or off. This is because it has less overhead than bounded_iter while providing the same guarantees for the on case,
+// while for the off case, it has more guarantees than __capacity_aware_iterator while occupying the same amount of space.
+// Otherwise, optional<T>'s iterator is __capacity_aware_iterator.
+void test_packed() {
+  // int has enough room, 3 bits free -> 0-2 range
+  { // operator++
+    std::optional<int> o{1};
+    auto i = o.end();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i, "__static_packed_bounded_iterator::operator++: Attempt to advance an iterator past the end");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i++, "__static_packed_bounded_iterator::operator++: Attempt to advance an iterator past the end");
+  }
+
+  { // operator--
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        --i, "__static_packed_bounded_iterator::operator--: Attempt to rewind an iterator past the start");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i--, "__static_packed_bounded_iterator::operator--: Attempt to rewind an iterator past the start");
+  }
+
+  { // operator*
+    std::optional<int> o;
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i, "__static_packed_bounded_iterator::operator*: Attempt to dereference an iterator at the end");
+  }
+
+  { // operator[]
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i[1], "__static_packed_bounded_iterator::operator[]: Attempt to index an iterator at or past the end");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i[-1], "__static_packed_bounded_iterator::operator[]: Attempt to index an iterator past the start");
+  }
+
+  { // operator->
+    std::optional<int> o{1};
+    auto i = o.end();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i.operator->(), "__static_packed_bounded_iterator::operator->: Attempt to dereference an iterator at the end");
+  }
+
+  { // operator+=
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i += 2, "__static_packed_bounded_iterator::operator+=: Attempt to advance an iterator past the end");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i += -1, "__static_packed_bounded_iterator::operator+=: Attempt to rewind an iterator past the start");
+  }
+
+  { // operator-=
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i -= 1, "__static_packed_bounded_iterator::operator-=: Attempt to rewind an iterator past the start");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i -= -2, "__static_packed_bounded_iterator::operator-=: Attempt to advance an iterator past the end");
+  }
+}
+
+void test_nonpacked() {
   {
-    std::optional<int> opt(1);
+    std::optional<short> opt(1);
     auto i = opt.begin();
 
     TEST_LIBCPP_ASSERT_FAILURE(
@@ -47,6 +120,10 @@ int main(int, char**) {
         i[-2],
         "__capacity_aware_iterator::operator[]: Attempting to index iterator past its container's possible range");
   }
+}
 
+int main(int, char**) {
+  test_packed();
+  test_nonpacked();
   return 0;
 }
diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.iterator/assert.bounded_iterator.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.iterator/assert.bounded_iterator.pass.cpp
index a7aecabd75a0126..c3eba8f6f8181c2 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.object/optional.iterator/assert.bounded_iterator.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.iterator/assert.bounded_iterator.pass.cpp
@@ -27,17 +27,93 @@
 
 #include "check_assertion.h"
 
-int main(int, char**) {
+// if T has the alignment required to fit a bounds check, optional<T>
+// will always have static_packed_bounded_iter regardless of if the bounded iterator
+// option is enabled for it.
+// see __static_packed_bounded_iterator.h for more information on how this is determined.
+
+void test_packed_iter() {
+  // int has enough room, 3 bits free -> 0-2 range
   { // operator++
     std::optional<int> o{1};
     auto i = o.end();
 
+    TEST_LIBCPP_ASSERT_FAILURE(
+        ++i, "__static_packed_bounded_iterator::operator++: Attempt to advance an iterator past the end");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i++, "__static_packed_bounded_iterator::operator++: Attempt to advance an iterator past the end");
+  }
+
+  { // operator--
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        --i, "__static_packed_bounded_iterator::operator--: Attempt to rewind an iterator past the start");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i--, "__static_packed_bounded_iterator::operator--: Attempt to rewind an iterator past the start");
+  }
+
+  { // operator*
+    std::optional<int> o;
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        *i, "__static_packed_bounded_iterator::operator*: Attempt to dereference an iterator at the end");
+  }
+
+  { // operator[]
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i[1], "__static_packed_bounded_iterator::operator[]: Attempt to index an iterator at or past the end");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i[-1], "__static_packed_bounded_iterator::operator[]: Attempt to index an iterator past the start");
+  }
+
+  { // operator->
+    std::optional<int> o{1};
+    auto i = o.end();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i.operator->(), "__static_packed_bounded_iterator::operator->: Attempt to dereference an iterator at the end");
+  }
+
+  { // operator+=
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i += 2, "__static_packed_bounded_iterator::operator+=: Attempt to advance an iterator past the end");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i += -1, "__static_packed_bounded_iterator::operator+=: Attempt to rewind an iterator past the start");
+  }
+
+  { // operator-=
+    std::optional<int> o{1};
+    auto i = o.begin();
+
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i -= 1, "__static_packed_bounded_iterator::operator-=: Attempt to rewind an iterator past the start");
+    TEST_LIBCPP_ASSERT_FAILURE(
+        i -= -2, "__static_packed_bounded_iterator::operator-=: Attempt to advance an iterator past the end");
+  }
+}
+
+// short doesn't have the alignment required to use static_packed_bounded_iter
+// so optional<short>'s iterator is bounded_iter with the option enabled.
+void test_bounded_iter() {
+  { // operator++
+    std::optional<short> o{1};
+    auto i = o.end();
+
     TEST_LIBCPP_ASSERT_FAILURE(++i, "__bounded_iter::operator++: Attempt to advance an iterator past the end");
     TEST_LIBCPP_ASSERT_FAILURE(i++, "__bounded_iter::operator++: Attempt to advance an iterator past the end");
   }
 
   { // operator--
-    std::optional<int> o{1};
+    std::optional<short> o{1};
     auto i = o.begin();
 
     TEST_LIBCPP_ASSERT_FAILURE(--i, "__bounded_iter::operator--: Attempt to rewind an iterator past the start");
@@ -45,14 +121,14 @@ int main(int, char**) {
   }
 
   { // operator*
-    std::optional<int> o;
+    std::optional<short> o;
     auto i = o.begin();
 
     TEST_LIBCPP_ASSERT_FAILURE(*i, "__bounded_iter::operator*: Attempt to dereference an iterator at the end");
   }
 
   { // operator[]
-    std::optional<int> o{1};
+    std::optional<short> o{1};
     auto i = o.begin();
 
     TEST_LIBCPP_ASSERT_FAILURE(i[1], "__bounded_iter::operator[]: Attempt to index an iterator at or past the end");
@@ -60,7 +136,7 @@ int main(int, char**) {
   }
 
   { // operator->
-    std::optional<int> o{1};
+    std::optional<short> o{1};
     auto i = o.end();
 
     TEST_LIBCPP_ASSERT_FAILURE(
@@ -68,7 +144,7 @@ int main(int, char**) {
   }
 
   { // operator+=
-    std::optional<int> o{1};
+    std::optional<short> o{1};
     auto i = o.begin();
 
     TEST_LIBCPP_ASSERT_FAILURE(i += 2, "__bounded_iter::operator+=: Attempt to advance an iterator past the end");
@@ -76,12 +152,17 @@ int main(int, char**) {
   }
 
   { // operator-=
-    std::optional<int> o{1};
+    std::optional<short> o{1};
     auto i = o.begin();
 
     TEST_LIBCPP_ASSERT_FAILURE(i -= 1, "__bounded_iter::operator-=: Attempt to rewind an iterator past the start");
     TEST_LIBCPP_ASSERT_FAILURE(i -= -2, "__bounded_iter::operator-=: Attempt to advance an iterator past the end");
   }
+}
+
+int main(int, char**) {
+  test_bounded_iter();
+  test_packed_iter();
 
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp
index 81234525923a109..196227e9f7dcffc 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/begin.pass.cpp
@@ -52,18 +52,23 @@ constexpr bool test() {
 constexpr bool tests() {
   assert(test<int>());
   assert(test<char>());
+  assert(test<short>());
   assert(test<const int>());
   assert(test<const char>());
   assert(test<int&>());
   assert(test<char&>());
+  assert(test<short&>());
   assert(test<const int&>());
   assert(test<const char&>());
+  assert(test<const short&>());
   return true;
 }
 
 int main(int, char**) {
   assert(tests());
-  static_assert(tests());
+
+  // blocked on constexpr pointer tagging
+  // static_assert(tests());
 
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp
index a79d1d51a5b11ca..91bd61b1ac8ce6d 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/borrowed_range.compile.pass.cpp
@@ -31,4 +31,6 @@ void test_borrowed_range() {
   borrowed_range<int[]>();
   borrowed_range<int[10]>();
   borrowed_range<int()>();
+  borrowed_range<char>();
+  borrowed_range<short>();
 }
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
index b3f778328c0cc97..38c9f5fdea28535 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/compare.pass.cpp
@@ -93,7 +93,8 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-  static_assert(test());
+  // blocked on constexpr pointer tagging
+  // static_assert(test());
 
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp
index c62c9fc7746d6a8..22eb38926338278 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/end.pass.cpp
@@ -62,19 +62,23 @@ constexpr bool test() {
 constexpr bool tests() {
   assert(test<int>());
   assert(test<char>());
+  assert(test<short>());
   assert(test<const int>());
   assert(test<const char>());
   assert(test<int&>());
   assert(test<char&>());
+  assert(test<short&>());
   assert(test<const int&>());
   assert(test<const char&>());
-
+  assert(test<const short&>());
   return true;
 }
 
 int main(int, char**) {
   assert(tests());
-  static_assert(tests());
+
+  // blocked on constexpr pointer tagging
+  // static_assert(tests());
 
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp b/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
index 996811d078b8699..502cbfdb4b85a05 100644
--- a/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.iterator/iterator.pass.cpp
@@ -139,13 +139,16 @@ constexpr bool test() {
   test<int>(1);
   test<char>('a');
   test<bool>(true);
+  test<short>(2);
   test<const int>(2);
   test<const char>('b');
   test<int&>(1);
   test<char&>('a');
   test<bool&>(true);
+  test<short&>(1);
   test<const int&>(2);
   test<const char&>('b');
+  test<const short&>(1);
 
   static_assert(!std::ranges::range<std::optional<int (&)()>>);
   static_assert(!std::ranges::range<std::optional<int (&)[]>>);
@@ -156,7 +159,8 @@ constexpr bool test() {
 
 int main(int, char**) {
   assert(test());
-  static_assert(test());
+
+  // static_assert(test());
 
   return 0;
 }

>From a180b94cf9737e38c6c69ba256cf4bb6b3e54cf9 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 2 Oct 2026 14:48:02 -0400
Subject: [PATCH 4/9] Fixup

---
 libcxx/include/__optional/optional.h             |  8 ++++----
 libcxx/include/__optional/optional_ref.h         |  8 ++++----
 .../optional.version.compile.pass.cpp            | 16 +++++-----------
 .../version.version.compile.pass.cpp             | 16 +++++-----------
 4 files changed, 18 insertions(+), 30 deletions(-)

diff --git a/libcxx/include/__optional/optional.h b/libcxx/include/__optional/optional.h
index bbd53528ccdd5c3..98ba4ea8761e9d6 100644
--- a/libcxx/include/__optional/optional.h
+++ b/libcxx/include/__optional/optional.h
@@ -689,7 +689,7 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
   using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
 
   template <bool = std::__range_fits_in_alignment(alignof(_Tp), 1)>
-  struct _LIBCPP_NODEBUG __iterator {
+  struct __iterator {
     using __type _LIBCPP_NODEBUG       = std::__static_packed_bounded_iterator<__pointer, 1>;
     using __const_type _LIBCPP_NODEBUG = std::__static_packed_bounded_iterator<__const_pointer, 1>;
 
@@ -700,8 +700,8 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
   };
 
   template <>
-  struct _LIBCPP_NODEBUG __iterator<false> {
-#    if _LIBCPP_ABI_BOUNDED_ITERATORS
+  struct __iterator<false> {
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
     using __type _LIBCPP_NODEBUG       = std::__bounded_iter<__pointer>;
     using __const_type _LIBCPP_NODEBUG = std::__bounded_iter<__const_pointer>;
 #    else
@@ -711,7 +711,7 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
 
     template <class _PtrType>
     static auto __make(_PtrType __p, [[__maybe_unused__]] unsigned __end_offset) noexcept {
-#    if _LIBCPP_ABI_BOUNDED_ITERATORS
+#    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
       return std::__make_bounded_iter<_PtrType>(__p, __p, __p + __end_offset)
 #    else
       return std::__make_capacity_aware_iterator<_PtrType, 1>(__p);
diff --git a/libcxx/include/__optional/optional_ref.h b/libcxx/include/__optional/optional_ref.h
index 8b411475ae25229..fe0b5c817791791 100644
--- a/libcxx/include/__optional/optional_ref.h
+++ b/libcxx/include/__optional/optional_ref.h
@@ -63,7 +63,7 @@ struct __optional_ref_iterator_base<_Tp&> {
   using __pointer = add_pointer_t<_Tp>;
 
   template <bool = std::__range_fits_in_alignment(alignof(_Tp), 1)>
-  struct _LIBCPP_NODEBUG __iterator {
+  struct __iterator {
     using __type = std::__static_packed_bounded_iterator<__pointer, 1>;
 
     static __type __make(__pointer __p, unsigned) noexcept {
@@ -72,15 +72,15 @@ struct __optional_ref_iterator_base<_Tp&> {
   };
 
   template <>
-  struct _LIBCPP_NODEBUG __iterator<false> {
-#  if _LIBCPP_ABI_BOUNDED_ITERATORS
+  struct __iterator<false> {
+#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
     using __type = std::__bounded_iter<__pointer>;
 #  else
     using __type = std::__capacity_aware_iterator<__pointer, 1>;
 #  endif
 
     static __type __make(__pointer __p, [[__maybe_unused__]] unsigned __end_offset) noexcept {
-#  if _LIBCPP_ABI_BOUNDED_ITERATORS
+#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
       return std::__make_bounded_iter<__pointer>(__p, __p, __p + __end_offset);
 #  else
       return std::__make_capacity_aware_iterator<__pointer, 1>(__p);
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
index ae403fadcc23352..7ba0bdaef5477fb 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.compile.pass.cpp
@@ -182,17 +182,11 @@
 #    error "__cpp_lib_optional should have the value 202506L in c++29"
 #  endif
 
-#  if !defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-#    ifndef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should be defined in c++29"
-#    endif
-#    if __cpp_lib_optional_range_support != 202406L
-#      error "__cpp_lib_optional_range_support should have the value 202406L in c++29"
-#    endif
-#  else
-#    ifdef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should not be defined when the requirement '!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR' is not met!"
-#    endif
+#  ifndef __cpp_lib_optional_range_support
+#    error "__cpp_lib_optional_range_support should be defined in c++29"
+#  endif
+#  if __cpp_lib_optional_range_support != 202406L
+#    error "__cpp_lib_optional_range_support should have the value 202406L in c++29"
 #  endif
 
 #endif // TEST_STD_VER > 26
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index e85af92365f7bc8..2b3c27a2c69ef14 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -9978,17 +9978,11 @@
 #    error "__cpp_lib_optional should have the value 202506L in c++29"
 #  endif
 
-#  if !defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR
-#    ifndef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should be defined in c++29"
-#    endif
-#    if __cpp_lib_optional_range_support != 202406L
-#      error "__cpp_lib_optional_range_support should have the value 202406L in c++29"
-#    endif
-#  else
-#    ifdef __cpp_lib_optional_range_support
-#      error "__cpp_lib_optional_range_support should not be defined when the requirement '!defined(_LIBCPP_VERSION) || _LIBCPP_HAS_EXPERIMENTAL_OPTIONAL_ITERATOR' is not met!"
-#    endif
+#  ifndef __cpp_lib_optional_range_support
+#    error "__cpp_lib_optional_range_support should be defined in c++29"
+#  endif
+#  if __cpp_lib_optional_range_support != 202406L
+#    error "__cpp_lib_optional_range_support should have the value 202406L in c++29"
 #  endif
 
 #  ifndef __cpp_lib_out_ptr

>From 21f3f553b07c2df06c496857a6e488c8a6a8b967 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 2 Oct 2026 15:20:57 -0400
Subject: [PATCH 5/9] annotate internal types as nodebug

---
 libcxx/include/__optional/optional_ref.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__optional/optional_ref.h b/libcxx/include/__optional/optional_ref.h
index fe0b5c817791791..939a2c0e3615554 100644
--- a/libcxx/include/__optional/optional_ref.h
+++ b/libcxx/include/__optional/optional_ref.h
@@ -60,11 +60,11 @@ template <class _Tp>
   requires(is_object_v<_Tp> && !__is_unbounded_array_v<_Tp>)
 struct __optional_ref_iterator_base<_Tp&> {
 protected:
-  using __pointer = add_pointer_t<_Tp>;
+  using __pointer _LIBCPP_NODEBUG = add_pointer_t<_Tp>;
 
   template <bool = std::__range_fits_in_alignment(alignof(_Tp), 1)>
   struct __iterator {
-    using __type = std::__static_packed_bounded_iterator<__pointer, 1>;
+    using __type _LIBCPP_NODEBUG = std::__static_packed_bounded_iterator<__pointer, 1>;
 
     static __type __make(__pointer __p, unsigned) noexcept {
       return std::__make_static_packed_bounded_iter<__pointer, 1>(__p, 0);
@@ -74,9 +74,9 @@ struct __optional_ref_iterator_base<_Tp&> {
   template <>
   struct __iterator<false> {
 #  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    using __type = std::__bounded_iter<__pointer>;
+    using __type _LIBCPP_NO_DEBUG = std::__bounded_iter<__pointer>;
 #  else
-    using __type = std::__capacity_aware_iterator<__pointer, 1>;
+    using __type _LIBCPP_NODEBUG = std::__capacity_aware_iterator<__pointer, 1>;
 #  endif
 
     static __type __make(__pointer __p, [[__maybe_unused__]] unsigned __end_offset) noexcept {

>From 7b31bb35fe310c32b5b105ad20f36a2d4e4081cc Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 2 Oct 2026 15:52:16 -0400
Subject: [PATCH 6/9] simplify a little

---
 libcxx/include/__optional/optional.h     |  6 +--
 libcxx/include/__optional/optional_ref.h | 48 ++++++++++--------------
 2 files changed, 23 insertions(+), 31 deletions(-)

diff --git a/libcxx/include/__optional/optional.h b/libcxx/include/__optional/optional.h
index 98ba4ea8761e9d6..f1c5f2b8d3f356b 100644
--- a/libcxx/include/__optional/optional.h
+++ b/libcxx/include/__optional/optional.h
@@ -688,7 +688,7 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
   using __pointer _LIBCPP_NODEBUG       = add_pointer_t<_Tp>;
   using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
 
-  template <bool = std::__range_fits_in_alignment(alignof(_Tp), 1)>
+  template <class _Up = _Tp, bool = std::__range_fits_in_alignment(alignof(_Up), 1)>
   struct __iterator {
     using __type _LIBCPP_NODEBUG       = std::__static_packed_bounded_iterator<__pointer, 1>;
     using __const_type _LIBCPP_NODEBUG = std::__static_packed_bounded_iterator<__const_pointer, 1>;
@@ -699,8 +699,8 @@ class _LIBCPP_DECLSPEC_EMPTY_BASES optional
     }
   };
 
-  template <>
-  struct __iterator<false> {
+  template <class _Up>
+  struct __iterator<_Up, false> {
 #    ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
     using __type _LIBCPP_NODEBUG       = std::__bounded_iter<__pointer>;
     using __const_type _LIBCPP_NODEBUG = std::__bounded_iter<__const_pointer>;
diff --git a/libcxx/include/__optional/optional_ref.h b/libcxx/include/__optional/optional_ref.h
index 939a2c0e3615554..52aa031d743bd71 100644
--- a/libcxx/include/__optional/optional_ref.h
+++ b/libcxx/include/__optional/optional_ref.h
@@ -24,6 +24,7 @@
 #include <__optional/nullopt_t.h>
 #include <__optional/swap.h>
 #include <__type_traits/add_pointer.h>
+#include <__type_traits/conditional.h>
 #include <__type_traits/decay.h>
 #include <__type_traits/invoke.h>
 #include <__type_traits/is_array.h>
@@ -59,37 +60,19 @@ struct __optional_ref_iterator_base {};
 template <class _Tp>
   requires(is_object_v<_Tp> && !__is_unbounded_array_v<_Tp>)
 struct __optional_ref_iterator_base<_Tp&> {
-protected:
+private:
   using __pointer _LIBCPP_NODEBUG = add_pointer_t<_Tp>;
 
-  template <bool = std::__range_fits_in_alignment(alignof(_Tp), 1)>
-  struct __iterator {
-    using __type _LIBCPP_NODEBUG = std::__static_packed_bounded_iterator<__pointer, 1>;
-
-    static __type __make(__pointer __p, unsigned) noexcept {
-      return std::__make_static_packed_bounded_iter<__pointer, 1>(__p, 0);
-    }
-  };
-
-  template <>
-  struct __iterator<false> {
-#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-    using __type _LIBCPP_NO_DEBUG = std::__bounded_iter<__pointer>;
-#  else
-    using __type _LIBCPP_NODEBUG = std::__capacity_aware_iterator<__pointer, 1>;
-#  endif
-
-    static __type __make(__pointer __p, [[__maybe_unused__]] unsigned __end_offset) noexcept {
-#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
-      return std::__make_bounded_iter<__pointer>(__p, __p, __p + __end_offset);
+public:
+  using iterator =
+      conditional_t< std::__range_fits_in_alignment(alignof(_Tp), 1),
+                     std::__static_packed_bounded_iterator<__pointer, 1>,
+#  if _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+                     std::__bounded_iter<__pointer>
 #  else
-      return std::__make_capacity_aware_iterator<__pointer, 1>(__p);
+                     std::__capacity_aware_iterator<__pointer, 1>
 #  endif
-    }
-  };
-
-public:
-  using iterator = __iterator<>::__type;
+                     >;
 };
 
 template <class _Tp>
@@ -302,7 +285,16 @@ class optional<_Tp&> : public __optional_ref_iterator_base<_Tp&> {
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto begin() const noexcept
     requires __has_iterator_
   {
-    return __optional_ref_iterator_base<_Tp&>::template __iterator<>::__make(__value_, this->has_value() ? 1 : 0);
+    using __pointer _LIBCPP_NODEBUG = add_pointer_t<_Tp>;
+    if constexpr (std::__range_fits_in_alignment(alignof(_Tp&), 1)) {
+      return std::__make_static_packed_bounded_iter<__pointer, 1>(__value_, 0);
+    } else {
+#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+      return std::__make_bounded_iter<__pointer>(__value_, __value_, __value_ + this->has_value() ? 1 : 0);
+#  else
+      return std::__make_capacity_aware_iterator<__pointer, 1>(__value_);
+#  endif
+    }
   }
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto end() const noexcept

>From acefa847dd30aa301867ceed8ab9dd8415a7de98 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 2 Oct 2026 21:24:41 -0400
Subject: [PATCH 7/9] Fixup

---
 libcxx/include/__optional/optional_ref.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/__optional/optional_ref.h b/libcxx/include/__optional/optional_ref.h
index 52aa031d743bd71..d95684012b5086d 100644
--- a/libcxx/include/__optional/optional_ref.h
+++ b/libcxx/include/__optional/optional_ref.h
@@ -67,7 +67,7 @@ struct __optional_ref_iterator_base<_Tp&> {
   using iterator =
       conditional_t< std::__range_fits_in_alignment(alignof(_Tp), 1),
                      std::__static_packed_bounded_iterator<__pointer, 1>,
-#  if _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
+#  ifdef _LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL
                      std::__bounded_iter<__pointer>
 #  else
                      std::__capacity_aware_iterator<__pointer, 1>

>From cb8a459eb03fc6d19622abfeb41b5c4f2d2f0ee6 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 2 Oct 2026 21:26:10 -0400
Subject: [PATCH 8/9] Update hardening docs

---
 libcxx/docs/Hardening.md | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/libcxx/docs/Hardening.md b/libcxx/docs/Hardening.md
index 38d59775885da65..61fdabb1e90fd1b 100644
--- a/libcxx/docs/Hardening.md
+++ b/libcxx/docs/Hardening.md
@@ -427,11 +427,12 @@ CMake configuration time. The available options are:
 
   ABI impact: changes the iterator type of `std::array`, its size and its layout.
 
-- `_LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL` -- changes the iterator type of `std::optional` to a
-  bounded iterator that keeps track of whether it's within the bounds of its container and asserts it
-  on every dereference and when performing iterator arithmetic.
+- `_LIBCPP_ABI_BOUNDED_ITERATORS_IN_OPTIONAL` -- For `T` with alignment <= 2, this changes the iterator type
+  of `std::optional` to a bounded iterator that keeps track of whether it's within the bounds of its container
+  and asserts it on every dereference and when performing iterator arithmetic. For alignment > 2, this option has
+  no impact, as the default iterator type has bounds checking, but without any memory overhead.
 
-  ABI impact: changes the iterator type of `std::optional`.
+  ABI impact: changes the iterator type of `std::optional` for `T` with alignment <= 2.
 
 ### ABI tags
 

>From 651441cbbcac5487c523348484256b2c221041e6 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Fri, 2 Oct 2026 21:29:45 -0400
Subject: [PATCH 9/9] Update paper status

---
 libcxx/docs/Status/Cxx26Papers.csv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv
index f3cdf8c53bab426..f18784ad95bcc71 100644
--- a/libcxx/docs/Status/Cxx26Papers.csv
+++ b/libcxx/docs/Status/Cxx26Papers.csv
@@ -66,7 +66,7 @@
 "`P2747R2 <https://wg21.link/P2747R2>`__","``constexpr`` placement new","2024-06 (St. Louis)","|Complete|","20","`#105427 <https://github.com/llvm/llvm-project/issues/105427>`__",""
 "`P2997R1 <https://wg21.link/P2997R1>`__","Removing the common reference requirement from the indirectly invocable concepts","2024-06 (St. Louis)","|Complete|","19","`#105428 <https://github.com/llvm/llvm-project/issues/105428>`__","Implemented as a DR against C++20."
 "`P2389R2 <https://wg21.link/P2389R2>`__","``dextents`` Index Type Parameter","2024-06 (St. Louis)","|Complete|","19","`#105429 <https://github.com/llvm/llvm-project/issues/105429>`__",""
-"`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","|Complete|","22","`#105430 <https://github.com/llvm/llvm-project/issues/105430>`__",""
+"`P3168R2 <https://wg21.link/P3168R2>`__","Give ``std::optional`` Range Support","2024-06 (St. Louis)","|Partial|","22","`#105430 <https://github.com/llvm/llvm-project/issues/105430>`__","Iterator type is not constexpr."
 "`P3217R0 <https://wg21.link/P3217R0>`__","Adjoints to 'Enabling list-initialization for algorithms': find_last","2024-06 (St. Louis)","","","`#105431 <https://github.com/llvm/llvm-project/issues/105431>`__",""
 "`P2985R0 <https://wg21.link/P2985R0>`__","A type trait for detecting virtual base classes","2024-06 (St. Louis)","|Complete|","20","`#105432 <https://github.com/llvm/llvm-project/issues/105432>`__",""
 "`P0843R14 <https://wg21.link/P0843R14>`__","``inplace_vector``","2024-06 (St. Louis)","","","`#105433 <https://github.com/llvm/llvm-project/issues/105433>`__",""



More information about the libcxx-commits mailing list