[libcxx-commits] [libcxx] [libc++] Correct `optional<T&>` implementation (PR #174537)

William Tran-Viet via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 8 10:17:39 PST 2026


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

>From bb5ca98ecfd8edf0fa9e6b13776960e1cddc7629 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Mon, 5 Jan 2026 15:36:40 -0500
Subject: [PATCH 01/26] Fix optional<T&>

---
 libcxx/include/optional                       | 277 +++++++++++++++---
 .../ref_constructs_from_temporary.verify.cpp  |  35 ++-
 2 files changed, 252 insertions(+), 60 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 568c86556d156..487cfa1e7ce6e 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -510,8 +510,6 @@ struct __optional_storage_base<_Tp, true> {
 
   _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr value_type&& __get() const&& noexcept { return std::forward<value_type>(*__value_); }
-
   template <class _UArg>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) {
     _LIBCPP_ASSERT_INTERNAL(!has_value(), "__construct called for engaged __optional_storage");
@@ -909,38 +907,61 @@ public:
       : __base(in_place, __il, std::forward<_Args>(__args)...) {}
 
   template <class _Up = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr optional(_Up&& __v)
+#    if _LIBCPP_STD_VER >= 26
+      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
+#    endif
+      : __base(in_place, std::forward<_Up>(__v)) {
+  }
 
   template <class _Up                                                                        = remove_cv_t<_Tp>,
             enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v) : __base(in_place, std::forward<_Up>(__v)) {}
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit optional(_Up&& __v)
+#    if _LIBCPP_STD_VER >= 26
+      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
+#    endif
+      : __base(in_place, std::forward<_Up>(__v)) {
+  }
 
   // LWG2756: conditionally explicit conversion from const optional<_Up>&
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>& __v)
+#    if _LIBCPP_STD_VER >= 26
+      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up&>)
+#    endif
+  {
     this->__construct_from(__v);
   }
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(const optional<_Up>& __v)
+#    if _LIBCPP_STD_VER >= 26
+      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up&>)
+#    endif
+  {
     this->__construct_from(__v);
   }
 
   // LWG2756: conditionally explicit conversion from optional<_Up>&&
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(optional<_Up>&& __v)
+#    if _LIBCPP_STD_VER >= 26
+      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
+#    endif
+  {
     this->__construct_from(std::move(__v));
   }
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit optional(optional<_Up>&& __v)
+#    if _LIBCPP_STD_VER >= 26
+      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp&, _Up>)
+#    endif
+  {
     this->__construct_from(std::move(__v));
   }
 
-  // deleted optional<T&> constructors
+  // deleted optional<T&> constructors and additional optional<T&> constructors
 #    if _LIBCPP_STD_VER >= 26
-  template <class _Up, class... _Args, enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>, int> = 0>
-    requires __libcpp_opt_ref_ctor_deleted<_Up>
-  explicit optional(in_place_t, initializer_list<_Up>, _Args&&...) = delete;
-
+  // optional(U&&)
   template <class _Up = _Tp, enable_if_t<_CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>(), int> = 0>
     requires __libcpp_opt_ref_ctor_deleted<_Up>
   optional(_Up&&) = delete;
@@ -950,6 +971,21 @@ public:
     requires __libcpp_opt_ref_ctor_deleted<_Up>
   explicit optional(_Up&&) = delete;
 
+  // optional(optional<U>& rhs)
+  template <class _Up>
+    requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+            (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
+  constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
+      optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) {
+    this->__construct_from(__rhs);
+  }
+
+  template <class _Up>
+    requires __libcpp_opt_ref_ctor_deleted<_Up> && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+                 (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
+  constexpr explicit optional(optional<_Up>& __rhs) noexcept = delete;
+
+  // optional(const optional<U>&)
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>(), int> = 0>
     requires __libcpp_opt_ref_ctor_deleted<_Up>
   optional(const optional<_Up>&) = delete;
@@ -958,6 +994,7 @@ public:
     requires __libcpp_opt_ref_ctor_deleted<_Up>
   explicit optional(const optional<_Up>&) = delete;
 
+  // optional(optional<U>&&)
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_implicit<_Up>(), int> = 0>
     requires __libcpp_opt_ref_ctor_deleted<_Up>
   optional(optional<_Up>&&) = delete;
@@ -965,6 +1002,20 @@ public:
   template <class _Up, enable_if_t<_CheckOptionalLikeCtor<_Up, _Up&&>::template __enable_explicit<_Up>(), int> = 0>
     requires __libcpp_opt_ref_ctor_deleted<_Up>
   explicit optional(optional<_Up>&&) = delete;
+
+  // optional(const optional<U>&&)
+  template <class _Up>
+    requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+            (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!is_convertible_v<const _Up, _Tp&>)
+      optional(const optional<_Up>&& __v) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) {
+    this->__construct_from(std::move(__v));
+  }
+
+  template <class _Up>
+    requires __libcpp_opt_ref_ctor_deleted<_Up> && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+                 (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>&& __v) noexcept = delete;
 #    endif
 
 #    if _LIBCPP_STD_VER >= 23
@@ -1013,8 +1064,12 @@ public:
     return *this;
   }
 
-  template <class... _Args, enable_if_t<is_constructible_v<_Tp, _Args...>, int> = 0>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args) {
+  template <class... _Args, enable_if_t<__is_constructible_for_optional_v<_Tp, _Args...>, int> = 0>
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(_Args&&... __args)
+#    if _LIBCPP_STD_VER >= 26
+      noexcept(is_lvalue_reference_v<_Tp> && is_nothrow_constructible_v<_Tp, _Args...>)
+#    endif
+  {
     reset();
     this->__construct(std::forward<_Args>(__args)...);
     return this->__get();
@@ -1022,20 +1077,19 @@ public:
 
   template <class _Up,
             class... _Args,
-            enable_if_t<is_constructible_v<_Tp, initializer_list<_Up>&, _Args...>
-#    if _LIBCPP_STD_VER >= 26
-                            && !reference_constructs_from_temporary_v<_Tp&, _Up>
-#    endif
-                        ,
-                        int> = 0>
+            enable_if_t<__is_constructible_for_optional_initializer_list_v<_Tp, _Up, _Args...>, int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp& emplace(initializer_list<_Up> __il, _Args&&... __args) {
     reset();
     this->__construct(__il, std::forward<_Args>(__args)...);
     return this->__get();
   }
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
-  swap(optional& __opt) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(optional& __opt) noexcept(
+      (is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>)
+#    if _LIBCPP_STD_VER >= 26
+      || is_lvalue_reference_v<_Tp>
+#    endif
+  ) {
     if (this->has_value() == __opt.has_value()) {
       if (this->has_value())
         this->__swap(__opt);
@@ -1050,32 +1104,56 @@ public:
     }
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp const> operator->() const noexcept {
+  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp const> operator->() const noexcept
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
     return std::addressof(this->__get());
   }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp> operator->() noexcept {
+  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp> operator->() noexcept
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
     return std::addressof(this->__get());
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
     return this->__get();
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
     return this->__get();
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
     return std::move(this->__get());
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
     return std::move(this->__get());
   }
@@ -1085,25 +1163,41 @@ public:
   using __base::__get;
   using __base::has_value;
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& value() const& {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& value() const&
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     if (!this->has_value())
       std::__throw_bad_optional_access();
     return this->__get();
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() & {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() &
+#    if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     if (!this->has_value())
       std::__throw_bad_optional_access();
     return this->__get();
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() && {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() &&
+#    if _LIBCPP_STD_VER >= 26
+      requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     if (!this->has_value())
       std::__throw_bad_optional_access();
     return std::move(this->__get());
   }
 
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&& {
+      [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&&
+#    if _LIBCPP_STD_VER >= 26
+        requires(!is_lvalue_reference_v<_Tp>)
+#    endif
+  {
     if (!this->has_value())
       std::__throw_bad_optional_access();
     return std::move(this->__get());
@@ -1111,8 +1205,7 @@ public:
 
   template <class _Up = remove_cv_t<_Tp>>
 #    if _LIBCPP_STD_VER >= 26
-    requires(!(is_lvalue_reference_v<_Tp> && is_function_v<__libcpp_remove_reference_t<_Tp>>) &&
-             !(is_lvalue_reference_v<_Tp> && is_array_v<__libcpp_remove_reference_t<_Tp>>))
+    requires(!is_lvalue_reference_v<_Tp>)
 #    endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
     static_assert(is_copy_constructible_v<_Tp>, "optional<T>::value_or: T must be copy constructible");
@@ -1130,19 +1223,11 @@ public:
     return this->has_value() ? std::move(this->__get()) : static_cast<_Tp>(std::forward<_Up>(__v));
   }
 
-#    if _LIBCPP_STD_VER >= 26
-  template <class _Up = remove_cv_t<_Tp>>
-    requires(is_lvalue_reference_v<_Tp> &&
-             !(is_function_v<__libcpp_remove_reference_t<_Tp>> || is_array_v<__libcpp_remove_reference_t<_Tp>>))
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
-    static_assert(is_move_constructible_v<_Tp>, "optional<T>::value_or: T must be move constructible");
-    static_assert(is_convertible_v<_Up, _Tp>, "optional<T>::value_or: U must be convertible to T");
-    return this->has_value() ? this->__get() : static_cast<_Tp>(std::forward<_Up>(__v));
-  }
-#    endif
-
 #    if _LIBCPP_STD_VER >= 23
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
     using _Up = invoke_result_t<_Func, _Tp&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1153,6 +1238,9 @@ public:
   }
 
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
     using _Up = invoke_result_t<_Func, const _Tp&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1163,6 +1251,9 @@ public:
   }
 
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
     using _Up = invoke_result_t<_Func, _Tp&&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1173,6 +1264,9 @@ public:
   }
 
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
     using _Up = invoke_result_t<_Func, const _Tp&&>;
     static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
@@ -1183,6 +1277,9 @@ public:
   }
 
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
@@ -1195,6 +1292,9 @@ public:
   }
 
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
     using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
@@ -1207,6 +1307,9 @@ public:
   }
 
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
     static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
@@ -1219,8 +1322,11 @@ public:
   }
 
   template <class _Func>
+#      if _LIBCPP_STD_VER >= 26
+    requires(!is_lvalue_reference_v<_Tp>)
+#      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
-    using _Up = remove_cvref_t<invoke_result_t<_Func, const _Tp&&>>;
+    using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
     static_assert(!is_array_v<_Up>, "Result of f(std::move(value())) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(std::move(value())) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(std::move(value())) should not be std::nullopt_t");
@@ -1233,6 +1339,9 @@ public:
   template <invocable _Func>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
     requires is_copy_constructible_v<_Tp>
+#      if _LIBCPP_STD_VER >= 26
+             && (!is_lvalue_reference_v<_Tp>)
+#      endif
   {
     static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
                   "Result of f() should be the same type as this optional");
@@ -1244,6 +1353,9 @@ public:
   template <invocable _Func>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
     requires is_move_constructible_v<_Tp>
+#      if _LIBCPP_STD_VER >= 26
+             && (!is_lvalue_reference_v<_Tp>)
+#      endif
   {
     static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
                   "Result of f() should be the same type as this optional");
@@ -1254,6 +1366,77 @@ public:
 #    endif // _LIBCPP_STD_VER >= 23
 
   using __base::reset;
+
+// optional<T&> overloads
+#    if _LIBCPP_STD_VER >= 26
+
+  _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp> operator->() const noexcept
+    requires(is_lvalue_reference_v<_Tp>)
+  {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
+    return std::addressof(this->__get());
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() const noexcept
+    requires(is_lvalue_reference_v<_Tp>)
+  {
+    _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
+    return this->__get();
+  }
+
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() const
+    requires(is_lvalue_reference_v<_Tp>)
+  {
+    if (!this->has_value())
+      std::__throw_bad_optional_access();
+    return this->__get();
+  }
+
+  template <class _Up = remove_cvref_t<_Tp>>
+    requires(is_lvalue_reference_v<_Tp> && is_object_v<__libcpp_remove_reference_t<_Tp>> &&
+             !is_array_v<__libcpp_remove_reference_t<_Tp>>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decay_t<_Tp> value_or(_Up&& __v) const {
+    using _X = remove_cvref_t<_Tp>;
+    static_assert(is_constructible_v<_X, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
+    static_assert(is_convertible_v<_Up, _X>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
+    return this->has_value() ? this->__get() : static_cast<_X>(std::forward<_Up>(__v));
+  }
+
+  template <class _Func>
+    requires(is_lvalue_reference_v<_Tp>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const {
+    using _Up = invoke_result_t<_Func, _Tp&>;
+    static_assert(__is_std_optional<remove_cvref_t<_Up>>::value,
+                  "Result of f(value()) must be a specialization of std::optional");
+    if (*this)
+      return std::invoke(std::forward<_Func>(__f), value());
+    return remove_cvref_t<_Up>();
+  }
+
+  template <class _Func>
+    requires(is_lvalue_reference_v<_Tp>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional<remove_cv_t<invoke_result_t<_Func, _Tp&>>>
+  transform(_Func&& __f) const {
+    using _Up = remove_cvref_t<_Tp>;
+    static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
+    static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
+    static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");
+    static_assert(is_object_v<_Up>, "Result of f(value()) should be an object type");
+    if (*this)
+      return optional<_Up>(__optional_construct_from_invoke_tag{}, std::forward<_Func>(__f), value());
+    return optional<_Up>();
+  }
+
+  template <invocable _Func>
+    requires(is_lvalue_reference_v<_Tp>)
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const {
+    static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
+                  "Result of f() should be the same type as this optional");
+    if (*this)
+      return *this;
+    return std::forward<_Func>(__f)();
+  }
+#    endif
 };
 
 template <class _Tp>
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp
index 01b241ffbe79b..b59aa8051b39e 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp
@@ -8,7 +8,13 @@
 
 // REQUIRES: std-at-least-c++26
 
-// optional
+// <optional>
+
+// optional(U&& u) noexcept(is_nothrow_constructible_v<T&, U>);
+// optional(optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, U&>);
+// optional(const optional<U>& rhs) noexcept(is_nothrow_constructible_v<T&, const U&>);
+// optional(optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, U>);
+// optional(const optional<U>&& rhs) noexcept(is_nothrow_constructible_v<T&, const U>);
 
 #include <optional>
 #include <utility>
@@ -20,16 +26,19 @@ struct X {
 };
 
 int main(int, char**) {
-  const std::optional<int> _co(1);
-  std::optional<int> _o(1);
-
-  // expected-error-re@*:* 8 {{call to deleted constructor of 'std::optional<{{.*}}>'}}
-  std::optional<const int&> o1{1};                     // optional(U&&)
-  std::optional<const int&> o2{std::optional<int>(1)}; // optional(optional<U>&&)
-  std::optional<const int&> o3{_co};                   // optional(const optional<U>&)
-  std::optional<const int&> o4{_o};                    // optional(optional<U>&)
-  std::optional<const X&> o5{1};                       // optional(U&&)
-  std::optional<const X&> o6{std::optional<int>(1)};   // optional(optional<U>&&)
-  std::optional<const X&> o7{_co};                     // optional(const optional<U>&)
-  std::optional<const X&> o8{_o};                      // optional(optional<U>&)
+  const std::optional<int> co(1);
+  std::optional<int> o0(1);
+
+  // expected-error-re@*:* 10 {{call to deleted constructor of 'std::optional<{{.*}}>'}}
+  std::optional<const int&> o1{1};             // optional(U&&)
+  std::optional<const int&> o2{o0};            // optional(optional<U>&)
+  std::optional<const int&> o3{co};            // optional(const optional<U>&)
+  std::optional<const int&> o4{std::move(o0)}; // optional(optional<U>&&&)
+  std::optional<const int&> o5{std::move(co)}; // optional(optional<U>&&&)
+
+  std::optional<const X&> o6{1};              // optional(U&&)
+  std::optional<const X&> o7{o0};             // optional(optional<U>&)
+  std::optional<const X&> o8(co);             // optional(const optional<U>&)
+  std::optional<const X&> o9{std::move(o0)};  // optional(optional<U>&&)
+  std::optional<const X&> o10{std::move(co)}; // optional(const optional<U>&&)
 }

>From 14f8afe5f92f380ee9b713c26ffdf1500cf05ff5 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 01:24:27 -0500
Subject: [PATCH 02/26] Tests

---
 .../value_or.compile.pass.cpp                 |  4 +-
 .../optional.monadic/and_then.pass.cpp        | 27 ++++---
 .../optional.monadic/or_else.pass.cpp         | 17 ++++
 .../optional.monadic/transform.pass.cpp       | 14 ++--
 .../assign_value.pass.cpp                     | 26 ++++--
 .../emplace.compile.fail.cpp                  | 26 ++++++
 .../optional.object.assign/emplace.pass.cpp   |  1 +
 .../optional.object.assign/nullopt_t.pass.cpp | 11 +++
 .../optional.object.ctor/U.pass.cpp           | 41 +++++++++-
 .../const_optional_U.pass.cpp                 | 48 +++++++++++
 .../optional.object.ctor/in_place_t.pass.cpp  | 21 ++++-
 .../optional.object.ctor/move.pass.cpp        | 32 +++++---
 .../optional.object.ctor/optional_U.pass.cpp  | 52 ++++++++++++
 .../optional.object.mod/reset.pass.cpp        |  1 +
 .../optional.object.observe/bool.pass.cpp     | 34 +++++++-
 .../dereference.pass.cpp                      | 37 ++++++++-
 .../dereference_const.pass.cpp                | 81 ++++++++++++-------
 .../dereference_const_rvalue.pass.cpp         | 43 +++++++++-
 .../dereference_rvalue.pass.cpp               | 43 +++++++++-
 .../has_value.pass.cpp                        |  8 +-
 .../optional.object.observe/op_arrow.pass.cpp |  7 +-
 .../op_arrow_const.pass.cpp                   |  7 +-
 .../value_const.pass.cpp                      | 44 +++++++++-
 .../value_const_rvalue.pass.cpp               | 44 +++++++++-
 .../optional.object.observe/value_or.pass.cpp |  4 +-
 25 files changed, 582 insertions(+), 91 deletions(-)
 create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.compile.fail.cpp

diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.observe/value_or.compile.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.observe/value_or.compile.pass.cpp
index 25df0dd6c1936..1071184561dc1 100644
--- a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.observe/value_or.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.observe/value_or.compile.pass.cpp
@@ -22,7 +22,7 @@ concept has_value_or = requires(Opt opt, T&& t) {
 };
 
 static_assert(has_value_or<std::optional<int>, int>);
-static_assert(has_value_or<std::optional<int&>, int&>);
-static_assert(has_value_or<std::optional<const int&>, const int&>);
+static_assert(has_value_or<std::optional<int&>, int>);
+static_assert(has_value_or<std::optional<const int&>, int>);
 static_assert(!has_value_or<std::optional<int (&)[1]>&&, int (&)[1]>);
 static_assert(!has_value_or<std::optional<int (&)()>&&, int (&)()>);
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
index 810283a4bc80e..93bbd74cd8678 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/and_then.pass.cpp
@@ -18,6 +18,7 @@
 #include <cassert>
 #include <concepts>
 #include <optional>
+#include <utility>
 
 #include "test_macros.h"
 
@@ -260,8 +261,9 @@ constexpr bool test() {
 
 #if TEST_STD_VER >= 26
 constexpr bool test_ref() {
-  // Test & overload
-  {
+  // Test "overloads", only the const (no ref-qualifier) and_then() should be called
+
+  { // &
     // Without & qualifier on F's operator()
     {
       int j = 42;
@@ -276,21 +278,21 @@ constexpr bool test_ref() {
     {
       int j = 42;
       std::optional<int&> i{j};
+      auto& io = i;
       RefQual l{};
       NORefQual nl{};
-      std::same_as<std::optional<int>> decltype(auto) r = i.and_then(l);
+      std::same_as<std::optional<int>> decltype(auto) r = io.and_then(l);
 
       assert(r == 1);
-      assert(i.and_then(nl) == std::nullopt);
+      assert(io.and_then(nl) == std::nullopt);
     }
   }
 
-  // Test const& overload
-  {
+  { // const&
     // Without & qualifier on F's operator()
     {
       int j = 42;
-      std::optional<const int&> i{j};
+      const std::optional<const int&> i{j};
       std::same_as<std::optional<int>> decltype(auto) r = i.and_then(CLVal{});
 
       assert(r == 1);
@@ -309,7 +311,8 @@ constexpr bool test_ref() {
       assert(i.and_then(nl) == std::nullopt);
     }
   }
-  // Test && overload
+
+  // &&
   {
     //With & qualifier on F's operator()
     {
@@ -318,11 +321,11 @@ constexpr bool test_ref() {
       std::same_as<std::optional<int>> decltype(auto) r = i.and_then(RVRefQual{});
 
       assert(r == 1);
-      assert(i.and_then(NORVRefQual{}) == std::nullopt);
+      assert(std::move(i).and_then(NORVRefQual{}) == std::nullopt);
     }
   }
 
-  // Test const&& overload
+  // const&&
   {
     //With & qualifier on F's operator()
     {
@@ -330,10 +333,10 @@ constexpr bool test_ref() {
       const std::optional<int&> i{j};
       const RVCRefQual l{};
       const NORVCRefQual nl{};
-      std::same_as<std::optional<int>> decltype(auto) r = i.and_then(std::move(l));
+      std::same_as<std::optional<int>> decltype(auto) r = std::move(i).and_then(std::move(l));
 
       assert(r == 1);
-      assert(i.and_then(std::move(nl)) == std::nullopt);
+      assert(std::move(i).and_then(std::move(nl)) == std::nullopt);
     }
   }
   return true;
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
index 0c330e30055a2..326013cd6557f 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/or_else.pass.cpp
@@ -75,6 +75,13 @@ constexpr bool test() {
     });
     assert(opt == j);
   }
+
+  {
+    int i = 2;
+    const std::optional<int&> opt;
+    assert(opt.or_else([&] { return std::optional<int&>{i}; }) == i);
+  }
+
   {
     int i = 2;
     std::optional<int&> opt;
@@ -87,6 +94,16 @@ constexpr bool test() {
     });
     assert(opt == j);
   }
+
+  {
+    int i                         = 2;
+    const std::optional<int&> opt = i;
+    assert(std::move(opt).or_else([] {
+      assert(false);
+      return std::optional<int&>{};
+    }) == i);
+  }
+
 #endif
 
   return true;
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
index 36939f0b6b62e..57bdbaadca5de 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
@@ -204,6 +204,8 @@ constexpr bool test() {
 
 #if TEST_STD_VER >= 26
 constexpr bool test_ref() {
+  // Test that no matter the ref qualifier on the object .transform() is invoked on, only the added
+  // const (no ref-qualifier) overload is used
   {
     std::optional<int&> opt1;
     std::same_as<std::optional<int>> decltype(auto) opt1r = opt1.transform([](int i) { return i + 2; });
@@ -218,7 +220,7 @@ constexpr bool test_ref() {
 
     assert(*o2 == 44);
   }
-  // Test & overload
+  // &
   {
     // Without & qualifier on F's operator()
     {
@@ -244,7 +246,7 @@ constexpr bool test_ref() {
     // Without & qualifier on F's operator()
     {
       int i = 42;
-      std::optional<const int&> opt{i};
+      const std::optional<const int&> opt{i};
       std::same_as<std::optional<int>> decltype(auto) o3 = std::as_const(opt).transform(CLVal{});
 
       assert(*o3 == 1);
@@ -266,8 +268,8 @@ constexpr bool test_ref() {
     // Without & qualifier on F's operator()
     {
       int i = 42;
-      std::optional<int> opt{i};
-      std::same_as<std::optional<int>> decltype(auto) o3 = std::move(opt).transform(RVal{});
+      std::optional<int&> opt{i};
+      std::same_as<std::optional<int>> decltype(auto) o3 = std::move(opt).transform(LVal{});
 
       assert(*o3 == 1);
     }
@@ -286,9 +288,9 @@ constexpr bool test_ref() {
     //With & qualifier on F's operator()
     {
       int i = 42;
-      std::optional<int&> opt{i};
+      const std::optional<int&> opt{i};
       const RVCRefQual rvc{};
-      std::same_as<std::optional<int>> decltype(auto) o3 = opt.transform(std::move(rvc));
+      std::same_as<std::optional<int>> decltype(auto) o3 = std::move(opt).transform(std::move(rvc));
       assert(*o3 == 1);
     }
   }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
index ddb9ffc4bf80c..1923c0ed07d33 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
@@ -16,6 +16,7 @@
 #include <cassert>
 #include <memory>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 #include "archetypes.h"
 
@@ -252,9 +253,9 @@ constexpr T pr38638(T v)
 
 #if TEST_STD_VER >= 26
 
-template <typename T, std::remove_reference_t<T> _Val>
-constexpr void test_with_ref() {
-  T t{_Val};
+template <typename T>
+constexpr bool test_with_ref(std::decay_t<T> val) {
+  T t{val};
   { // to empty
     optional<T&> opt;
     opt = t;
@@ -280,7 +281,7 @@ constexpr void test_with_ref() {
   }
   // test two objects, make sure that the optional only changes what it holds a reference to
   {
-    T t2{_Val};
+    T t2{val};
     optional<T&> opt{t};
     opt = t2;
 
@@ -299,6 +300,20 @@ constexpr void test_with_ref() {
     assert(std::addressof(*opt) == std::addressof(j));
     assert(*opt == 2);
   }
+
+  { // test that no copy is made when assigning
+    TracedCopyMove t1{};
+    TracedCopyMove t2{};
+
+    optional<TracedCopyMove&> o(t1);
+
+    o = t2;
+    assert(std::addressof(*o) == &t2);
+    assert(o->constCopy == 0);
+    assert(o->nonConstCopy == 0);
+  }
+
+  return true;
 }
 #endif
 
@@ -333,7 +348,8 @@ int main(int, char**)
     static_assert(pr38638(3) == 5, "");
 
 #if TEST_STD_VER >= 26
-    test_with_ref<int, 3>();
+    assert(test_with_ref<int>(3));
+    static_assert(test_with_ref<int>(3));
 #endif
     return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.compile.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.compile.fail.cpp
new file mode 100644
index 0000000000000..bcd06517b9885
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.compile.fail.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+// <optional>
+
+// template <class... Args> T& optional<T&>::emplace(Arg& arg);
+// Ensure that emplace isn't found if reference_constructs_From_temporary_v == true
+#include <optional>
+#include <type_traits>
+
+struct X {};
+void test() {
+  int i = 1;
+  std::optional<X&> f{};
+  static_assert(!std::is_constructible_v<X&, int>);
+  f.emplace(i); // is_constructible<_Tp&, U> == false
+
+  std::optional<const int&> t{};
+  t.emplace(1); // reference_constructs_from_temporary_v == false
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
index 629e315add4d9..3321d55ec5869 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
@@ -231,6 +231,7 @@ constexpr bool test_ref() {
     auto& v = opt.emplace(t);
     static_assert(std::is_same_v<T&, decltype(v)>);
     assert(static_cast<bool>(opt) == true);
+    ASSERT_NOEXCEPT(opt.emplace(t));
     assert(*opt == t);
     assert(&v == &*opt);
     assert(&t == &*opt);
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
index 9d0843b7338df..e85c0c435aa37 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
@@ -61,6 +61,17 @@ TEST_CONSTEXPR_CXX20 bool test()
         assert(state == State::destroyed);
         assert(static_cast<bool>(opt) == false);
     }
+
+#if TEST_STD_VER >= 26
+    {
+      int i = 0;
+      optional<int&> o{i};
+      ASSERT_NOEXCEPT(o = std::nullopt);
+      o = std::nullopt;
+      assert(!o.has_value());
+      assert(static_cast<bool>(o) == false);
+    }
+#endif
     return true;
 }
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
index 1e951ebdf1d74..091e0ef00d2d4 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -149,9 +149,48 @@ void test_explicit() {
 #endif
 }
 
+#if TEST_STD_VER >= 26
+struct Throws {
+  int val = 42;
+  bool b  = false;
+  constexpr Throws() {};
+  operator int&() {
+    if (b) {
+      TEST_THROW(1);
+    }
+    return val;
+  }
+};
+
+constexpr bool test_ref() {
+  {
+    int i = 0;
+    std::optional<int&> o(i);
+    ASSERT_NOEXCEPT(std::optional<int&>(i));
+    assert(o.has_value());
+    assert(&(*o) == &i);
+    assert(*o == 0);
+    assert(o.value() == 0);
+  }
+
+#  ifndef TEST_HAS_NO_EXCEPTIONS
+  {
+    using T = Throws;
+    T t{};
+    ASSERT_NOT_NOEXCEPT(std::optional<int&>(t));
+    // TODO: There doesn't seem to be a usable type which can actually make the ctor not noexcept
+  }
+#  endif
+  return true;
+}
+#endif
+
 int main(int, char**) {
   test_implicit();
   test_explicit();
-
+#if TEST_STD_VER >= 26
+  assert(test_ref());
+  static_assert(test_ref());
+#endif
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
index 70fd76ec6ed0b..376ece0f820ab 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
@@ -11,6 +11,7 @@
 
 // template <class U>
 //   optional(const optional<U>& rhs);
+//optional<T&>: optional(const optional<U>&& rhs);
 
 #include <cassert>
 #include <optional>
@@ -86,6 +87,53 @@ constexpr bool test_all() {
   return true;
 }
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  // optional(const optional<U>&)
+  {
+    int i = 1;
+    const std::optional<int&> o1{i};
+    const std::optional<int&> o2{o1};
+
+    ASSERT_NOEXCEPT(std::optional<int&>(o2));
+    assert(o2.has_value());
+    assert(&(*o1) == &(*o2));
+    assert(*o1 == i);
+    assert(*o2 == i);
+  }
+
+  {
+    const std::optional<int&> o1;
+    const std::optional<int&> o2{o1};
+    ASSERT_NOEXCEPT(std::optional<int&>(o2));
+    assert(!o2.has_value());
+  }
+
+  // optional(optional<U>&&)
+  {
+    int i = 1;
+    const std::optional<int&> o1{i};
+    const std::optional<int&> o2{std::move(o1)};
+
+    // trivial move constructor should just copy the reference
+    ASSERT_NOEXCEPT(std::optional<int&>(std::move(o2)));
+    assert(o2.has_value());
+    assert(&(*o1) == &(*o2));
+    assert(*o1 == i);
+    assert(*o2 == i);
+  }
+
+  {
+    const std::optional<int&> o1;
+    const std::optional<int&> o2{std::move(o1)};
+    ASSERT_NOEXCEPT(std::optional<int&>(o2));
+    assert(!o2.has_value());
+  }
+
+  return true;
+}
+#endif
+
 int main(int, char**) {
   test_all<int, short>();
   test_all<X, int>();
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
index c8bdfc78225fa..c3b498e56a5a1 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
@@ -78,6 +78,23 @@ constexpr bool test_ref_initializer_list() {
 
   return true;
 }
+
+constexpr bool test_ref() {
+  { // optional(in_place_t, _Arg&&)
+    Y y{1, 2};
+    optional<Y&> xo(in_place, y);
+
+    Y x2{1, 2};
+
+    assert(*xo == x2);
+    assert(&(*xo) == &y);
+  }
+
+  assert(test_ref_initializer_list());
+  static_assert(test_ref_initializer_list());
+
+  return true;
+}
 #endif
 
 int main(int, char**) {
@@ -148,8 +165,8 @@ int main(int, char**) {
 #endif
 
 #if TEST_STD_VER >= 26
-  test_ref_initializer_list();
-  static_assert(test_ref_initializer_list());
+  test_ref();
+  static_assert(test_ref());
 #endif
 
   return 0;
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
index 583debcaac650..bb36283a5e3ea 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
@@ -78,26 +78,34 @@ void test_reference_extension() {
   T::reset();
   {
     T t;
-    T::reset_constructors();
-    test_ref<T&>();
-    test_ref<T&>(t);
+    {
+      T::reset_constructors();
+      test_ref<T&>();
+      test_ref<T&>(t);
+      assert(T::alive == 1);
+      assert(T::constructed == 0);
+      assert(T::assigned == 0);
+      assert(T::destroyed == 0);
+    } // destroying the optional<T&> doesn't destroy the underlying T
     assert(T::alive == 1);
-    assert(T::constructed == 0);
-    assert(T::assigned == 0);
     assert(T::destroyed == 0);
   }
   assert(T::destroyed == 1);
   assert(T::alive == 0);
   {
     T t;
-    const T& ct = t;
-    T::reset_constructors();
-    test_ref<T const&>();
-    test_ref<T const&>(t);
-    test_ref<T const&>(ct);
+    {
+      const T& ct = t;
+      T::reset_constructors();
+      test_ref<T const&>();
+      test_ref<T const&>(t);
+      test_ref<T const&>(ct);
+      assert(T::alive == 1);
+      assert(T::constructed == 0);
+      assert(T::assigned == 0);
+      assert(T::destroyed == 0);
+    }
     assert(T::alive == 1);
-    assert(T::constructed == 0);
-    assert(T::assigned == 0);
     assert(T::destroyed == 0);
   }
   assert(T::alive == 0);
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
index 709b106c800a6..743f0661f380f 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -12,6 +12,8 @@
 // template <class U>
 //   optional(optional<U>&& rhs);
 
+// optional<T&>: optional(optional<U>& rhs)
+
 #include <cassert>
 #include <memory>
 #include <optional>
@@ -68,6 +70,52 @@ TEST_CONSTEXPR_CXX20 bool test_all() {
   return true;
 }
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  // optional(optional<U>&)
+  {
+    int i = 1;
+    std::optional<int&> o1{i};
+    std::optional<int&> o2{o1};
+
+    ASSERT_NOEXCEPT(std::optional<int&>(o2));
+    assert(o2.has_value());
+    assert(&(*o1) == &(*o2));
+    assert(*o1 == i);
+    assert(*o2 == i);
+  }
+
+  {
+    std::optional<int&> o1;
+    std::optional<int&> o2{o1};
+    ASSERT_NOEXCEPT(std::optional<int&>(o2));
+    assert(!o2.has_value());
+  }
+  // optional(optional<U>&&)
+  {
+    int i = 1;
+    std::optional<int&> o1{i};
+    std::optional<int&> o2{std::move(o1)};
+
+    // trivial move constructor should just copy the reference
+    ASSERT_NOEXCEPT(std::optional<int&>(o2));
+    assert(o2.has_value());
+    assert(&(*o1) == &(*o2));
+    assert(*o1 == i);
+    assert(*o2 == i);
+  }
+
+  {
+    std::optional<int&> o1;
+    std::optional<int&> o2{std::move(o1)};
+    ASSERT_NOEXCEPT(std::optional<int&>(o2));
+    assert(!o2.has_value());
+  }
+
+  return true;
+}
+#endif
+
 int main(int, char**) {
   test_all<short, int>();
   test_all<int, X>();
@@ -86,5 +134,9 @@ int main(int, char**) {
 
   static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), "");
 
+#if TEST_STD_VER >= 26
+  assert(test_ref());
+  static_assert(test_ref());
+#endif
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp
index e23e481f6a05d..a7ae22861d32e 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp
@@ -75,6 +75,7 @@ int main(int, char**)
       optional<X&> opt(x);
       X::dtor_called = false;
       opt.reset();
+      ASSERT_NOEXCEPT(opt.reset());
       assert(X::dtor_called == false);
       assert(static_cast<bool>(opt) == false);
     }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp
index 684f18ff3df20..ccc6dea8a111a 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp
@@ -10,13 +10,36 @@
 // <optional>
 
 // constexpr explicit optional<T>::operator bool() const noexcept;
+// constexpr explicit optional<T&>::operator bool() const noexcept;
 
+#include <cassert>
 #include <optional>
 #include <type_traits>
-#include <cassert>
 
 #include "test_macros.h"
 
+#if TEST_STD_VER >= 26
+
+constexpr bool test_ref() {
+  {
+    std::optional<int&> opt;
+    ASSERT_NOEXCEPT(bool(opt));
+    assert(!opt);
+    static_assert(!std::is_convertible<std::optional<int&>, bool>::value, "");
+  }
+  {
+    int i = 1;
+    std::optional<int&> opt(i);
+    ASSERT_NOEXCEPT(bool(opt));
+    assert(opt);
+    static_assert(!std::is_convertible<std::optional<int&>, bool>::value, "");
+  }
+
+  return true;
+}
+
+#endif
+
 int main(int, char**)
 {
     using std::optional;
@@ -34,5 +57,12 @@ int main(int, char**)
         static_assert(opt, "");
     }
 
-  return 0;
+#if TEST_STD_VER >= 26
+    {
+      assert(test_ref());
+      static_assert(test_ref());
+    }
+#endif
+
+    return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
index 6c1bf8aa15a8d..6084cc11ff031 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
@@ -11,10 +11,11 @@
 
 // constexpr T& optional<T>::operator*() &;
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <memory>
+#include <optional>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -39,6 +40,38 @@ test()
     return (*opt).test();
 }
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  {
+    TracedCopyMove x{};
+    std::optional<TracedCopyMove&> opt(x);
+    static_assert(noexcept(*opt));
+    ASSERT_SAME_TYPE(decltype(*opt), TracedCopyMove&);
+
+    assert(std::addressof(*opt) == std::addressof(x));
+    assert(x.constMove == 0);
+    assert(x.nonConstMove == 0);
+    assert(x.constCopy == 0);
+    assert(x.nonConstCopy == 0);
+  }
+
+  {
+    TracedCopyMove x{};
+    std::optional<const TracedCopyMove&> opt(x);
+    static_assert(noexcept(*opt));
+    ASSERT_SAME_TYPE(decltype(*opt), const TracedCopyMove&);
+
+    assert(std::addressof(*opt) == std::addressof(x));
+    assert(x.constMove == 0);
+    assert(x.nonConstMove == 0);
+    assert(x.constCopy == 0);
+    assert(x.nonConstCopy == 0);
+  }
+
+  return true;
+}
+#endif
+
 int main(int, char**)
 {
     {
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
index c15d4e4af74cc..ff69126030c6d 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
@@ -11,10 +11,11 @@
 
 // constexpr const T& optional<T>::operator*() const &;
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <memory>
+#include <optional>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -32,40 +33,60 @@ struct Y
     int test() const {return 2;}
 };
 
-int main(int, char**)
-{
-    {
-        const optional<X> opt; ((void)opt);
-        ASSERT_SAME_TYPE(decltype(*opt), X const&);
-        ASSERT_NOEXCEPT(*opt);
-    }
-    {
-        constexpr optional<X> opt(X{});
-        static_assert((*opt).test() == 3, "");
-    }
 #if TEST_STD_VER >= 26
-    {
-      X x{};
-      const optional<X&> opt{x};
-      ASSERT_SAME_TYPE(decltype(*opt), X&);
-      ASSERT_NOEXCEPT(*opt);
-    }
-    {
-      X x{};
-      const optional<const X&> opt{x};
-      ASSERT_SAME_TYPE(decltype(*opt), const X&);
-      ASSERT_NOEXCEPT(*opt);
-    }
-    {
-      static constexpr X x{};
-      constexpr optional<const X&> opt(x);
-      static_assert((*opt).test() == 3);
-    }
+constexpr bool test_ref() {
+  using T = TracedCopyMove;
+  {
+    T x{};
+    const std::optional<T&> opt(x);
+    ASSERT_NOEXCEPT(*opt);
+    ASSERT_SAME_TYPE(decltype(*opt), TracedCopyMove&);
+
+    assert(std::addressof(*opt) == std::addressof(x));
+    assert((*opt).constMove == 0);
+    assert((*opt).nonConstMove == 0);
+    assert((*opt).constCopy == 0);
+    assert((*opt).nonConstCopy == 0);
+  }
+
+  {
+    T x{};
+    const std::optional<const T&> opt(x);
+    ASSERT_NOEXCEPT(*opt);
+    ASSERT_SAME_TYPE(decltype(*opt), const TracedCopyMove&);
+
+    assert(std::addressof(*opt) == std::addressof(x));
+    assert((*opt).constMove == 0);
+    assert((*opt).nonConstMove == 0);
+    assert((*opt).constCopy == 0);
+    assert((*opt).nonConstCopy == 0);
+  }
+
+  return true;
+}
+
 #endif
+
+int main(int, char**) {
+  {
+    const optional<X> opt;
+    ((void)opt);
+    ASSERT_SAME_TYPE(decltype(*opt), X const&);
+    ASSERT_NOEXCEPT(*opt);
+  }
+  {
+    constexpr optional<X> opt(X{});
+    static_assert((*opt).test() == 3, "");
+  }
     {
         constexpr optional<Y> opt(Y{});
         assert((*opt).test() == 2);
     }
 
+#if TEST_STD_VER >= 26
+    assert(test_ref());
+    static_assert(test_ref());
+#endif
+
     return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
index 646857fdc0465..64ef7a55c7c97 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
@@ -11,10 +11,12 @@
 
 // constexpr T&& optional<T>::operator*() const &&;
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <memory>
+#include <optional>
+#include <utility>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -32,6 +34,38 @@ struct Y
     int test() const && {return 2;}
 };
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  { // const&&
+    TracedCopyMove x{};
+    const std::optional<TracedCopyMove&> opt(x);
+    ASSERT_NOEXCEPT(*std::move(opt));
+    ASSERT_SAME_TYPE(decltype(*std::move(opt)), TracedCopyMove&);
+
+    assert(std::addressof(*(std::move(opt))) == std::addressof(x));
+    assert((*std::move(opt)).constMove == 0);
+    assert((*std::move(opt)).nonConstMove == 0);
+    assert((*std::move(opt)).constCopy == 0);
+    assert((*std::move(opt)).nonConstCopy == 0);
+  }
+
+  {
+    TracedCopyMove x{};
+    const std::optional<const TracedCopyMove&> opt(x);
+    ASSERT_NOEXCEPT(*std::move(opt));
+    ASSERT_SAME_TYPE(decltype(*std::move(opt)), const TracedCopyMove&);
+
+    assert(std::addressof(*(std::move(opt))) == std::addressof(x));
+    assert((*std::move(opt)).constMove == 0);
+    assert((*std::move(opt)).nonConstMove == 0);
+    assert((*std::move(opt)).constCopy == 0);
+    assert((*std::move(opt)).nonConstCopy == 0);
+  }
+
+  return true;
+}
+#endif
+
 int main(int, char**)
 {
     {
@@ -48,5 +82,10 @@ int main(int, char**)
         assert((*std::move(opt)).test() == 2);
     }
 
+#if TEST_STD_VER >= 26
+    assert(test_ref());
+    static_assert(test_ref());
+#endif
+
     return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
index 16bf2e4336c69..0206eb668d155 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
@@ -11,10 +11,10 @@
 
 // constexpr T&& optional<T>::operator*() &&;
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <optional>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -39,6 +39,40 @@ test()
     return (*std::move(opt)).test();
 }
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  // ensure underlying value isn't moved from
+  {
+    TracedCopyMove x{};
+    std::optional<TracedCopyMove&> opt(x);
+    ASSERT_NOEXCEPT(*std::move(opt));
+    ASSERT_SAME_TYPE(decltype(*std::move(opt)), TracedCopyMove&);
+
+    assert(std::addressof(*std::move(opt)) == std::addressof(x));
+    assert((*std::move(opt)).constMove == 0);
+    assert((*std::move(opt)).nonConstMove == 0);
+    assert((*std::move(opt)).constCopy == 0);
+    assert((*std::move(opt)).nonConstCopy == 0);
+  }
+
+  {
+    TracedCopyMove x{};
+    std::optional<const TracedCopyMove&> opt(x);
+    ASSERT_NOEXCEPT(*std::move(opt));
+    ASSERT_SAME_TYPE(decltype(*std::move(opt)), const TracedCopyMove&);
+
+    assert(std::addressof(*std::move(opt)) == std::addressof(x));
+    assert((*std::move(opt)).constMove == 0);
+    assert((*std::move(opt)).nonConstMove == 0);
+    assert((*std::move(opt)).constCopy == 0);
+    assert((*std::move(opt)).nonConstCopy == 0);
+  }
+
+  return true;
+}
+
+#endif
+
 int main(int, char**)
 {
     {
@@ -52,5 +86,10 @@ int main(int, char**)
     }
     static_assert(test() == 7, "");
 
+#if TEST_STD_VER >= 26
+    assert(test_ref());
+    static_assert(test_ref());
+#endif
+
     return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp
index 9873a767cfbe6..d8c424fc41c74 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp
@@ -11,9 +11,8 @@
 
 // constexpr bool optional<T>::has_value() const noexcept;
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <optional>
 
 #include "test_macros.h"
 
@@ -37,8 +36,13 @@ int main(int, char**)
     {
       static constexpr int i = 0;
       constexpr optional<const int&> opt{i};
+      ASSERT_NOEXCEPT(opt.has_value());
       static_assert(opt.has_value());
     }
+    {
+      constexpr optional<const int&> opt{};
+      static_assert(!opt.has_value());
+    }
 #endif
 
     return 0;
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp
index 96d22743ac7fe..bb050f20debe1 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp
@@ -11,9 +11,9 @@
 
 // constexpr T* optional<T>::operator->();
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <memory>
+#include <optional>
 
 #include "test_macros.h"
 
@@ -53,17 +53,20 @@ int main(int, char**)
       std::optional<X&> opt(x);
       ASSERT_SAME_TYPE(decltype(opt.operator->()), X*);
       ASSERT_NOEXCEPT(opt.operator->());
+      assert(opt.operator->() == std::addressof(x));
     }
     {
       X x{};
       std::optional<const X&> opt(x);
       ASSERT_SAME_TYPE(decltype(opt.operator->()), const X*);
       ASSERT_NOEXCEPT(opt.operator->());
+      assert(opt.operator->() == std::addressof(x));
     }
     {
       X x{};
       optional<X&> opt{x};
       assert(opt->test() == 3);
+      assert(opt.operator->() == std::addressof(x));
     }
     {
       X x{};
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp
index e9694fd6d9640..0461a04b85d45 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp
@@ -11,9 +11,9 @@
 
 // constexpr const T* optional<T>::operator->() const;
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <memory>
+#include <optional>
 
 #include "test_macros.h"
 
@@ -60,17 +60,20 @@ int main(int, char**)
       const std::optional<X&> opt(x);
       ASSERT_SAME_TYPE(decltype(opt.operator->()), X*);
       ASSERT_NOEXCEPT(opt.operator->());
+      assert(opt.operator->() == std::addressof(x));
     }
     {
       X x{};
       const std::optional<const X&> opt(x);
       ASSERT_SAME_TYPE(decltype(opt.operator->()), const X*);
       ASSERT_NOEXCEPT(opt.operator->());
+      assert(opt.operator->() == std::addressof(x));
     }
     {
       static constexpr Z z{};
       constexpr optional<const Z&> opt(z);
       static_assert(opt->test() == 1);
+      static_assert(opt.operator->() == std::addressof(z));
     }
 #endif
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
index ea62f76d4082a..3bd1342bf935d 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
@@ -12,10 +12,11 @@
 
 // constexpr const T& optional<T>::value() const &;
 
-#include <optional>
-#include <type_traits>
 #include <cassert>
+#include <memory>
+#include <optional>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -33,6 +34,38 @@ struct X
     int test() && {return 6;}
 };
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  {
+    TracedCopyMove x{};
+    const std::optional<TracedCopyMove&> opt(x);
+    ASSERT_NOT_NOEXCEPT(opt.value());
+    ASSERT_SAME_TYPE(decltype(opt.value()), TracedCopyMove&);
+
+    assert(std::addressof(opt.value()) == std::addressof(x));
+    assert(opt->constMove == 0);
+    assert(opt->nonConstMove == 0);
+    assert(opt->constCopy == 0);
+    assert(opt->nonConstCopy == 0);
+  }
+
+  {
+    TracedCopyMove x{};
+    const std::optional<const TracedCopyMove&> opt(x);
+    ASSERT_NOT_NOEXCEPT(opt.value());
+    ASSERT_SAME_TYPE(decltype(opt.value()), const TracedCopyMove&);
+
+    assert(std::addressof(opt.value()) == std::addressof(x));
+    assert(opt->constMove == 0);
+    assert(opt->nonConstMove == 0);
+    assert(opt->constCopy == 0);
+    assert(opt->nonConstCopy == 0);
+  }
+
+  return true;
+}
+#endif
+
 int main(int, char**)
 {
     {
@@ -62,5 +95,10 @@ int main(int, char**)
     }
 #endif
 
-  return 0;
+#if TEST_STD_VER >= 26
+    assert(test_ref());
+    static_assert(test_ref());
+#endif
+
+    return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
index 49dbe4e58b57d..3893995ac198b 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
@@ -12,10 +12,11 @@
 
 // constexpr const T& optional<T>::value() const &&;
 
+#include <cassert>
 #include <optional>
 #include <type_traits>
-#include <cassert>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -33,6 +34,40 @@ struct X
     int test() && {return 6;}
 };
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  {
+    TracedCopyMove x{};
+    const std::optional<TracedCopyMove&> opt(x);
+    ASSERT_NOT_NOEXCEPT(std::move(opt).value());
+    ASSERT_SAME_TYPE(decltype(std::move(opt).value()), TracedCopyMove&);
+
+    assert(std::addressof(std::move(opt).value()) == std::addressof(x));
+    auto& val = std::move(opt).value();
+    assert(val.constMove == 0);
+    assert(val.nonConstMove == 0);
+    assert(val.constCopy == 0);
+    assert(val.nonConstCopy == 0);
+  }
+
+  {
+    TracedCopyMove x{};
+    const std::optional<const TracedCopyMove&> opt(x);
+    ASSERT_NOT_NOEXCEPT(std::move(opt).value());
+    ASSERT_SAME_TYPE(decltype(std::move(opt).value()), const TracedCopyMove&);
+
+    assert(std::addressof(std::move(opt).value()) == std::addressof(x));
+    auto& val = std::move(opt).value();
+    assert(val.constMove == 0);
+    assert(val.nonConstMove == 0);
+    assert(val.constCopy == 0);
+    assert(val.nonConstCopy == 0);
+  }
+
+  return true;
+}
+#endif
+
 int main(int, char**)
 {
     {
@@ -61,6 +96,9 @@ int main(int, char**)
         }
     }
 #endif
-
-  return 0;
+#if TEST_STD_VER >= 26
+    assert(test_ref());
+    static_assert(test_ref());
+#endif
+    return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp
index 66890ff9c9b91..f4ad896ed9816 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp
@@ -84,6 +84,7 @@ constexpr int test()
     {
       int y = 2;
       optional<int&> opt;
+      ASSERT_SAME_TYPE(decltype(std::move(opt).value_or(y)), int);
       assert(std::move(opt).value_or(y) == 2);
       assert(!opt);
     }
@@ -93,7 +94,8 @@ constexpr int test()
 
 int main(int, char**)
 {
-    static_assert(test() == 0);
+  assert(test() == 0);
+  static_assert(test() == 0);
 
   return 0;
 }

>From 4128dccd4660db0e1a38077a4cc7cfea390fbc4f Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 01:47:13 -0500
Subject: [PATCH 03/26] Modify copy_move_types.h to not fail if included in
 tests <C++23

---
 libcxx/test/support/copy_move_types.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libcxx/test/support/copy_move_types.h b/libcxx/test/support/copy_move_types.h
index dec8d94cac379..aa62eea97b4a3 100644
--- a/libcxx/test/support/copy_move_types.h
+++ b/libcxx/test/support/copy_move_types.h
@@ -12,9 +12,10 @@
 #include "test_allocator.h"
 #include <type_traits>
 #include <tuple>
+#include "test_macros.h"
 
 // Types that can be used to test copy/move operations
-
+#if TEST_STD_VER >= 23
 struct MutableCopy {
   int val;
   bool alloc_constructed{false};
@@ -342,4 +343,6 @@ struct TracedAssignment {
     return *this;
   }
 };
+
+#endif // TEST_STD_VER >= 23
 #endif

>From da9ec1d4709085ef2a81603f35414d4cbc55ac12 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 02:11:33 -0500
Subject: [PATCH 04/26] Formatting + missing _LIBCPP_HIDE_FROM_ABI

---
 libcxx/include/optional                                |  8 ++++----
 .../optional.object.observe/dereference_const.pass.cpp | 10 +++++-----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 487cfa1e7ce6e..6e209207307df 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -975,7 +975,7 @@ public:
   template <class _Up>
     requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
             (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
-  constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
       optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) {
     this->__construct_from(__rhs);
   }
@@ -1185,7 +1185,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() &&
 #    if _LIBCPP_STD_VER >= 26
-      requires(!is_lvalue_reference_v<_Tp>)
+    requires(!is_lvalue_reference_v<_Tp>)
 #    endif
   {
     if (!this->has_value())
@@ -1193,9 +1193,9 @@ public:
     return std::move(this->__get());
   }
 
-      [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&&
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&&
 #    if _LIBCPP_STD_VER >= 26
-        requires(!is_lvalue_reference_v<_Tp>)
+    requires(!is_lvalue_reference_v<_Tp>)
 #    endif
   {
     if (!this->has_value())
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
index ff69126030c6d..8108af78e5109 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
@@ -78,15 +78,15 @@ int main(int, char**) {
     constexpr optional<X> opt(X{});
     static_assert((*opt).test() == 3, "");
   }
-    {
-        constexpr optional<Y> opt(Y{});
-        assert((*opt).test() == 2);
-    }
+  {
+    constexpr optional<Y> opt(Y{});
+    assert((*opt).test() == 2);
+  }
 
 #if TEST_STD_VER >= 26
     assert(test_ref());
     static_assert(test_ref());
 #endif
 
-    return 0;
+  return 0;
 }

>From ea55289fe6e0ceda39e40135b6c382253a404180 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 02:19:31 -0500
Subject: [PATCH 05/26] More formatting

---
 .../optional.object.observe/dereference_const.pass.cpp        | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
index 8108af78e5109..e0a83b5744451 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
@@ -84,8 +84,8 @@ int main(int, char**) {
   }
 
 #if TEST_STD_VER >= 26
-    assert(test_ref());
-    static_assert(test_ref());
+  assert(test_ref());
+  static_assert(test_ref());
 #endif
 
   return 0;

>From 9f50ee9546c50a554b3ffb47a9dffcb550abad1c Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 15:31:54 -0500
Subject: [PATCH 06/26] Fix transform(), remove using in value_or

---
 libcxx/include/optional | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 6e209207307df..26bb8b00d5adc 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -1396,10 +1396,9 @@ public:
     requires(is_lvalue_reference_v<_Tp> && is_object_v<__libcpp_remove_reference_t<_Tp>> &&
              !is_array_v<__libcpp_remove_reference_t<_Tp>>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decay_t<_Tp> value_or(_Up&& __v) const {
-    using _X = remove_cvref_t<_Tp>;
-    static_assert(is_constructible_v<_X, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
-    static_assert(is_convertible_v<_Up, _X>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
-    return this->has_value() ? this->__get() : static_cast<_X>(std::forward<_Up>(__v));
+    static_assert(is_constructible_v<remove_cvref_t<_Tp>, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
+    static_assert(is_convertible_v<_Up, remove_cvref_t<_Tp>>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
+    return this->has_value() ? this->__get() : static_cast<remove_cvref_t<_Tp>>(std::forward<_Up>(__v));
   }
 
   template <class _Func>
@@ -1417,7 +1416,7 @@ public:
     requires(is_lvalue_reference_v<_Tp>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional<remove_cv_t<invoke_result_t<_Func, _Tp&>>>
   transform(_Func&& __f) const {
-    using _Up = remove_cvref_t<_Tp>;
+    using _Up = remove_cvref_t<invoke_result_t<_Func, _Tp&>>;
     static_assert(!is_array_v<_Up>, "Result of f(value()) should not be an Array");
     static_assert(!is_same_v<_Up, in_place_t>, "Result of f(value()) should not be std::in_place_t");
     static_assert(!is_same_v<_Up, nullopt_t>, "Result of f(value()) should not be std::nullopt_t");

>From 1a065f7920c4e978f3a1c0270c806879a5b77836 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 15:32:17 -0500
Subject: [PATCH 07/26] Add transform, swap tests

---
 .../optional.monadic/transform.pass.cpp       | 10 +++++
 .../optional.object.swap/swap.pass.cpp        | 45 +++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
index 57bdbaadca5de..964991fe6ae95 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
@@ -220,6 +220,16 @@ constexpr bool test_ref() {
 
     assert(*o2 == 44);
   }
+
+  {
+    int i = 42;
+    float k = 4.0f;
+    std::optional<int&> opt{i};
+    std::same_as<std::optional<float>> decltype(auto) o2 =
+        opt.transform([&](int&) { return k; });
+    assert(*o2 == 4.0f);
+  }
+
   // &
   {
     // Without & qualifier on F's operator()
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp
index a82ca615e0c8c..afc1617affe3a 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp
@@ -397,6 +397,51 @@ int main(int, char**)
         assert(static_cast<bool>(opt2) == true);
         assert(*opt2 == 2);
     }
+
+#  if TEST_STD_VER >= 26
+    {
+      Z z{1};
+      optional<Z&> opt1{z};
+      optional<Z&> opt2;
+      ASSERT_NOEXCEPT(opt1.swap(opt2));
+      assert(opt1);
+      assert(*opt1 == 1);
+      assert(&(*opt1) == &z);
+      assert(!opt2);
+
+      opt1.swap(opt2);
+      assert(*opt2 == 1);
+      assert(&(*opt2) == &z);
+      assert(opt2 && !opt1);
+    }
+
+    {
+      Z z1{1};
+      optional<Z&> opt1;
+      optional<Z&> opt2{z1};
+      ASSERT_NOEXCEPT(opt1.swap(opt2));
+
+      opt1.swap(opt2);
+      assert(opt1 && !opt2);
+      assert(*opt1 == 1);
+      assert(&(*opt1) == &z1);
+    }
+
+    {
+      Z z1{1};
+      Z z2{2};
+      optional<Z&> opt1{z1};
+      optional<Z&> opt2{z2};
+      ASSERT_NOEXCEPT(opt1.swap(opt2));
+
+      opt1.swap(opt2);
+      assert(opt1 && opt2);
+      assert(*opt1 == 2);
+      assert(*opt2 == 1);
+      assert(&(*opt1) == &z2);
+      assert(&(*opt2) == &z1);
+    }
+#  endif
 #endif
 
   return 0;

>From a8bc6165b17b6345aa9554032c43cce42ea94151 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 15:35:40 -0500
Subject: [PATCH 08/26] Formatting

---
 libcxx/include/optional                                     | 6 ++++--
 .../utilities/optional/optional.monadic/transform.pass.cpp  | 5 ++---
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 26bb8b00d5adc..1d34cb7478b9a 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -1396,8 +1396,10 @@ public:
     requires(is_lvalue_reference_v<_Tp> && is_object_v<__libcpp_remove_reference_t<_Tp>> &&
              !is_array_v<__libcpp_remove_reference_t<_Tp>>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decay_t<_Tp> value_or(_Up&& __v) const {
-    static_assert(is_constructible_v<remove_cvref_t<_Tp>, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
-    static_assert(is_convertible_v<_Up, remove_cvref_t<_Tp>>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
+    static_assert(
+        is_constructible_v<remove_cvref_t<_Tp>, _Tp&>, "optional<T&>::value_or: remove_cv_t<T> must be constructible");
+    static_assert(
+        is_convertible_v<_Up, remove_cvref_t<_Tp>>, "optional<T&>::value_or: U must be convertible to remove_cv_t<T>");
     return this->has_value() ? this->__get() : static_cast<remove_cvref_t<_Tp>>(std::forward<_Up>(__v));
   }
 
diff --git a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
index 964991fe6ae95..b8536b790f749 100644
--- a/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.monadic/transform.pass.cpp
@@ -222,11 +222,10 @@ constexpr bool test_ref() {
   }
 
   {
-    int i = 42;
+    int i   = 42;
     float k = 4.0f;
     std::optional<int&> opt{i};
-    std::same_as<std::optional<float>> decltype(auto) o2 =
-        opt.transform([&](int&) { return k; });
+    std::same_as<std::optional<float>> decltype(auto) o2 = opt.transform([&](int&) { return k; });
     assert(*o2 == 4.0f);
   }
 

>From b165f0e1f3739a000d07e50bb0379494e24c49a8 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 15:50:16 -0500
Subject: [PATCH 09/26] Add tests for optional<U&>&& -> optional<U> to check
 for stealing move

---
 .../optional.object.assign/optional_U.pass.cpp           | 9 +++++++++
 .../optional.object.ctor/optional_U.pass.cpp             | 8 ++++++++
 2 files changed, 17 insertions(+)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
index cc1b17157f2b4..2c105e3269671 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
@@ -293,7 +293,16 @@ TEST_CONSTEXPR_CXX20 bool test()
       assert(state[0] == state_t::inactive);
       assert(state[1] == state_t::copy_assigned);
     }
+#if TEST_STD_VER >= 26
+    {
+      state_t state{state_t::constructed};
+      StateTracker t{state};
+      std::optional<StateTracker&> o1{t};
+      std::optional<StateTracker> o2 = std::move(o1);
+      assert(state != state_t::move_assigned);
+    }
 
+#endif
     return true;
 }
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
index 743f0661f380f..741fd0c8b2967 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -20,6 +20,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -111,6 +112,13 @@ constexpr bool test_ref() {
     ASSERT_NOEXCEPT(std::optional<int&>(o2));
     assert(!o2.has_value());
   }
+  {
+    TracedCopyMove t{};
+    std::optional<TracedCopyMove&> o1{t};
+    std::optional<TracedCopyMove> o2{std::move(o1)};
+    assert(t.constMove == 0);
+    assert(t.nonConstMove == 0);
+  }
 
   return true;
 }

>From 4945ebeccdacdf362d9bcc4a35ecb6e6f59ab58a Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 16:31:45 -0500
Subject: [PATCH 10/26] Fix GCC warning

---
 .../optional.object/optional.object.assign/optional_U.pass.cpp | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
index 2c105e3269671..2a70a23c8cb20 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
@@ -299,7 +299,9 @@ TEST_CONSTEXPR_CXX20 bool test()
       StateTracker t{state};
       std::optional<StateTracker&> o1{t};
       std::optional<StateTracker> o2 = std::move(o1);
+      (void) *o2;
       assert(state != state_t::move_assigned);
+      assert(state == state_t::constructed);
     }
 
 #endif
@@ -310,6 +312,7 @@ TEST_CONSTEXPR_CXX20 bool test()
 int main(int, char**)
 {
 #if TEST_STD_VER > 17
+    assert(test());
     static_assert(test());
 #endif
     test_with_test_type();

>From 425cbc48e1280bc50378d7c262caa534297569c7 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 16:35:08 -0500
Subject: [PATCH 11/26] Formatting

---
 .../optional.object.assign/optional_U.pass.cpp              | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
index 2a70a23c8cb20..d23858e9974d5 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
@@ -299,7 +299,7 @@ TEST_CONSTEXPR_CXX20 bool test()
       StateTracker t{state};
       std::optional<StateTracker&> o1{t};
       std::optional<StateTracker> o2 = std::move(o1);
-      (void) *o2;
+      (void)*o2;
       assert(state != state_t::move_assigned);
       assert(state == state_t::constructed);
     }
@@ -312,8 +312,8 @@ TEST_CONSTEXPR_CXX20 bool test()
 int main(int, char**)
 {
 #if TEST_STD_VER > 17
-    assert(test());
-    static_assert(test());
+  assert(test());
+  static_assert(test());
 #endif
     test_with_test_type();
     test_ambiguous_assign();

>From e900f6f495fa6408b61809784e412d93637ce2ac Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 19:31:12 -0500
Subject: [PATCH 12/26] Some more tests

---
 .../const_optional_U.pass.cpp                 | 33 +++++++++++
 .../optional.object.assign/copy.pass.cpp      | 56 +++++++++++++++++++
 .../optional.object.assign/move.pass.cpp      | 18 ++++++
 3 files changed, 107 insertions(+)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
index 4751f8e60994e..e754b3090fb3a 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
@@ -195,6 +195,34 @@ void test_ambiguous_assign() {
     }
 }
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  {
+    int t{2};
+    const std::optional<int&> o1{t};
+    std::optional<int&> o2 = o1;
+
+    assert(&(*o2) == &t);
+    assert(o1.has_value());
+    assert(o2.has_value());
+    assert(*o2 == 2);
+  }
+
+  {
+    int t{2};
+
+    const std::optional<int&> o1{t};
+    std::optional<int> o2 = o1;
+
+    assert(&(*o2) != &t);
+    assert(o1.has_value());
+    assert(o2.has_value());
+    assert(*o2 == 2);
+  }
+
+  return true;
+}
+#endif
 
 int main(int, char**)
 {
@@ -251,5 +279,10 @@ int main(int, char**)
     }
 #endif
 
+#if TEST_STD_VER >= 26
+    assert(test_ref());
+    static_assert(test_ref());
+#endif
+
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
index 9753fdb46b862..1206f85e1fbf8 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
@@ -15,6 +15,7 @@
 #include <type_traits>
 #include <cassert>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 #include "archetypes.h"
 
@@ -49,6 +50,56 @@ constexpr bool assign_value(optional<Tp>&& lhs) {
     return lhs.has_value() && rhs.has_value() && *lhs == *rhs;
 }
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  struct TraceCopyAssign {
+    int copyAssign              = 0;
+    mutable int constCopyAssign = 0;
+
+    constexpr TraceCopyAssign() = default;
+    constexpr TraceCopyAssign(TraceCopyAssign& r)
+        : copyAssign(r.copyAssign + 1), constCopyAssign(r.constCopyAssign) {}
+    constexpr TraceCopyAssign(const TraceCopyAssign& r)
+        : copyAssign(r.copyAssign), constCopyAssign(r.constCopyAssign + 1) {}
+    constexpr TraceCopyAssign& operator=(const TraceCopyAssign&) {
+      copyAssign++;
+      return *this;
+    }
+    constexpr const TraceCopyAssign& operator=(const TraceCopyAssign&) const {
+      constCopyAssign++;
+      return *this;
+    }
+  };
+  using T = TraceCopyAssign;
+  {
+    T t{};
+    std::optional<T&> o1{t};
+    std::optional<T&> o2 = o1;
+
+    assert(&(*o2) == &t);
+    assert(&(*o2) == &(*o1));
+    assert(t.constCopyAssign == 0);
+    assert(t.copyAssign == 0);
+    assert(o1.has_value());
+    assert(o2.has_value());
+  }
+  {
+    T t{};
+    std::optional<T&> o1{t};
+    std::optional<T> o2 = o1;
+
+    assert(&(*o2) != &t);
+    assert(&(*o2) != &(*o1));
+    assert(o2->constCopyAssign == 0);
+    assert(o2->copyAssign == 1);
+    assert(o1.has_value());
+    assert(o2.has_value());
+  }
+
+  return true;
+}
+#endif
+
 int main(int, char**)
 {
     {
@@ -100,5 +151,10 @@ int main(int, char**)
     }
 #endif
 
+#if TEST_STD_VER >= 26
+  assert(test_ref());
+  static_assert(test_ref());
+#endif
+
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
index 85971e38f7b70..be8098adea01d 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
@@ -18,6 +18,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "copy_move_types.h"
 #include "test_macros.h"
 #include "archetypes.h"
 
@@ -66,6 +67,23 @@ constexpr bool assign_value(optional<Tp>&& lhs) {
     return lhs.has_value() && rhs.has_value() && *lhs == Tp{101};
 }
 
+#if TEST_STD_VER >= 26
+constexpr bool test_ref() {
+  using T = TracedAssignment;
+  {
+    T t{};
+    std::optional<T&> o1{t};
+    std::optional<T&> o2 = std::move(o1);
+
+    assert(&(*o2) == &t);
+    assert(o1.has_value());
+    assert(o2.has_value());
+    assert(t.moveAssign == 0);
+  }
+  return true;
+}
+#endif
+
 int main(int, char**)
 {
     {

>From 85e0b1062c667bba4b521bfcd222d8d83817a979 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 19:31:35 -0500
Subject: [PATCH 13/26] Remove ref-qualifier

---
 libcxx/include/optional | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 1d34cb7478b9a..64a5aae1d570e 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -508,7 +508,7 @@ struct __optional_storage_base<_Tp, true> {
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_value() const noexcept { return __value_ != nullptr; }
 
-  _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const& noexcept { return *__value_; }
+  _LIBCPP_HIDE_FROM_ABI constexpr value_type& __get() const noexcept { return *__value_; }
 
   template <class _UArg>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __construct(_UArg&& __val) {

>From d77b160f2f2e453830c1403f737a910407d6dea0 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 19:32:34 -0500
Subject: [PATCH 14/26] Format

---
 .../optional.object/optional.object.assign/copy.pass.cpp       | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
index 1206f85e1fbf8..ee6fa6bcb1cc0 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
@@ -57,8 +57,7 @@ constexpr bool test_ref() {
     mutable int constCopyAssign = 0;
 
     constexpr TraceCopyAssign() = default;
-    constexpr TraceCopyAssign(TraceCopyAssign& r)
-        : copyAssign(r.copyAssign + 1), constCopyAssign(r.constCopyAssign) {}
+    constexpr TraceCopyAssign(TraceCopyAssign& r) : copyAssign(r.copyAssign + 1), constCopyAssign(r.constCopyAssign) {}
     constexpr TraceCopyAssign(const TraceCopyAssign& r)
         : copyAssign(r.copyAssign), constCopyAssign(r.constCopyAssign + 1) {}
     constexpr TraceCopyAssign& operator=(const TraceCopyAssign&) {

>From fde551d1b6bc37a0d693690c431b38543e8b0ad3 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 19:52:32 -0500
Subject: [PATCH 15/26] Correct some constructor conditions

---
 libcxx/include/optional | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 64a5aae1d570e..60d8bb851ce43 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -973,7 +973,7 @@ public:
 
   // optional(optional<U>& rhs)
   template <class _Up>
-    requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+    requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
             (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
   _LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_Up&, _Tp&>)
       optional(optional<_Up>& __rhs) noexcept(is_nothrow_constructible_v<_Tp&, _Up&>) {
@@ -981,7 +981,7 @@ public:
   }
 
   template <class _Up>
-    requires __libcpp_opt_ref_ctor_deleted<_Up> && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+    requires __libcpp_opt_ref_ctor_deleted<_Up> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
                  (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up&>
   constexpr explicit optional(optional<_Up>& __rhs) noexcept = delete;
 
@@ -1005,7 +1005,7 @@ public:
 
   // optional(const optional<U>&&)
   template <class _Up>
-    requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+    requires(!__libcpp_opt_ref_ctor_deleted<_Up>) && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
             (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit(!is_convertible_v<const _Up, _Tp&>)
       optional(const optional<_Up>&& __v) noexcept(is_nothrow_constructible_v<_Tp&, const _Up>) {
@@ -1013,7 +1013,7 @@ public:
   }
 
   template <class _Up>
-    requires __libcpp_opt_ref_ctor_deleted<_Up> && (!__is_std_optional<remove_cvref_t<_Tp>>::value) &&
+    requires __libcpp_opt_ref_ctor_deleted<_Up> && (!is_same_v<remove_cvref_t<_Tp>, optional<_Up>>) &&
                  (!is_same_v<_Tp&, _Up>) && is_constructible_v<_Tp&, _Up>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional(const optional<_Up>&& __v) noexcept = delete;
 #    endif

>From a8777b46a3134256948b5ff1473a58f09dd47e0f Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Tue, 6 Jan 2026 19:52:38 -0500
Subject: [PATCH 16/26] Formatting

---
 .../optional.object.assign/const_optional_U.pass.cpp        | 2 +-
 .../optional.object/optional.object.assign/copy.pass.cpp    | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
index e754b3090fb3a..6b6dcbf428380 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
@@ -284,5 +284,5 @@ int main(int, char**)
     static_assert(test_ref());
 #endif
 
-  return 0;
+    return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
index ee6fa6bcb1cc0..04c00873a0359 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
@@ -151,9 +151,9 @@ int main(int, char**)
 #endif
 
 #if TEST_STD_VER >= 26
-  assert(test_ref());
-  static_assert(test_ref());
+    assert(test_ref());
+    static_assert(test_ref());
 #endif
 
-  return 0;
+    return 0;
 }

>From fb88bb6b074351da4f45bdf58808a00e3562a552 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 7 Jan 2026 21:30:55 -0500
Subject: [PATCH 17/26] Address test comments

---
 ...ce.compile.fail.cpp => emplace.verify.cpp} | 12 +++---
 .../ref_constructs_from_temporary.verify.cpp  |  2 +-
 .../dereference_const.pass.cpp                | 41 +++++++++----------
 3 files changed, 27 insertions(+), 28 deletions(-)
 rename libcxx/test/std/utilities/optional/optional.object/optional.object.assign/{emplace.compile.fail.cpp => emplace.verify.cpp} (55%)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.compile.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.verify.cpp
similarity index 55%
rename from libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.compile.fail.cpp
rename to libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.verify.cpp
index bcd06517b9885..a0bfa078f189c 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.compile.fail.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.verify.cpp
@@ -9,8 +9,8 @@
 // REQUIRES: std-at-least-c++26
 // <optional>
 
-// template <class... Args> T& optional<T&>::emplace(Arg& arg);
-// Ensure that emplace isn't found if reference_constructs_From_temporary_v == true
+// template <class U> T& optional<T&>::emplace(U&& arg);
+// Ensure that emplace isn't found if reference_constructs_From_temporary_v == true or is_constructible_v<_Tp&, U> == false
 #include <optional>
 #include <type_traits>
 
@@ -18,9 +18,9 @@ struct X {};
 void test() {
   int i = 1;
   std::optional<X&> f{};
-  static_assert(!std::is_constructible_v<X&, int>);
-  f.emplace(i); // is_constructible<_Tp&, U> == false
+  static_assert(!std::is_constructible_v<X&, int>); // is_constructible_v<_Tp&, U> == false
+  f.emplace(i); // expected-error {{no matching member function for call to 'emplace'}}
 
-  std::optional<const int&> t{};
-  t.emplace(1); // reference_constructs_from_temporary_v == false
+  std::optional<const int&> t{}; // reference_constructs_from_temporary_v == false
+  t.emplace(1);                  // expected-error {{no matching member function for call to 'emplace'}}
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp
index b59aa8051b39e..53ac77a2e5620 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/ref_constructs_from_temporary.verify.cpp
@@ -25,7 +25,7 @@ struct X {
   X(int j) : i(j) {}
 };
 
-int main(int, char**) {
+void test() {
   const std::optional<int> co(1);
   std::optional<int> o0(1);
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
index e0a83b5744451..9d8245643cdba 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
@@ -64,29 +64,28 @@ constexpr bool test_ref() {
 
   return true;
 }
-
 #endif
 
-int main(int, char**) {
-  {
-    const optional<X> opt;
-    ((void)opt);
-    ASSERT_SAME_TYPE(decltype(*opt), X const&);
-    ASSERT_NOEXCEPT(*opt);
-  }
-  {
-    constexpr optional<X> opt(X{});
-    static_assert((*opt).test() == 3, "");
-  }
-  {
-    constexpr optional<Y> opt(Y{});
-    assert((*opt).test() == 2);
-  }
-
+int main(int, char**)
+{
+    {
+        const optional<X> opt; ((void)opt);
+        ASSERT_SAME_TYPE(decltype(*opt), X const&);
+        ASSERT_NOEXCEPT(*opt);
+    }
+    {
+        constexpr optional<X> opt(X{});
+        static_assert((*opt).test() == 3, "");
+    }
+    {
+        constexpr optional<Y> opt(Y{});
+        assert((*opt).test() == 2);
+    }
 #if TEST_STD_VER >= 26
-  assert(test_ref());
-  static_assert(test_ref());
+    {
+      assert(test_ref());
+      static_assert(test_ref());
+    }
 #endif
-
-  return 0;
+    return 0;
 }

>From 40acb3c19f64b3cb89939f2881aace2dd6b48269 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Wed, 7 Jan 2026 21:31:51 -0500
Subject: [PATCH 18/26] Replace every !is_lvalue_reference_v with is_object_v

---
 libcxx/include/optional | 46 ++++++++++++++++++++---------------------
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 60d8bb851ce43..0fc2bfa4e5ab3 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -704,7 +704,7 @@ struct __optional_iterator {};
 #    if _LIBCPP_STD_VER >= 26
 
 template <class _Tp>
-struct __optional_iterator<_Tp, enable_if_t<!is_lvalue_reference_v<_Tp>>> {
+struct __optional_iterator<_Tp, enable_if_t<is_object_v<_Tp>>> {
 private:
   using __pointer _LIBCPP_NODEBUG       = add_pointer_t<_Tp>;
   using __const_pointer _LIBCPP_NODEBUG = add_pointer_t<const _Tp>;
@@ -1106,7 +1106,7 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp const> operator->() const noexcept
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
@@ -1115,7 +1115,7 @@ public:
 
   _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp> operator->() noexcept
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator-> called on a disengaged value");
@@ -1124,7 +1124,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator*() const& noexcept
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
@@ -1133,7 +1133,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() & noexcept
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
@@ -1142,7 +1142,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& operator*() && noexcept
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
@@ -1151,7 +1151,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& operator*() const&& noexcept
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(this->has_value(), "optional operator* called on a disengaged value");
@@ -1165,7 +1165,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& value() const&
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     if (!this->has_value())
@@ -1175,7 +1175,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp& value() &
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     if (!this->has_value())
@@ -1185,7 +1185,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp&& value() &&
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     if (!this->has_value())
@@ -1195,7 +1195,7 @@ public:
 
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp const&& value() const&&
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   {
     if (!this->has_value())
@@ -1205,7 +1205,7 @@ public:
 
   template <class _Up = remove_cv_t<_Tp>>
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) const& {
     static_assert(is_copy_constructible_v<_Tp>, "optional<T>::value_or: T must be copy constructible");
@@ -1215,7 +1215,7 @@ public:
 
   template <class _Up = remove_cv_t<_Tp>>
 #    if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #    endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp value_or(_Up&& __v) && {
     static_assert(is_move_constructible_v<_Tp>, "optional<T>::value_or: T must be move constructible");
@@ -1226,7 +1226,7 @@ public:
 #    if _LIBCPP_STD_VER >= 23
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) & {
     using _Up = invoke_result_t<_Func, _Tp&>;
@@ -1239,7 +1239,7 @@ public:
 
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const& {
     using _Up = invoke_result_t<_Func, const _Tp&>;
@@ -1252,7 +1252,7 @@ public:
 
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) && {
     using _Up = invoke_result_t<_Func, _Tp&&>;
@@ -1265,7 +1265,7 @@ public:
 
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto and_then(_Func&& __f) const&& {
     using _Up = invoke_result_t<_Func, const _Tp&&>;
@@ -1278,7 +1278,7 @@ public:
 
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) & {
     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&>>;
@@ -1293,7 +1293,7 @@ public:
 
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const& {
     using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&>>;
@@ -1308,7 +1308,7 @@ public:
 
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) && {
     using _Up = remove_cv_t<invoke_result_t<_Func, _Tp&&>>;
@@ -1323,7 +1323,7 @@ public:
 
   template <class _Func>
 #      if _LIBCPP_STD_VER >= 26
-    requires(!is_lvalue_reference_v<_Tp>)
+    requires(is_object_v<_Tp>)
 #      endif
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto transform(_Func&& __f) const&& {
     using _Up = remove_cv_t<invoke_result_t<_Func, const _Tp&&>>;
@@ -1340,7 +1340,7 @@ public:
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) const&
     requires is_copy_constructible_v<_Tp>
 #      if _LIBCPP_STD_VER >= 26
-             && (!is_lvalue_reference_v<_Tp>)
+             && (is_object_v<_Tp>)
 #      endif
   {
     static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,
@@ -1354,7 +1354,7 @@ public:
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr optional or_else(_Func&& __f) &&
     requires is_move_constructible_v<_Tp>
 #      if _LIBCPP_STD_VER >= 26
-             && (!is_lvalue_reference_v<_Tp>)
+             && (is_object_v<_Tp>)
 #      endif
   {
     static_assert(is_same_v<remove_cvref_t<invoke_result_t<_Func>>, optional>,

>From a22c00b52eccd83325893f40801b2b77165e8fe4 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 00:17:02 -0500
Subject: [PATCH 19/26] Revert change to copy_move_types.h, just guard the
 include

---
 .../optional.object.assign/assign_value.pass.cpp              | 4 +++-
 .../optional.object/optional.object.assign/copy.pass.cpp      | 1 -
 .../optional.object/optional.object.assign/move.pass.cpp      | 4 +++-
 .../optional.object/optional.object.ctor/optional_U.pass.cpp  | 4 +++-
 .../optional.object.observe/dereference.pass.cpp              | 4 +++-
 .../optional.object.observe/dereference_const.pass.cpp        | 4 +++-
 .../optional.object.observe/dereference_const_rvalue.pass.cpp | 4 +++-
 .../optional.object.observe/dereference_rvalue.pass.cpp       | 4 +++-
 .../optional.object.observe/value_const.pass.cpp              | 4 +++-
 .../optional.object.observe/value_const_rvalue.pass.cpp       | 4 +++-
 libcxx/test/support/copy_move_types.h                         | 3 ---
 11 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
index 1923c0ed07d33..d0f9e70bae869 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
@@ -16,9 +16,11 @@
 #include <cassert>
 #include <memory>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
 #include "archetypes.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
index 04c00873a0359..b4702baa49e1c 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
@@ -15,7 +15,6 @@
 #include <type_traits>
 #include <cassert>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
 #include "archetypes.h"
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
index be8098adea01d..c447557cfa9d4 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
@@ -18,9 +18,11 @@
 #include <type_traits>
 #include <utility>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
 #include "archetypes.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
index 741fd0c8b2967..7d26f82baac0a 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -20,8 +20,10 @@
 #include <type_traits>
 #include <utility>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
index 6084cc11ff031..72cf0446c7eb9 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
@@ -15,8 +15,10 @@
 #include <memory>
 #include <optional>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
index 9d8245643cdba..52ddaa34ea674 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
@@ -15,8 +15,10 @@
 #include <memory>
 #include <optional>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
index 64ef7a55c7c97..cbff9cf3b1d6b 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
@@ -16,8 +16,10 @@
 #include <optional>
 #include <utility>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
index 0206eb668d155..9c394bb13a2a0 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
@@ -14,8 +14,10 @@
 #include <cassert>
 #include <optional>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
index 3bd1342bf935d..044134126a374 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
@@ -16,8 +16,10 @@
 #include <memory>
 #include <optional>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 using std::in_place_t;
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
index 3893995ac198b..66911bf85f5fe 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
@@ -16,8 +16,10 @@
 #include <optional>
 #include <type_traits>
 
-#include "copy_move_types.h"
 #include "test_macros.h"
+#if TEST_STD_VER >= 26
+#  include "copy_move_types.h"
+#endif
 
 using std::optional;
 using std::in_place_t;
diff --git a/libcxx/test/support/copy_move_types.h b/libcxx/test/support/copy_move_types.h
index aa62eea97b4a3..b0c99cbca6c07 100644
--- a/libcxx/test/support/copy_move_types.h
+++ b/libcxx/test/support/copy_move_types.h
@@ -12,10 +12,8 @@
 #include "test_allocator.h"
 #include <type_traits>
 #include <tuple>
-#include "test_macros.h"
 
 // Types that can be used to test copy/move operations
-#if TEST_STD_VER >= 23
 struct MutableCopy {
   int val;
   bool alloc_constructed{false};
@@ -344,5 +342,4 @@ struct TracedAssignment {
   }
 };
 
-#endif // TEST_STD_VER >= 23
 #endif

>From d11901dd1ce3c70cb99729e26d679ad4085fad67 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 00:18:17 -0500
Subject: [PATCH 20/26] Format

---
 .../optional.object.observe/dereference_const.pass.cpp        | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
index 52ddaa34ea674..aefe8d37a142a 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
@@ -80,8 +80,8 @@ int main(int, char**)
         static_assert((*opt).test() == 3, "");
     }
     {
-        constexpr optional<Y> opt(Y{});
-        assert((*opt).test() == 2);
+      constexpr optional<Y> opt(Y{});
+      assert((*opt).test() == 2);
     }
 #if TEST_STD_VER >= 26
     {

>From 1c9f2202c1429460ab604e2babbc4505aff0d371 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 01:06:08 -0500
Subject: [PATCH 21/26] Implement convert-ref-init-val

---
 libcxx/include/optional | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 0fc2bfa4e5ab3..f11c15a49cd7a 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -477,11 +477,6 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> {
     }
   }
 
-  template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from_val(_Up&& __val) {
-    this->__get() = std::forward<_Up>(__val);
-  }
-
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap(__optional_storage_base& __rhs) {
     using std::swap;
     swap(this->__get(), __rhs.__get());
@@ -496,12 +491,18 @@ struct __optional_storage_base<_Tp, true> {
 
   _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {}
 
+  template <class _Up>
+  _LIBCPP_HIDE_FROM_ABI constexpr void __convert_init_ref_val(_Up&& __val) {
+    _Tp& __r(std::forward<_Up>(__val));
+    __value_ = std::addressof(__r);
+  }
+
   template <class _UArg>
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
-      : __value_(std::addressof(__uarg)) {
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg) {
     static_assert(!__reference_constructs_from_temporary_v<_Tp, _UArg>,
                   "Attempted to construct a reference element in optional from a "
                   "possible temporary");
+    __convert_init_ref_val(__uarg);
   }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
@@ -516,7 +517,7 @@ struct __optional_storage_base<_Tp, true> {
     static_assert(!__reference_constructs_from_temporary_v<_Tp, _UArg>,
                   "Attempted to construct a reference element in tuple from a "
                   "possible temporary");
-    __value_ = std::addressof(__val);
+    __convert_init_ref_val(__val);
   }
 
   template <class _That>
@@ -538,11 +539,6 @@ struct __optional_storage_base<_Tp, true> {
     }
   }
 
-  template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __assign_from_val(_Up&& __val) noexcept {
-    __value_ = std::addressof(__val);
-  }
-
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap(__optional_storage_base& __rhs) noexcept {
     std::swap(__value_, __rhs.__value_);
   }
@@ -1040,11 +1036,11 @@ public:
             enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>,
                              _Or<_IsNotSame<__remove_cvref_t<_Up>, _Tp>, _Not<is_scalar<_Tp>>>,
                              is_constructible<_Tp, _Up>,
-                             is_assignable<_Tp&, _Up>>::value,
+                             is_assignable<_Tp&, _Up>, is_object<_Tp>>::value,
                         int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
     if (this->has_value())
-      this->__assign_from_val(std::forward<_Up>(__v));
+      this->__get() = std::forward<_Up>(__v);
     else
       this->__construct(std::forward<_Up>(__v));
     return *this;

>From e2dadeaebab52d07137efda132ad45c4372a337a Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 01:07:35 -0500
Subject: [PATCH 22/26] Add more test cases

---
 .../optional.object.assign/assign_value.pass.cpp      |  4 +++-
 .../optional.object/optional.object.ctor/U.pass.cpp   | 11 +++++++----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
index d0f9e70bae869..f1e2493954d38 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
@@ -350,8 +350,10 @@ int main(int, char**)
     static_assert(pr38638(3) == 5, "");
 
 #if TEST_STD_VER >= 26
-    assert(test_with_ref<int>(3));
+    test_with_ref<int>(3);
+    test_with_ref<ConstexprTestTypes::Copyable>({});
     static_assert(test_with_ref<int>(3));
+    static_assert(test_with_ref<ConstexprTestTypes::Copyable>({}));
 #endif
     return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
index 091e0ef00d2d4..c25c65bc64b2b 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -154,7 +154,7 @@ struct Throws {
   int val = 42;
   bool b  = false;
   constexpr Throws() {};
-  operator int&() {
+  constexpr operator int&() {
     if (b) {
       TEST_THROW(1);
     }
@@ -175,10 +175,13 @@ constexpr bool test_ref() {
 
 #  ifndef TEST_HAS_NO_EXCEPTIONS
   {
-    using T = Throws;
-    T t{};
+    Throws t{};
     ASSERT_NOT_NOEXCEPT(std::optional<int&>(t));
-    // TODO: There doesn't seem to be a usable type which can actually make the ctor not noexcept
+    try {
+      std::optional<int&> o(t);
+    } catch (int) {
+      assert(false);
+    }
   }
 #  endif
   return true;

>From 07abef36bec6fc23c4a539c0c2762188c4e7ff0d Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 01:10:29 -0500
Subject: [PATCH 23/26] Formatting

---
 libcxx/include/optional | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index f11c15a49cd7a..88774b168cee3 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -1036,7 +1036,8 @@ public:
             enable_if_t<_And<_IsNotSame<__remove_cvref_t<_Up>, optional>,
                              _Or<_IsNotSame<__remove_cvref_t<_Up>, _Tp>, _Not<is_scalar<_Tp>>>,
                              is_constructible<_Tp, _Up>,
-                             is_assignable<_Tp&, _Up>, is_object<_Tp>>::value,
+                             is_assignable<_Tp&, _Up>,
+                             is_object<_Tp>>::value,
                         int> = 0>
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 optional& operator=(_Up&& __v) {
     if (this->has_value())

>From b8f8263ebfe222e61d275e9599569c78dfd38c63 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 01:23:37 -0500
Subject: [PATCH 24/26] copy_move_types whitespace

---
 libcxx/test/support/copy_move_types.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/support/copy_move_types.h b/libcxx/test/support/copy_move_types.h
index b0c99cbca6c07..dec8d94cac379 100644
--- a/libcxx/test/support/copy_move_types.h
+++ b/libcxx/test/support/copy_move_types.h
@@ -14,6 +14,7 @@
 #include <tuple>
 
 // Types that can be used to test copy/move operations
+
 struct MutableCopy {
   int val;
   bool alloc_constructed{false};
@@ -341,5 +342,4 @@ struct TracedAssignment {
     return *this;
   }
 };
-
 #endif

>From ce1de1efa91f398d7f76cc164b10014ec539cded Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 12:27:04 -0500
Subject: [PATCH 25/26] Properly forward, fix swap forwarding issue

---
 libcxx/include/optional | 48 +++++++++++++++++++++++++----------------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 88774b168cee3..096ba2d1f3130 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -477,9 +477,21 @@ struct __optional_storage_base : __optional_destruct_base<_Tp> {
     }
   }
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap(__optional_storage_base& __rhs) {
+  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
+  __swap(__optional_storage_base& __rhs) noexcept(is_nothrow_move_constructible_v<_Tp> && is_nothrow_swappable_v<_Tp>) {
     using std::swap;
-    swap(this->__get(), __rhs.__get());
+    if (this->has_value() == __rhs.has_value()) {
+      if (this->has_value())
+        swap(this->__get(), __rhs.__get());
+    } else {
+      if (this->has_value()) {
+        __rhs.__construct(std::move(this->__get()));
+        this->reset();
+      } else {
+        this->__construct(std::move(__rhs.__get()));
+        __rhs.reset();
+      }
+    }
   }
 };
 
@@ -492,7 +504,7 @@ struct __optional_storage_base<_Tp, true> {
   _LIBCPP_HIDE_FROM_ABI constexpr __optional_storage_base() noexcept : __value_(nullptr) {}
 
   template <class _Up>
-  _LIBCPP_HIDE_FROM_ABI constexpr void __convert_init_ref_val(_Up&& __val) {
+  _LIBCPP_HIDE_FROM_ABI constexpr void __convert_init_ref_val(_Up&& __val) noexcept {
     _Tp& __r(std::forward<_Up>(__val));
     __value_ = std::addressof(__r);
   }
@@ -502,7 +514,7 @@ struct __optional_storage_base<_Tp, true> {
     static_assert(!__reference_constructs_from_temporary_v<_Tp, _UArg>,
                   "Attempted to construct a reference element in optional from a "
                   "possible temporary");
-    __convert_init_ref_val(__uarg);
+    __convert_init_ref_val(std::forward<_UArg>(__uarg));
   }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void reset() noexcept { __value_ = nullptr; }
@@ -517,7 +529,7 @@ struct __optional_storage_base<_Tp, true> {
     static_assert(!__reference_constructs_from_temporary_v<_Tp, _UArg>,
                   "Attempted to construct a reference element in tuple from a "
                   "possible temporary");
-    __convert_init_ref_val(__val);
+    __convert_init_ref_val(std::forward<_UArg>(__val));
   }
 
   template <class _That>
@@ -540,7 +552,18 @@ struct __optional_storage_base<_Tp, true> {
   }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap(__optional_storage_base& __rhs) noexcept {
-    std::swap(__value_, __rhs.__value_);
+    if (this->has_value() == __rhs.has_value()) {
+      if (this->has_value())
+        std::swap(__value_, __rhs.__value_);
+    } else {
+      if (this->has_value()) {
+        __rhs.__construct(this->__get());
+        reset();
+      } else {
+        this->__construct(__rhs.__get());
+        __rhs.reset();
+      }
+    }
   }
 };
 
@@ -1087,18 +1110,7 @@ public:
       || is_lvalue_reference_v<_Tp>
 #    endif
   ) {
-    if (this->has_value() == __opt.has_value()) {
-      if (this->has_value())
-        this->__swap(__opt);
-    } else {
-      if (this->has_value()) {
-        __opt.__construct(std::move(this->__get()));
-        reset();
-      } else {
-        this->__construct(std::move(__opt.__get()));
-        __opt.reset();
-      }
-    }
+    this->__swap(__opt);
   }
 
   _LIBCPP_HIDE_FROM_ABI constexpr add_pointer_t<_Tp const> operator->() const noexcept

>From c911118b789100dbfc20583381da1adcec8ae0b7 Mon Sep 17 00:00:00 2001
From: William Tran-Viet <wtranviet at proton.me>
Date: Thu, 8 Jan 2026 13:13:26 -0500
Subject: [PATCH 26/26] Add lvalue, rvalue reference conversion type test

---
 .../optional.object.ctor/U.pass.cpp           | 49 ++++++++++++-----
 .../const_optional_U.pass.cpp                 | 28 +++++++++-
 .../optional.object.ctor/copy.pass.cpp        |  7 ++-
 .../optional.object.ctor/optional_U.pass.cpp  | 22 ++++++++
 .../optional.object/optional_helper_types.h   | 54 +++++++++++++++++++
 5 files changed, 144 insertions(+), 16 deletions(-)
 create mode 100644 libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h

diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
index c25c65bc64b2b..1cdb429f485e5 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -21,6 +21,8 @@
 #include "archetypes.h"
 #include "test_convertible.h"
 
+#include "../optional_helper_types.h"
+
 using std::optional;
 
 struct ImplicitThrow {
@@ -150,18 +152,6 @@ void test_explicit() {
 }
 
 #if TEST_STD_VER >= 26
-struct Throws {
-  int val = 42;
-  bool b  = false;
-  constexpr Throws() {};
-  constexpr operator int&() {
-    if (b) {
-      TEST_THROW(1);
-    }
-    return val;
-  }
-};
-
 constexpr bool test_ref() {
   {
     int i = 0;
@@ -173,12 +163,45 @@ constexpr bool test_ref() {
     assert(o.value() == 0);
   }
 
+  {
+    ReferenceConversion<int> t{1, 2};
+    ASSERT_NOEXCEPT(std::optional<int&>(t));
+    std::optional<int&> o(t);
+    assert(o.has_value());
+    assert(&(*o) == &t.lvalue);
+    assert(*o == 1);
+  }
+
+  {
+    ReferenceConversion<int> t{1, 2};
+    ASSERT_NOEXCEPT(std::optional<int&>(std::move(t)));
+    std::optional<int&> o(std::move(t));
+    assert(o.has_value());
+    assert(&(*o) == &t.rvalue);
+    assert(*o == 2);
+  }
+
 #  ifndef TEST_HAS_NO_EXCEPTIONS
   {
-    Throws t{};
+    ReferenceConversionThrows<int> t{1, 2, false};
     ASSERT_NOT_NOEXCEPT(std::optional<int&>(t));
     try {
       std::optional<int&> o(t);
+      assert(o.has_value());
+      assert(&(*o) == &t.lvalue);
+      assert(*o == 1);
+    } catch (int) {
+      assert(false);
+    }
+  }
+  {
+    ReferenceConversionThrows<int> t{1, 2, false};
+    ASSERT_NOT_NOEXCEPT(std::optional<int&>(std::move(t)));
+    try {
+      std::optional<int&> o(std::move(t));
+      assert(o.has_value());
+      assert(&(*o) == &t.rvalue);
+      assert(*o == 2);
     } catch (int) {
       assert(false);
     }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
index 376ece0f820ab..597110bcb54fe 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
@@ -17,6 +17,7 @@
 #include <optional>
 #include <type_traits>
 
+#include "../optional_helper_types.h"
 #include "test_macros.h"
 
 using std::optional;
@@ -109,7 +110,17 @@ constexpr bool test_ref() {
     assert(!o2.has_value());
   }
 
-  // optional(optional<U>&&)
+  {
+    ReferenceConversion<int> t{1, 2};
+    const std::optional<ReferenceConversion<int>&> o1(t);
+    const std::optional<int&> o2(o1);
+    ASSERT_NOEXCEPT(std::optional<int&>(o1));
+    assert(o2.has_value());
+    assert(&(*o2) == &t.lvalue);
+    assert(*o2 == 1);
+  }
+
+  // optional(const optional<U>&&)
   {
     int i = 1;
     const std::optional<int&> o1{i};
@@ -130,6 +141,16 @@ constexpr bool test_ref() {
     assert(!o2.has_value());
   }
 
+  {
+    ReferenceConversion<int> t{1, 2};
+    const std::optional<ReferenceConversion<int>&> o1(t);
+    const std::optional<int&> o2(std::move(o1));
+    ASSERT_NOEXCEPT(std::optional<int&>(o1));
+    assert(o2.has_value());
+    assert(&(*o2) == &t.lvalue);
+    assert(*o2 == 1);
+  }
+
   return true;
 }
 #endif
@@ -157,6 +178,9 @@ int main(int, char**) {
   }
 
   static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value), "");
-
+#if TEST_STD_VER >= 26
+  assert(test_ref());
+  static_assert(test_ref());
+#endif
   return 0;
 }
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
index f61a22c23a04d..bd407c6d25561 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -69,8 +69,8 @@ void test_ref(InitArgs&&... args) {
     assert(&(*lhs) == &(*rhs));
 }
 
+#if TEST_STD_VER >= 26
 void test_reference_extension() {
-#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
   using T = TestTypes::TestType;
   T::reset();
   {
@@ -99,12 +99,15 @@ void test_reference_extension() {
   }
   assert(T::alive == 0);
   assert(T::destroyed == 1);
+
+#if 0 // optional<T&&> is not permitted.
   {
     static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
     static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
   }
 #endif
 }
+#endif
 
 int main(int, char**) {
   test<int>();
@@ -153,9 +156,11 @@ int main(int, char**) {
   {
     test_throwing_ctor();
   }
+#if TEST_STD_VER >= 26
   {
     test_reference_extension();
   }
+#endif
   {
     constexpr std::optional<int> o1{4};
     constexpr std::optional<int> o2 = o1;
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
index 7d26f82baac0a..39a80efa475f7 100644
--- a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -25,6 +25,8 @@
 #  include "copy_move_types.h"
 #endif
 
+#include "../optional_helper_types.h"
+
 using std::optional;
 
 template <class T, class U>
@@ -94,6 +96,16 @@ constexpr bool test_ref() {
     ASSERT_NOEXCEPT(std::optional<int&>(o2));
     assert(!o2.has_value());
   }
+
+  {
+    ReferenceConversion<int> t{1, 2};
+    std::optional<ReferenceConversion<int>&> o1(t);
+    std::optional<int&> o2(o1);
+    ASSERT_NOEXCEPT(std::optional<int&>(o1));
+    assert(o2.has_value());
+    assert(&(*o2) == &t.lvalue);
+    assert(*o2 == 1);
+  }
   // optional(optional<U>&&)
   {
     int i = 1;
@@ -122,6 +134,16 @@ constexpr bool test_ref() {
     assert(t.nonConstMove == 0);
   }
 
+  {
+    ReferenceConversion<int> t{1, 2};
+    std::optional<ReferenceConversion<int>&> o1(t);
+    std::optional<int&> o2(std::move(o1));
+    ASSERT_NOEXCEPT(std::optional<int&>(o1));
+    assert(o2.has_value());
+    assert(&(*o2) == &t.lvalue);
+    assert(*o2 == 1);
+  }
+
   return true;
 }
 #endif
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h b/libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h
new file mode 100644
index 0000000000000..704d99acb15e9
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional_helper_types.h
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// TODO: We should consolidate all the helper types used in the optional tests into here.
+
+#include "test_macros.h"
+
+#ifndef LIBCXX_UTILITIES_OPTIONAL_HELPER_TYPES_H
+#  define LIBCXX_UTILITIES_OPTIONAL_HELPER_TYPES_H
+
+template <typename T>
+struct ReferenceConversion {
+  T lvalue;
+  T rvalue;
+
+  constexpr ReferenceConversion(T lval, T rval) : lvalue(lval), rvalue(rval) {}
+
+  constexpr operator T&() & noexcept { return lvalue; }
+
+  constexpr operator T&() && noexcept { return rvalue; }
+};
+
+template <typename T>
+struct ReferenceConversionThrows {
+  T lvalue;
+  T rvalue;
+  bool throws{false};
+
+  constexpr ReferenceConversionThrows(T lval, T rval, bool except = false)
+      : lvalue(lval), rvalue(rval), throws(except) {}
+
+  constexpr operator T&() & {
+    if (throws) {
+      TEST_THROW(1);
+    }
+
+    return lvalue;
+  }
+
+  constexpr operator T&() && {
+    if (throws) {
+      TEST_THROW(2);
+    }
+
+    return rvalue;
+  }
+};
+
+#endif



More information about the libcxx-commits mailing list