[C++] Implement D1959R0, remove weak_equality and strong_equality.
diff mbox series

Message ID 20191107170516.31345-1-jason@redhat.com
State New
Headers show
Series
  • [C++] Implement D1959R0, remove weak_equality and strong_equality.
Related show

Commit Message

Jason Merrill Nov. 7, 2019, 5:05 p.m. UTC
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<=>.

Tested x86_64-pc-linux-gnu, applying to trunk.

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.
---
 gcc/cp/method.c                               |  47 +-----
 gcc/cp/typeck.c                               |  13 +-
 .../g++.dg/cpp2a/spaceship-scalar1-neg.C      |  25 ++++
 .../g++.dg/cpp2a/spaceship-scalar1.C          |  27 ----
 .../g++.dg/cpp2a/spaceship-scalar1a.C         |  12 --
 .../g++.dg/cpp2a/spaceship-scalar3.C          |  18 +--
 libstdc++-v3/libsupc++/compare                | 136 +-----------------
 7 files changed, 44 insertions(+), 234 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1-neg.C


base-commit: 210e2303be57d041ae9805821ab62450c5b607bd

Comments

Jakub Jelinek Nov. 7, 2019, 11:30 p.m. UTC | #1
On Thu, Nov 07, 2019 at 05:05:16PM +0000, Jason Merrill wrote:
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1-neg.C
> @@ -0,0 +1,25 @@
> +// { dg-do run { target c++2a } }
> +
> +#include <compare>
> +
> +#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" }
...

I've noticed this test being UNRESOLVED (the execution part of it, because
we expect errors during compilation).

Fixed thusly, tested on x86_64-linux, committed to trunk as obvious:

2019-11-08  Jakub Jelinek  <jakub@redhat.com>

	* g++.dg/cpp2a/spaceship-scalar1-neg.C: Change dg-do from run to
	compile.

--- gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1-neg.C	(revision 277932)
+++ gcc/testsuite/g++.dg/cpp2a/spaceship-scalar1-neg.C	(working copy)
@@ -1,4 +1,4 @@
-// { dg-do run { target c++2a } }
+// { dg-do compile { target c++2a } }
 
 #include <compare>
 


	Jakub

Patch
diff mbox series

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<tree> &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 <compare>
+
+#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 <class T, class U, class R>
 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 <compare>
-
 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/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