• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 template<typename T> struct X {
19   X();
20   bool operator==(const X&) const = default; // #x expected-note 4{{deleted here}}
21   T t; // expected-note 3{{because there is no viable comparison function for member 't'}}
22        // expected-note@-1 {{because it would invoke a deleted comparison function for member 't'}}
23 };
24 
25 struct Mutable {
26   bool operator==(const Mutable&) const = default;
27   mutable D d;
28 };
29 
test()30 void test() {
31   void(X<A>() == X<A>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
32   void(X<B>() == X<B>());
33   void(X<C>() == X<C>());
34   void(X<D>() == X<D>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
35   void(Mutable() == Mutable());
36 
37   // FIXME: We would benefit from a note identifying the member of 'X' we were comparing here and below.
38   // expected-error@#x {{call to deleted constructor of 'E'}}
39   void(X<E>() == X<E>()); // expected-note {{in defaulted equality comparison operator for 'X<E>' first required here}}
40 
41   // FIXME: We would benefit from a note pointing at the selected 'operator==' here.
42   // expected-error@#x {{value of type 'void' is not contextually convertible to 'bool'}}
43   void(X<F>() == X<F>()); // expected-note {{in defaulted equality comparison operator for 'X<F>' first required here}}
44 
45   void(X<G>() == X<G>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
46 
47   void(X<A[3]>() == X<A[3]>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
48   void(X<B[3]>() == X<B[3]>());
49 }
50 
51 namespace Access {
52   class A {
53     bool operator==(const A &) const; // expected-note 2{{implicitly declared private here}}
54   };
55   struct B : A { // expected-note 2{{because it would invoke a private 'operator==' to compare base class 'A'}}
56     bool operator==(const B &) const = default; // expected-warning {{deleted}}
57     friend bool operator==(const B &, const B &) = default; // expected-warning {{deleted}}
58   };
59 
60   class C {
61   protected:
62     bool operator==(const C &) const; // expected-note 2{{declared protected here}}
63   };
64   struct D : C {
65     bool operator==(const D &) const = default;
66     friend bool operator==(const D &, const D&) = default;
67   };
68   struct E {
69     C c; // expected-note 2{{because it would invoke a protected 'operator==' member of 'Access::C' to compare member 'c'}}
70     bool operator==(const E &) const = default; // expected-warning {{deleted}}
71     friend bool operator==(const E &, const E &) = default; // expected-warning {{deleted}}
72   };
73 
74   struct F : C {
75     using C::operator==;
76   };
77   struct G : F {
78     bool operator==(const G&) const = default;
79     friend bool operator==(const G&, const G&) = default;
80   };
81 
82   struct H : C {
83   private:
84     using C::operator==; // expected-note 2{{declared private here}}
85   };
86   struct I : H { // expected-note 2{{private 'operator==' to compare base class 'H'}}
87     bool operator==(const I&) const = default; // expected-warning {{deleted}}
88     friend bool operator==(const I&, const I&) = default; // expected-warning {{deleted}}
89   };
90 
91   class J {
92     bool operator==(const J&) const;
93     friend class K;
94   };
95   class K {
96     J j;
97     bool operator==(const K&) const = default;
98     friend bool operator==(const K&, const K&) = default;
99   };
100 
101   struct X {
102     bool operator==(const X&) const; // expected-note {{ambiguity is between a regular call to this operator and a call with the argument order reversed}}
103   };
104   struct Y : private X { // expected-note {{private}}
105     using X::operator==;
106   };
107   struct Z : Y {
108     // Note: this function is not deleted. The selected operator== is
109     // accessible. But the derived-to-base conversion involves an inaccessible
110     // base class, which we don't check for until we define the function.
111     bool operator==(const Z&) const = default; // expected-error {{cannot cast 'const Access::Y' to its private base class 'const Access::X'}} expected-warning {{ambiguous}}
112   };
113   bool z = Z() == Z(); // expected-note {{first required here}}
114 }
115