https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118387

--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>:

https://gcc.gnu.org/g:4c688399db12c509c081d52b8926ac6d7de6068c

commit r15-6799-g4c688399db12c509c081d52b8926ac6d7de6068c
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Fri Jan 10 18:42:58 2025 +0100

    c++: Fix ICE with invalid defaulted operator <=> [PR118387]

    In the following testcase there are 2 issues, one is that B doesn't
    have operator<=> and the other is that A's operator<=> has int return
    type, i.e. not the standard comparison category.
    Because of the int return type, retcat is cc_last; when we first
    try to synthetize it, it is therefore with tentative false and complain
    tf_none, we find that B doesn't have operator<=> and because retcat isn't
    tc_last, don't try to search for other operators in genericize_spaceship.
    And then mark the operator deleted.
    When trying to explain the use of the deleted operator, tentative is still
    false, but complain is tf_error_or_warning.
    do_one_comp will first do:
      tree comp = build_new_op (loc, code, flags, lhs, rhs,
                                NULL_TREE, NULL_TREE, &overload,
                                tentative ? tf_none : complain);
    and because complain isn't tf_none, it will actually diagnose the bug
    already, but then (tentative || complain) is true and we call
    genericize_spaceship, which has
      if (tag == cc_last && is_auto (type))
        {
    ...
        }

      gcc_checking_assert (tag < cc_last);
    and because tag is cc_last and type isn't auto, we just ICE on that
    assertion.

    The patch fixes it by returning error_mark_node from genericize_spaceship
    instead of failing the assertion.

    Note, the PR raises another problem.
    If on the same testcase the B b; line is removed, we silently synthetize
    operator<=> which will crash at runtime due to returning without a return
    statement.  That is because the standard says that in that case
    it should return static_cast<int>(std::strong_ordering::equal);
    but I can't find anywhere wording which would say that if that isn't
    valid, the function is deleted.
    https://eel.is/c++draft/class.compare#class.spaceship-2.2
    seems to talk just about cases where there are some members and their
    comparison is invalid it is deleted, but here there are none and it
    follows
    https://eel.is/c++draft/class.compare#class.spaceship-3.sentence-2
    So, we synthetize with tf_none, see the static_cast is invalid, don't
    add error_mark_node statement silently, but as the function isn't deleted,
    we just silently emit it.
    Should the standard be amended to say that the operator should be deleted
    even if it has no elements and the static cast from
    https://eel.is/c++draft/class.compare#class.spaceship-3.sentence-2
    ?

    2025-01-10  Jakub Jelinek  <ja...@redhat.com>

            PR c++/118387
            * method.cc (genericize_spaceship): For tag == cc_last if
            type is not auto just return error_mark_node instead of failing
            checking assertion.

            * g++.dg/cpp2a/spaceship-synth17.C: New test.

Reply via email to