[libcxx-commits] [libcxx] [libc++] Implement P2830R10: Standardized Constexpr Type Ordering (PR #216616)
Matthias Wippich via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Aug 23 12:04:36 PDT 2026
https://github.com/Tsche updated https://github.com/llvm/llvm-project/pull/216616
>From cccd37d78b5cf402733f998ee601905543366c59 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Mon, 17 Aug 2026 01:49:15 +0200
Subject: [PATCH 1/8] [libc++] Implement P2830R10: Standardized Constexpr Type
Ordering
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +
libcxx/docs/ReleaseNotes/24.rst | 3 +
libcxx/docs/Status/Cxx26Issues.csv | 2 +-
libcxx/docs/Status/Cxx26Papers.csv | 6 +-
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__compare/type_order.h | 40 ++++++++++
libcxx/include/compare | 4 +
libcxx/include/module.modulemap.in | 1 +
libcxx/include/version | 4 +
libcxx/modules/std/compare.inc | 6 ++
.../cmp.type/no_specializations.verify.cpp | 30 ++++++++
.../cmp/cmp.type/type_order.compile.pass.cpp | 75 +++++++++++++++++++
.../compare.version.compile.pass.cpp | 9 +++
.../version.version.compile.pass.cpp | 9 +++
.../generate_feature_test_macro_components.py | 7 ++
15 files changed, 195 insertions(+), 4 deletions(-)
create mode 100644 libcxx/include/__compare/type_order.h
create mode 100644 libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
create mode 100644 libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index b710e3800f70d..44879f08233b3 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -550,6 +550,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_tuple_like`` *unimplemented*
---------------------------------------------------------- -----------------
+ ``__cpp_lib_type_order`` ``202506L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202306L``
========================================================== =================
diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index e9a36ae94392f..71442d215bb62 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -47,6 +47,9 @@ Implemented Papers
- P3961R1: Less double indirection in ``function_ref`` (RU-220) (`Github <https://llvm.org/PR189606>`__)
- P1901R2: Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers (`Github <https://llvm.org/PR105372>`__)
- P0528R3: The Curious Case of Padding Bits, Featuring Atomic Compare-and-Exchange (`Github <https://llvm.org/PR76180>`__)
+- P2830R10: Standardized Constexpr Type Ordering (`Github <https://llvm.org/TBD>`__)
+- P3778R0: Fix for ``type_order`` template definition (`Github <https://llvm.org/TBD>`__)
+- P4140R0: Proposed resolution for US70-126: allow incomplete types in type_order (`Github <https://llvm.org/TBD>`__)
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 46242eace0c97..3ffa6bb3009e8 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -183,7 +183,7 @@
"`LWG4301 <https://wg21.link/LWG4301>`__","``condition_variable{_any}::wait_{for, until}`` should take timeout by value","2025-11 (Kona)","","","`#171341 <https://github.com/llvm/llvm-project/issues/171341>`__",""
"`LWG4302 <https://wg21.link/LWG4302>`__","Problematic ``vector_sum_of_squares`` wording","2025-11 (Kona)","","","`#171342 <https://github.com/llvm/llvm-project/issues/171342>`__",""
"`LWG4304 <https://wg21.link/LWG4304>`__","``std::optional<NonReturnable&>`` is ill-formed due to ``value_or``","2025-11 (Kona)","","","`#171343 <https://github.com/llvm/llvm-project/issues/171343>`__",""
-"`LWG4305 <https://wg21.link/LWG4305>`__","Missing user requirements on ``type_order`` template","2025-11 (Kona)","","","`#171344 <https://github.com/llvm/llvm-project/issues/171344>`__",""
+"`LWG4305 <https://wg21.link/LWG4305>`__","Missing user requirements on ``type_order`` template","2025-11 (Kona)","|Complete|","24","`#171344 <https://github.com/llvm/llvm-project/issues/171344>`__",""
"`LWG4308 <https://wg21.link/LWG4308>`__","``std::optional<T&>::iterator`` can't be a contiguous iterator for some ``T``","2025-11 (Kona)","|Complete|","22","`#171345 <https://github.com/llvm/llvm-project/issues/171345>`__",""
"`LWG4312 <https://wg21.link/LWG4312>`__","Const and value category mismatch for ``allocator_arg_t``/``allocator_arg`` in the description of uses-allocator construction","2025-11 (Kona)","","","`#171346 <https://github.com/llvm/llvm-project/issues/171346>`__",""
"`LWG4315 <https://wg21.link/LWG4315>`__","Insufficient specification of ``vector_two_norm`` and ``matrix_frob_norm``","2025-11 (Kona)","","","`#171347 <https://github.com/llvm/llvm-project/issues/171347>`__",""
diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv
index bbc6310beeb63..fc38b0a47070e 100644
--- a/libcxx/docs/Status/Cxx26Papers.csv
+++ b/libcxx/docs/Status/Cxx26Papers.csv
@@ -137,7 +137,7 @@
"`P3383R3 <https://wg21.link/P3383R3>`__","``mdspan.at()``","2025-06 (Sofia)","|Complete|","23","`#148149 <https://github.com/llvm/llvm-project/issues/148149>`__",""
"`P2927R3 <https://wg21.link/P2927R3>`__","Inspecting ``exception_ptr``","2025-06 (Sofia)","","","`#148150 <https://github.com/llvm/llvm-project/issues/148150>`__",""
"`P3748R0 <https://wg21.link/P3748R0>`__","Inspecting ``exception_ptr`` should be constexpr","2025-06 (Sofia)","","","`#148151 <https://github.com/llvm/llvm-project/issues/148151>`__",""
-"`P2830R10 <https://wg21.link/P2830R10>`__","Standardized Constexpr Type Ordering","2025-06 (Sofia)","","","`#148152 <https://github.com/llvm/llvm-project/issues/148152>`__",""
+"`P2830R10 <https://wg21.link/P2830R10>`__","Standardized Constexpr Type Ordering","2025-06 (Sofia)","|Complete|","24","`#148152 <https://github.com/llvm/llvm-project/issues/148152>`__",""
"`P3570R2 <https://wg21.link/P3570R2>`__","optional variants in sender/receiver","2025-06 (Sofia)","","","`#148153 <https://github.com/llvm/llvm-project/issues/148153>`__",""
"`P3481R5 <https://wg21.link/P3481R5>`__","``std::execution::bulk()`` issues","2025-06 (Sofia)","","","`#148155 <https://github.com/llvm/llvm-project/issues/148155>`__",""
"`P3433R1 <https://wg21.link/P3433R1>`__","Allocator Support for Operation States","2025-06 (Sofia)","","","`#148157 <https://github.com/llvm/llvm-project/issues/148157>`__",""
@@ -168,7 +168,7 @@
"`P3774R1 <https://wg21.link/P3774R1>`__","Rename ``std::nontype``, and make it broadly useful","2025-11 (Kona)","","","`#171279 <https://github.com/llvm/llvm-project/issues/171279>`__",""
"`P3819R0 <https://wg21.link/P3819R0>`__","Remove ``evaluation_exception()`` from contract-violation handling for C++26","2025-11 (Kona)","","","`#171280 <https://github.com/llvm/llvm-project/issues/171280>`__",""
"`P3612R1 <https://wg21.link/P3612R1>`__","Harmonize proxy-reference operations (LWG 3638 and 4187)","2025-11 (Kona)","","","`#171281 <https://github.com/llvm/llvm-project/issues/171281>`__",""
-"`P3778R0 <https://wg21.link/P3778R0>`__","Fix for ``type_order`` template definition","2025-11 (Kona)","","","`#171284 <https://github.com/llvm/llvm-project/issues/171284>`__",""
+"`P3778R0 <https://wg21.link/P3778R0>`__","Fix for ``type_order`` template definition","2025-11 (Kona)","|Complete|","24","`#171284 <https://github.com/llvm/llvm-project/issues/171284>`__",""
"`P1789R3 <https://wg21.link/P1789R3>`__","Library Support for Expansion Statements","2025-11 (Kona)","|Complete|","22","`#167268 <https://github.com/llvm/llvm-project/issues/167268>`__",""
"`P3922R1 <https://wg21.link/P3922R1>`__","Missing deduction guide from ``simd::mask`` to ``simd::vec``","2025-11 (Kona)","","","`#171285 <https://github.com/llvm/llvm-project/issues/171285>`__",""
"`P3878R1 <https://wg21.link/P3878R1>`__","Standard library hardening should not use the 'observe' semantic","2025-11 (Kona)","","","`#171286 <https://github.com/llvm/llvm-project/issues/171286>`__",""
@@ -185,7 +185,7 @@
"`P4012R1 <https://wg21.link/P4012R1>`__","Value-preserving consteval broadcast to ``simd::vec``","2026-03 (Croydon)","","","`#189592 <https://github.com/llvm/llvm-project/issues/189592>`__",""
"`P3886R0 <https://wg21.link/P3886R0>`__","Wording for AT1-057","2026-03 (Croydon)","","","`#189593 <https://github.com/llvm/llvm-project/issues/189593>`__",""
"`P3936R1 <https://wg21.link/P3936R1>`__","Safer ``atomic_ref::address`` (FR-030-310)","2026-03 (Croydon)","|Complete|","23","`#189594 <https://github.com/llvm/llvm-project/issues/189594>`__",""
-"`P4140R0 <https://wg21.link/P4140R0>`__","Proposed resolution for US70-126: allow incomplete types in type_order","2026-03 (Croydon)","","","`#189595 <https://github.com/llvm/llvm-project/issues/189595>`__",""
+"`P4140R0 <https://wg21.link/P4140R0>`__","Proposed resolution for US70-126: allow incomplete types in type_order","2026-03 (Croydon)","|Complete|","24","`#189595 <https://github.com/llvm/llvm-project/issues/189595>`__",""
"`P3373R4 <https://wg21.link/P3373R4>`__","Of Operation States and Their Lifetimes","2026-03 (Croydon)","","","`#189597 <https://github.com/llvm/llvm-project/issues/189597>`__",""
"`P3986R1 <https://wg21.link/P3986R1>`__","A Wording Strategy for Inlinable Receivers","2026-03 (Croydon)","","","`#189598 <https://github.com/llvm/llvm-project/issues/189598>`__",""
"`P3059R2 <https://wg21.link/P3059R2>`__","Making user-defined constructors of view iterators/sentinels private","2026-03 (Croydon)","|Complete|","24","`#189599 <https://github.com/llvm/llvm-project/issues/189599>`__",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index a1d6a09aa6b20..88dfda8dec31c 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -308,6 +308,7 @@ set(files
__compare/strong_order.h
__compare/synth_three_way.h
__compare/three_way_comparable.h
+ __compare/type_order.h
__compare/weak_order.h
__concepts/arithmetic.h
__concepts/assignable.h
diff --git a/libcxx/include/__compare/type_order.h b/libcxx/include/__compare/type_order.h
new file mode 100644
index 0000000000000..9cfd84c134b68
--- /dev/null
+++ b/libcxx/include/__compare/type_order.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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___COMPARE_TYPE_ORDER
+#define _LIBCPP___COMPARE_TYPE_ORDER
+
+#include <__compare/ordering.h>
+#include <__config>
+
+#ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+
+// [compare.type], type ordering
+template <class _Tp, class _Up>
+struct _LIBCPP_NO_SPECIALIZATIONS type_order {
+ static constexpr strong_ordering value = __builtin_type_order(_Tp, _Up);
+ using value_type = strong_ordering;
+
+ _LIBCPP_HIDE_FROM_ABI constexpr operator value_type() const noexcept { return value; }
+ _LIBCPP_HIDE_FROM_ABI constexpr value_type operator()() const noexcept { return value; }
+};
+
+template <class _Tp, class _Up>
+constexpr strong_ordering type_order_v = __builtin_type_order(_Tp, _Up);
+
+#endif // _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___COMPARE_TYPE_ORDER
diff --git a/libcxx/include/compare b/libcxx/include/compare
index de1f845271a48..747cbf578a97d 100644
--- a/libcxx/include/compare
+++ b/libcxx/include/compare
@@ -161,6 +161,10 @@ namespace std {
# include <__compare/weak_order.h>
# endif // _LIBCPP_STD_VER >= 20
+# if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+# include <__compare/type_order.h>
+# endif
+
# include <version>
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index 4512cc71153ca..570ea706458e1 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1064,6 +1064,7 @@ module std {
module strong_order { header "__compare/strong_order.h" }
module synth_three_way { header "__compare/synth_three_way.h" }
module three_way_comparable { header "__compare/three_way_comparable.h" }
+ module type_order { header "__compare/type_order.h" }
module weak_order { header "__compare/weak_order.h" }
header "compare"
diff --git a/libcxx/include/version b/libcxx/include/version
index 9a151910ae590..ca6f8b81cdb61 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -283,6 +283,7 @@ __cpp_lib_tuple_like 202311L <map> <tuple> <u
202207L // C++23
__cpp_lib_tuples_by_type 201304L <tuple> <utility>
__cpp_lib_type_identity 201806L <type_traits>
+__cpp_lib_type_order 202506L <compare> // C++26
__cpp_lib_type_trait_variable_templates 201510L <type_traits>
__cpp_lib_uncaught_exceptions 201411L <exception>
__cpp_lib_unordered_map_try_emplace 201411L <unordered_map>
@@ -645,6 +646,9 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_to_string 202306L
# undef __cpp_lib_tuple_like
// # define __cpp_lib_tuple_like 202311L
+# if __has_builtin(__builtin_type_order)
+# define __cpp_lib_type_order 202506L
+# endif
# undef __cpp_lib_variant
# define __cpp_lib_variant 202306L
#endif
diff --git a/libcxx/modules/std/compare.inc b/libcxx/modules/std/compare.inc
index 9d002d301efc3..fcd12fddabd52 100644
--- a/libcxx/modules/std/compare.inc
+++ b/libcxx/modules/std/compare.inc
@@ -48,4 +48,10 @@ export namespace std {
using std::__cpo::weak_order;
} // namespace __cpo
+#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+ // [compare.type], type ordering
+ using std::type_order;
+ using std::type_order_v;
+#endif
+
} // namespace std
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
new file mode 100644
index 0000000000000..d24c43824736c
--- /dev/null
+++ b/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17, c++20, c++23
+
+// These compilers do not support __builtin_type_order
+// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
+// UNSUPPORTED: gcc-15
+
+// <compare>
+
+// template<class T, class U>
+// struct type_order;
+
+#include <compare>
+
+#if !__has_warning("-Winvalid-specializations")
+// expected-no-diagnostics
+#else
+template <>
+struct std::type_order<int, int>; // expected-error {{cannot be specialized}}
+
+template <class T>
+struct std::type_order<T, int>; // expected-error {{cannot be specialized}}
+#endif
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
new file mode 100644
index 0000000000000..1de526a4126b5
--- /dev/null
+++ b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17, c++20, c++23
+
+// These compilers do not support __builtin_type_order
+// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
+// UNSUPPORTED: gcc-15
+
+// <compare>
+
+// template<class T, class U>
+// struct type_order;
+// template<class T, class U>
+// constexpr strong_ordering type_order_v = type_order<T, U>::value;
+
+#include <compare>
+#include <concepts>
+#include "test_macros.h"
+
+template <class T, class U>
+constexpr bool test_order(std::strong_ordering expected) {
+ return std::type_order<T, U>()() == expected && std::type_order<T, U>::value == expected &&
+ std::type_order_v<T, U> == expected && static_cast<std::strong_ordering>(std::type_order<T, U>()) == expected;
+}
+
+template <class T, class U>
+constexpr bool eq = test_order<T, U>(std::strong_ordering::equal);
+template <class T, class U>
+constexpr bool ne =
+ std::type_order<T, U>()() != std::strong_ordering::equal &&
+ std::type_order<T, U>::value != std::strong_ordering::equal &&
+ std::type_order_v<T, U> != std::strong_ordering::equal &&
+ static_cast<std::strong_ordering>(std::type_order<T, U>()) != std::strong_ordering::equal;
+template <class T, class U>
+constexpr bool lt = test_order<T, U>(std::strong_ordering::less);
+template <class T, class U>
+constexpr bool gt = test_order<T, U>(std::strong_ordering::greater);
+
+struct A {};
+struct B {};
+struct C {};
+
+static_assert(std::same_as<std::type_order<A, A>::value_type, std::strong_ordering>);
+static_assert(std::same_as<decltype(std::type_order<A, A>::value), const std::strong_ordering>);
+static_assert(std::same_as<decltype(std::type_order_v<A, A>), const std::strong_ordering>);
+
+ASSERT_NOEXCEPT((std::type_order<int, int>()()));
+ASSERT_NOEXCEPT((static_cast<std::strong_ordering>(std::type_order<int, int>())));
+
+static_assert(ne<int, const int>);
+static_assert(ne<int, int&>);
+static_assert(ne<int&, int&&>);
+
+static_assert(eq<A, A>);
+static_assert(ne<A, B> && ne<B, A>);
+
+// since we do lexicographical compare of the mangled names and both A and B
+// are class types, A must compare less than B regardless of ABI
+static_assert(lt<A, B>);
+static_assert(gt<B, A>);
+static_assert(!(lt<A, B> && lt<B, C>) || lt<A, C>);
+
+struct incomplete;
+static_assert(eq<incomplete, incomplete>);
+static_assert(ne<incomplete, A>);
+
+template <auto>
+constexpr bool test_template_arg = true;
+static_assert(test_template_arg<std::type_order<A, incomplete>{}>);
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp
index 907535a087de2..3e777fd67000d 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp
@@ -63,6 +63,15 @@
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++26"
# endif
+# if __has_builtin(__builtin_type_order)
+# ifndef __cpp_lib_type_order
+# error "__cpp_lib_type_order should be defined in c++26"
+# endif
+# if __cpp_lib_type_order != 202506L
+# error "__cpp_lib_type_order should have the value 202506L in c++26"
+# endif
+# endif
+
#endif // TEST_STD_VER > 23
// clang-format on
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 f7a89d4d7f2e6..d5efb58d54764 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
@@ -8335,6 +8335,15 @@
# error "__cpp_lib_type_identity should have the value 201806L in c++26"
# endif
+# if __has_builtin(__builtin_type_order)
+# ifndef __cpp_lib_type_order
+# error "__cpp_lib_type_order should be defined in c++26"
+# endif
+# if __cpp_lib_type_order != 202506L
+# error "__cpp_lib_type_order should have the value 202506L in c++26"
+# endif
+# endif
+
# ifndef __cpp_lib_type_trait_variable_templates
# error "__cpp_lib_type_trait_variable_templates should be defined in c++26"
# endif
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 07de473bbc038..142be159b7eb2 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1494,6 +1494,13 @@ def add_version_header(tc):
"values": {"c++20": 201806},
"headers": ["type_traits"],
},
+ {
+ "name": "__cpp_lib_type_order",
+ "values": {"c++26": 202506},
+ "headers": ["compare"],
+ "test_suite_guard": "__has_builtin(__builtin_type_order)",
+ "libcxx_guard": "__has_builtin(__builtin_type_order)",
+ },
{
"name": "__cpp_lib_type_trait_variable_templates",
"values": {"c++17": 201510},
>From 4a6268abb62bf8deb6282c2f643cce240833c581 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Mon, 17 Aug 2026 02:19:54 +0200
Subject: [PATCH 2/8] rerun generator scripts
---
libcxx/include/version | 8 +++----
.../compare.version.compile.pass.cpp | 24 +++++++++++++++++++
.../version.version.compile.pass.cpp | 24 +++++++++++++++++++
3 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/version b/libcxx/include/version
index ca6f8b81cdb61..c96942a5b6c74 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -283,7 +283,7 @@ __cpp_lib_tuple_like 202311L <map> <tuple> <u
202207L // C++23
__cpp_lib_tuples_by_type 201304L <tuple> <utility>
__cpp_lib_type_identity 201806L <type_traits>
-__cpp_lib_type_order 202506L <compare> // C++26
+__cpp_lib_type_order 202506L <compare>
__cpp_lib_type_trait_variable_templates 201510L <type_traits>
__cpp_lib_uncaught_exceptions 201411L <exception>
__cpp_lib_unordered_map_try_emplace 201411L <unordered_map>
@@ -646,9 +646,9 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_to_string 202306L
# undef __cpp_lib_tuple_like
// # define __cpp_lib_tuple_like 202311L
-# if __has_builtin(__builtin_type_order)
-# define __cpp_lib_type_order 202506L
-# endif
+# if __has_builtin(__builtin_type_order)
+# define __cpp_lib_type_order 202506L
+# endif
# undef __cpp_lib_variant
# define __cpp_lib_variant 202306L
#endif
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp
index 3e777fd67000d..a1c0f478ed623 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.compile.pass.cpp
@@ -24,18 +24,30 @@
# error "__cpp_lib_three_way_comparison should not be defined before c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
#elif TEST_STD_VER == 14
# ifdef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should not be defined before c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
#elif TEST_STD_VER == 17
# ifdef __cpp_lib_three_way_comparison
# error "__cpp_lib_three_way_comparison should not be defined before c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
#elif TEST_STD_VER == 20
# ifndef __cpp_lib_three_way_comparison
@@ -45,6 +57,10 @@
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
#elif TEST_STD_VER == 23
# ifndef __cpp_lib_three_way_comparison
@@ -54,6 +70,10 @@
# error "__cpp_lib_three_way_comparison should have the value 201907L in c++23"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
#elif TEST_STD_VER > 23
# ifndef __cpp_lib_three_way_comparison
@@ -70,6 +90,10 @@
# if __cpp_lib_type_order != 202506L
# error "__cpp_lib_type_order should have the value 202506L in c++26"
# endif
+# else
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined when the requirement '__has_builtin(__builtin_type_order)' is not met!"
+# endif
# 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 d5efb58d54764..96e6f503a28b0 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
@@ -928,6 +928,10 @@
# error "__cpp_lib_type_identity should not be defined before c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_type_trait_variable_templates
# error "__cpp_lib_type_trait_variable_templates should not be defined before c++17"
# endif
@@ -1945,6 +1949,10 @@
# error "__cpp_lib_type_identity should not be defined before c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
# ifdef __cpp_lib_type_trait_variable_templates
# error "__cpp_lib_type_trait_variable_templates should not be defined before c++17"
# endif
@@ -3142,6 +3150,10 @@
# error "__cpp_lib_type_identity should not be defined before c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
# ifndef __cpp_lib_type_trait_variable_templates
# error "__cpp_lib_type_trait_variable_templates should be defined in c++17"
# endif
@@ -4615,6 +4627,10 @@
# error "__cpp_lib_type_identity should have the value 201806L in c++20"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
# ifndef __cpp_lib_type_trait_variable_templates
# error "__cpp_lib_type_trait_variable_templates should be defined in c++20"
# endif
@@ -6316,6 +6332,10 @@
# error "__cpp_lib_type_identity should have the value 201806L in c++23"
# endif
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined before c++26"
+# endif
+
# ifndef __cpp_lib_type_trait_variable_templates
# error "__cpp_lib_type_trait_variable_templates should be defined in c++23"
# endif
@@ -8342,6 +8362,10 @@
# if __cpp_lib_type_order != 202506L
# error "__cpp_lib_type_order should have the value 202506L in c++26"
# endif
+# else
+# ifdef __cpp_lib_type_order
+# error "__cpp_lib_type_order should not be defined when the requirement '__has_builtin(__builtin_type_order)' is not met!"
+# endif
# endif
# ifndef __cpp_lib_type_trait_variable_templates
>From c2fac1f853c5ca68ed14b91455f5088252148258 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Mon, 17 Aug 2026 02:21:42 +0200
Subject: [PATCH 3/8] add pr number
---
libcxx/docs/ReleaseNotes/24.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index 71442d215bb62..370ee63ffc15b 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -47,9 +47,9 @@ Implemented Papers
- P3961R1: Less double indirection in ``function_ref`` (RU-220) (`Github <https://llvm.org/PR189606>`__)
- P1901R2: Enabling the Use of ``weak_ptr`` as Keys in Unordered Associative Containers (`Github <https://llvm.org/PR105372>`__)
- P0528R3: The Curious Case of Padding Bits, Featuring Atomic Compare-and-Exchange (`Github <https://llvm.org/PR76180>`__)
-- P2830R10: Standardized Constexpr Type Ordering (`Github <https://llvm.org/TBD>`__)
-- P3778R0: Fix for ``type_order`` template definition (`Github <https://llvm.org/TBD>`__)
-- P4140R0: Proposed resolution for US70-126: allow incomplete types in type_order (`Github <https://llvm.org/TBD>`__)
+- P2830R10: Standardized Constexpr Type Ordering (`Github <https://llvm.org/PR216616>`__)
+- P3778R0: Fix for ``type_order`` template definition (`Github <https://llvm.org/PR216616>`__)
+- P4140R0: Proposed resolution for US70-126: allow incomplete types in type_order (`Github <https://llvm.org/PR216616>`__)
Improvements and New Features
-----------------------------
>From 78caa7f0edb1cbc853b8d5ab109477b14300cceb Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Mon, 17 Aug 2026 02:24:56 +0200
Subject: [PATCH 4/8] define ne in terms of lt/gt
---
.../cmp/cmp.type/type_order.compile.pass.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
index 1de526a4126b5..5d16d72e40955 100644
--- a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
@@ -32,15 +32,11 @@ constexpr bool test_order(std::strong_ordering expected) {
template <class T, class U>
constexpr bool eq = test_order<T, U>(std::strong_ordering::equal);
template <class T, class U>
-constexpr bool ne =
- std::type_order<T, U>()() != std::strong_ordering::equal &&
- std::type_order<T, U>::value != std::strong_ordering::equal &&
- std::type_order_v<T, U> != std::strong_ordering::equal &&
- static_cast<std::strong_ordering>(std::type_order<T, U>()) != std::strong_ordering::equal;
-template <class T, class U>
constexpr bool lt = test_order<T, U>(std::strong_ordering::less);
template <class T, class U>
constexpr bool gt = test_order<T, U>(std::strong_ordering::greater);
+template <class T, class U>
+constexpr bool ne = lt<T, U> || gt<T, U>;
struct A {};
struct B {};
>From 53f05b46610861566e0a7b1b527125ac10dd06d6 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Tue, 18 Aug 2026 05:59:06 +0200
Subject: [PATCH 5/8] address review comments
---
libcxx/include/__compare/type_order.h | 4 ++--
libcxx/include/compare | 2 +-
.../cmp/cmp.type/nodiscard.verify.cpp | 22 +++++++++++++++++++
.../cmp.type/no_specializations.verify.cpp | 2 +-
.../cmp/cmp.type/type_order.compile.pass.cpp | 9 ++++----
5 files changed, 30 insertions(+), 9 deletions(-)
create mode 100644 libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp
diff --git a/libcxx/include/__compare/type_order.h b/libcxx/include/__compare/type_order.h
index 9cfd84c134b68..fe8e260fdc4ae 100644
--- a/libcxx/include/__compare/type_order.h
+++ b/libcxx/include/__compare/type_order.h
@@ -27,11 +27,11 @@ struct _LIBCPP_NO_SPECIALIZATIONS type_order {
using value_type = strong_ordering;
_LIBCPP_HIDE_FROM_ABI constexpr operator value_type() const noexcept { return value; }
- _LIBCPP_HIDE_FROM_ABI constexpr value_type operator()() const noexcept { return value; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr value_type operator()() const noexcept { return value; }
};
template <class _Tp, class _Up>
-constexpr strong_ordering type_order_v = __builtin_type_order(_Tp, _Up);
+inline constexpr strong_ordering type_order_v = __builtin_type_order(_Tp, _Up);
#endif // _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
diff --git a/libcxx/include/compare b/libcxx/include/compare
index 747cbf578a97d..7fa8f76713495 100644
--- a/libcxx/include/compare
+++ b/libcxx/include/compare
@@ -161,7 +161,7 @@ namespace std {
# include <__compare/weak_order.h>
# endif // _LIBCPP_STD_VER >= 20
-# if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+# if _LIBCPP_STD_VER >= 26
# include <__compare/type_order.h>
# endif
diff --git a/libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp b/libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..e71cd615786ab
--- /dev/null
+++ b/libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// These compilers do not support __builtin_type_order
+// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
+// UNSUPPORTED: gcc-15
+
+// Check that type_order::operator() is marked [[nodiscard]]
+
+#include <compare>
+
+void test() {
+ std::type_order<int, char>()();
+ // expected-warning at -1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+}
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
index d24c43824736c..e2f24e6aaa48f 100644
--- a/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// REQUIRES: std-at-least-c++26
// These compilers do not support __builtin_type_order
// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
index 5d16d72e40955..da3d5f3a256d8 100644
--- a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+// REQUIRES: std-at-least-c++26
// These compilers do not support __builtin_type_order
// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
@@ -21,7 +21,6 @@
#include <compare>
#include <concepts>
-#include "test_macros.h"
template <class T, class U>
constexpr bool test_order(std::strong_ordering expected) {
@@ -46,8 +45,8 @@ static_assert(std::same_as<std::type_order<A, A>::value_type, std::strong_orderi
static_assert(std::same_as<decltype(std::type_order<A, A>::value), const std::strong_ordering>);
static_assert(std::same_as<decltype(std::type_order_v<A, A>), const std::strong_ordering>);
-ASSERT_NOEXCEPT((std::type_order<int, int>()()));
-ASSERT_NOEXCEPT((static_cast<std::strong_ordering>(std::type_order<int, int>())));
+static_assert(noexcept(std::type_order<int, int>()()));
+static_assert(noexcept(static_cast<std::strong_ordering>(std::type_order<int, int>())));
static_assert(ne<int, const int>);
static_assert(ne<int, int&>);
@@ -56,7 +55,7 @@ static_assert(ne<int&, int&&>);
static_assert(eq<A, A>);
static_assert(ne<A, B> && ne<B, A>);
-// since we do lexicographical compare of the mangled names and both A and B
+// Since we do lexicographical compare of the mangled names and both A and B
// are class types, A must compare less than B regardless of ABI
static_assert(lt<A, B>);
static_assert(gt<B, A>);
>From 1c3e4b66805dd33a001c499a1da2545f7fab1a2f Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Wed, 19 Aug 2026 04:46:57 +0200
Subject: [PATCH 6/8] fix build
---
libcxx/include/__compare/type_order.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/__compare/type_order.h b/libcxx/include/__compare/type_order.h
index fe8e260fdc4ae..11f936dfd1547 100644
--- a/libcxx/include/__compare/type_order.h
+++ b/libcxx/include/__compare/type_order.h
@@ -16,10 +16,10 @@
# pragma GCC system_header
#endif
-_LIBCPP_BEGIN_NAMESPACE_STD
-
#if _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+_LIBCPP_BEGIN_NAMESPACE_STD
+
// [compare.type], type ordering
template <class _Tp, class _Up>
struct _LIBCPP_NO_SPECIALIZATIONS type_order {
@@ -33,8 +33,8 @@ struct _LIBCPP_NO_SPECIALIZATIONS type_order {
template <class _Tp, class _Up>
inline constexpr strong_ordering type_order_v = __builtin_type_order(_Tp, _Up);
-#endif // _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
-
_LIBCPP_END_NAMESPACE_STD
+#endif // _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+
#endif // _LIBCPP___COMPARE_TYPE_ORDER
>From 3598fbe1aa78bf61c0e4e743d32588f151ee2c75 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Thu, 20 Aug 2026 16:05:44 +0200
Subject: [PATCH 7/8] reduce test
---
.../cmp/cmp.type/type_order.compile.pass.cpp | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
index da3d5f3a256d8..9668f07ab18a6 100644
--- a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
@@ -10,7 +10,6 @@
// These compilers do not support __builtin_type_order
// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
-// UNSUPPORTED: gcc-15
// <compare>
@@ -39,7 +38,6 @@ constexpr bool ne = lt<T, U> || gt<T, U>;
struct A {};
struct B {};
-struct C {};
static_assert(std::same_as<std::type_order<A, A>::value_type, std::strong_ordering>);
static_assert(std::same_as<decltype(std::type_order<A, A>::value), const std::strong_ordering>);
@@ -50,17 +48,10 @@ static_assert(noexcept(static_cast<std::strong_ordering>(std::type_order<int, in
static_assert(ne<int, const int>);
static_assert(ne<int, int&>);
-static_assert(ne<int&, int&&>);
static_assert(eq<A, A>);
static_assert(ne<A, B> && ne<B, A>);
-// Since we do lexicographical compare of the mangled names and both A and B
-// are class types, A must compare less than B regardless of ABI
-static_assert(lt<A, B>);
-static_assert(gt<B, A>);
-static_assert(!(lt<A, B> && lt<B, C>) || lt<A, C>);
-
struct incomplete;
static_assert(eq<incomplete, incomplete>);
static_assert(ne<incomplete, A>);
>From 598fd3201af0eb211ddb7a8c71f8f5af2b41b410 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <mfwippich at gmail.com>
Date: Sun, 23 Aug 2026 21:04:05 +0200
Subject: [PATCH 8/8] address review comments
---
libcxx/include/__compare/type_order.h | 4 +--
.../cmp/cmp.type/nodiscard.verify.cpp | 22 --------------
.../no_specializations.verify.cpp | 16 ++++++++++
.../language.support/nodiscard.verify.cpp | 4 +++
.../cmp.type/no_specializations.verify.cpp | 30 -------------------
.../cmp/cmp.type/type_order.compile.pass.cpp | 13 ++++----
6 files changed, 30 insertions(+), 59 deletions(-)
delete mode 100644 libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp
delete mode 100644 libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
diff --git a/libcxx/include/__compare/type_order.h b/libcxx/include/__compare/type_order.h
index 11f936dfd1547..cd5735b869e7a 100644
--- a/libcxx/include/__compare/type_order.h
+++ b/libcxx/include/__compare/type_order.h
@@ -27,11 +27,11 @@ struct _LIBCPP_NO_SPECIALIZATIONS type_order {
using value_type = strong_ordering;
_LIBCPP_HIDE_FROM_ABI constexpr operator value_type() const noexcept { return value; }
- [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr value_type operator()() const noexcept { return value; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr value_type operator()() noexcept { return value; }
};
template <class _Tp, class _Up>
-inline constexpr strong_ordering type_order_v = __builtin_type_order(_Tp, _Up);
+_LIBCPP_NO_SPECIALIZATIONS inline constexpr strong_ordering type_order_v = __builtin_type_order(_Tp, _Up);
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp b/libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp
deleted file mode 100644
index e71cd615786ab..0000000000000
--- a/libcxx/test/libcxx/language.support/cmp/cmp.type/nodiscard.verify.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// These compilers do not support __builtin_type_order
-// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
-// UNSUPPORTED: gcc-15
-
-// Check that type_order::operator() is marked [[nodiscard]]
-
-#include <compare>
-
-void test() {
- std::type_order<int, char>()();
- // expected-warning at -1 {{ignoring return value of function declared with 'nodiscard' attribute}}
-}
diff --git a/libcxx/test/libcxx/language.support/no_specializations.verify.cpp b/libcxx/test/libcxx/language.support/no_specializations.verify.cpp
index b7b75b7e9a00d..5559c00d4ed4e 100644
--- a/libcxx/test/libcxx/language.support/no_specializations.verify.cpp
+++ b/libcxx/test/libcxx/language.support/no_specializations.verify.cpp
@@ -13,6 +13,8 @@
#include <compare>
+#include "test_macros.h"
+
#if !__has_warning("-Winvalid-specialization")
// expected-no-diagnostics
#else
@@ -20,4 +22,18 @@ struct S {};
template <>
struct std::compare_three_way_result<S>; // expected-error {{cannot be specialized}}
+
+# if TEST_STD_VER > 23
+template <>
+struct std::type_order<int, int>; // expected-error {{cannot be specialized}}
+
+template <class T>
+struct std::type_order<T, int>; // expected-error {{cannot be specialized}}
+
+template <>
+constexpr std::strong_ordering std::type_order_v<int, int> = false; // expected-error {{cannot be specialized}}
+
+template <class T>
+constexpr std::strong_ordering std::type_order_v<T, int> = false; // expected-error {{cannot be specialized}}
+# endif
#endif
diff --git a/libcxx/test/libcxx/language.support/nodiscard.verify.cpp b/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
index b3a6658e53286..618f12a6d63c6 100644
--- a/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/language.support/nodiscard.verify.cpp
@@ -36,6 +36,10 @@ void test() {
std::is_lteq(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::is_gt(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
std::is_gteq(oRes); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+# if TEST_STD_VER > 23
+ std::type_order<int, char>()();
+ // expected-warning at -1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+# endif
}
#endif
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp b/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
deleted file mode 100644
index e2f24e6aaa48f..0000000000000
--- a/libcxx/test/std/language.support/cmp/cmp.type/no_specializations.verify.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// These compilers do not support __builtin_type_order
-// UNSUPPORTED: clang-21, clang-22, clang-23, apple-clang-21
-// UNSUPPORTED: gcc-15
-
-// <compare>
-
-// template<class T, class U>
-// struct type_order;
-
-#include <compare>
-
-#if !__has_warning("-Winvalid-specializations")
-// expected-no-diagnostics
-#else
-template <>
-struct std::type_order<int, int>; // expected-error {{cannot be specialized}}
-
-template <class T>
-struct std::type_order<T, int>; // expected-error {{cannot be specialized}}
-#endif
diff --git a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
index 9668f07ab18a6..c69bdceb5b8d0 100644
--- a/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
+++ b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
@@ -28,16 +28,17 @@ constexpr bool test_order(std::strong_ordering expected) {
}
template <class T, class U>
-constexpr bool eq = test_order<T, U>(std::strong_ordering::equal);
+constexpr bool eq = test_order<T, U>(std::strong_ordering::equal) && test_order<U, T>(std::strong_ordering::equal);
template <class T, class U>
-constexpr bool lt = test_order<T, U>(std::strong_ordering::less);
+constexpr bool lt = test_order<T, U>(std::strong_ordering::less) && test_order<U, T>(std::strong_ordering::greater);
template <class T, class U>
-constexpr bool gt = test_order<T, U>(std::strong_ordering::greater);
+constexpr bool gt = test_order<T, U>(std::strong_ordering::greater) && test_order<U, T>(std::strong_ordering::less);
template <class T, class U>
-constexpr bool ne = lt<T, U> || gt<T, U>;
+constexpr bool ne = (lt<T, U> || gt<T, U>);
struct A {};
struct B {};
+struct C {};
static_assert(std::same_as<std::type_order<A, A>::value_type, std::strong_ordering>);
static_assert(std::same_as<decltype(std::type_order<A, A>::value), const std::strong_ordering>);
@@ -50,7 +51,9 @@ static_assert(ne<int, const int>);
static_assert(ne<int, int&>);
static_assert(eq<A, A>);
-static_assert(ne<A, B> && ne<B, A>);
+static_assert(ne<A, B>);
+
+static_assert((!(lt<A, B> && lt<B, C>) || lt<A, C>)^(!(gt<A, B> && gt<B, C>) || gt<A, C>));
struct incomplete;
static_assert(eq<incomplete, incomplete>);
More information about the libcxx-commits
mailing list