From 29c7661c6f92d80f63a9a3cc37f3dc790a161f3f Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 26 Jun 2025 16:15:20 +0200 Subject: 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 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 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. --- libstdc++-v3/include/bits/version.def | 10 +++ libstdc++-v3/include/bits/version.h | 10 +++ libstdc++-v3/libsupc++/compare | 23 ++++++ libstdc++-v3/src/c++23/std.cc.in | 4 + .../18_support/comparisons/type_order/1.cc | 95 ++++++++++++++++++++++ 5 files changed, 142 insertions(+) create mode 100644 libstdc++-v3/testsuite/18_support/comparisons/type_order/1.cc (limited to 'libstdc++-v3') 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 #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 + 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 + 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 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 +// . + +// { dg-do compile { target c++26 } } + +#include + +#if __cpp_lib_type_order != 202506L +# error "__cpp_lib_type_order != 202506" +#endif + +static_assert (std::is_same_v ::value), + const std::strong_ordering>); +static_assert (std::is_same_v ), + const std::strong_ordering>); +struct S; +struct T; +template +struct U +{ +}; +typedef int int2; +struct V {}; +namespace +{ + struct W {}; +} + +template +struct eq +{ + constexpr eq () + { + static_assert (std::type_order ::value == std::strong_ordering::equal); + static_assert (std::type_order ::value == std::strong_ordering::equal); + static_assert (std::type_order_v == std::strong_ordering::equal); + static_assert (std::type_order_v == std::strong_ordering::equal); + } +}; +template +struct ne +{ + constexpr ne () + { + static_assert (std::type_order ::value != std::strong_ordering::equal); + static_assert (std::type_order ::value != std::strong_ordering::equal); + static_assert (std::type_order ::value == std::strong_ordering::greater + ? std::type_order ::value == std::strong_ordering::less + : std::type_order ::value == std::strong_ordering::greater); + static_assert (std::type_order_v != std::strong_ordering::equal); + static_assert (std::type_order_v != std::strong_ordering::equal); + static_assert (std::type_order_v == std::strong_ordering::greater + ? std::type_order_v == std::strong_ordering::less + : std::type_order_v == std::strong_ordering::greater); + } +}; + +constexpr eq a; +constexpr eq b; +constexpr eq c; +constexpr eq d; +constexpr eq e; +constexpr eq f; +constexpr eq , U > g; +constexpr eq h; +constexpr eq i; +constexpr eq j; +constexpr ne k; +constexpr ne l; +constexpr ne m; +constexpr ne n; +constexpr ne , U > o; +constexpr ne , U > p; +static_assert (std::type_order_v != std::strong_ordering::less + || std::type_order_v != std::strong_ordering::less + || std::type_order_v == std::strong_ordering::less); +constexpr ne q; +constexpr eq r; +constexpr ne s; +constexpr eq , U > t; +constexpr ne , U > u; -- cgit v1.1