Bug 92431

Summary: ICE with spaceship in constexpr evaluation
Product: gcc Reporter: Jonathan Wakely <redi>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: jakub, jason, webrown.cpp
Priority: P3 Keywords: ice-on-valid-code
Version: 10.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2019-11-09 00:00:00
Bug Depends on:    
Bug Blocks: 55004    

Description Jonathan Wakely 2019-11-09 11:19:53 UTC
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.
Comment 1 Jonathan Wakely 2019-11-09 16:30:53 UTC
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?
Comment 2 Jonathan Wakely 2019-11-09 16:31:57 UTC
Slightly further reduced:

#include <compare>

constexpr std::weak_ordering
cmp(int e, int f)
{
  return e <=> f;
}

auto o = cmp(1, 2);
Comment 3 Jakub Jelinek 2019-11-09 18:17:58 UTC
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.
Comment 4 Jonathan Wakely 2019-11-13 16:26:50 UTC
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
Comment 5 Jonathan Wakely 2020-08-07 16:17:32 UTC
This was fixed by r10-6572-dfffecb802681fbdb56629d3bdd96491ac660be0

    c++: Fix static initialization from <=>.
    
    Constant evaluation of genericize_spaceship produced a CONSTRUCTOR, which we
    then wanted to bind to a reference, which we can't do.  So wrap the result
    in a TARGET_EXPR so we get something with an address.
    
    We also need to handle treating the result of cxx_eval_binary_expression as
    a glvalue for SPACESHIP_EXPR.
    
    My earlier change to add uid_sensitive to maybe_constant_value was wrong; we
    don't even look at the cache when manifestly_const_eval, and I failed to
    adjust the later call to cxx_eval_outermost_constant_expr.
    
    gcc/cp/ChangeLog
    2020-02-11  Jason Merrill  <jason@redhat.com>
    
            PR c++/93650
            PR c++/90691
            * constexpr.c (maybe_constant_value): Correct earlier change.
            (cxx_eval_binary_expression) [SPACESHIP_EXPR]: Pass lval through.
            * method.c (genericize_spaceship): Wrap result in TARGET_EXPR.
Comment 6 Jonathan Wakely 2020-08-07 16:47:52 UTC
(In reply to Jonathan Wakely from comment #4)
> This is incomplete because std::strong_order doesn't support
> floating-point types.

See PR 96526 regarding that.

> The partial_order and weak_order tests use VERIFY instead of
> static_assert because of PR 92431.

Some of those VERIFYs have been changed to static_assert in r11-2609
Comment 7 Andrew Pinski 2021-07-28 22:15:22 UTC
Looks to be fixed for the GCC 10 release.