Implement C++20 operator<=>.
commitfff9b0f386c1fefa5795edd779a5025dba544e17
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Nov 2019 23:56:18 +0000 (5 23:56 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Nov 2019 23:56:18 +0000 (5 23:56 +0000)
tree6a00e1710db7a55cbcfec28cfbaf837950a9c70b
parentb21df1924784a889f5300e3d74161e8b88dade83
Implement C++20 operator<=>.

There are three major pieces to this support: scalar operator<=>,
synthesis of comparison operators, and rewritten/reversed overload
resolution (e.g. a < b becomes 0 > b <=> a).

Unlike other defaulted functions, where we use synthesized_method_walk to
semi-simulate what the definition of the function will be like, this patch
determines the characteristics of a comparison operator by trying to define
it.

My handling of non-dependent rewritten operators in templates can still use
some work: build_min_non_dep_op_overload can't understand the rewrites and
crashes, so I'm avoiding it for now by clearing *overload.  This means we'll
do name lookup again at instantiation time, which can incorrectly mean a
different result.  I'll poke at this more in stage 3.

I'm leaving out a fourth section ("strong structural equality") even though
I've implemented it, because it seems likely to change radically tomorrow.

Thanks to Tim van Deurzen and Jakub for implementing lexing of the <=>
operator, and Jonathan for the initial <compare> header.

gcc/cp/
* cp-tree.h (struct lang_decl_fn): Add maybe_deleted bitfield.
(DECL_MAYBE_DELETED): New.
(enum special_function_kind): Add sfk_comparison.
(LOOKUP_REWRITTEN, LOOKUP_REVERSED): New.
* call.c (struct z_candidate): Add rewritten and reversed methods.
(add_builtin_candidate): Handle SPACESHIP_EXPR.
(add_builtin_candidates): Likewise.
(add_candidates): Don't add a reversed candidate if the parms are
the same.
(add_operator_candidates): Split out from build_new_op_1.  Handle
rewritten and reversed candidates.
(add_candidate): Swap conversions of reversed candidate.
(build_new_op_1): Swap them back.  Build a second operation for
rewritten candidates.
(extract_call_expr): Handle rewritten calls.
(same_fn_or_template): New.
(joust): Handle rewritten and reversed candidates.
* class.c (add_implicitly_declared_members): Add implicit op==.
(classtype_has_op, classtype_has_defaulted_op): New.
* constexpr.c (cxx_eval_binary_expression): Handle SPACESHIP_EXPR.
(cxx_eval_constant_expression, potential_constant_expression_1):
Likewise.
* cp-gimplify.c (genericize_spaceship): New.
(cp_genericize_r): Use it.
* cp-objcp-common.c (cp_common_init_ts): Handle SPACESHIP_EXPR.
* decl.c (finish_function): Handle deleted function.
* decl2.c (grokfield): SET_DECL_FRIEND_CONTEXT on defaulted friend.
(mark_used): Check DECL_MAYBE_DELETED.  Remove assumption that
defaulted functions are non-static members.
* error.c (dump_expr): Handle SPACESHIP_EXPR.
* method.c (type_has_trivial_fn): False for sfk_comparison.
(enum comp_cat_tag, struct comp_cat_info_t): New types.
(comp_cat_cache): New array variable.
(lookup_comparison_result, lookup_comparison_category)
(is_cat, cat_tag_for, spaceship_comp_cat)
(spaceship_type, genericize_spaceship)
(common_comparison_type, early_check_defaulted_comparison)
(comp_info, build_comparison_op): New.
(synthesize_method): Handle sfk_comparison.  Handle deleted.
(get_defaulted_eh_spec, maybe_explain_implicit_delete)
(explain_implicit_non_constexpr, implicitly_declare_fn)
(defaulted_late_check, defaultable_fn_check): Handle sfk_comparison.
* name-lookup.c (get_std_name_hint): Add comparison categories.
* tree.c (special_function_p): Add sfk_comparison.
* typeck.c (cp_build_binary_op): Handle SPACESHIP_EXPR.

2019-11-05  Tim van Deurzen  <tim@kompiler.org>

Add new tree code for the spaceship operator.
gcc/cp/
* cp-tree.def: Add new tree code.
* operators.def: New binary operator.
* parser.c: Add new token and tree code.
libcpp/
* cpplib.h: Add spaceship operator for C++.
* lex.c: Implement conditional lexing of spaceship operator for C++20.

2019-11-05  Jonathan Wakely  <jwakely@redhat.com>

libstdc++-v3/
* libsupc++/compare: New header.
* libsupc++/Makefile.am (std_HEADERS): Add compare.
* include/std/version: Define __cpp_lib_three_way_comparison.
* include/std/functional: #include <compare>.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@277865 138bc75d-0d04-0410-961f-82ee72b054a4
56 files changed:
gcc/c-family/c-cppbuiltin.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/constexpr.c
gcc/cp/cp-gimplify.c
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/method.c
gcc/cp/name-lookup.c
gcc/cp/operators.def
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/c-c++-common/cpp/spaceship-1.c [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp/spaceship-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq1a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-eq7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-err1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-err2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-scalar2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-synth1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-synth1a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-synth2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-synth3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-synth3a.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-weak1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/pr21802.C
gcc/testsuite/g++.old-deja/g++.robertl/eb22.C
libcpp/ChangeLog
libcpp/include/cpplib.h
libcpp/lex.c
libstdc++-v3/ChangeLog
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/std/functional
libstdc++-v3/include/std/version
libstdc++-v3/libsupc++/Makefile.am
libstdc++-v3/libsupc++/compare [new file with mode: 0644]
libstdc++-v3/testsuite/std/concepts/concepts.object/regular.cc