Bug 92426 - ICE on spaceship declaration plus other P1185R2 interaction issue
Summary: ICE on spaceship declaration plus other P1185R2 interaction issue
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-11-08 19:22 UTC by Cameron
Modified: 2023-09-10 20:53 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-11-08 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Cameron 2019-11-08 19:22:01 UTC
I was playing around with the spaceship operator using gcc10 on godbolt and discovered an issue trying to compile the following program:

struct Basics {
  int i;
  char c;
  float f;
  double d;
  auto operator<=>(const Basics&) const = default;
};
 
struct Arrays {
  int ai[1];
  char ac[2];
  float af[3];
  double ad[2][2];
  auto operator<=>(const Arrays&) const = default;
};
 
struct Bases : Basics, Arrays {
  auto operator<=>(const Bases&) const = default;
};
 
int main() {
  constexpr Bases a = { { 0, 'c', 1.f, 1. },
                        { { 1 }, { 'a', 'b' }, { 1.f, 2.f, 3.f }, { { 1., 2. }, { 3., 4. } } } };
  constexpr Bases b = { { 0, 'c', 1.f, 1. },
                        { { 1 }, { 'a', 'b' }, { 1.f, 2.f, 3.f }, { { 1., 2. }, { 3., 4. } } } };
  static_assert(a == b);
  static_assert(!(a != b));
  static_assert(!(a < b));
  static_assert(a <= b);
  static_assert(!(a > b));
  static_assert(a >= b);
}

The program ultimately ICEs gcc10 but working with a reduced repro shows some other gaps:

struct Arrays {
    int a[2];
#ifdef MEMBERS
    auto operator<=>(const Arrays&) const = default;
#endif
#ifdef FRIENDS
    friend auto operator<=>(const Arrays&, const Arrays&) = default;
    // friend bool operator==(const Arrays&, const Arrays&) = default; // should be implicitly declared
#endif
};

int main() {
    constexpr Arrays a1 { 1, 2 };
    constexpr Arrays a2 { 3, 4 };
    static_assert(a1 == a1);  // OK
    static_assert(a1 != a2);  // OK
    static_assert(a1 < a2);   // ICE
}

When MEMBERS is defined it only ICEs at the final static assert, but with FRIENDS it both leaves the implicitly declared operator== undeclared _and_ ICEs.  Additionally, replacing `auto` with `std::strong_ordering` produces an ICE in finish_expr_stmt so I assume arrays just aren't handled yet?
Comment 1 Marek Polacek 2019-11-08 22:02:02 UTC
Confirmed:

92426.C: In member function ‘constexpr auto Basics::operator<=>(const Basics&) const’:
92426.C:6:8: internal compiler error: tree check: expected class ‘type’, have ‘exceptional’ (error_mark) in is_cat, at cp/method.c:999
    6 |   auto operator<=>(const Basics&) const = default;
      |        ^~~~~~~~
0x18bbf02 tree_class_check_failed(tree_node const*, tree_code_class, char const*, int, char const*)
	/home/mpolacek/src/gcc/gcc/tree.c:9726
0x87f90b tree_class_check(tree_node*, tree_code_class, char const*, int, char const*)
	/home/mpolacek/src/gcc/gcc/tree.h:3395
0xa33a2e is_cat
	/home/mpolacek/src/gcc/gcc/cp/method.c:999
0xa33bc7 cat_tag_for
	/home/mpolacek/src/gcc/gcc/cp/method.c:1011
0xa34a09 common_comparison_type
	/home/mpolacek/src/gcc/gcc/cp/method.c:1150
0xa3560b build_comparison_op
	/home/mpolacek/src/gcc/gcc/cp/method.c:1325
0xa3669c synthesize_method(tree_node*)
	/home/mpolacek/src/gcc/gcc/cp/method.c:1485
0x9b7744 mark_used(tree_node*, int)
	/home/mpolacek/src/gcc/gcc/cp/decl2.c:5485
0x8a02ec build_over_call
	/home/mpolacek/src/gcc/gcc/cp/call.c:8946
0x8952f2 build_new_op_1
	/home/mpolacek/src/gcc/gcc/cp/call.c:6224
0x895f2a build_new_op(op_location_t const&, tree_code, int, tree_node*, tree_node*, tree_node*, tree_node**, int)
	/home/mpolacek/src/gcc/gcc/cp/call.c:6490
0xa3555c build_comparison_op
	/home/mpolacek/src/gcc/gcc/cp/method.c:1319
0xa3669c synthesize_method(tree_node*)
	/home/mpolacek/src/gcc/gcc/cp/method.c:1485
0x9b7744 mark_used(tree_node*, int)
	/home/mpolacek/src/gcc/gcc/cp/decl2.c:5485
0x8a02ec build_over_call
	/home/mpolacek/src/gcc/gcc/cp/call.c:8946
0x8952f2 build_new_op_1
	/home/mpolacek/src/gcc/gcc/cp/call.c:6224
0x895f2a build_new_op(op_location_t const&, tree_code, int, tree_node*, tree_node*, tree_node*, tree_node**, int)
	/home/mpolacek/src/gcc/gcc/cp/call.c:6490
0xbde344 build_x_binary_op(op_location_t const&, tree_code, tree_node*, tree_code, tree_node*, tree_code, tree_node**, int)
	/home/mpolacek/src/gcc/gcc/cp/typeck.c:4222
0xa789a3 cp_parser_binary_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:9645
0xa78e02 cp_parser_assignment_expression
	/home/mpolacek/src/gcc/gcc/cp/parser.c:9780
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 2 W E Brown 2019-11-09 09:33:14 UTC
Please note that the submitted test program seems not to meet the #include requirement as articulated in N4835 clause [expr.spaceship] p10:

"10 The five comparison category types (17.11.2) (the types std::strong_ordering, std::strong_equality, std::weak_ordering, std::weak_equality, and std::partial_ordering) are not predefined; if the header <compare> (17.11.1) is not included prior to a use of such a class type – even an implicit use in which the type is not named (e.g., via the auto specifier (9.2.8.5) in a defaulted three-way comparison (11.11.3) or use of the built-in operator) – the program is ill-formed."
Comment 3 Cameron 2019-11-09 21:09:22 UTC
(In reply to W E Brown from comment #2)
> Please note that the submitted test program seems not to meet the #include
> requirement as articulated in N4835 clause [expr.spaceship] p10:
> 
> "10 The five comparison category types (17.11.2) (the types
> std::strong_ordering, std::strong_equality, std::weak_ordering,
> std::weak_equality, and std::partial_ordering) are not predefined; if the
> header <compare> (17.11.1) is not included prior to a use of such a class
> type – even an implicit use in which the type is not named (e.g., via the
> auto specifier (9.2.8.5) in a defaulted three-way comparison (11.11.3) or
> use of the built-in operator) – the program is ill-formed."

My mistake, I over simplified the example.  There should have been a #include <compare> in both cases.
Comment 4 Andrew Pinski 2021-08-13 00:09:36 UTC
I can't reproduce the ICE in GCC 10.1.0 or 11.1.0 or on the trunk.