[libcxx-commits] [libcxx] [libc++][concepts] P2404R3: Move-only types for equality_comparable_with, totally_ordered_with, and three_way_comparable_with (PR #99420)

Janet Cobb via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jul 19 23:17:38 PDT 2024


https://github.com/randomnetcat updated https://github.com/llvm/llvm-project/pull/99420

>From 363738b998edbb39e6836a320d9ebc9c0c3cb28d Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Wed, 17 Jul 2024 21:53:02 -0400
Subject: [PATCH 01/12] P2404R3: Move-only types for relational concepts

---
 libcxx/docs/ReleaseNotes/19.rst               |  1 +
 libcxx/docs/Status/Cxx23Papers.csv            |  2 +-
 libcxx/docs/Status/SpaceshipPapers.csv        |  2 +-
 libcxx/include/CMakeLists.txt                 |  1 +
 .../include/__compare/three_way_comparable.h  | 17 +++++++
 .../__concepts/comparison_common_type.h       | 39 ++++++++++++++++
 .../include/__concepts/equality_comparable.h  | 19 ++++++++
 libcxx/include/module.modulemap               | 45 ++++++++++---------
 .../equality_comparable_with.compile.pass.cpp | 10 +++++
 ...three_way_comparable_with.compile.pass.cpp | 28 ++++++++++++
 libcxx/test/support/compare_types.h           | 23 ++++++++++
 11 files changed, 163 insertions(+), 24 deletions(-)
 create mode 100644 libcxx/include/__concepts/comparison_common_type.h

diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index e6d8acb74aeb2..1699c97652488 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -55,6 +55,7 @@ Implemented Papers
 - P2231R1 - Missing ``constexpr`` in ``std::optional`` and ``std::variant``
 - P0019R8 - ``std::atomic_ref``
 - P2389R2 - Alias template ``dims`` for the ``extents`` of ``mdspan``
+- P2404R3 - Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``
 
 Improvements and New Features
 -----------------------------
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 4f589cd938d7c..bc13e4d9ebfd3 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -67,7 +67,7 @@
 "`P2302R4 <https://wg21.link/P2302R4>`__","LWG","``std::ranges::contains``","July 2022","|Complete|","19.0","|ranges|"
 "`P2322R6 <https://wg21.link/P2322R6>`__","LWG","``ranges::fold``","July 2022","","","|ranges|"
 "`P2374R4 <https://wg21.link/P2374R4>`__","LWG","``views::cartesian_product``","July 2022","","","|ranges|"
-"`P2404R3 <https://wg21.link/P2404R3>`__","LWG","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","July 2022","",""
+"`P2404R3 <https://wg21.link/P2404R3>`__","LWG","Move-only types for ``equality_comparable_with``, ``totally_ordered_with``, and ``three_way_comparable_with``","July 2022","|Complete|","19.0"
 "`P2408R5 <https://wg21.link/P2408R5>`__","LWG","Ranges iterators as inputs to non-Ranges algorithms","July 2022","","","|ranges|"
 "`P2417R2 <https://wg21.link/P2417R2>`__","LWG","A more ``constexpr`` ``bitset``","July 2022","|Complete|","16.0"
 "`P2419R2 <https://wg21.link/P2419R2>`__","LWG","Clarify handling of encodings in localized formatting of chrono types","July 2022","",""
diff --git a/libcxx/docs/Status/SpaceshipPapers.csv b/libcxx/docs/Status/SpaceshipPapers.csv
index 39e1f968c1754..5fbf6a53b6db7 100644
--- a/libcxx/docs/Status/SpaceshipPapers.csv
+++ b/libcxx/docs/Status/SpaceshipPapers.csv
@@ -1,6 +1,6 @@
 "Number","Name","Status","First released version"
 `P1614R2 <https://wg21.link/P1614R2>`_,The Mothership has Landed,|In Progress|,
-`P2404R3 <https://wg21.link/P2404R3>`_,"Relaxing ``equality_comparable_with``'s, ``totally_ordered_with``'s, and ``three_way_comparable_with``'s common reference requirements to support move-only types",,
+`P2404R3 <https://wg21.link/P2404R3>`_,"Relaxing ``equality_comparable_with``'s, ``totally_ordered_with``'s, and ``three_way_comparable_with``'s common reference requirements to support move-only types","|Complete|","19.0"
 `LWG3330 <https://wg21.link/LWG3330>`_,Include ``<compare>`` from most library headers,"|Complete|","13.0"
 `LWG3347 <https://wg21.link/LWG3347>`_,"``std::pair<T, U>`` now requires ``T`` and ``U`` to be *less-than-comparable*",|Nothing To Do|,
 `LWG3350 <https://wg21.link/LWG3350>`_,Simplify return type of ``lexicographical_compare_three_way``,|Nothing To Do|,
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index cd64fe91449c2..e618847b1e27c 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -296,6 +296,7 @@ set(files
   __concepts/class_or_enum.h
   __concepts/common_reference_with.h
   __concepts/common_with.h
+  __concepts/comparison_common_type.h
   __concepts/constructible.h
   __concepts/convertible_to.h
   __concepts/copyable.h
diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h
index 7a44ea9158a6f..3b14725be3309 100644
--- a/libcxx/include/__compare/three_way_comparable.h
+++ b/libcxx/include/__compare/three_way_comparable.h
@@ -12,6 +12,7 @@
 #include <__compare/common_comparison_category.h>
 #include <__compare/ordering.h>
 #include <__concepts/common_reference_with.h>
+#include <__concepts/comparison_common_type.h>
 #include <__concepts/equality_comparable.h>
 #include <__concepts/same_as.h>
 #include <__concepts/totally_ordered.h>
@@ -37,6 +38,20 @@ concept three_way_comparable =
       { __a <=> __b } -> __compares_as<_Cat>;
     };
 
+#  if _LIBCPP_STD_VER >= 23
+
+template <class _Tp, class _Up, class _cat = partial_ordering>
+concept three_way_comparable_with =
+    three_way_comparable<_Tp, _cat> && three_way_comparable<_Up, _cat> && __comparison_common_type_with<_Tp, _Up> &&
+    three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _cat> &&
+    __weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> &&
+    requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
+      { __t <=> __u } -> __compares_as<_cat>;
+      { __u <=> __t } -> __compares_as<_cat>;
+    };
+
+#  else
+
 template <class _Tp, class _Up, class _Cat = partial_ordering>
 concept three_way_comparable_with =
     three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> &&
@@ -48,6 +63,8 @@ concept three_way_comparable_with =
       { __u <=> __t } -> __compares_as<_Cat>;
     };
 
+#  endif // _LIBCPP_STD_VER >= 23
+
 #endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
new file mode 100644
index 0000000000000..a1f246d2a6dca
--- /dev/null
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
+#define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
+
+#include "__concepts/convertible_to.h"
+#include "__concepts/same_as.h"
+#include "__config"
+#include "__type_traits/common_reference.h"
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+template <class _Tp, class _Up, class _C = common_reference_t<const _Tp&, const _Up&>>
+concept __comparison_common_type_with_impl =
+    same_as<common_reference_t<const _Tp&, const _Up&>, common_reference_t<const _Up&, const _Tp&>> && requires {
+      requires convertible_to<const _Tp&, const _C&> || convertible_to<_Tp, const _C&>;
+      requires convertible_to<const _Up&, const _C&> || convertible_to<_Up, const _C&>;
+    };
+
+template <class _Tp, class _Up>
+concept __comparison_common_type_with = __comparison_common_type_with_impl<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
diff --git a/libcxx/include/__concepts/equality_comparable.h b/libcxx/include/__concepts/equality_comparable.h
index 278fc76409289..1904b2e451a8d 100644
--- a/libcxx/include/__concepts/equality_comparable.h
+++ b/libcxx/include/__concepts/equality_comparable.h
@@ -11,6 +11,7 @@
 
 #include <__concepts/boolean_testable.h>
 #include <__concepts/common_reference_with.h>
+#include <__concepts/comparison_common_type.h>
 #include <__config>
 #include <__type_traits/common_reference.h>
 #include <__type_traits/make_const_lvalue_ref.h>
@@ -37,6 +38,22 @@ concept __weakly_equality_comparable_with =
 template <class _Tp>
 concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
 
+#  if _LIBCPP_STD_VER >= 23
+
+// clang-format off
+template <class _Tp, class _Up>
+concept equality_comparable_with =
+    equality_comparable<_Tp> && equality_comparable<_Up> &&
+    __comparison_common_type_with<_Tp, _Up> &&
+    equality_comparable<
+        common_reference_t<
+            __make_const_lvalue_ref<_Tp>,
+            __make_const_lvalue_ref<_Up>>> &&
+    __weakly_equality_comparable_with<_Tp, _Up>;
+// clang-format on
+
+#  else
+
 // clang-format off
 template <class _Tp, class _Up>
 concept equality_comparable_with =
@@ -49,6 +66,8 @@ concept equality_comparable_with =
     __weakly_equality_comparable_with<_Tp, _Up>;
 // clang-format on
 
+#  endif // _LIBCPP_STD_VER >= 23
+
 #endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index f4aaa14c1c2ee..eabb32daf2c96 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1173,43 +1173,44 @@ module std_private_compare_weak_order                     [system] { header "__c
 
 module std_private_complex_complex_fwd            [system] { header "__fwd/complex.h" }
 
-module std_private_concepts_arithmetic            [system] { header "__concepts/arithmetic.h" }
-module std_private_concepts_assignable            [system] { header "__concepts/assignable.h" }
-module std_private_concepts_boolean_testable      [system] { header "__concepts/boolean_testable.h" }
-module std_private_concepts_class_or_enum         [system] { header "__concepts/class_or_enum.h" }
-module std_private_concepts_common_reference_with [system] { header "__concepts/common_reference_with.h" }
-module std_private_concepts_common_with           [system] { header "__concepts/common_with.h" }
-module std_private_concepts_constructible         [system] {
+module std_private_concepts_arithmetic              [system] { header "__concepts/arithmetic.h" }
+module std_private_concepts_assignable              [system] { header "__concepts/assignable.h" }
+module std_private_concepts_boolean_testable        [system] { header "__concepts/boolean_testable.h" }
+module std_private_concepts_class_or_enum           [system] { header "__concepts/class_or_enum.h" }
+module std_private_concepts_common_reference_with   [system] { header "__concepts/common_reference_with.h" }
+module std_private_concepts_common_with             [system] { header "__concepts/common_with.h" }
+module std_private_cooncepts_comparison_common_type [system] { header "__concepts/comparison_common_type.h" }
+module std_private_concepts_constructible           [system] {
   header "__concepts/constructible.h"
   export std_private_concepts_destructible
 }
-module std_private_concepts_convertible_to        [system] { header "__concepts/convertible_to.h" }
-module std_private_concepts_copyable              [system] { header "__concepts/copyable.h" }
-module std_private_concepts_derived_from          [system] { header "__concepts/derived_from.h" }
-module std_private_concepts_destructible          [system] {
+module std_private_concepts_convertible_to          [system] { header "__concepts/convertible_to.h" }
+module std_private_concepts_copyable                [system] { header "__concepts/copyable.h" }
+module std_private_concepts_derived_from            [system] { header "__concepts/derived_from.h" }
+module std_private_concepts_destructible            [system] {
   header "__concepts/destructible.h"
   export std_private_type_traits_is_nothrow_destructible
 }
-module std_private_concepts_different_from        [system] { header "__concepts/different_from.h" }
-module std_private_concepts_equality_comparable   [system] {
+module std_private_concepts_different_from          [system] { header "__concepts/different_from.h" }
+module std_private_concepts_equality_comparable     [system] {
   header "__concepts/equality_comparable.h"
   export std_private_type_traits_common_reference
 }
-module std_private_concepts_invocable             [system] { header "__concepts/invocable.h" }
-module std_private_concepts_movable               [system] {
+module std_private_concepts_invocable               [system] { header "__concepts/invocable.h" }
+module std_private_concepts_movable                 [system] {
   header "__concepts/movable.h"
   export std_private_type_traits_is_object
 }
-module std_private_concepts_predicate             [system] { header "__concepts/predicate.h" }
-module std_private_concepts_regular               [system] { header "__concepts/regular.h" }
-module std_private_concepts_relation              [system] { header "__concepts/relation.h" }
-module std_private_concepts_same_as               [system] {
+module std_private_concepts_predicate               [system] { header "__concepts/predicate.h" }
+module std_private_concepts_regular                 [system] { header "__concepts/regular.h" }
+module std_private_concepts_relation                [system] { header "__concepts/relation.h" }
+module std_private_concepts_same_as                 [system] {
   header "__concepts/same_as.h"
   export std_private_type_traits_is_same
 }
-module std_private_concepts_semiregular           [system] { header "__concepts/semiregular.h" }
-module std_private_concepts_swappable             [system] { header "__concepts/swappable.h" }
-module std_private_concepts_totally_ordered       [system] { header "__concepts/totally_ordered.h" }
+module std_private_concepts_semiregular             [system] { header "__concepts/semiregular.h" }
+module std_private_concepts_swappable               [system] { header "__concepts/swappable.h" }
+module std_private_concepts_totally_ordered         [system] { header "__concepts/totally_ordered.h" }
 
 module std_private_condition_variable_condition_variable [system] {
   header "__condition_variable/condition_variable.h"
diff --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
index e0edd1f332f81..45e3e88a10d14 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
@@ -1119,4 +1119,14 @@ static_assert(
     std::common_reference_with<one_way_ne const&, explicit_operators const&>);
 static_assert(
     !check_equality_comparable_with<one_way_ne, explicit_operators>());
+
+#if TEST_STD_VER >= 23
+static_assert(check_equality_comparable_with<move_only_equality_with_int, int>());
+static_assert(check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
+#else
+static_assert(!check_equality_comparable_with<move_only_equality_with_int, int>());
+static_assert(!check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
+#endif // TEST_STD_VER >= 23
+
+static_assert(!check_equality_comparable_with<immobile_comparable_with_int, int>());
 } // namespace types_fit_for_purpose
diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
index 50d9722aa29c0..2920240dddf55 100644
--- a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
@@ -14,6 +14,7 @@
 #include <compare>
 
 #include "compare_types.h"
+#include "test_macros.h"
 
 template <class T, class U = T, typename Cat = std::partial_ordering>
 constexpr bool check_three_way_comparable_with() {
@@ -223,4 +224,31 @@ struct SpaceshipNonConstArgument {
 };
 
 static_assert(!check_three_way_comparable_with<SpaceshipNonConstArgument>());
+
+struct MoveOnlyIntComparable {
+  MoveOnlyIntComparable(int) {}
+
+  MoveOnlyIntComparable(MoveOnlyIntComparable&&)            = default;
+  MoveOnlyIntComparable& operator=(MoveOnlyIntComparable&&) = default;
+
+  friend auto operator<=>(MoveOnlyIntComparable const&, MoveOnlyIntComparable const&) = default;
+};
+
+#if TEST_STD_VER >= 23
+static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
+#else
+static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
+#endif // TEST_STD_VER >= 23
+
+struct ImmobileIntComparable {
+  ImmobileIntComparable(int) {}
+
+  ImmobileIntComparable(ImmobileIntComparable&&)            = delete;
+  ImmobileIntComparable& operator=(ImmobileIntComparable&&) = delete;
+
+  friend auto operator<=>(ImmobileIntComparable const&, ImmobileIntComparable const&) = default;
+};
+
+static_assert(!check_three_way_comparable_with<ImmobileIntComparable, int>());
+
 } // namespace user_defined
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index 8155f6221540c..eea219d033ae9 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -529,4 +529,27 @@ struct ForwardingTestObject {
   constexpr bool operator>=(const ForwardingTestObject&) const& { return false; }
 };
 
+struct move_only_equality_with_int {
+  move_only_equality_with_int(int);
+
+  move_only_equality_with_int(move_only_equality_with_int&&)            = default;
+  move_only_equality_with_int& operator=(move_only_equality_with_int&&) = default;
+
+  move_only_equality_with_int(move_only_equality_with_int const&)            = delete;
+  move_only_equality_with_int& operator=(move_only_equality_with_int const&) = delete;
+
+  friend bool operator==(move_only_equality_with_int const&, move_only_equality_with_int const&) = default;
+  friend bool operator==(move_only_equality_with_int const&, int);
+};
+
+struct immobile_comparable_with_int {
+  immobile_comparable_with_int(int);
+
+  immobile_comparable_with_int(immobile_comparable_with_int&&)            = delete;
+  immobile_comparable_with_int& operator=(immobile_comparable_with_int&&) = delete;
+
+  friend bool operator==(immobile_comparable_with_int const&, immobile_comparable_with_int const&) = default;
+  friend bool operator==(immobile_comparable_with_int const&, int);
+};
+
 #endif // TEST_SUPPORT_COMPARE_TYPES_H

>From 400144dbc59f68edb96caacac12e8a6b4bac3352 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Wed, 17 Jul 2024 23:28:10 -0400
Subject: [PATCH 02/12] Fix _Cat capitalization

---
 libcxx/include/__compare/three_way_comparable.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h
index 3b14725be3309..f43c6fb010332 100644
--- a/libcxx/include/__compare/three_way_comparable.h
+++ b/libcxx/include/__compare/three_way_comparable.h
@@ -40,14 +40,14 @@ concept three_way_comparable =
 
 #  if _LIBCPP_STD_VER >= 23
 
-template <class _Tp, class _Up, class _cat = partial_ordering>
+template <class _Tp, class _Up, class _Cat = partial_ordering>
 concept three_way_comparable_with =
-    three_way_comparable<_Tp, _cat> && three_way_comparable<_Up, _cat> && __comparison_common_type_with<_Tp, _Up> &&
-    three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _cat> &&
+    three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> && __comparison_common_type_with<_Tp, _Up> &&
+    three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> &&
     __weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> &&
     requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
-      { __t <=> __u } -> __compares_as<_cat>;
-      { __u <=> __t } -> __compares_as<_cat>;
+      { __t <=> __u } -> __compares_as<_Cat>;
+      { __u <=> __t } -> __compares_as<_Cat>;
     };
 
 #  else

>From b03940ef26d99003b5858c2420875453003dbf2e Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Wed, 17 Jul 2024 23:31:09 -0400
Subject: [PATCH 03/12] Make test class naming consistent

---
 .../equality_comparable_with.compile.pass.cpp        |  2 +-
 libcxx/test/support/compare_types.h                  | 12 ++++++------
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
index 45e3e88a10d14..9cc7d38d1c490 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
@@ -1128,5 +1128,5 @@ static_assert(!check_equality_comparable_with<move_only_equality_with_int, int>(
 static_assert(!check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
 #endif // TEST_STD_VER >= 23
 
-static_assert(!check_equality_comparable_with<immobile_comparable_with_int, int>());
+static_assert(!check_equality_comparable_with<immobile_equality_with_int, int>());
 } // namespace types_fit_for_purpose
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index eea219d033ae9..ea24454594110 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -542,14 +542,14 @@ struct move_only_equality_with_int {
   friend bool operator==(move_only_equality_with_int const&, int);
 };
 
-struct immobile_comparable_with_int {
-  immobile_comparable_with_int(int);
+struct immobile_equality_with_int {
+  immobile_equality_with_int(int);
 
-  immobile_comparable_with_int(immobile_comparable_with_int&&)            = delete;
-  immobile_comparable_with_int& operator=(immobile_comparable_with_int&&) = delete;
+  immobile_equality_with_int(immobile_equality_with_int&&)            = delete;
+  immobile_equality_with_int& operator=(immobile_equality_with_int&&) = delete;
 
-  friend bool operator==(immobile_comparable_with_int const&, immobile_comparable_with_int const&) = default;
-  friend bool operator==(immobile_comparable_with_int const&, int);
+  friend bool operator==(immobile_equality_with_int const&, immobile_equality_with_int const&) = default;
+  friend bool operator==(immobile_equality_with_int const&, int);
 };
 
 #endif // TEST_SUPPORT_COMPARE_TYPES_H

>From 35d032afa35a5c56303966a91c793b9a76016dca Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 10:13:09 -0400
Subject: [PATCH 04/12] immobile -> nonmovable

---
 .../equality_comparable_with.compile.pass.cpp        |  2 +-
 .../three_way_comparable_with.compile.pass.cpp       | 12 ++++++------
 libcxx/test/support/compare_types.h                  | 12 ++++++------
 3 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
index 9cc7d38d1c490..bdb42249b8a27 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
@@ -1128,5 +1128,5 @@ static_assert(!check_equality_comparable_with<move_only_equality_with_int, int>(
 static_assert(!check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
 #endif // TEST_STD_VER >= 23
 
-static_assert(!check_equality_comparable_with<immobile_equality_with_int, int>());
+static_assert(!check_equality_comparable_with<nonmovable_equality_with_int, int>());
 } // namespace types_fit_for_purpose
diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
index 2920240dddf55..ee3284d42f540 100644
--- a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
@@ -240,15 +240,15 @@ static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
 static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
 #endif // TEST_STD_VER >= 23
 
-struct ImmobileIntComparable {
-  ImmobileIntComparable(int) {}
+struct NonMovableIntComparable {
+  NonMovableIntComparable(int) {}
 
-  ImmobileIntComparable(ImmobileIntComparable&&)            = delete;
-  ImmobileIntComparable& operator=(ImmobileIntComparable&&) = delete;
+  NonMovableIntComparable(NonMovableIntComparable&&)            = delete;
+  NonMovableIntComparable& operator=(NonMovableIntComparable&&) = delete;
 
-  friend auto operator<=>(ImmobileIntComparable const&, ImmobileIntComparable const&) = default;
+  friend auto operator<=>(NonMovableIntComparable const&, NonMovableIntComparable const&) = default;
 };
 
-static_assert(!check_three_way_comparable_with<ImmobileIntComparable, int>());
+static_assert(!check_three_way_comparable_with<NonMovableIntComparable, int>());
 
 } // namespace user_defined
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index ea24454594110..62203318be725 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -542,14 +542,14 @@ struct move_only_equality_with_int {
   friend bool operator==(move_only_equality_with_int const&, int);
 };
 
-struct immobile_equality_with_int {
-  immobile_equality_with_int(int);
+struct nonmovable_equality_with_int {
+  nonmovable_equality_with_int(int);
 
-  immobile_equality_with_int(immobile_equality_with_int&&)            = delete;
-  immobile_equality_with_int& operator=(immobile_equality_with_int&&) = delete;
+  nonmovable_equality_with_int(nonmovable_equality_with_int&&)            = delete;
+  nonmovable_equality_with_int& operator=(nonmovable_equality_with_int&&) = delete;
 
-  friend bool operator==(immobile_equality_with_int const&, immobile_equality_with_int const&) = default;
-  friend bool operator==(immobile_equality_with_int const&, int);
+  friend bool operator==(nonmovable_equality_with_int const&, nonmovable_equality_with_int const&) = default;
+  friend bool operator==(nonmovable_equality_with_int const&, int);
 };
 
 #endif // TEST_SUPPORT_COMPARE_TYPES_H

>From b87e6aafbf348eb8bd897aff45de7f6e667ffdcf Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 10:16:29 -0400
Subject: [PATCH 05/12] _C -> _CommonRef

---
 libcxx/include/__concepts/comparison_common_type.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
index a1f246d2a6dca..ed95ee3a66700 100644
--- a/libcxx/include/__concepts/comparison_common_type.h
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -22,11 +22,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 23
 
-template <class _Tp, class _Up, class _C = common_reference_t<const _Tp&, const _Up&>>
+template <class _Tp, class _Up, class _CommonRef = common_reference_t<const _Tp&, const _Up&>>
 concept __comparison_common_type_with_impl =
     same_as<common_reference_t<const _Tp&, const _Up&>, common_reference_t<const _Up&, const _Tp&>> && requires {
-      requires convertible_to<const _Tp&, const _C&> || convertible_to<_Tp, const _C&>;
-      requires convertible_to<const _Up&, const _C&> || convertible_to<_Up, const _C&>;
+      requires convertible_to<const _Tp&, const _CommonRef&> || convertible_to<_Tp, const _CommonRef&>;
+      requires convertible_to<const _Up&, const _CommonRef&> || convertible_to<_Up, const _CommonRef&>;
     };
 
 template <class _Tp, class _Up>

>From d5ff4aab7751d1bb4e38f2cc5dc87beeb014ce14 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 11:53:15 -0400
Subject: [PATCH 06/12] Update other comparison tests

---
 .../ranges_partial_sort_copy.pass.cpp         | 21 +++++++++++++++++--
 .../range.cmp/equal_to.pass.cpp               |  7 ++++++-
 .../range.cmp/greater.pass.cpp                |  7 ++++++-
 .../range.cmp/greater_equal.pass.cpp          |  7 ++++++-
 .../function.objects/range.cmp/less.pass.cpp  |  7 ++++++-
 .../range.cmp/less_equal.pass.cpp             |  7 ++++++-
 .../range.cmp/not_equal_to.pass.cpp           |  7 ++++++-
 7 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
index 532ee9b03efc0..0f799bca97775 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
@@ -75,7 +75,12 @@ static_assert(!HasPartialSortCopyIter<int*, int*, int*, int*, IndirectUnaryPredi
 static_assert(!HasPartialSortCopyIter<int*, int*, int*, int*, IndirectUnaryPredicateNotCopyConstructible>);
 
 // !indirectly_copyable<I1, I2>
-static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*>);
+struct OrderedConvertibleToInt {
+  friend auto operator<=>(OrderedConvertibleToInt const&, OrderedConvertibleToInt const&) = default;
+  operator int() const;
+};
+
+static_assert(!HasPartialSortCopyIter<int*, int*, OrderedConvertibleToInt*, OrderedConvertibleToInt*>);
 
 // !sortable<I2, Comp, Proj2>
 static_assert(!HasPartialSortCopyIter<int*, int*, const int*, const int*>);
@@ -84,6 +89,12 @@ struct NoComparator {};
 // !indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>>
 static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator*, NoComparator*>);
 
+#if TEST_STD_VER >= 23
+static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
+#else
+static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
+#endif // TEST_STD_VER >= 23
+
 // Test constraints of the (range) overload.
 // ======================================================
 
@@ -109,7 +120,7 @@ static_assert(!HasPartialSortCopyRange<R<int*>, RandomAccessRangeNotDerivedFrom>
 static_assert(!HasPartialSortCopyRange<R<int*>, RandomAccessRangeBadIndex>);
 
 // !indirectly_copyable<iterator_t<R1>, iterator_t<R2>>
-static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+static_assert(!HasPartialSortCopyRange<R<int*>, R<OrderedConvertibleToInt*>>);
 
 // !sortable<iterator_t<R2>, Comp, Proj2>
 static_assert(!HasPartialSortCopyRange<R<int*>, R<const int*>>);
@@ -117,6 +128,12 @@ static_assert(!HasPartialSortCopyRange<R<int*>, R<const int*>>);
 // !indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>>
 static_assert(!HasPartialSortCopyRange<R<NoComparator*>, R<NoComparator*>>);
 
+#if TEST_STD_VER >= 23
+static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+#else
+static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+#endif // TEST_STD_VER >= 23
+
 static_assert(std::is_same_v<std::ranges::partial_sort_copy_result<int, int>, std::ranges::in_out_result<int, int>>);
 
 template <class Iter, class Sent, class OutIter, class OutSent, std::size_t N>
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
index 6d207548b2175..d5431140841e2 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -28,9 +28,14 @@ struct NotEqualityComparable {
 };
 
 static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
-static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
 static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
 
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
 static_assert(requires { typename std::ranges::equal_to::is_transparent; });
 
 constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
index 002ec10e07aff..7a91a6add6cc0 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
 };
 
 static_assert(!std::is_invocable_v<std::ranges::greater, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
 static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, explicit_operators>);
 
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
 static_assert(requires { typename std::ranges::greater::is_transparent; });
 
 constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
index ad24a98a168cf..7878d6bac04dc 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
 };
 
 static_assert(!std::is_invocable_v<std::ranges::greater_equal, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
 static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators, explicit_operators>);
 
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
 static_assert(requires { typename std::ranges::greater_equal::is_transparent; });
 
 constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
index 5afb7e0ebdef4..8dca5c80da772 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
 };
 
 static_assert(!std::is_invocable_v<std::ranges::less, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
 static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explicit_operators>);
 
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
 static_assert(requires { typename std::ranges::less::is_transparent; });
 
 constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
index 3aa903fa6321a..88d001e9fc1e7 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -27,9 +27,14 @@ struct NotTotallyOrdered {
 };
 
 static_assert(!std::is_invocable_v<std::ranges::less_equal, NotTotallyOrdered, NotTotallyOrdered>);
-static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
 static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, explicit_operators>);
 
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
 static_assert(requires { typename std::ranges::less_equal::is_transparent; });
 
 constexpr bool test() {
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
index 4b46bae76ce48..9463967e7e2f0 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -28,9 +28,14 @@ struct NotEqualityComparable {
 };
 
 static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
-static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
 static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
 
+#if TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#else
+static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER >= 23
+
 static_assert(requires { typename std::ranges::not_equal_to::is_transparent; });
 
 struct PtrAndNotEqOperator {

>From 2debff627bd88dc601c1824954deb619e4d84a91 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 13:36:47 -0400
Subject: [PATCH 07/12] Invert test conditionals

---
 .../equality_comparable_with.compile.pass.cpp          | 10 +++++-----
 .../three_way_comparable_with.compile.pass.cpp         |  8 ++++----
 .../function.objects/range.cmp/equal_to.pass.cpp       |  8 ++++----
 .../function.objects/range.cmp/greater.pass.cpp        |  8 ++++----
 .../function.objects/range.cmp/greater_equal.pass.cpp  |  8 ++++----
 .../utilities/function.objects/range.cmp/less.pass.cpp |  8 ++++----
 .../function.objects/range.cmp/less_equal.pass.cpp     |  8 ++++----
 .../function.objects/range.cmp/not_equal_to.pass.cpp   |  8 ++++----
 8 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
index bdb42249b8a27..d1f41b6701648 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
@@ -1120,13 +1120,13 @@ static_assert(
 static_assert(
     !check_equality_comparable_with<one_way_ne, explicit_operators>());
 
-#if TEST_STD_VER >= 23
-static_assert(check_equality_comparable_with<move_only_equality_with_int, int>());
-static_assert(check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
-#else
+#if TEST_STD_VER < 23
 static_assert(!check_equality_comparable_with<move_only_equality_with_int, int>());
 static_assert(!check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(check_equality_comparable_with<move_only_equality_with_int, int>());
+static_assert(check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
+#endif // TEST_STD_VER < 23
 
 static_assert(!check_equality_comparable_with<nonmovable_equality_with_int, int>());
 } // namespace types_fit_for_purpose
diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
index ee3284d42f540..5f3f06fb33149 100644
--- a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
@@ -234,11 +234,11 @@ struct MoveOnlyIntComparable {
   friend auto operator<=>(MoveOnlyIntComparable const&, MoveOnlyIntComparable const&) = default;
 };
 
-#if TEST_STD_VER >= 23
-static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
-#else
+#if TEST_STD_VER < 23
 static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
+#endif // TEST_STD_VER < 23
 
 struct NonMovableIntComparable {
   NonMovableIntComparable(int) {}
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
index d5431140841e2..10b9aa6e59fd6 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -30,11 +30,11 @@ struct NotEqualityComparable {
 static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
 static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
 
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
 
 static_assert(requires { typename std::ranges::equal_to::is_transparent; });
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
index 7a91a6add6cc0..b8d1da2d1410f 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
 static_assert(!std::is_invocable_v<std::ranges::greater, NotTotallyOrdered, NotTotallyOrdered>);
 static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, explicit_operators>);
 
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
 
 static_assert(requires { typename std::ranges::greater::is_transparent; });
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
index 7878d6bac04dc..26ec6663364ee 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
 static_assert(!std::is_invocable_v<std::ranges::greater_equal, NotTotallyOrdered, NotTotallyOrdered>);
 static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators, explicit_operators>);
 
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
 
 static_assert(requires { typename std::ranges::greater_equal::is_transparent; });
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
index 8dca5c80da772..70ed88fbcea2c 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
 static_assert(!std::is_invocable_v<std::ranges::less, NotTotallyOrdered, NotTotallyOrdered>);
 static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explicit_operators>);
 
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
 
 static_assert(requires { typename std::ranges::less::is_transparent; });
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
index 88d001e9fc1e7..d422bea55f9eb 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -29,11 +29,11 @@ struct NotTotallyOrdered {
 static_assert(!std::is_invocable_v<std::ranges::less_equal, NotTotallyOrdered, NotTotallyOrdered>);
 static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, explicit_operators>);
 
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
-#else
+#if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
 
 static_assert(requires { typename std::ranges::less_equal::is_transparent; });
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
index 9463967e7e2f0..147a248348da8 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -30,11 +30,11 @@ struct NotEqualityComparable {
 static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
 static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
 
-#if TEST_STD_VER >= 23
-static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+#if TEST_STD_VER < 23
+static_assert(!std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
 #else
-static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
-#endif // TEST_STD_VER >= 23
+static_assert(std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
+#endif // TEST_STD_VER < 23
 
 static_assert(requires { typename std::ranges::not_equal_to::is_transparent; });
 

>From bb8ee9d7bf238acca940ffbb5c8b57a7ff2bc9fb Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 13:49:41 -0400
Subject: [PATCH 08/12] Don't split definitions of
 equality_comparable_with/totally_ordered_with

---
 .../include/__compare/three_way_comparable.h   | 17 -----------------
 .../__concepts/comparison_common_type.h        | 16 ++++++++++++++--
 .../include/__concepts/equality_comparable.h   | 18 ------------------
 libcxx/test/support/compare_types.h            |  3 +++
 4 files changed, 17 insertions(+), 37 deletions(-)

diff --git a/libcxx/include/__compare/three_way_comparable.h b/libcxx/include/__compare/three_way_comparable.h
index f43c6fb010332..ad6d05a681145 100644
--- a/libcxx/include/__compare/three_way_comparable.h
+++ b/libcxx/include/__compare/three_way_comparable.h
@@ -38,8 +38,6 @@ concept three_way_comparable =
       { __a <=> __b } -> __compares_as<_Cat>;
     };
 
-#  if _LIBCPP_STD_VER >= 23
-
 template <class _Tp, class _Up, class _Cat = partial_ordering>
 concept three_way_comparable_with =
     three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> && __comparison_common_type_with<_Tp, _Up> &&
@@ -50,21 +48,6 @@ concept three_way_comparable_with =
       { __u <=> __t } -> __compares_as<_Cat>;
     };
 
-#  else
-
-template <class _Tp, class _Up, class _Cat = partial_ordering>
-concept three_way_comparable_with =
-    three_way_comparable<_Tp, _Cat> && three_way_comparable<_Up, _Cat> &&
-    common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> &&
-    three_way_comparable<common_reference_t<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>, _Cat> &&
-    __weakly_equality_comparable_with<_Tp, _Up> && __partially_ordered_with<_Tp, _Up> &&
-    requires(__make_const_lvalue_ref<_Tp> __t, __make_const_lvalue_ref<_Up> __u) {
-      { __t <=> __u } -> __compares_as<_Cat>;
-      { __u <=> __t } -> __compares_as<_Cat>;
-    };
-
-#  endif // _LIBCPP_STD_VER >= 23
-
 #endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
index ed95ee3a66700..cff61e14d501d 100644
--- a/libcxx/include/__concepts/comparison_common_type.h
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -9,10 +9,12 @@
 #ifndef _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
 #define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
 
+#include "__concepts/common_reference_with.h"
 #include "__concepts/convertible_to.h"
 #include "__concepts/same_as.h"
 #include "__config"
 #include "__type_traits/common_reference.h"
+#include "__type_traits/make_const_lvalue_ref.h"
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -20,7 +22,15 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-#if _LIBCPP_STD_VER >= 23
+#if _LIBCPP_STD_VER >= 20
+
+#  if _LIBCPP_STD_VER < 23
+
+template <class _Tp, class _Up>
+concept __comparison_common_type_with =
+    common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>>;
+
+#  else
 
 template <class _Tp, class _Up, class _CommonRef = common_reference_t<const _Tp&, const _Up&>>
 concept __comparison_common_type_with_impl =
@@ -32,7 +42,9 @@ concept __comparison_common_type_with_impl =
 template <class _Tp, class _Up>
 concept __comparison_common_type_with = __comparison_common_type_with_impl<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
 
-#endif // _LIBCPP_STD_VER >= 23
+#  endif // _LIBCPP_STD_VER < 23
+
+#endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/__concepts/equality_comparable.h b/libcxx/include/__concepts/equality_comparable.h
index 1904b2e451a8d..56fc6f8b685c0 100644
--- a/libcxx/include/__concepts/equality_comparable.h
+++ b/libcxx/include/__concepts/equality_comparable.h
@@ -38,8 +38,6 @@ concept __weakly_equality_comparable_with =
 template <class _Tp>
 concept equality_comparable = __weakly_equality_comparable_with<_Tp, _Tp>;
 
-#  if _LIBCPP_STD_VER >= 23
-
 // clang-format off
 template <class _Tp, class _Up>
 concept equality_comparable_with =
@@ -52,22 +50,6 @@ concept equality_comparable_with =
     __weakly_equality_comparable_with<_Tp, _Up>;
 // clang-format on
 
-#  else
-
-// clang-format off
-template <class _Tp, class _Up>
-concept equality_comparable_with =
-    equality_comparable<_Tp> && equality_comparable<_Up> &&
-    common_reference_with<__make_const_lvalue_ref<_Tp>, __make_const_lvalue_ref<_Up>> &&
-    equality_comparable<
-        common_reference_t<
-            __make_const_lvalue_ref<_Tp>,
-            __make_const_lvalue_ref<_Up>>> &&
-    __weakly_equality_comparable_with<_Tp, _Up>;
-// clang-format on
-
-#  endif // _LIBCPP_STD_VER >= 23
-
 #endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/support/compare_types.h b/libcxx/test/support/compare_types.h
index 62203318be725..b52e201f240ac 100644
--- a/libcxx/test/support/compare_types.h
+++ b/libcxx/test/support/compare_types.h
@@ -548,6 +548,9 @@ struct nonmovable_equality_with_int {
   nonmovable_equality_with_int(nonmovable_equality_with_int&&)            = delete;
   nonmovable_equality_with_int& operator=(nonmovable_equality_with_int&&) = delete;
 
+  nonmovable_equality_with_int(nonmovable_equality_with_int const&)            = delete;
+  nonmovable_equality_with_int& operator=(nonmovable_equality_with_int const&) = delete;
+
   friend bool operator==(nonmovable_equality_with_int const&, nonmovable_equality_with_int const&) = default;
   friend bool operator==(nonmovable_equality_with_int const&, int);
 };

>From 441884dbb6a4ab3466a982c5b69aac4367a1b53e Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Thu, 18 Jul 2024 15:00:34 -0400
Subject: [PATCH 09/12] Fix last >= 23 check

---
 .../ranges_partial_sort_copy.pass.cpp            | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
index 0f799bca97775..fc00f9c79a94e 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
@@ -89,11 +89,11 @@ struct NoComparator {};
 // !indirect_strict_weak_order<Comp, projected<I1, Proj1>, projected<I2, Proj2>>
 static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator*, NoComparator*>);
 
-#if TEST_STD_VER >= 23
-static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
-#else
+#if TEST_STD_VER < 23
 static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
+#endif // TEST_STD_VER < 23
 
 // Test constraints of the (range) overload.
 // ======================================================
@@ -128,11 +128,11 @@ static_assert(!HasPartialSortCopyRange<R<int*>, R<const int*>>);
 // !indirect_strict_weak_order<Comp, projected<iterator_t<R1>, Proj1>, projected<iterator_t<R2>, Proj2>>
 static_assert(!HasPartialSortCopyRange<R<NoComparator*>, R<NoComparator*>>);
 
-#if TEST_STD_VER >= 23
-static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
-#else
+#if TEST_STD_VER < 23
 static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
-#endif // TEST_STD_VER >= 23
+#else
+static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
+#endif // TEST_STD_VER < 23
 
 static_assert(std::is_same_v<std::ranges::partial_sort_copy_result<int, int>, std::ranges::in_out_result<int, int>>);
 

>From a415b0bfaa8480a8bcc573637fdeba91635aa78c Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Fri, 19 Jul 2024 11:18:57 -0400
Subject: [PATCH 10/12] Fix quotation mark includes

---
 libcxx/include/__concepts/comparison_common_type.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libcxx/include/__concepts/comparison_common_type.h b/libcxx/include/__concepts/comparison_common_type.h
index cff61e14d501d..e3fd12e571c7e 100644
--- a/libcxx/include/__concepts/comparison_common_type.h
+++ b/libcxx/include/__concepts/comparison_common_type.h
@@ -9,12 +9,12 @@
 #ifndef _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
 #define _LIBCPP___CONCEPTS_COMPARISON_COMMON_TYPE_H
 
-#include "__concepts/common_reference_with.h"
-#include "__concepts/convertible_to.h"
-#include "__concepts/same_as.h"
-#include "__config"
-#include "__type_traits/common_reference.h"
-#include "__type_traits/make_const_lvalue_ref.h"
+#include <__concepts/common_reference_with.h>
+#include <__concepts/convertible_to.h>
+#include <__concepts/same_as.h>
+#include <__config>
+#include <__type_traits/common_reference.h>
+#include <__type_traits/make_const_lvalue_ref.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header

>From 29634b0443d1deb9e64747faccbf8101fe529f1a Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Fri, 19 Jul 2024 11:21:36 -0400
Subject: [PATCH 11/12] Add comments to tests

---
 .../partial.sort.copy/ranges_partial_sort_copy.pass.cpp         | 2 ++
 .../equality_comparable_with.compile.pass.cpp                   | 1 +
 .../cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp  | 1 +
 .../std/utilities/function.objects/range.cmp/equal_to.pass.cpp  | 1 +
 .../std/utilities/function.objects/range.cmp/greater.pass.cpp   | 1 +
 .../utilities/function.objects/range.cmp/greater_equal.pass.cpp | 1 +
 .../test/std/utilities/function.objects/range.cmp/less.pass.cpp | 1 +
 .../utilities/function.objects/range.cmp/less_equal.pass.cpp    | 1 +
 .../utilities/function.objects/range.cmp/not_equal_to.pass.cpp  | 1 +
 9 files changed, 10 insertions(+)

diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
index fc00f9c79a94e..ffe024b3dc69f 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/partial.sort.copy/ranges_partial_sort_copy.pass.cpp
@@ -92,6 +92,7 @@ static_assert(!HasPartialSortCopyIter<NoComparator*, NoComparator*, NoComparator
 #if TEST_STD_VER < 23
 static_assert(!HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
 #else
+// P2404
 static_assert(HasPartialSortCopyIter<int*, int*, MoveOnly*, MoveOnly*>);
 #endif // TEST_STD_VER < 23
 
@@ -131,6 +132,7 @@ static_assert(!HasPartialSortCopyRange<R<NoComparator*>, R<NoComparator*>>);
 #if TEST_STD_VER < 23
 static_assert(!HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
 #else
+// P2404
 static_assert(HasPartialSortCopyRange<R<int*>, R<MoveOnly*>>);
 #endif // TEST_STD_VER < 23
 
diff --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
index d1f41b6701648..ba890be18dde1 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
@@ -1124,6 +1124,7 @@ static_assert(
 static_assert(!check_equality_comparable_with<move_only_equality_with_int, int>());
 static_assert(!check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
 #else
+// P2404
 static_assert(check_equality_comparable_with<move_only_equality_with_int, int>());
 static_assert(check_equality_comparable_with<std::unique_ptr<int>, std::nullptr_t>());
 #endif // TEST_STD_VER < 23
diff --git a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
index 5f3f06fb33149..89a269dadc023 100644
--- a/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.concept/three_way_comparable_with.compile.pass.cpp
@@ -237,6 +237,7 @@ struct MoveOnlyIntComparable {
 #if TEST_STD_VER < 23
 static_assert(!check_three_way_comparable_with<MoveOnlyIntComparable, int>());
 #else
+// P2404
 static_assert(check_three_way_comparable_with<MoveOnlyIntComparable, int>());
 #endif // TEST_STD_VER < 23
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
index 10b9aa6e59fd6..5007c933ce076 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -33,6 +33,7 @@ static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, exp
 #if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
 #else
+// P2404
 static_assert(std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
 #endif // TEST_STD_VER < 23
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
index b8d1da2d1410f..765915a628f4a 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, expl
 #if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
 #else
+// P2404
 static_assert(std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
 #endif // TEST_STD_VER < 23
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
index 26ec6663364ee..3d3cdef3124f8 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators
 #if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
 #else
+// P2404
 static_assert(std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
 #endif // TEST_STD_VER < 23
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
index 70ed88fbcea2c..bbf92361002c2 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explici
 #if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
 #else
+// P2404
 static_assert(std::is_invocable_v<std::ranges::less, int, MoveOnly>);
 #endif // TEST_STD_VER < 23
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
index d422bea55f9eb..4d3b85dce1183 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -32,6 +32,7 @@ static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, e
 #if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
 #else
+// P2404
 static_assert(std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
 #endif // TEST_STD_VER < 23
 
diff --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
index 147a248348da8..2acacd6a18fb4 100644
--- a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -33,6 +33,7 @@ static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, exp
 #if TEST_STD_VER < 23
 static_assert(!std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
 #else
+// P2404
 static_assert(std::is_invocable_v<std::ranges::not_equal_to, int, MoveOnly>);
 #endif // TEST_STD_VER < 23
 

>From ddb3d2f241a99f42b74b791737d148b201690b11 Mon Sep 17 00:00:00 2001
From: Janet Cobb <git at randomcat.org>
Date: Sat, 20 Jul 2024 02:17:20 -0400
Subject: [PATCH 12/12] Bump __cpp_lib_concepts

---
 libcxx/docs/FeatureTestMacroTable.rst                    | 2 ++
 libcxx/include/version                                   | 5 ++++-
 .../concepts.version.compile.pass.cpp                    | 9 +++++----
 .../version.version.compile.pass.cpp                     | 9 +++++----
 libcxx/utils/generate_feature_test_macro_components.py   | 2 +-
 5 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 1e347d043ef69..3e0fbdb770621 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -312,6 +312,8 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_byteswap``                                     ``202110L``
     ---------------------------------------------------------- -----------------
+    ``__cpp_lib_concepts``                                     ``202207L``
+    ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_bitset``                             ``202207L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_charconv``                           ``202207L``
diff --git a/libcxx/include/version b/libcxx/include/version
index c971336bcb85c..d83a9a498f812 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -59,7 +59,8 @@ __cpp_lib_chrono                                        201611L <chrono>
 __cpp_lib_chrono_udls                                   201304L <chrono>
 __cpp_lib_clamp                                         201603L <algorithm>
 __cpp_lib_complex_udls                                  201309L <complex>
-__cpp_lib_concepts                                      202002L <concepts>
+__cpp_lib_concepts                                      202207L <concepts>
+                                                        202002L // C++20
 __cpp_lib_constexpr_algorithms                          201806L <algorithm> <utility>
 __cpp_lib_constexpr_bitset                              202207L <bitset>
 __cpp_lib_constexpr_charconv                            202207L <charconv>
@@ -457,6 +458,8 @@ __cpp_lib_void_t                                        201411L <type_traits>
 // # define __cpp_lib_associative_heterogeneous_erasure    202110L
 # define __cpp_lib_bind_back                            202202L
 # define __cpp_lib_byteswap                             202110L
+# undef  __cpp_lib_concepts
+# define __cpp_lib_concepts                             202207L
 # define __cpp_lib_constexpr_bitset                     202207L
 # define __cpp_lib_constexpr_charconv                   202207L
 // # define __cpp_lib_constexpr_cmath                      202202L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp
index aa82b9ef87b87..7f4cba190efb3 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.compile.pass.cpp
@@ -17,6 +17,7 @@
 
 /*  Constant              Value
     __cpp_lib_concepts    202002L [C++20]
+                          202207L [C++23]
 */
 
 #include <concepts>
@@ -54,8 +55,8 @@
 # ifndef __cpp_lib_concepts
 #   error "__cpp_lib_concepts should be defined in c++23"
 # endif
-# if __cpp_lib_concepts != 202002L
-#   error "__cpp_lib_concepts should have the value 202002L in c++23"
+# if __cpp_lib_concepts != 202207L
+#   error "__cpp_lib_concepts should have the value 202207L in c++23"
 # endif
 
 #elif TEST_STD_VER > 23
@@ -63,8 +64,8 @@
 # ifndef __cpp_lib_concepts
 #   error "__cpp_lib_concepts should be defined in c++26"
 # endif
-# if __cpp_lib_concepts != 202002L
-#   error "__cpp_lib_concepts should have the value 202002L in c++26"
+# if __cpp_lib_concepts != 202207L
+#   error "__cpp_lib_concepts should have the value 202207L in c++26"
 # endif
 
 #endif // TEST_STD_VER > 23
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index a01ee702a5172..bda4c54ffad17 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -55,6 +55,7 @@
     __cpp_lib_clamp                                         201603L [C++17]
     __cpp_lib_complex_udls                                  201309L [C++14]
     __cpp_lib_concepts                                      202002L [C++20]
+                                                            202207L [C++23]
     __cpp_lib_constexpr_algorithms                          201806L [C++20]
     __cpp_lib_constexpr_bitset                              202207L [C++23]
     __cpp_lib_constexpr_charconv                            202207L [C++23]
@@ -4828,8 +4829,8 @@
 # ifndef __cpp_lib_concepts
 #   error "__cpp_lib_concepts should be defined in c++23"
 # endif
-# if __cpp_lib_concepts != 202002L
-#   error "__cpp_lib_concepts should have the value 202002L in c++23"
+# if __cpp_lib_concepts != 202207L
+#   error "__cpp_lib_concepts should have the value 202207L in c++23"
 # endif
 
 # ifndef __cpp_lib_constexpr_algorithms
@@ -6462,8 +6463,8 @@
 # ifndef __cpp_lib_concepts
 #   error "__cpp_lib_concepts should be defined in c++26"
 # endif
-# if __cpp_lib_concepts != 202002L
-#   error "__cpp_lib_concepts should have the value 202002L in c++26"
+# if __cpp_lib_concepts != 202207L
+#   error "__cpp_lib_concepts should have the value 202207L in c++26"
 # endif
 
 # ifndef __cpp_lib_constexpr_algorithms
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 773b1523cde4e..f55184c53b600 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -307,7 +307,7 @@ def add_version_header(tc):
         },
         {
             "name": "__cpp_lib_concepts",
-            "values": {"c++20": 202002},
+            "values": {"c++20": 202002, "c++23": 202207},
             "headers": ["concepts"],
         },
         {



More information about the libcxx-commits mailing list