xref: /llvm-project/clang/test/CXX/class/class.compare/class.eq/p2.cpp (revision 02bb2beeef3d93360694de29573430f584caafe9)
1 // RUN: %clang_cc1 -std=c++2a -verify %s
2 
3 struct A {};
4 struct B { bool operator==(B) const; };
5 struct C { int operator==(C) const; };
6 struct D {
7   // expected-note@+2 {{candidate function not viable: 'this' argument has type 'const}}
8   // expected-note@+1 {{candidate function (with reversed parameter order) not viable: 1st argument ('const}}
9   bool operator==(D);
10 };
11 struct E {
12   E(const E &) = delete; // expected-note {{deleted}}
13   int operator==(E) const; // expected-note {{passing}}
14 };
15 struct F { void operator==(F) const; };
16 struct G { bool operator==(G) const = delete; }; // expected-note {{deleted here}}
17 
18 struct H1 {
19   bool operator==(const H1 &) const = default;
20   bool operator<(const H1 &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
21   // expected-note@-1 {{because there is no viable three-way comparison function for 'H1'}}
22   void (*x)();
23 };
24 struct H2 {
25   bool operator==(const H2 &) const = default;
26   bool operator<(const H2 &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
27   // expected-note@-1 {{because there is no viable three-way comparison function for 'H2'}}
28   void (H2::*x)();
29 };
30 struct H3 {
31   bool operator==(const H3 &) const = default;
32   bool operator<(const H3 &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}
33   // expected-note@-1 {{because there is no viable three-way comparison function for 'H3'}}
34   int H3::*x;
35 };
36 
37 template<typename T> struct X {
38   X();
39   bool operator==(const X&) const = default; // #x expected-note 4{{deleted here}}
40   T t; // expected-note 3{{because there is no viable 'operator==' for member 't'}}
41        // expected-note@-1 {{because it would invoke a deleted comparison function for member 't'}}
42 };
43 
44 struct Mutable {
45   bool operator==(const Mutable&) const = default;
46   mutable D d;
47 };
48 
test()49 void test() {
50   void(X<A>() == X<A>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
51   void(X<B>() == X<B>());
52   void(X<C>() == X<C>());
53   void(X<D>() == X<D>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
54   void(Mutable() == Mutable());
55 
56   // FIXME: We would benefit from a note identifying the member of 'X' we were comparing here and below.
57   // expected-error@#x {{call to deleted constructor of 'E'}}
58   void(X<E>() == X<E>()); // expected-note {{in defaulted equality comparison operator for 'X<E>' first required here}}
59 
60   // FIXME: We would benefit from a note pointing at the selected 'operator==' here.
61   // expected-error@#x {{value of type 'void' is not contextually convertible to 'bool'}}
62   void(X<F>() == X<F>()); // expected-note {{in defaulted equality comparison operator for 'X<F>' first required here}}
63 
64   void(X<G>() == X<G>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
65 
66   void(X<A[3]>() == X<A[3]>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
67   void(X<B[3]>() == X<B[3]>());
68 }
69 
70 namespace Access {
71   class A {
72     bool operator==(const A &) const; // expected-note 2{{implicitly declared private here}}
73   };
74   struct B : A { // expected-note 2{{because it would invoke a private 'operator==' to compare base class 'A'}}
75     bool operator==(const B &) const = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
76     friend bool operator==(const B &, const B &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
77   };
78 
79   class C {
80   protected:
81     bool operator==(const C &) const; // expected-note 2{{declared protected here}}
82   };
83   struct D : C {
84     bool operator==(const D &) const = default;
85     friend bool operator==(const D &, const D&) = default;
86   };
87   struct E {
88     C c; // expected-note 2{{because it would invoke a protected 'operator==' member of 'Access::C' to compare member 'c'}}
89     bool operator==(const E &) const = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
90     friend bool operator==(const E &, const E &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
91   };
92 
93   struct F : C {
94     using C::operator==;
95   };
96   struct G : F {
97     bool operator==(const G&) const = default;
98     friend bool operator==(const G&, const G&) = default;
99   };
100 
101   struct H : C {
102   private:
103     using C::operator==; // expected-note 2{{declared private here}}
104   };
105   struct I : H { // expected-note 2{{private 'operator==' to compare base class 'H'}}
106     bool operator==(const I&) const = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
107     friend bool operator==(const I&, const I&) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
108   };
109 
110   class J {
111     bool operator==(const J&) const;
112     friend class K;
113   };
114   class K {
115     J j;
116     bool operator==(const K&) const = default;
117     friend bool operator==(const K&, const K&) = default;
118   };
119 
120   struct X {
121     bool operator==(const X&) const; // expected-note {{ambiguity is between a regular call to this operator and a call with the argument order reversed}}
122   };
123   struct Y : private X { // expected-note {{private}}
124     using X::operator==;
125   };
126   struct Z : Y {
127     // Note: this function is not deleted. The selected operator== is
128     // accessible. But the derived-to-base conversion involves an inaccessible
129     // base class, which we don't check for until we define the function.
130     bool operator==(const Z&) const = default; // expected-error {{cannot cast 'const Y' to its private base class 'const X'}} expected-warning {{ambiguous}}
131   };
132   bool z = Z() == Z(); // expected-note {{first required here}}
133 }
134