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