[libcxx-commits] [libcxx] [libc++][optional] LWG4497: `std::nullopt_t` should be comparable (PR #214975)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Sun Aug 16 08:49:37 PDT 2026


https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/214975

>From e646e821d30cb8e9bbad38549c29e3e59f5109cb Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Sun, 3 May 2026 23:22:57 +0300
Subject: [PATCH 01/14] [libcxx] Make std::nullopt_t comparable

---
 libcxx/docs/Status/Cxx2cIssues.csv            |  2 +-
 libcxx/include/optional                       |  3 ++
 .../optional.nullopt/nullopt_t.pass.cpp       | 49 +++++++++++++------
 3 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index c875f75528894..84330900aaa8e 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -309,7 +309,7 @@
 "`LWG4492 <https://wg21.link/LWG4492>`__","``std::generate`` and ``std::ranges::generate`` wording is unclear for parallel algorithms","2026-03 (Croydon)","","","`#189851 <https://github.com/llvm/llvm-project/issues/189851>`__",""
 "`LWG4493 <https://wg21.link/LWG4493>`__","Specification for some functions of bit reference types seems missing","2026-03 (Croydon)","","","`#189852 <https://github.com/llvm/llvm-project/issues/189852>`__",""
 "`LWG4496 <https://wg21.link/LWG4496>`__","Precedes vs Reachable in [meta.reflection]","2026-03 (Croydon)","","","`#189853 <https://github.com/llvm/llvm-project/issues/189853>`__",""
-"`LWG4497 <https://wg21.link/LWG4497>`__","``std::nullopt_t`` should be comparable","2026-03 (Croydon)","","","`#189854 <https://github.com/llvm/llvm-project/issues/189854>`__",""
+"`LWG4497 <https://wg21.link/LWG4497>`__","``std::nullopt_t`` should be comparable","2026-03 (Croydon)","|Complete|","23","`#189854 <https://github.com/llvm/llvm-project/issues/189854>`__",""
 "`LWG4499 <https://wg21.link/LWG4499>`__","``flat_set::insert_range`` specification may be problematic","2026-03 (Croydon)","","","`#189855 <https://github.com/llvm/llvm-project/issues/189855>`__",""
 "`LWG4500 <https://wg21.link/LWG4500>`__","``constant_wrapper`` wording problems","2026-03 (Croydon)","|Complete|","23","`#189856 <https://github.com/llvm/llvm-project/issues/189856>`__",""
 "`LWG4504 <https://wg21.link/LWG4504>`__","Wording problem in ``{simple_}counting_scope``","2026-03 (Croydon)","","","`#189857 <https://github.com/llvm/llvm-project/issues/189857>`__",""
diff --git a/libcxx/include/optional b/libcxx/include/optional
index f7e12f84beba0..7705ba49c49e7 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -362,6 +362,9 @@ struct nullopt_t {
     explicit __secret_tag() = default;
   };
   _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
+#    if _LIBCPP_STD_VER >= 26
+  _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const nullopt_t&) const noexcept = default;
+#    endif
 };
 
 inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
index 842b75893cbe4..a580348e0da9a 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
@@ -13,31 +13,50 @@
 // inline constexpr nullopt_t nullopt(unspecified);
 
 // [optional.nullopt]/2:
-//   Type nullopt_t shall not have a default constructor or an initializer-list
-//   constructor, and shall not be an aggregate.
+//   Type nullopt_t does not have a default constructor or an initializer-list
+//   constructor, and is not an aggregate. nullopt_t models copyable and
+//   three_way_comparable<strong_ordering>.
 
 #include <optional>
 #include <type_traits>
+#if _LIBCPP_STD_VER >= 26
+#  include <vector>
+#  include <ranges>
+#  include <cassert>
+#  include <algorithm>
+#endif
 
 #include "test_macros.h"
 
-using std::nullopt_t;
 using std::nullopt;
+using std::nullopt_t;
 
-constexpr bool test()
-{
-    nullopt_t foo{nullopt};
-    (void)foo;
-    return true;
+constexpr bool test() {
+  nullopt_t foo{nullopt};
+  (void)foo;
+  return true;
 }
 
-int main(int, char**)
-{
-    static_assert(std::is_empty_v<nullopt_t>);
-    static_assert(!std::is_default_constructible_v<nullopt_t>);
-
-    static_assert(std::is_same_v<const nullopt_t, decltype(nullopt)>);
-    static_assert(test());
+int main(int, char**) {
+  static_assert(std::is_empty_v<nullopt_t>);
+  static_assert(!std::is_default_constructible_v<nullopt_t>);
+
+  static_assert(std::is_same_v<const nullopt_t, decltype(nullopt)>);
+  static_assert(test());
+#if TEST_STD_VER >= 26
+  // Test comparisons between nullopt_t
+  static_assert(nullopt == nullopt);
+  static_assert(!(nullopt != nullopt));
+  static_assert(nullopt <= nullopt);
+  static_assert(nullopt >= nullopt);
+  static_assert((nullopt <=> nullopt) == std::strong_ordering::equal);
+
+  // Test ranges::find with nullopt
+  std::vector<std::optional<int>> v = {1, 2, nullopt, 4, 5};
+  auto itr                          = std::ranges::find(v, nullopt);
+  assert(itr != v.end());
+  assert(*itr == nullopt);
+#endif
 
   return 0;
 }

>From b50af237fadeaf71132cabec302b88d607f95f89 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Wed, 6 May 2026 00:30:34 +0300
Subject: [PATCH 02/14] Address comments

---
 libcxx/include/optional                                | 10 ++++++++--
 .../optional/optional.nullopt/nullopt_t.pass.cpp       | 10 ++++++----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 7705ba49c49e7..1bdc808190ba4 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -362,8 +362,14 @@ struct nullopt_t {
     explicit __secret_tag() = default;
   };
   _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
-#    if _LIBCPP_STD_VER >= 26
-  _LIBCPP_HIDE_FROM_ABI constexpr strong_ordering operator<=>(const nullopt_t&) const noexcept = default;
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator==(const nullopt_t&, const nullopt_t) { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator!=(const nullopt_t&, const nullopt_t) { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>(const nullopt_t&, const nullopt_t) { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<(const nullopt_t&, const nullopt_t) { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>=(const nullopt_t&, const nullopt_t) { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<=(const nullopt_t&, const nullopt_t) { return true; }
+#    if _LIBCPP_STD_VER >= 20
+  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(const nullopt_t&, const nullopt_t&) = default;
 #    endif
 };
 
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
index a580348e0da9a..54b352f4f167b 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
@@ -19,7 +19,7 @@
 
 #include <optional>
 #include <type_traits>
-#if _LIBCPP_STD_VER >= 26
+#if _LIBCPP_STD_VER >= 20
 #  include <vector>
 #  include <ranges>
 #  include <cassert>
@@ -43,14 +43,16 @@ int main(int, char**) {
 
   static_assert(std::is_same_v<const nullopt_t, decltype(nullopt)>);
   static_assert(test());
-#if TEST_STD_VER >= 26
-  // Test comparisons between nullopt_t
+
   static_assert(nullopt == nullopt);
   static_assert(!(nullopt != nullopt));
   static_assert(nullopt <= nullopt);
   static_assert(nullopt >= nullopt);
-  static_assert((nullopt <=> nullopt) == std::strong_ordering::equal);
+  static_assert(!(nullopt > nullopt));
+  static_assert(!(nullopt < nullopt));
 
+#if TEST_STD_VER >= 20
+  static_assert((nullopt <=> nullopt) == std::strong_ordering::equal);
   // Test ranges::find with nullopt
   std::vector<std::optional<int>> v = {1, 2, nullopt, 4, 5};
   auto itr                          = std::ranges::find(v, nullopt);

>From 898f82308944b8e46c4490b6ce28be479a9c2ca4 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Wed, 6 May 2026 10:29:02 +0300
Subject: [PATCH 03/14] Enable only <=> operator in c++20 and later

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

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 1bdc808190ba4..55301ae7f331b 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -362,14 +362,15 @@ struct nullopt_t {
     explicit __secret_tag() = default;
   };
   _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
+#    if _LIBCPP_STD_VER >= 20
+  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(const nullopt_t&, const nullopt_t&) = default;
+#    else
   _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator==(const nullopt_t&, const nullopt_t) { return true; }
   _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator!=(const nullopt_t&, const nullopt_t) { return false; }
   _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>(const nullopt_t&, const nullopt_t) { return false; }
   _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<(const nullopt_t&, const nullopt_t) { return false; }
   _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>=(const nullopt_t&, const nullopt_t) { return true; }
   _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<=(const nullopt_t&, const nullopt_t) { return true; }
-#    if _LIBCPP_STD_VER >= 20
-  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(const nullopt_t&, const nullopt_t&) = default;
 #    endif
 };
 

>From 75f9c15db4b556fba5c8b840c28eecb01c41a548 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Fri, 8 May 2026 23:40:54 +0300
Subject: [PATCH 04/14] Address comments

---
 libcxx/include/optional                       | 16 +++---
 .../compare.three_way.pass.cpp                | 53 +++++++++++++++++++
 .../optional.nullopt/nullopt_t.pass.cpp       | 27 +---------
 3 files changed, 63 insertions(+), 33 deletions(-)
 create mode 100644 libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp

diff --git a/libcxx/include/optional b/libcxx/include/optional
index 55301ae7f331b..b25e780a54a8a 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -362,15 +362,15 @@ struct nullopt_t {
     explicit __secret_tag() = default;
   };
   _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
-#    if _LIBCPP_STD_VER >= 20
-  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(const nullopt_t&, const nullopt_t&) = default;
+#    if _LIBCPP_STD_VER <= 17
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator==(nullopt_t, nullopt_t) { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator!=(nullopt_t, nullopt_t) { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>(nullopt_t, nullopt_t) { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<(nullopt_t, nullopt_t) { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>=(nullopt_t, nullopt_t) { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<=(nullopt_t, nullopt_t) { return true; }
 #    else
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator==(const nullopt_t&, const nullopt_t) { return true; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator!=(const nullopt_t&, const nullopt_t) { return false; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>(const nullopt_t&, const nullopt_t) { return false; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<(const nullopt_t&, const nullopt_t) { return false; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>=(const nullopt_t&, const nullopt_t) { return true; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<=(const nullopt_t&, const nullopt_t) { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(nullopt_t, nullopt_t) = default;
 #    endif
 };
 
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
new file mode 100644
index 0000000000000..291d219bbd6b1
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+// <optional>
+
+// struct nullopt_t{see below};
+// inline constexpr nullopt_t nullopt(unspecified);
+
+// [optional.nullopt]/2:
+//  nullopt_t models copyable and three_way_comparable<strong_ordering>.
+
+#include <ratio>
+#include <vector>
+#include <ranges>
+#include <cassert>
+#include <algorithm>
+#include <optional>
+
+#include "test_macros.h"
+
+using std::nullopt;
+
+constexpr bool test() {
+  static_assert(nullopt == nullopt);
+  static_assert(!(nullopt != nullopt));
+  static_assert(nullopt <= nullopt);
+  static_assert(nullopt >= nullopt);
+  static_assert(!(nullopt > nullopt));
+  static_assert(!(nullopt < nullopt));
+
+#if TEST_STD_VER > 17
+  static_assert((nullopt <=> nullopt) == std::strong_ordering::equal);
+  // Test ranges::find with nullopt
+  std::vector<std::optional<int>> v = {1, 2, nullopt, 4, 5};
+  auto itr                          = std::ranges::find(v, nullopt);
+  assert(itr != v.end());
+  assert(*itr == nullopt);
+#endif
+
+  return true;
+}
+
+int main(int, char**) {
+  static_assert(test());
+
+  return 0;
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
index 54b352f4f167b..47ffa262ee7c2 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
@@ -13,18 +13,11 @@
 // inline constexpr nullopt_t nullopt(unspecified);
 
 // [optional.nullopt]/2:
-//   Type nullopt_t does not have a default constructor or an initializer-list
-//   constructor, and is not an aggregate. nullopt_t models copyable and
-//   three_way_comparable<strong_ordering>.
+//   Type nullopt_t shall not have a default constructor or an initializer-list
+//   constructor, and shall not be an aggregate.
 
 #include <optional>
 #include <type_traits>
-#if _LIBCPP_STD_VER >= 20
-#  include <vector>
-#  include <ranges>
-#  include <cassert>
-#  include <algorithm>
-#endif
 
 #include "test_macros.h"
 
@@ -44,21 +37,5 @@ int main(int, char**) {
   static_assert(std::is_same_v<const nullopt_t, decltype(nullopt)>);
   static_assert(test());
 
-  static_assert(nullopt == nullopt);
-  static_assert(!(nullopt != nullopt));
-  static_assert(nullopt <= nullopt);
-  static_assert(nullopt >= nullopt);
-  static_assert(!(nullopt > nullopt));
-  static_assert(!(nullopt < nullopt));
-
-#if TEST_STD_VER >= 20
-  static_assert((nullopt <=> nullopt) == std::strong_ordering::equal);
-  // Test ranges::find with nullopt
-  std::vector<std::optional<int>> v = {1, 2, nullopt, 4, 5};
-  auto itr                          = std::ranges::find(v, nullopt);
-  assert(itr != v.end());
-  assert(*itr == nullopt);
-#endif
-
   return 0;
 }

>From 1bfa5477c5e37e47092a0ebaf6dacea84fe88a35 Mon Sep 17 00:00:00 2001
From: Mohamed Atef <mohamedatef1698 at gmail.com>
Date: Sat, 9 May 2026 15:58:46 +0300
Subject: [PATCH 05/14] Finalize comparable nullopt

---
 .../compare.three_way.pass.cpp                | 16 +++++++++-----
 .../optional.nullopt/nullopt_t.pass.cpp       | 22 ++++++++++---------
 2 files changed, 23 insertions(+), 15 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
index 291d219bbd6b1..476c2f5fd33b8 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14
+// REQUIRES: std-at-least-c++17
 // <optional>
 
 // struct nullopt_t{see below};
@@ -15,17 +15,21 @@
 // [optional.nullopt]/2:
 //  nullopt_t models copyable and three_way_comparable<strong_ordering>.
 
-#include <ratio>
-#include <vector>
-#include <ranges>
-#include <cassert>
 #include <algorithm>
+#include <cassert>
+#include <concepts>
 #include <optional>
+#include <vector>
 
 #include "test_macros.h"
 
 using std::nullopt;
 
+#if TEST_STD_VER >= 20
+static_assert(std::copyable<std::nullopt_t>);
+static_assert(std::three_way_comparable<std::nullopt_t, std::strong_ordering>);
+#endif
+
 constexpr bool test() {
   static_assert(nullopt == nullopt);
   static_assert(!(nullopt != nullopt));
@@ -47,6 +51,8 @@ constexpr bool test() {
 }
 
 int main(int, char**) {
+  test();
+
   static_assert(test());
 
   return 0;
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
index 47ffa262ee7c2..842b75893cbe4 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
@@ -21,21 +21,23 @@
 
 #include "test_macros.h"
 
-using std::nullopt;
 using std::nullopt_t;
+using std::nullopt;
 
-constexpr bool test() {
-  nullopt_t foo{nullopt};
-  (void)foo;
-  return true;
+constexpr bool test()
+{
+    nullopt_t foo{nullopt};
+    (void)foo;
+    return true;
 }
 
-int main(int, char**) {
-  static_assert(std::is_empty_v<nullopt_t>);
-  static_assert(!std::is_default_constructible_v<nullopt_t>);
+int main(int, char**)
+{
+    static_assert(std::is_empty_v<nullopt_t>);
+    static_assert(!std::is_default_constructible_v<nullopt_t>);
 
-  static_assert(std::is_same_v<const nullopt_t, decltype(nullopt)>);
-  static_assert(test());
+    static_assert(std::is_same_v<const nullopt_t, decltype(nullopt)>);
+    static_assert(test());
 
   return 0;
 }

>From 5ea20d33b862a41b8a30535717713e86d4c83a36 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <zingam at outlook.com>
Date: Sat, 8 Aug 2026 16:41:08 +0300
Subject: [PATCH 06/14] Apply suggestions from code review

Co-authored-by: Hristo Hristov <zingam at outlook.com>
---
 libcxx/docs/Status/Cxx2cIssues.csv            |  2 +-
 libcxx/include/optional                       | 23 ++++++++++---------
 .../compare.three_way.pass.cpp                | 22 +++++++++---------
 3 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index 84330900aaa8e..e6f9af2495255 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -309,7 +309,7 @@
 "`LWG4492 <https://wg21.link/LWG4492>`__","``std::generate`` and ``std::ranges::generate`` wording is unclear for parallel algorithms","2026-03 (Croydon)","","","`#189851 <https://github.com/llvm/llvm-project/issues/189851>`__",""
 "`LWG4493 <https://wg21.link/LWG4493>`__","Specification for some functions of bit reference types seems missing","2026-03 (Croydon)","","","`#189852 <https://github.com/llvm/llvm-project/issues/189852>`__",""
 "`LWG4496 <https://wg21.link/LWG4496>`__","Precedes vs Reachable in [meta.reflection]","2026-03 (Croydon)","","","`#189853 <https://github.com/llvm/llvm-project/issues/189853>`__",""
-"`LWG4497 <https://wg21.link/LWG4497>`__","``std::nullopt_t`` should be comparable","2026-03 (Croydon)","|Complete|","23","`#189854 <https://github.com/llvm/llvm-project/issues/189854>`__",""
+"`LWG4497 <https://wg21.link/LWG4497>`__","``std::nullopt_t`` should be comparable","2026-03 (Croydon)","|Complete|","24","`#189854 <https://github.com/llvm/llvm-project/issues/189854>`__",""
 "`LWG4499 <https://wg21.link/LWG4499>`__","``flat_set::insert_range`` specification may be problematic","2026-03 (Croydon)","","","`#189855 <https://github.com/llvm/llvm-project/issues/189855>`__",""
 "`LWG4500 <https://wg21.link/LWG4500>`__","``constant_wrapper`` wording problems","2026-03 (Croydon)","|Complete|","23","`#189856 <https://github.com/llvm/llvm-project/issues/189856>`__",""
 "`LWG4504 <https://wg21.link/LWG4504>`__","Wording problem in ``{simple_}counting_scope``","2026-03 (Croydon)","","","`#189857 <https://github.com/llvm/llvm-project/issues/189857>`__",""
diff --git a/libcxx/include/optional b/libcxx/include/optional
index b25e780a54a8a..866f039353973 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -361,17 +361,18 @@ struct nullopt_t {
   struct __secret_tag {
     explicit __secret_tag() = default;
   };
-  _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
-#    if _LIBCPP_STD_VER <= 17
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator==(nullopt_t, nullopt_t) { return true; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator!=(nullopt_t, nullopt_t) { return false; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>(nullopt_t, nullopt_t) { return false; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<(nullopt_t, nullopt_t) { return false; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>=(nullopt_t, nullopt_t) { return true; }
-  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<=(nullopt_t, nullopt_t) { return true; }
-#    else
-  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(nullopt_t, nullopt_t) = default;
-#    endif
+_LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
+
+#    if _LIBCPP_STD_VER <= 17
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator==(nullopt_t, nullopt_t) noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator!=(nullopt_t, nullopt_t) noexcept { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>(nullopt_t, nullopt_t) noexcept { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<(nullopt_t, nullopt_t) noexcept { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>=(nullopt_t, nullopt_t) noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<=(nullopt_t, nullopt_t) noexcept { return true; }
+#    else
+  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(nullopt_t, nullopt_t) = default;
+#    endif // if _LIBCPP_STD_VER <= 17
 };
 
 inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
index 476c2f5fd33b8..c0d17e809920f 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 // REQUIRES: std-at-least-c++17
+
 // <optional>
 
 // struct nullopt_t{see below};
@@ -23,7 +24,6 @@
 
 #include "test_macros.h"
 
-using std::nullopt;
 
 #if TEST_STD_VER >= 20
 static_assert(std::copyable<std::nullopt_t>);
@@ -31,18 +31,18 @@ static_assert(std::three_way_comparable<std::nullopt_t, std::strong_ordering>);
 #endif
 
 constexpr bool test() {
-  static_assert(nullopt == nullopt);
-  static_assert(!(nullopt != nullopt));
-  static_assert(nullopt <= nullopt);
-  static_assert(nullopt >= nullopt);
-  static_assert(!(nullopt > nullopt));
-  static_assert(!(nullopt < nullopt));
-
-#if TEST_STD_VER > 17
-  static_assert((nullopt <=> nullopt) == std::strong_ordering::equal);
+  assert(std::nullopt == std:nullopt);
+  assert(!(std:nullopt != std:nullopt));
+  assert(std:nullopt <= std:nullopt);
+  assert(std:nullopt >= std:nullopt);
+  assert(!(std:nullopt > std:nullopt));
+  assert(!(std:nullopt < std:nullopt));
+
+#if TEST_STD_VER >= 20
+  assert((std:nullopt <=> std:nullopt) == std::strong_ordering::equal);
   // Test ranges::find with nullopt
   std::vector<std::optional<int>> v = {1, 2, nullopt, 4, 5};
-  auto itr                          = std::ranges::find(v, nullopt);
+  auto it                           = std::ranges::find(v, nullopt);
   assert(itr != v.end());
   assert(*itr == nullopt);
 #endif

>From 597a0e1f8bd3061de50172cd4ba5db690a5e3e7d Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 8 Aug 2026 18:20:18 +0300
Subject: [PATCH 07/14] Add hidden friends

---
 libcxx/include/__optional/nullopt_t.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/libcxx/include/__optional/nullopt_t.h b/libcxx/include/__optional/nullopt_t.h
index afca31927254a..555ab64187579 100644
--- a/libcxx/include/__optional/nullopt_t.h
+++ b/libcxx/include/__optional/nullopt_t.h
@@ -28,6 +28,21 @@ struct nullopt_t {
     explicit __secret_tag() = default;
   };
   _LIBCPP_HIDE_FROM_ABI constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
+
+#  if _LIBCPP_STD_VER >= 20
+
+  _LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering operator<=>(nullopt_t, nullopt_t) = default;
+
+#  else
+
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator==(nullopt_t, nullopt_t) noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator!=(nullopt_t, nullopt_t) noexcept { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>(nullopt_t, nullopt_t) noexcept { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<(nullopt_t, nullopt_t) noexcept { return false; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator>=(nullopt_t, nullopt_t) noexcept { return true; }
+  _LIBCPP_HIDE_FROM_ABI constexpr friend bool operator<=(nullopt_t, nullopt_t) noexcept { return true; }
+
+#  endif // _LIBCPP_STD_VER >= 20
 };
 
 inline constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};

>From d0742c2054c668def90c7c531050d743e742e7c8 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 8 Aug 2026 18:32:17 +0300
Subject: [PATCH 08/14] Fixes

---
 .../compare.three_way.pass.cpp                | 27 ++++++++++---------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
index c0d17e809920f..d2391f36f2087 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -24,27 +24,29 @@
 
 #include "test_macros.h"
 
-
 #if TEST_STD_VER >= 20
 static_assert(std::copyable<std::nullopt_t>);
 static_assert(std::three_way_comparable<std::nullopt_t, std::strong_ordering>);
 #endif
 
 constexpr bool test() {
-  assert(std::nullopt == std:nullopt);
-  assert(!(std:nullopt != std:nullopt));
-  assert(std:nullopt <= std:nullopt);
-  assert(std:nullopt >= std:nullopt);
-  assert(!(std:nullopt > std:nullopt));
-  assert(!(std:nullopt < std:nullopt));
+  assert(std::nullopt == std::nullopt);
+  assert(!(std::nullopt != std::nullopt));
+  assert(std::nullopt <= std::nullopt);
+  assert(std::nullopt >= std::nullopt);
+  assert(!(std::nullopt > std::nullopt));
+  assert(!(std::nullopt < std::nullopt));
 
 #if TEST_STD_VER >= 20
-  assert((std:nullopt <=> std:nullopt) == std::strong_ordering::equal);
+  assert((std::nullopt <=> std::nullopt) == std::strong_ordering::equal);
+
   // Test ranges::find with nullopt
-  std::vector<std::optional<int>> v = {1, 2, nullopt, 4, 5};
-  auto it                           = std::ranges::find(v, nullopt);
-  assert(itr != v.end());
-  assert(*itr == nullopt);
+  std::vector<std::optional<int>> v = {1, 2, std::nullopt, 4, 5};
+
+  auto it = std::ranges::find(v, std::nullopt);
+
+  assert(it != v.end());
+  assert(*it == std::nullopt);
 #endif
 
   return true;
@@ -52,7 +54,6 @@ constexpr bool test() {
 
 int main(int, char**) {
   test();
-
   static_assert(test());
 
   return 0;

>From 28fb2151f883bfc65317577738591fe24e453f9c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 8 Aug 2026 18:41:47 +0300
Subject: [PATCH 09/14] More fixes

---
 .../compare.three_way.pass.cpp                | 59 +++++++++++++++----
 1 file changed, 47 insertions(+), 12 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
index d2391f36f2087..8fba1311b922e 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -30,23 +30,58 @@ static_assert(std::three_way_comparable<std::nullopt_t, std::strong_ordering>);
 #endif
 
 constexpr bool test() {
-  assert(std::nullopt == std::nullopt);
-  assert(!(std::nullopt != std::nullopt));
-  assert(std::nullopt <= std::nullopt);
-  assert(std::nullopt >= std::nullopt);
-  assert(!(std::nullopt > std::nullopt));
-  assert(!(std::nullopt < std::nullopt));
+  { // ==
+    static_assert(std::is_same_v<decltype(std::nullopt == std::nullopt), bool>);
+    static_assert(noexcept(std::nullopt == std::nullopt));
+
+    assert(std::nullopt == std::nullopt);
+  }
+  { // !=
+    static_assert(std::is_same_v<decltype(std::nullopt != std::nullopt), bool>);
+    static_assert(noexcept(std::nullopt != std::nullopt));
+
+    assert(!(std::nullopt != std::nullopt));
+  }
+  { // <=
+    static_assert(std::is_same_v<decltype(std::nullopt <= std::nullopt), bool>);
+    static_assert(noexcept(std::nullopt <= std::nullopt));
+
+    assert(std::nullopt <= std::nullopt);
+  }
+  { // >=
+    static_assert(std::is_same_v<decltype(std::nullopt >= std::nullopt), bool>);
+    static_assert(noexcept(std::nullopt >= std::nullopt));
+
+    assert(std::nullopt >= std::nullopt);
+  }
+  { // >
+    static_assert(std::is_same_v<decltype(std::nullopt > std::nullopt), bool>);
+    static_assert(noexcept(std::nullopt > std::nullopt));
+
+    assert(!(std::nullopt > std::nullopt));
+  }
+  { // <
+    static_assert(std::is_same_v<decltype(std::nullopt < std::nullopt), bool>);
+    static_assert(noexcept(std::nullopt < std::nullopt));
+
+    assert(!(std::nullopt < std::nullopt));
+  }
 
 #if TEST_STD_VER >= 20
-  assert((std::nullopt <=> std::nullopt) == std::strong_ordering::equal);
+  { // <=>
+    std::same_as<std::strong_ordering> auto result = (std::nullopt <=> std::nullopt);
+    static_assert(noexcept(std::nullopt <=> std::nullopt));
+    assert(result == std::strong_ordering::equal);
+  }
 
-  // Test ranges::find with nullopt
-  std::vector<std::optional<int>> v = {1, 2, std::nullopt, 4, 5};
+  { // Test ranges::find with nullopt
+    std::vector<std::optional<int>> v = {1, 2, std::nullopt, 4, 5};
 
-  auto it = std::ranges::find(v, std::nullopt);
+    auto it = std::ranges::find(v, std::nullopt);
 
-  assert(it != v.end());
-  assert(*it == std::nullopt);
+    assert(it != v.end());
+    assert(*it == std::nullopt);
+  }
 #endif
 
   return true;

>From 0bd6c7810d8e26b7c17727e0075b24e6dd0d5e6e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 8 Aug 2026 18:47:35 +0300
Subject: [PATCH 10/14] Minor fix

---
 .../optional/optional.nullopt/compare.three_way.pass.cpp         | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
index 8fba1311b922e..caa16bba60424 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -71,6 +71,7 @@ constexpr bool test() {
   { // <=>
     std::same_as<std::strong_ordering> auto result = (std::nullopt <=> std::nullopt);
     static_assert(noexcept(std::nullopt <=> std::nullopt));
+
     assert(result == std::strong_ordering::equal);
   }
 

>From 6054b43ba23a10974757149490086b3585532348 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 8 Aug 2026 19:15:36 +0300
Subject: [PATCH 11/14] Fixed modules

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

diff --git a/libcxx/include/__optional/nullopt_t.h b/libcxx/include/__optional/nullopt_t.h
index 555ab64187579..74c47d4160638 100644
--- a/libcxx/include/__optional/nullopt_t.h
+++ b/libcxx/include/__optional/nullopt_t.h
@@ -10,6 +10,7 @@
 #ifndef _LIBCPP___OPTIONAL_NULLOPT_T_H
 #define _LIBCPP___OPTIONAL_NULLOPT_T_H
 
+#include <__compare/ordering.h>
 #include <__config>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)

>From 10da659a740f0f5ce3752aff08f7124f6e4dab5b Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 8 Aug 2026 19:19:56 +0300
Subject: [PATCH 12/14] Fixes

---
 .../compare.three_way.pass.cpp                | 28 +++++++++++--------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
index caa16bba60424..63aa0432d63d1 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -31,40 +31,46 @@ static_assert(std::three_way_comparable<std::nullopt_t, std::strong_ordering>);
 
 constexpr bool test() {
   { // ==
-    static_assert(std::is_same_v<decltype(std::nullopt == std::nullopt), bool>);
+    auto result = (std::nullopt == std::nullopt);
+    static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt == std::nullopt));
 
-    assert(std::nullopt == std::nullopt);
+    assert(result);
   }
   { // !=
-    static_assert(std::is_same_v<decltype(std::nullopt != std::nullopt), bool>);
+    auto result = (std::nullopt != std::nullopt);
+    static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt != std::nullopt));
 
-    assert(!(std::nullopt != std::nullopt));
+    assert(!result);
   }
   { // <=
-    static_assert(std::is_same_v<decltype(std::nullopt <= std::nullopt), bool>);
+    auto result = (std::nullopt <= std::nullopt);
+    static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt <= std::nullopt));
 
-    assert(std::nullopt <= std::nullopt);
+    assert(result);
   }
   { // >=
-    static_assert(std::is_same_v<decltype(std::nullopt >= std::nullopt), bool>);
+    auto result = (std::nullopt >= std::nullopt);
+    static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt >= std::nullopt));
 
-    assert(std::nullopt >= std::nullopt);
+    assert(result);
   }
   { // >
-    static_assert(std::is_same_v<decltype(std::nullopt > std::nullopt), bool>);
+    auto result = (std::nullopt > std::nullopt);
+    static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt > std::nullopt));
 
     assert(!(std::nullopt > std::nullopt));
   }
   { // <
-    static_assert(std::is_same_v<decltype(std::nullopt < std::nullopt), bool>);
+    auto result = (std::nullopt < std::nullopt);
+    static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt < std::nullopt));
 
-    assert(!(std::nullopt < std::nullopt));
+    assert(!result);
   }
 
 #if TEST_STD_VER >= 20

>From 222e9ced29ab9375d70fa44136943fdb5d9a96bd Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 10 Aug 2026 08:12:55 +0300
Subject: [PATCH 13/14] Review comments

---
 .../optional.nullopt/compare.three_way.pass.cpp    | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
index 63aa0432d63d1..80c72ddd50224 100644
--- a/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
+++ b/libcxx/test/std/utilities/optional/optional.nullopt/compare.three_way.pass.cpp
@@ -31,42 +31,42 @@ static_assert(std::three_way_comparable<std::nullopt_t, std::strong_ordering>);
 
 constexpr bool test() {
   { // ==
-    auto result = (std::nullopt == std::nullopt);
+    decltype(auto) result = std::nullopt == std::nullopt;
     static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt == std::nullopt));
 
     assert(result);
   }
   { // !=
-    auto result = (std::nullopt != std::nullopt);
+    decltype(auto) result = std::nullopt != std::nullopt;
     static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt != std::nullopt));
 
     assert(!result);
   }
   { // <=
-    auto result = (std::nullopt <= std::nullopt);
+    decltype(auto) result = std::nullopt <= std::nullopt;
     static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt <= std::nullopt));
 
     assert(result);
   }
   { // >=
-    auto result = (std::nullopt >= std::nullopt);
+    decltype(auto) result = std::nullopt >= std::nullopt;
     static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt >= std::nullopt));
 
     assert(result);
   }
   { // >
-    auto result = (std::nullopt > std::nullopt);
+    decltype(auto) result = std::nullopt > std::nullopt;
     static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt > std::nullopt));
 
     assert(!(std::nullopt > std::nullopt));
   }
   { // <
-    auto result = (std::nullopt < std::nullopt);
+    decltype(auto) result = std::nullopt < std::nullopt;
     static_assert(std::is_same_v<decltype(result), bool>);
     static_assert(noexcept(std::nullopt < std::nullopt));
 
@@ -75,7 +75,7 @@ constexpr bool test() {
 
 #if TEST_STD_VER >= 20
   { // <=>
-    std::same_as<std::strong_ordering> auto result = (std::nullopt <=> std::nullopt);
+    std::same_as<std::strong_ordering> decltype(auto) result = std::nullopt <=> std::nullopt;
     static_assert(noexcept(std::nullopt <=> std::nullopt));
 
     assert(result == std::strong_ordering::equal);

>From 5d3ffbed53d5264056250c17c7f5359b3b4b8763 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 16 Aug 2026 18:47:47 +0300
Subject: [PATCH 14/14] Updated LWG4612

---
 libcxx/docs/Status/Cxx29Issues.csv | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libcxx/docs/Status/Cxx29Issues.csv b/libcxx/docs/Status/Cxx29Issues.csv
index 13056a97782df..d84eeb44a23ff 100644
--- a/libcxx/docs/Status/Cxx29Issues.csv
+++ b/libcxx/docs/Status/Cxx29Issues.csv
@@ -17,3 +17,6 @@
 "`LWG4567 <https://wg21.link/LWG4567>`__","Feature test macro value for ``apply_result``, ``is_applicable``","2026-06 (Brno)","","","`#204455 <https://github.com/llvm/llvm-project/issues/204455>`__",""
 "`LWG4568 <https://wg21.link/LWG4568>`__","``std::execution::spawn_future`` is mishandling dependent senders","2026-06 (Brno)","","","`#204456 <https://github.com/llvm/llvm-project/issues/204456>`__",""
 "`LWG4579 <https://wg21.link/LWG4579>`__","``make-state<Rcvr>::state-type::complete`` uses ``Env`` which is not in scope","2026-06 (Brno)","","","`#204457 <https://github.com/llvm/llvm-project/issues/204457>`__",""
+"","","","","","",""
+"`LWG4612 <https://wg21.link/LWG4612>`__","Specify the details of ``std::nullopt_t``","Not Adopted Yet","|Complete|","24","",""
+"","","","","","",""



More information about the libcxx-commits mailing list