[libc++] Implement P2830R10: Standardized Constexpr Type Ordering - #216616
Conversation
|
|
| using std::type_order; | ||
| using std::type_order_v; |
There was a problem hiding this comment.
No change requested: In type_traits.inc it looks like we are exporting the _v-variable but not the struct. I don't know why.
|
@llvm/pr-subscribers-libcxx Author: Matthias Wippich (Tsche) ChangesThis patch implements the library side of Resolves #148152 Patch is 24.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/216616.diff 16 Files Affected:
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 fc2b95de8a676..895e21c83c1b4 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/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
-----------------------------
diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 2f22fdb63a815..a8296213a7677 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..11f936dfd1547
--- /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
+
+#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 {
+ 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; }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr value_type operator()() const noexcept { return value; }
+};
+
+template <class _Tp, class _Up>
+inline constexpr strong_ordering type_order_v = __builtin_type_order(_Tp, _Up);
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 26 && __has_builtin(__builtin_type_order)
+
+#endif // _LIBCPP___COMPARE_TYPE_ORDER
diff --git a/libcxx/include/compare b/libcxx/include/compare
index de1f845271a48..7fa8f76713495 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
+# 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..c96942a5b6c74 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>
__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/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@-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
new file mode 100644
index 0000000000000..e2f24e6aaa48f
--- /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
+//
+//===----------------------------------------------------------------------===//
+
+// 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
new file mode 100644
index 0000000000000..da3d5f3a256d8
--- /dev/null
+++ b/libcxx/test/std/language.support/cmp/cmp.type/type_order.compile.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// 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;
+// template<class T, class U>
+// constexpr strong_ordering type_order_v = type_order<T, U>::value;
+
+#include <compare>
+#include <concepts>
+
+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 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 {};
+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>);
+
+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&>);
+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..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 t...
[truncated]
|
|
the test failure looks unrelated |
philnik777
left a comment
There was a problem hiding this comment.
Basically LGTM, but I'd like to see transitivity tested.
…vm#216616) This patch implements the library side of `std::type_order` from P2830R10 including the changes from P3778R0, P4140R0 and LWG4305. Since clang's `__builtin_type_order`'s semantics match GCC's, this does not need special casing for GCC. Resolves llvm#148152 Resolves llvm#171284 Resolves llvm#189595 Resolves llvm#171344
…vm#216616) This patch implements the library side of `std::type_order` from P2830R10 including the changes from P3778R0, P4140R0 and LWG4305. Since clang's `__builtin_type_order`'s semantics match GCC's, this does not need special casing for GCC. Resolves llvm#148152 Resolves llvm#171284 Resolves llvm#189595 Resolves llvm#171344
…vm#216616) This patch implements the library side of `std::type_order` from P2830R10 including the changes from P3778R0, P4140R0 and LWG4305. Since clang's `__builtin_type_order`'s semantics match GCC's, this does not need special casing for GCC. Resolves llvm#148152 Resolves llvm#171284 Resolves llvm#189595 Resolves llvm#171344
This patch implements the library side of
std::type_orderfrom P2830R10 including the changes from P3778R0, P4140R0 and LWG4305. Since clang's__builtin_type_order's semantics match GCC's, this does not need special casing for GCC.Resolves #148152
Resolves #171284
Resolves #189595
Resolves #171344