// RUN: %clang_cc1 -std=c++2a -verify %s struct A {}; struct B { bool operator==(B) const; }; struct C { int operator==(C) const; }; struct D { // expected-note@+2 {{candidate function not viable: 'this' argument has type 'const}} // expected-note@+1 {{candidate function (with reversed parameter order) not viable: 1st argument ('const}} bool operator==(D); }; struct E { E(const E &) = delete; // expected-note {{deleted}} int operator==(E) const; // expected-note {{passing}} }; struct F { void operator==(F) const; }; struct G { bool operator==(G) const = delete; }; // expected-note {{deleted here}} template 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 comparison function for member 't'}} // expected-note@-1 {{because it would invoke a deleted comparison function for member 't'}} }; struct Mutable { bool operator==(const Mutable&) const = default; mutable D d; }; void test() { void(X() == X()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}} void(X() == X()); void(X() == X()); void(X() == X()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}} void(Mutable() == Mutable()); // FIXME: We would benefit from a note identifying the member of 'X' we were comparing here and below. // expected-error@#x {{call to deleted constructor of 'E'}} void(X() == X()); // expected-note {{in defaulted equality comparison operator for 'X' first required here}} // FIXME: We would benefit from a note pointing at the selected 'operator==' here. // expected-error@#x {{value of type 'void' is not contextually convertible to 'bool'}} void(X() == X()); // expected-note {{in defaulted equality comparison operator for 'X' first required here}} void(X() == X()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}} void(X() == X()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}} void(X() == X()); } namespace Access { class A { bool operator==(const A &) const; // expected-note 2{{implicitly declared private here}} }; struct B : A { // expected-note 2{{because it would invoke a private 'operator==' to compare base class 'A'}} bool operator==(const B &) const = default; // expected-warning {{deleted}} friend bool operator==(const B &, const B &) = default; // expected-warning {{deleted}} }; class C { protected: bool operator==(const C &) const; // expected-note 2{{declared protected here}} }; struct D : C { bool operator==(const D &) const = default; friend bool operator==(const D &, const D&) = default; }; struct E { C c; // expected-note 2{{because it would invoke a protected 'operator==' member of 'Access::C' to compare member 'c'}} bool operator==(const E &) const = default; // expected-warning {{deleted}} friend bool operator==(const E &, const E &) = default; // expected-warning {{deleted}} }; struct F : C { using C::operator==; }; struct G : F { bool operator==(const G&) const = default; friend bool operator==(const G&, const G&) = default; }; struct H : C { private: using C::operator==; // expected-note 2{{declared private here}} }; struct I : H { // expected-note 2{{private 'operator==' to compare base class 'H'}} bool operator==(const I&) const = default; // expected-warning {{deleted}} friend bool operator==(const I&, const I&) = default; // expected-warning {{deleted}} }; class J { bool operator==(const J&) const; friend class K; }; class K { J j; bool operator==(const K&) const = default; friend bool operator==(const K&, const K&) = default; }; struct X { bool operator==(const X&) const; // expected-note {{ambiguity is between a regular call to this operator and a call with the argument order reversed}} }; struct Y : private X { // expected-note {{private}} using X::operator==; }; struct Z : Y { // Note: this function is not deleted. The selected operator== is // accessible. But the derived-to-base conversion involves an inaccessible // base class, which we don't check for until we define the function. bool operator==(const Z&) const = default; // expected-error {{cannot cast 'const Access::Y' to its private base class 'const Access::X'}} expected-warning {{ambiguous}} }; bool z = Z() == Z(); // expected-note {{first required here}} }