mizvekov updated this revision to Diff 319400. mizvekov added a comment. added tests
adds test that will catch original bug also adds some tests on default equality/relational operators this last one would have caught the issue of not accepting equality operator for function pointers, had I not remembered about it :) Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D95409/new/ https://reviews.llvm.org/D95409 Files: clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/class/class.compare/class.compare.default/p6.cpp clang/test/CXX/class/class.compare/class.spaceship/p4.cpp Index: clang/test/CXX/class/class.compare/class.spaceship/p4.cpp =================================================================== --- /dev/null +++ clang/test/CXX/class/class.compare/class.spaceship/p4.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +namespace std { +class partial_ordering { + int n; + constexpr partial_ordering(int n) : n(n) {} + +public: + static const partial_ordering less, equivalent, greater, unordered; + bool operator!=(int) { return n != 0; } +}; +constexpr partial_ordering partial_ordering::less{-1}, + partial_ordering::equivalent{0}, partial_ordering::greater{1}, + partial_ordering::unordered{2}; +} // namespace std + +struct A { + auto operator<=>(A const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + const int &a = 0; // expected-note {{defaulted 'operator<=>' is implicitly deleted because class 'A' has a reference member}} +}; + +struct B { + auto operator<=>(B const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + void (*a)(); // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}} +}; + +struct C { + auto operator<=>(C const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + void (C::*a)(); // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}} +}; + +struct D { + auto operator<=>(D const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + int D::*a; // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}} +}; Index: clang/test/CXX/class/class.compare/class.compare.default/p6.cpp =================================================================== --- /dev/null +++ clang/test/CXX/class/class.compare/class.compare.default/p6.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +struct A { + bool operator==(A const &) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}} + bool operator<(A const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + const int &a = 0; // expected-note {{defaulted 'operator==' is implicitly deleted because class 'A' has a reference member}} +}; + +struct B { + bool operator==(B const &) const = default; + bool operator<(B const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + void (*a)(); +}; + +struct C { + bool operator==(C const &) const = default; + bool operator<(C const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + void (C::*a)(); +}; + +struct D { + bool operator==(D const &) const = default; + bool operator<(D const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + int D::*a; +}; Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -7677,7 +7677,8 @@ if (Args[0]->getType()->isOverloadableType()) S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args); - else { + else if (OO == OO_EqualEqual || + !Args[0]->getType()->isFunctionPointerType()) { // FIXME: We determine whether this is a valid expression by checking to // see if there's a viable builtin operator candidate for it. That isn't // really what the rules ask us to do, but should give the right results.
Index: clang/test/CXX/class/class.compare/class.spaceship/p4.cpp =================================================================== --- /dev/null +++ clang/test/CXX/class/class.compare/class.spaceship/p4.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +namespace std { +class partial_ordering { + int n; + constexpr partial_ordering(int n) : n(n) {} + +public: + static const partial_ordering less, equivalent, greater, unordered; + bool operator!=(int) { return n != 0; } +}; +constexpr partial_ordering partial_ordering::less{-1}, + partial_ordering::equivalent{0}, partial_ordering::greater{1}, + partial_ordering::unordered{2}; +} // namespace std + +struct A { + auto operator<=>(A const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + const int &a = 0; // expected-note {{defaulted 'operator<=>' is implicitly deleted because class 'A' has a reference member}} +}; + +struct B { + auto operator<=>(B const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + void (*a)(); // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}} +}; + +struct C { + auto operator<=>(C const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + void (C::*a)(); // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}} +}; + +struct D { + auto operator<=>(D const &) const = default; // expected-warning {{explicitly defaulted three-way comparison operator is implicitly deleted}} + int D::*a; // expected-note {{defaulted 'operator<=>' is implicitly deleted because there is no viable comparison function for member 'a'}} +}; Index: clang/test/CXX/class/class.compare/class.compare.default/p6.cpp =================================================================== --- /dev/null +++ clang/test/CXX/class/class.compare/class.compare.default/p6.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -std=c++2a -verify %s + +struct A { + bool operator==(A const &) const = default; // expected-warning {{explicitly defaulted equality comparison operator is implicitly deleted}} + bool operator<(A const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + const int &a = 0; // expected-note {{defaulted 'operator==' is implicitly deleted because class 'A' has a reference member}} +}; + +struct B { + bool operator==(B const &) const = default; + bool operator<(B const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + void (*a)(); +}; + +struct C { + bool operator==(C const &) const = default; + bool operator<(C const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + void (C::*a)(); +}; + +struct D { + bool operator==(D const &) const = default; + bool operator<(D const &) const = default; // expected-warning {{explicitly defaulted relational comparison operator is implicitly deleted}} + // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because there is no viable comparison function}} + int D::*a; +}; Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -7677,7 +7677,8 @@ if (Args[0]->getType()->isOverloadableType()) S.LookupOverloadedBinOp(CandidateSet, OO, Fns, Args); - else { + else if (OO == OO_EqualEqual || + !Args[0]->getType()->isFunctionPointerType()) { // FIXME: We determine whether this is a valid expression by checking to // see if there's a viable builtin operator candidate for it. That isn't // really what the rules ask us to do, but should give the right results.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits