From: Jason Merrill Date: Thu, 7 Nov 2019 17:06:09 +0000 (-0500) Subject: Implement D1959R0, remove weak_equality and strong_equality. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4629ea55608ee2f1e04186dce2c7f55af0537ccb;p=gcc.git Implement D1959R0, remove weak_equality and strong_equality. Shortly after I finished implementing the previous semantics, the committee decided to remove the *_equality comparison categories, because they were largely obsoleted by the earlier change that separated operator== from its original dependency on operator<=>. gcc/cp/ * method.c (enum comp_cat_tag, comp_cat_info): Remove *_equality. (genericize_spaceship, common_comparison_type): Likewise. * typeck.c (cp_build_binary_op): Move SPACESHIP_EXPR to be with the relational operators, exclude other types no longer supported. libstdc++-v3/ * libsupc++/compare: Remove strong_equality and weak_equality. From-SVN: r277925 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a0b93e77e4d..2aa0afae113 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2019-11-07 Jason Merrill + + Implement D1959R0, remove weak_equality and strong_equality. + * method.c (enum comp_cat_tag, comp_cat_info): Remove *_equality. + (genericize_spaceship, common_comparison_type): Likewise. + * typeck.c (cp_build_binary_op): Move SPACESHIP_EXPR to be with the + relational operators, exclude other types no longer supported. + 2019-11-06 Jason Merrill Implement D1907R1 "structural type". diff --git a/gcc/cp/method.c b/gcc/cp/method.c index c9dd90fcba7..47441c10c52 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -882,8 +882,6 @@ do_build_copy_assign (tree fndecl) enum comp_cat_tag { - cc_weak_equality, - cc_strong_equality, cc_partial_ordering, cc_weak_ordering, cc_strong_ordering, @@ -901,8 +899,6 @@ struct comp_cat_info_t }; static const comp_cat_info_t comp_cat_info[cc_last] = { - { "weak_equality", "equivalent", "nonequivalent" }, - { "strong_equality", "equal", "nonequal" }, { "partial_ordering", "equivalent", "greater", "less", "unordered" }, { "weak_ordering", "equivalent", "greater", "less" }, { "strong_ordering", "equal", "greater", "less" } @@ -1028,21 +1024,8 @@ spaceship_comp_cat (tree optype) return cc_strong_ordering; else if (TREE_CODE (optype) == REAL_TYPE) return cc_partial_ordering; - else if (TYPE_PTRFN_P (optype) || TYPE_PTRMEM_P (optype) - || NULLPTR_TYPE_P (optype)) - return cc_strong_equality; - else if (TREE_CODE (optype) == COMPLEX_TYPE) - { - tree intype = optype; - while (TREE_CODE (intype) == COMPLEX_TYPE) - intype = TREE_TYPE (intype); - if (TREE_CODE (intype) == REAL_TYPE) - return cc_weak_equality; - else - return cc_strong_equality; - } - /* FIXME should vector <=> produce a vector of one of the above? */ + /* ??? should vector <=> produce a vector of one of the above? */ gcc_unreachable (); } @@ -1065,35 +1048,29 @@ genericize_spaceship (tree type, tree op0, tree op1) comp_cat_tag tag = cat_tag_for (type); gcc_checking_assert (tag < cc_last); - tree eq = lookup_comparison_result (tag, type, 0); - tree negt = lookup_comparison_result (tag, type, 1); - - if (tag == cc_strong_equality || tag == cc_weak_equality) - { - tree comp = fold_build2 (EQ_EXPR, boolean_type_node, op0, op1); - return fold_build3 (COND_EXPR, type, comp, eq, negt); - } - tree r; op0 = save_expr (op0); op1 = save_expr (op1); + tree gt = lookup_comparison_result (tag, type, 1); + if (tag == cc_partial_ordering) { /* op0 == op1 ? equivalent : op0 < op1 ? less : op0 > op1 ? greater : unordered */ tree uo = lookup_comparison_result (tag, type, 3); tree comp = fold_build2 (GT_EXPR, boolean_type_node, op0, op1); - r = fold_build3 (COND_EXPR, type, comp, negt, uo); + r = fold_build3 (COND_EXPR, type, comp, gt, uo); } else /* op0 == op1 ? equal : op0 < op1 ? less : greater */ - r = negt; + r = gt; tree lt = lookup_comparison_result (tag, type, 2); tree comp = fold_build2 (LT_EXPR, boolean_type_node, op0, op1); r = fold_build3 (COND_EXPR, type, comp, lt, r); + tree eq = lookup_comparison_result (tag, type, 0); comp = fold_build2 (EQ_EXPR, boolean_type_node, op0, op1); r = fold_build3 (COND_EXPR, type, comp, eq, r); @@ -1178,18 +1155,6 @@ common_comparison_type (vec &comps) return void_type_node; } - /* Otherwise, if at least one T i is std::weak_equality, or at least one T i - is std::strong_equality and at least one T j is std::partial_ordering or - std::weak_ordering, U is std::weak_equality. */ - if (tree t = seen[cc_weak_equality]) return t; - if (seen[cc_strong_equality] - && (seen[cc_partial_ordering] || seen[cc_weak_ordering])) - return lookup_comparison_category (cc_weak_equality); - - /* Otherwise, if at least one T i is std::strong_equality, U is - std::strong_equality. */ - if (tree t = seen[cc_strong_equality]) return t; - /* Otherwise, if at least one T i is std::partial_ordering, U is std::partial_ordering. */ if (tree t = seen[cc_partial_ordering]) return t; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 38a15d14620..124d16a31fb 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4889,7 +4889,6 @@ cp_build_binary_op (const op_location_t &location, case EQ_EXPR: case NE_EXPR: - case SPACESHIP_EXPR: if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE) goto vector_compare; if ((complain & tf_warning) @@ -4966,9 +4965,7 @@ cp_build_binary_op (const op_location_t &location, warn_for_null_address (location, op1, complain); } else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE) - || (code == SPACESHIP_EXPR - ? TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1) - : TYPE_PTRDATAMEM_P (type0) && TYPE_PTRDATAMEM_P (type1))) + || (TYPE_PTRDATAMEM_P (type0) && TYPE_PTRDATAMEM_P (type1))) result_type = composite_pointer_type (location, type0, type1, op0, op1, CPO_COMPARISON, complain); @@ -5172,6 +5169,7 @@ cp_build_binary_op (const op_location_t &location, case GE_EXPR: case LT_EXPR: case GT_EXPR: + case SPACESHIP_EXPR: if (TREE_CODE (orig_op0) == STRING_CST || TREE_CODE (orig_op1) == STRING_CST) { @@ -5369,7 +5367,9 @@ cp_build_binary_op (const op_location_t &location, tree_code orig_code0 = TREE_CODE (orig_type0); tree orig_type1 = TREE_TYPE (orig_op1); tree_code orig_code1 = TREE_CODE (orig_type1); - if ((orig_code0 == BOOLEAN_TYPE) != (orig_code1 == BOOLEAN_TYPE)) + if (!result_type) + /* Nope. */; + else if ((orig_code0 == BOOLEAN_TYPE) != (orig_code1 == BOOLEAN_TYPE)) /* "If one of the operands is of type bool and the other is not, the program is ill-formed." */ result_type = NULL_TREE; @@ -5378,6 +5378,9 @@ cp_build_binary_op (const op_location_t &location, /* We only do array/function-to-pointer conversion if "at least one of the operands is of pointer type". */ result_type = NULL_TREE; + else if (TYPE_PTRFN_P (result_type) || NULLPTR_TYPE_P (result_type)) + /* <=> no longer supports equality relations. */ + result_type = NULL_TREE; else if (orig_code0 == ENUMERAL_TYPE && orig_code1 == ENUMERAL_TYPE && !(same_type_ignoring_top_level_qualifiers_p (orig_type0, orig_type1))) diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1-neg.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1-neg.C new file mode 100644 index 00000000000..012416a212b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1-neg.C @@ -0,0 +1,25 @@ +// { dg-do run { target c++2a } } + +#include + +#define assert(X) do { if (!(X)) __builtin_abort(); } while(0) + +void f(){} +void g(){} + +int main() +{ + { + const auto v = &f <=> &g; // { dg-error "invalid operands" } + } + + { + struct A { int i; int j; }; + constexpr auto v = &A::i <=> &A::j; // { dg-error "invalid operands" } + } + + { + struct A { void f(); }; + constexpr auto v = &A::f <=> &A::f; // { dg-error "invalid operands" } + } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C index 2ca86b748ff..0d1dd63d368 100644 --- a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1.C @@ -4,9 +4,6 @@ #define assert(X) do { if (!(X)) __builtin_abort(); } while(0) -void f(){} -void g(){} - int main() { { @@ -66,28 +63,4 @@ int main() static_assert (!is_gt (v)); static_assert (is_gteq (v)); } - - { - // GCC doesn't consider &f == &g to be a constant expression (PR 69681) - const auto v = &f <=> &g; - static_assert (__is_same_as (decltype (v), const std::strong_equality)); - assert (!is_eq (v)); - assert (is_neq (v)); - } - - { - struct A { int i; int j; }; - constexpr auto v = &A::i <=> &A::j; - static_assert (__is_same_as (decltype (v), const std::strong_equality)); - static_assert (!is_eq (v)); - static_assert (is_neq (v)); - } - - { - struct A { void f(); }; - constexpr auto v = &A::f <=> &A::f; - static_assert (__is_same_as (decltype (v), const std::strong_equality)); - static_assert (is_eq (v)); - static_assert (!is_neq (v)); - } } diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C index 1dc95497fd9..552c92aa5bd 100644 --- a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1a.C @@ -4,9 +4,6 @@ #define assert(X) do { if (!(X)) __builtin_abort(); } while(0) -void f(){} -void g(){} - template constexpr bool check(T a, U b, R expected) { @@ -29,13 +26,4 @@ int main() static_assert (check (&ar[1], &ar[0], std::strong_ordering::greater)); static_assert (check (3.14, 3.14, std::partial_ordering::equivalent)); - - // GCC doesn't consider &f == &g to be a constant expression (PR 69681) - assert (check (&f, &g, std::strong_equality::nonequal)); - - struct A { int i; int j; }; - static_assert (check (&A::i, &A::j, std::strong_equality::nonequal)); - - struct A2 { void f(); }; - static_assert (check (&A2::f, &A2::f, std::strong_equality::equal)); } diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C index 20bc8e61455..7dacaf4b81d 100644 --- a/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar3.C @@ -1,21 +1,9 @@ -// { dg-do run { target c++2a } } +// { dg-do compile { target c++2a } } // { dg-options "-fext-numeric-literals" } -#include - int main() { // GCC complex literal extension - { - constexpr auto v = 1 <=> 1i; - static_assert (__is_same_as (decltype (v), const std::strong_equality)); - static_assert (!is_eq (v)); - static_assert (is_neq (v)); - } - { - constexpr auto v = 1i <=> 1.0i; - static_assert (__is_same_as (decltype (v), const std::weak_equality)); - static_assert (is_eq (v)); - static_assert (!is_neq (v)); - } + { constexpr auto v = 1 <=> 1i; } // { dg-error "invalid operands" } + { constexpr auto v = 1i <=> 1.0i; } // { dg-error "invalid operands" } } diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3eb20181139..cbea95ba403 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,7 @@ +2019-11-07 Jason Merrill + + * libsupc++/compare: Remove strong_equality and weak_equality. + 2019-11-06 Jonathan Wakely * include/Makefile.in: Regenerate. diff --git a/libstdc++-v3/libsupc++/compare b/libstdc++-v3/libsupc++/compare index 2e518ccbffd..84cc3f5c85f 100644 --- a/libstdc++-v3/libsupc++/compare +++ b/libstdc++-v3/libsupc++/compare @@ -59,103 +59,6 @@ namespace std }; } - class weak_equality - { - int _M_value; - - constexpr explicit - weak_equality(__cmp_cat::_Eq __val) noexcept - : _M_value(int(__val)) - { } - - public: - // valid values - - static const weak_equality equivalent; - static const weak_equality nonequivalent; - - // comparisons - - friend constexpr bool - operator==(weak_equality __v, __cmp_cat::__unspec) noexcept - { return __v._M_value == 0; } - - friend constexpr bool - operator==(weak_equality, weak_equality) noexcept = default; - - friend constexpr weak_equality - operator<=>(weak_equality __v, __cmp_cat::__unspec) noexcept - { return __v; } - - friend constexpr weak_equality - operator<=>(__cmp_cat::__unspec, weak_equality __v) noexcept - { return __v; } - }; - - // valid values' definitions - inline constexpr weak_equality - weak_equality::equivalent(__cmp_cat::_Eq::equivalent); - - inline constexpr weak_equality - weak_equality::nonequivalent(__cmp_cat::_Eq::nonequivalent); - - class strong_equality - { - int _M_value; - - constexpr explicit - strong_equality(__cmp_cat::_Eq __val) noexcept - : _M_value(int(__val)) - { } - - public: - // valid values - - static const strong_equality equal; - static const strong_equality nonequal; - static const strong_equality equivalent; - static const strong_equality nonequivalent; - - // conversion - constexpr operator weak_equality() const noexcept - { - if (_M_value == 0) - return weak_equality::equivalent; - else - return weak_equality::nonequivalent; - } - - // comparisons - - friend constexpr bool - operator==(strong_equality __v, __cmp_cat::__unspec) noexcept - { return __v._M_value == 0; } - - friend constexpr bool - operator==(strong_equality, strong_equality) noexcept = default; - - friend constexpr strong_equality - operator<=>(strong_equality __v, __cmp_cat::__unspec) noexcept - { return __v; } - - friend constexpr strong_equality - operator<=>(__cmp_cat::__unspec, strong_equality __v) noexcept - { return __v; } - }; - - // valid values' definitions - inline constexpr strong_equality - strong_equality::equal(__cmp_cat::_Eq::equal); - - inline constexpr strong_equality - strong_equality::nonequal(__cmp_cat::_Eq::nonequal); - - inline constexpr strong_equality - strong_equality::equivalent(__cmp_cat::_Eq::equivalent); - - inline constexpr strong_equality - strong_equality::nonequivalent(__cmp_cat::_Eq::nonequivalent); - class partial_ordering { int _M_value; @@ -183,15 +86,6 @@ namespace std static const partial_ordering greater; static const partial_ordering unordered; - // conversion - constexpr operator weak_equality() const noexcept - { - if (_M_value == 0) - return weak_equality::equivalent; - else - return weak_equality::nonequivalent; - } - // comparisons friend constexpr bool operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept @@ -279,15 +173,6 @@ namespace std static const weak_ordering equivalent; static const weak_ordering greater; - // conversions - constexpr operator weak_equality() const noexcept - { - if (_M_value == 0) - return weak_equality::equivalent; - else - return weak_equality::nonequivalent; - } - constexpr operator partial_ordering() const noexcept { if (_M_value == 0) @@ -385,23 +270,6 @@ namespace std static const strong_ordering equivalent; static const strong_ordering greater; - // conversions - constexpr operator weak_equality() const noexcept - { - if (_M_value == 0) - return weak_equality::equivalent; - else - return weak_equality::nonequivalent; - } - - constexpr operator strong_equality() const noexcept - { - if (_M_value == 0) - return strong_equality::equal; - else - return strong_equality::nonequal; - } - constexpr operator partial_ordering() const noexcept { if (_M_value == 0) @@ -494,11 +362,11 @@ namespace std // named comparison functions constexpr bool - is_eq(weak_equality __cmp) noexcept + is_eq(partial_ordering __cmp) noexcept { return __cmp == 0; } constexpr bool - is_neq(weak_equality __cmp) noexcept + is_neq(partial_ordering __cmp) noexcept { return __cmp != 0; } constexpr bool