AMP999 created this revision.
AMP999 added reviewers: clang, rsmith.
AMP999 added a project: clang.
Herald added a project: All.
AMP999 requested review of this revision.
Herald added a subscriber: cfe-commits.

https://godbolt.org/z/cMKE3o1aG

According to the issue https://github.com/llvm/llvm-project/issues/63960 , 
compiler falsely complains that no viable `operator<=>` was found while we are 
actually looking for a `operator==`.
This bug has been fixed through adding a check of the `OverloadedOperatorKind` 
type's object, `OO`, to see if it is `OO_EqualEqual` in addition to 
`OO_ExclaimEqual`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155714

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
  clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
  clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
  clang/test/CXX/class/class.compare/class.eq/p2.cpp
  clang/test/CXX/class/class.compare/class.spaceship/p1.cpp


Index: clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
+++ clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
@@ -80,7 +80,7 @@
   // expected-note@#base {{deleted comparison function for base class 'C'}}
   // expected-note@#base {{no viable three-way comparison function for base 
class 'D1'}}
   // expected-note@#base {{three-way comparison cannot be synthesized because 
there is no viable function for '<' comparison}}
-  // expected-note@#base {{no viable three-way comparison function for base 
class 'D2'}}
+  // expected-note@#base {{no viable 'operator==' for base class 'D2'}}
   // expected-note@#base {{three-way comparison cannot be synthesized because 
there is no viable function for '==' comparison}}
   // expected-note@#base {{deleted comparison function for base class 'E'}}
   // expected-note@#base {{implied comparison for base class 'F' is ambiguous}}
@@ -112,7 +112,7 @@
   // expected-note@#arr {{deleted comparison function for member 'arr'}}
   // expected-note@#arr {{no viable three-way comparison function for member 
'arr'}}
   // expected-note@#arr {{three-way comparison cannot be synthesized because 
there is no viable function for '<' comparison}}
-  // expected-note@#arr {{no viable three-way comparison function for member 
'arr'}}
+  // expected-note@#arr {{no viable 'operator==' for member 'arr'}}
   // expected-note@#arr {{three-way comparison cannot be synthesized because 
there is no viable function for '==' comparison}}
   // expected-note@#arr {{deleted comparison function for member 'arr'}}
   // expected-note@#arr {{implied comparison for member 'arr' is ambiguous}}
Index: clang/test/CXX/class/class.compare/class.eq/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.eq/p2.cpp
+++ clang/test/CXX/class/class.compare/class.eq/p2.cpp
@@ -37,7 +37,7 @@
 template<typename T> struct X {
   X();
   bool operator==(const X&) const = default; // #x expected-note 4{{deleted 
here}}
-  T t; // expected-note 3{{because there is no viable three-way comparison 
function for member 't'}}
+  T t; // expected-note 3{{because there is no viable 'operator==' for member 
't'}}
        // expected-note@-1 {{because it would invoke a deleted comparison 
function for member 't'}}
 };
 
Index: clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
+++ clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
@@ -5,6 +5,14 @@
   // expected-note@-1 {{defaulted 'operator!=' is implicitly deleted because 
there is no viable 'operator==' for 'A'}}
 };
 
+struct A2 {
+  struct E {};
+  E e;
+  bool operator==(const A2&) const = default; // expected-warning {{explicitly 
defaulted equality comparison operator is implicitly deleted}} 
expected-note{{replace 'default'}}
+  // expected-note@-2 {{defaulted 'operator==' is implicitly deleted because 
there is no viable 'operator==' for member 'e'}}
+};
+
+
 struct Q {};
 bool operator!=(Q, Q); // expected-note {{defaulted 'operator!=' is implicitly 
deleted because this non-rewritten comparison function would be the best match 
for the comparison}}
 struct B {
Index: clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
+++ clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
@@ -100,7 +100,7 @@
   struct Q {
     struct X {
       friend std::strong_ordering operator<=>(const X&, const X&);
-    } x; // expected-note {{no viable three-way comparison}}
+    } x; // expected-note {{no viable 'operator=='}}
     // expected-error@+1 {{defaulting the corresponding implicit 'operator==' 
for this defaulted 'operator<=>' would delete it after its first declaration}}
     friend std::strong_ordering operator<=>(const Q&, const Q&) = default;
   };
Index: clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
+++ clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
@@ -153,7 +153,7 @@
     friend bool operator==(A &, A &); // expected-note {{would lose const 
qualifier}}
   };
   struct B {
-    A a; // expected-note {{no viable three-way comparison}}
+    A a; // expected-note {{no viable 'operator=='}}
     friend bool operator==(B, B) = default; // ok
     friend bool operator==(const B&, const B&) = default; // expected-warning 
{{deleted}} expected-note{{replace 'default'}}
   };
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -8209,7 +8209,7 @@
 
       if (Diagnose == ExplainDeleted) {
         S.Diag(Subobj.Loc, diag::note_defaulted_comparison_no_viable_function)
-            << FD << (OO == OO_ExclaimEqual) << Subobj.Kind << Subobj.Decl;
+            << FD << (OO == OO_EqualEqual | OO == OO_ExclaimEqual) << 
Subobj.Kind << Subobj.Decl;
 
         // For a three-way comparison, list both the candidates for the
         // original operator and the candidates for the synthesized operator.


Index: clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
+++ clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
@@ -80,7 +80,7 @@
   // expected-note@#base {{deleted comparison function for base class 'C'}}
   // expected-note@#base {{no viable three-way comparison function for base class 'D1'}}
   // expected-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}}
-  // expected-note@#base {{no viable three-way comparison function for base class 'D2'}}
+  // expected-note@#base {{no viable 'operator==' for base class 'D2'}}
   // expected-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}}
   // expected-note@#base {{deleted comparison function for base class 'E'}}
   // expected-note@#base {{implied comparison for base class 'F' is ambiguous}}
@@ -112,7 +112,7 @@
   // expected-note@#arr {{deleted comparison function for member 'arr'}}
   // expected-note@#arr {{no viable three-way comparison function for member 'arr'}}
   // expected-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}}
-  // expected-note@#arr {{no viable three-way comparison function for member 'arr'}}
+  // expected-note@#arr {{no viable 'operator==' for member 'arr'}}
   // expected-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}}
   // expected-note@#arr {{deleted comparison function for member 'arr'}}
   // expected-note@#arr {{implied comparison for member 'arr' is ambiguous}}
Index: clang/test/CXX/class/class.compare/class.eq/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.eq/p2.cpp
+++ clang/test/CXX/class/class.compare/class.eq/p2.cpp
@@ -37,7 +37,7 @@
 template<typename T> struct X {
   X();
   bool operator==(const X&) const = default; // #x expected-note 4{{deleted here}}
-  T t; // expected-note 3{{because there is no viable three-way comparison function for member 't'}}
+  T t; // expected-note 3{{because there is no viable 'operator==' for member 't'}}
        // expected-note@-1 {{because it would invoke a deleted comparison function for member 't'}}
 };
 
Index: clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
+++ clang/test/CXX/class/class.compare/class.compare.secondary/p2.cpp
@@ -5,6 +5,14 @@
   // expected-note@-1 {{defaulted 'operator!=' is implicitly deleted because there is no viable 'operator==' for 'A'}}
 };
 
+struct A2 {
+  struct E {};
+  E e;
+  bool operator==(const A2&) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}} expected-note{{replace 'default'}}
+  // expected-note@-2 {{defaulted 'operator==' is implicitly deleted because there is no viable 'operator==' for member 'e'}}
+};
+
+
 struct Q {};
 bool operator!=(Q, Q); // expected-note {{defaulted 'operator!=' is implicitly deleted because this non-rewritten comparison function would be the best match for the comparison}}
 struct B {
Index: clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
+++ clang/test/CXX/class/class.compare/class.compare.default/p4.cpp
@@ -100,7 +100,7 @@
   struct Q {
     struct X {
       friend std::strong_ordering operator<=>(const X&, const X&);
-    } x; // expected-note {{no viable three-way comparison}}
+    } x; // expected-note {{no viable 'operator=='}}
     // expected-error@+1 {{defaulting the corresponding implicit 'operator==' for this defaulted 'operator<=>' would delete it after its first declaration}}
     friend std::strong_ordering operator<=>(const Q&, const Q&) = default;
   };
Index: clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
===================================================================
--- clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
+++ clang/test/CXX/class/class.compare/class.compare.default/p1.cpp
@@ -153,7 +153,7 @@
     friend bool operator==(A &, A &); // expected-note {{would lose const qualifier}}
   };
   struct B {
-    A a; // expected-note {{no viable three-way comparison}}
+    A a; // expected-note {{no viable 'operator=='}}
     friend bool operator==(B, B) = default; // ok
     friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
   };
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -8209,7 +8209,7 @@
 
       if (Diagnose == ExplainDeleted) {
         S.Diag(Subobj.Loc, diag::note_defaulted_comparison_no_viable_function)
-            << FD << (OO == OO_ExclaimEqual) << Subobj.Kind << Subobj.Decl;
+            << FD << (OO == OO_EqualEqual | OO == OO_ExclaimEqual) << Subobj.Kind << Subobj.Decl;
 
         // For a three-way comparison, list both the candidates for the
         // original operator and the candidates for the synthesized operator.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to