PR c++/92774 - ICE with implicitly deleted operator<=>.
authorJason Merrill <jason@redhat.com>
Wed, 11 Dec 2019 16:51:05 +0000 (11:51 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 11 Dec 2019 16:51:05 +0000 (11:51 -0500)
Missing error-recovery code.  While I was poking at this I also figured we
don't need to iterate over the members of a union.

* method.c (comp_info::~comp_info): Factor out of...
(build_comparison_op): Here.  Handle error return from build_new_op.

From-SVN: r279235

gcc/cp/ChangeLog
gcc/cp/method.c
gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C [new file with mode: 0644]

index 4cb79b2..6daee41 100644 (file)
@@ -1,5 +1,9 @@
 2019-12-11  Jason Merrill  <jason@redhat.com>
 
+       PR c++/92774 - ICE with implicitly deleted operator<=>.
+       * method.c (comp_info::~comp_info): Factor out of...
+       (build_comparison_op): Here.  Handle error return from build_new_op.
+
        PR c++/92859 - ADL and bit-field.
        * name-lookup.c: Use unlowered_expr_type.
 
index 83da20a..97c27c5 100644 (file)
@@ -1244,6 +1244,21 @@ struct comp_info
     if (noex && !expr_noexcept_p (expr, tf_none))
       noex = false;
   }
+
+  ~comp_info ()
+  {
+    if (first_time)
+      {
+       DECL_DECLARED_CONSTEXPR_P (fndecl) = constexp || was_constexp;
+       tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fndecl));
+       if (!raises || UNEVALUATED_NOEXCEPT_SPEC_P (raises))
+         {
+           raises = noex ? noexcept_true_spec : noexcept_false_spec;
+           TREE_TYPE (fndecl) = build_exception_variant (TREE_TYPE (fndecl),
+                                                         raises);
+         }
+      }
+  }
 };
 
 /* Build up the definition of a defaulted comparison operator.  Unlike other
@@ -1282,6 +1297,7 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
       if (complain & tf_error)
        inform (info.loc, "cannot default compare union %qT", ctype);
       DECL_DELETED_FN (fndecl) = true;
+      return;
     }
 
   tree compound_stmt = NULL_TREE;
@@ -1335,6 +1351,11 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
                                 NULL_TREE);
          tree comp = build_new_op (info.loc, code, flags, lhs_mem, rhs_mem,
                                    NULL_TREE, NULL, complain);
+         if (comp == error_mark_node)
+           {
+             DECL_DELETED_FN (fndecl) = true;
+             continue;
+           }
          comps.safe_push (comp);
        }
       if (code == SPACESHIP_EXPR && is_auto (rettype))
@@ -1430,18 +1451,6 @@ build_comparison_op (tree fndecl, tsubst_flags_t complain)
     finish_compound_stmt (compound_stmt);
   else
     --cp_unevaluated_operand;
-
-  if (info.first_time)
-    {
-      DECL_DECLARED_CONSTEXPR_P (fndecl) = info.constexp || info.was_constexp;
-      tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fndecl));
-      if (!raises || UNEVALUATED_NOEXCEPT_SPEC_P (raises))
-       {
-         raises = info.noex ? noexcept_true_spec : noexcept_false_spec;
-         TREE_TYPE (fndecl) = build_exception_variant (TREE_TYPE (fndecl),
-                                                       raises);
-       }
-    }
 }
 
 /* Synthesize FNDECL, a non-static member function.   */
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg2.C
new file mode 100644 (file)
index 0000000..ecc249a
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/92774
+// { dg-do compile { target c++2a } }
+
+#include <compare>
+
+template<typename T>
+struct X { };
+
+template<typename T>
+bool operator==(const X<T>&, const X<T>&) { return true; }
+template<typename T>
+bool operator<(const X<T>&, const X<T>&) { return true; }
+
+struct Y
+{
+  int a;
+  X<int> c;
+
+  auto operator <=>(Y const&) const = default; // { dg-error "no match" }
+};
+
+void f()
+{
+  auto x = Y() < Y();          // { dg-error "deleted" }
+}