aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-06-26 16:15:20 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2025-06-26 16:15:20 +0200
commit29c7661c6f92d80f63a9a3cc37f3dc790a161f3f (patch)
tree8aaa22d294e8790757a52568d043fd05208225f7 /libstdc++-v3
parentf8f7ace4f20829f2fad87662f5163c9b13427e39 (diff)
downloadgcc-29c7661c6f92d80f63a9a3cc37f3dc790a161f3f.zip
gcc-29c7661c6f92d80f63a9a3cc37f3dc790a161f3f.tar.gz
gcc-29c7661c6f92d80f63a9a3cc37f3dc790a161f3f.tar.bz2
c++, libstdc++: Implement C++26 P2830R10 - Constexpr Type Ordering
The following patch attempts to implement the C++26 P2830R10 - Constexpr Type Ordering paper, with a minor change that std::type_order<T, U> class template doesn't derive from integer_constant, because std::strong_ordering is not a structural type (except in MSVC), so instead it is just a class template with static constexpr strong_ordering value member and also value_type, type and 2 operators. The paper mostly talks about using something other than mangled names for the ordering, but given that the mangler is part of the GCC C++ FE, using the mangler seems to be the best ordering choice to me. 2025-06-26 Jakub Jelinek <jakub@redhat.com> gcc/cp/ * cp-trait.def: Implement C++26 P2830R10 - Constexpr Type Ordering. (TYPE_ORDER): New. * method.cc (type_order_value): Define. * cp-tree.h (type_order_value): Declare. * semantics.cc (trait_expr_value): Use gcc_unreachable also for CPTK_TYPE_ORDER, adjust comment. (finish_trait_expr): Handle CPTK_TYPE_ORDER. * constraint.cc (diagnose_trait_expr): Likewise. gcc/testsuite/ * g++.dg/cpp26/type-order1.C: New test. * g++.dg/cpp26/type-order2.C: New test. * g++.dg/cpp26/type-order3.C: New test. libstdc++-v3/ * include/bits/version.def (type_order): New. * include/bits/version.h: Regenerate. * libsupc++/compare: Define __glibcxx_want_type_order before including bits/version.h. (std::type_order, std::type_order_v): New trait and template variable. * src/c++23/std.cc.in (std::type_order, std::type_order_v): Export. * testsuite/18_support/comparisons/type_order/1.cc: New test.
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/include/bits/version.def10
-rw-r--r--libstdc++-v3/include/bits/version.h10
-rw-r--r--libstdc++-v3/libsupc++/compare23
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in4
-rw-r--r--libstdc++-v3/testsuite/18_support/comparisons/type_order/1.cc95
5 files changed, 142 insertions, 0 deletions
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 880586e..caec5d1 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2012,6 +2012,16 @@ ftms = {
};
};
+ftms = {
+ name = type_order;
+ values = {
+ v = 202506;
+ cxxmin = 26;
+ extra_cond = "__has_builtin(__builtin_type_order) "
+ "&& __cpp_lib_three_way_comparison >= 201907L";
+ };
+};
+
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 4300adb..2dc21b6 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2253,4 +2253,14 @@
#endif /* !defined(__cpp_lib_sstream_from_string_view) && defined(__glibcxx_want_sstream_from_string_view) */
#undef __glibcxx_want_sstream_from_string_view
+#if !defined(__cpp_lib_type_order)
+# if (__cplusplus > 202302L) && (__has_builtin(__builtin_type_order) && __cpp_lib_three_way_comparison >= 201907L)
+# define __glibcxx_type_order 202506L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_type_order)
+# define __cpp_lib_type_order 202506L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_type_order) && defined(__glibcxx_want_type_order) */
+#undef __glibcxx_want_type_order
+
#undef __glibcxx_want_all
diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare
index 8811bc0..82b5c53 100644
--- a/libstdc++-v3/libsupc++/compare
+++ b/libstdc++-v3/libsupc++/compare
@@ -35,6 +35,7 @@
#endif
#define __glibcxx_want_three_way_comparison
+#define __glibcxx_want_type_order
#include <bits/version.h>
#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L
@@ -1261,6 +1262,28 @@ namespace std _GLIBCXX_VISIBILITY(default)
std::declval<_Up&>()));
} // namespace __detail
/// @endcond
+
+#if __glibcxx_type_order >= 202506L // C++ >= 26
+ /// Total ordering of types.
+ /// @since C++26
+
+ template<typename _Tp, typename _Up>
+ struct type_order
+ {
+ static constexpr strong_ordering value = __builtin_type_order(_Tp, _Up);
+ using value_type = strong_ordering;
+ using type = type_order<_Tp, _Up>;
+ constexpr operator value_type() const noexcept { return value; }
+ constexpr value_type operator()() const noexcept { return value; }
+ };
+
+ /// @ingroup variable_templates
+ /// @since C++26
+ template<typename _Tp, typename _Up>
+ inline constexpr strong_ordering type_order_v
+ = __builtin_type_order(_Tp, _Up);
+#endif // __glibcxx_type_order >= 202506L
+
#endif // __cpp_lib_three_way_comparison >= 201907L
} // namespace std
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 109f590..36b19ae 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -888,6 +888,10 @@ export namespace std
using std::partial_order;
using std::strong_order;
using std::weak_order;
+#if __glibcxx_type_order >= 202506L
+ using std::type_order;
+ using std::type_order_v;
+#endif
}
// 28.4 <complex>
diff --git a/libstdc++-v3/testsuite/18_support/comparisons/type_order/1.cc b/libstdc++-v3/testsuite/18_support/comparisons/type_order/1.cc
new file mode 100644
index 0000000..b510494
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/comparisons/type_order/1.cc
@@ -0,0 +1,95 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++26 } }
+
+#include <compare>
+
+#if __cpp_lib_type_order != 202506L
+# error "__cpp_lib_type_order != 202506"
+#endif
+
+static_assert (std::is_same_v <decltype (std::type_order <int, int>::value),
+ const std::strong_ordering>);
+static_assert (std::is_same_v <decltype (std::type_order_v <char, short>),
+ const std::strong_ordering>);
+struct S;
+struct T;
+template <typename T>
+struct U
+{
+};
+typedef int int2;
+struct V {};
+namespace
+{
+ struct W {};
+}
+
+template <typename T, typename U>
+struct eq
+{
+ constexpr eq ()
+ {
+ static_assert (std::type_order <T, U>::value == std::strong_ordering::equal);
+ static_assert (std::type_order <U, T>::value == std::strong_ordering::equal);
+ static_assert (std::type_order_v <T, U> == std::strong_ordering::equal);
+ static_assert (std::type_order_v <U, T> == std::strong_ordering::equal);
+ }
+};
+template <typename T, typename U>
+struct ne
+{
+ constexpr ne ()
+ {
+ static_assert (std::type_order <T, U>::value != std::strong_ordering::equal);
+ static_assert (std::type_order <U, T>::value != std::strong_ordering::equal);
+ static_assert (std::type_order <T, U>::value == std::strong_ordering::greater
+ ? std::type_order <U, T>::value == std::strong_ordering::less
+ : std::type_order <U, T>::value == std::strong_ordering::greater);
+ static_assert (std::type_order_v <T, U> != std::strong_ordering::equal);
+ static_assert (std::type_order_v <U, T> != std::strong_ordering::equal);
+ static_assert (std::type_order_v <T, U> == std::strong_ordering::greater
+ ? std::type_order_v <U, T> == std::strong_ordering::less
+ : std::type_order_v <U, T> == std::strong_ordering::greater);
+ }
+};
+
+constexpr eq <void, void> a;
+constexpr eq <const void, const void> b;
+constexpr eq <int, int> c;
+constexpr eq <long int, long int> d;
+constexpr eq <const volatile unsigned, const volatile unsigned> e;
+constexpr eq <S, S> f;
+constexpr eq <U <int>, U <int>> g;
+constexpr eq <unsigned[2], unsigned[2]> h;
+constexpr eq <int, int2> i;
+constexpr eq <int (*) (int, long), int (*) (int, long)> j;
+constexpr ne <int, long> k;
+constexpr ne <const int, int> l;
+constexpr ne <S, T> m;
+constexpr ne <int &, int &&> n;
+constexpr ne <U <S>, U <T>> o;
+constexpr ne <U <short>, U <char>> p;
+static_assert (std::type_order_v <S, T> != std::strong_ordering::less
+ || std::type_order_v <T, V> != std::strong_ordering::less
+ || std::type_order_v <S, V> == std::strong_ordering::less);
+constexpr ne <int (*) (int, long), int (*) (int, int)> q;
+constexpr eq <W, W> r;
+constexpr ne <V, W> s;
+constexpr eq <U <W>, U <W>> t;
+constexpr ne <U <V>, U <W>> u;