This crashes when compiled with -std=gnu++2a: #include <compare> template<typename _Tp, typename _Up> concept op_cmp = requires(_Tp&& __t, _Up&& __u) { std::weak_ordering(static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u)); }; struct Weak_order { template<typename _Tp, typename _Up> constexpr std::weak_ordering operator()(_Tp&& __e, _Up&& __f) const { if constexpr (op_cmp<_Tp, _Up>) return static_cast<_Tp&&>(__e) <=> static_cast<_Up&&>(__f); } }; constexpr Weak_order weak_order{}; auto o = weak_order(1, 2); wo.cc:22:25: in 'constexpr' expansion of 'weak_order.Weak_order::operator()<int, int>(1, 2)' wo.cc:22:25: internal compiler error: in cxx_eval_constant_expression, at cp/constexpr.c:5123 22 | auto o = weak_order(1, 2); | ^ 0x5d0fd7 cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:5123 0x88f898 cxx_bind_parameters_in_call /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:1424 0x88f898 cxx_eval_call_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:1921 0x892d5a cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:4924 0x893cbd cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:4995 0x89c27a cxx_eval_store_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:4254 0x893046 cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:5013 0x8916d3 cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:5025 0x892513 cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:5064 0x893da0 cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:5327 0x890adb cxx_eval_call_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:2072 0x892d5a cxx_eval_constant_expression /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:4924 0x895d8e cxx_eval_outermost_constant_expr /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:5868 0x89a24b maybe_constant_value(tree_node*, tree_node*, bool) /home/jwakely/src/gcc/gcc/gcc/cp/constexpr.c:6138 0xa55490 store_init_value(tree_node*, tree_node*, vec<tree_node*, va_gc, vl_embed>**, int) /home/jwakely/src/gcc/gcc/gcc/cp/typeck2.c:858 0x8c952d check_initializer /home/jwakely/src/gcc/gcc/gcc/cp/decl.c:6718 0x8ebfdf cp_finish_decl(tree_node*, tree_node*, bool, tree_node*, int) /home/jwakely/src/gcc/gcc/gcc/cp/decl.c:7634 0x99660e cp_parser_init_declarator /home/jwakely/src/gcc/gcc/gcc/cp/parser.c:20727 0x9764b2 cp_parser_simple_declaration /home/jwakely/src/gcc/gcc/gcc/cp/parser.c:13624 0x99e997 cp_parser_declaration /home/jwakely/src/gcc/gcc/gcc/cp/parser.c:13322 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions.
Reduced: #include <compare> template<typename T, typename U> constexpr std::weak_ordering cmp(T e, U f) { return e <=> f; } auto o = cmp(1, 2); wo.cc:10:18: in 'constexpr' expansion of 'cmp<int, int>(1, 2)' wo.cc:10:18: internal compiler error: in cxx_eval_constant_expression, at cp/constexpr.c:5123 10 | auto o = cmp(1, 2); | ^ Related to converting the strong_ordering result of <=> to weak_ordering?
Slightly further reduced: #include <compare> constexpr std::weak_ordering cmp(int e, int f) { return e <=> f; } auto o = cmp(1, 2);
Further reduced: namespace std { enum E { e }; struct strong_ordering { int c; constexpr strong_ordering(E) : c () {} static const strong_ordering less; static strong_ordering equal; static strong_ordering greater; constexpr operator int() {} }; strong_ordering constexpr strong_ordering::less(e); } constexpr int cmp (int d, int e) { return d <=> e; } auto f = cmp (1, 2); We have ADDR_EXPR of a SPACESHIP_EXPR originally, the SPACESHIP_EXPR is constexpr evaluated into a CONSTRUCTOR but the ADDR_EXPR handling code in in cxx_eval_constant_expression asserts that ADDR_EXPR operand doesn't evaluate into a CONSTRUCTOR when lval is true.
Author: redi Date: Wed Nov 13 16:26:18 2019 New Revision: 278149 URL: https://gcc.gnu.org/viewcvs?rev=278149&root=gcc&view=rev Log: libsupc++: Implement comparison algorithms for C++20 This is incomplete because std::strong_order doesn't support floating-point types. The partial_order and weak_order tests use VERIFY instead of static_assert because of PR 92431. * libsupc++/compare (strong_order, weak_order, partial_order) (compare_strong_order_fallback, compare_weak_order_fallback) (compare_partial_order_fallback): Define customization point objects for C++20. * testsuite/18_support/comparisons/algorithms/partial_order.cc: New test. * testsuite/18_support/comparisons/algorithms/strong_order.cc: New test. * testsuite/18_support/comparisons/algorithms/weak_order.cc: New test. Added: trunk/libstdc++-v3/testsuite/18_support/comparisons/algorithms/ trunk/libstdc++-v3/testsuite/18_support/comparisons/algorithms/partial_order.cc trunk/libstdc++-v3/testsuite/18_support/comparisons/algorithms/strong_order.cc trunk/libstdc++-v3/testsuite/18_support/comparisons/algorithms/weak_order.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/libsupc++/compare