diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/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. diff --git a/clang/test/CXX/class/class.compare/class.compare.default/p6.cpp b/clang/test/CXX/class/class.compare/class.compare.default/p6.cpp new file mode 100644 --- /dev/null +++ b/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; +}; diff --git a/clang/test/CXX/class/class.compare/class.spaceship/p4.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p4.cpp new file mode 100644 --- /dev/null +++ b/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'}} +};