overloaded-operator.cpp revision 439d3c3d76f858df5f25239f2a70f04312eacb5b
1// RUN: %clang_cc1 -fsyntax-only -verify %s
2class X { };
3
4X operator+(X, X);
5
6void f(X x) {
7  x = x + x;
8}
9
10struct Y;
11struct Z;
12
13struct Y {
14  Y(const Z&);
15};
16
17struct Z {
18  Z(const Y&);
19};
20
21Y operator+(Y, Y);
22bool operator-(Y, Y); // expected-note{{candidate function}}
23bool operator-(Z, Z); // expected-note{{candidate function}}
24
25void g(Y y, Z z) {
26  y = y + z;
27  bool b = y - z; // expected-error{{use of overloaded operator '-' is ambiguous}}
28}
29
30struct A {
31  bool operator==(Z&); // expected-note 2{{candidate function}}
32};
33
34A make_A();
35
36bool operator==(A&, Z&); // expected-note 3{{candidate function}}
37
38void h(A a, const A ac, Z z) {
39  make_A() == z;
40  a == z; // expected-error{{use of overloaded operator '==' is ambiguous}}
41  ac == z; // expected-error{{invalid operands to binary expression ('const A' and 'Z')}}
42}
43
44struct B {
45  bool operator==(const B&) const;
46
47  void test(Z z) {
48    make_A() == z;
49  }
50};
51
52// we shouldn't see warnings about self-comparison,
53// this is a member function, we dunno what it'll do
54bool i(B b)
55{
56  return b == b;
57}
58
59enum Enum1 { };
60enum Enum2 { };
61
62struct E1 {
63  E1(Enum1) { }
64};
65
66struct E2 {
67  E2(Enum2);
68};
69
70// C++ [over.match.oper]p3 - enum restriction.
71float& operator==(E1, E2);  // expected-note{{candidate function}}
72
73void enum_test(Enum1 enum1, Enum2 enum2, E1 e1, E2 e2, Enum1 next_enum1) {
74  float &f1 = (e1 == e2);
75  float &f2 = (enum1 == e2);
76  float &f3 = (e1 == enum2);
77  float &f4 = (enum1 == next_enum1);  // expected-error{{non-const lvalue reference to type 'float' cannot bind to a temporary of type 'bool'}}
78}
79
80// PR5244 - Argument-dependent lookup would include the two operators below,
81// which would break later assumptions and lead to a crash.
82class pr5244_foo
83{
84  pr5244_foo(int);
85  pr5244_foo(char);
86};
87
88bool operator==(const pr5244_foo& s1, const pr5244_foo& s2); // expected-note{{candidate function}}
89bool operator==(char c, const pr5244_foo& s); // expected-note{{candidate function}}
90
91enum pr5244_bar
92{
93    pr5244_BAR
94};
95
96class pr5244_baz
97{
98public:
99    pr5244_bar quux;
100};
101
102void pr5244_barbaz()
103{
104  pr5244_baz quuux;
105  (void)(pr5244_BAR == quuux.quux);
106}
107
108
109
110struct PostInc {
111  PostInc operator++(int);
112  PostInc& operator++();
113};
114
115struct PostDec {
116  PostDec operator--(int);
117  PostDec& operator--();
118};
119
120void incdec_test(PostInc pi, PostDec pd) {
121  const PostInc& pi1 = pi++;
122  const PostDec& pd1 = pd--;
123  PostInc &pi2 = ++pi;
124  PostDec &pd2 = --pd;
125}
126
127struct SmartPtr {
128  int& operator*();
129  long& operator*() const volatile;
130};
131
132void test_smartptr(SmartPtr ptr, const SmartPtr cptr,
133                   const volatile SmartPtr cvptr) {
134  int &ir = *ptr;
135  long &lr = *cptr;
136  long &lr2 = *cvptr;
137}
138
139
140struct ArrayLike {
141  int& operator[](int);
142};
143
144void test_arraylike(ArrayLike a) {
145  int& ir = a[17];
146}
147
148struct SmartRef {
149  int* operator&();
150};
151
152void test_smartref(SmartRef r) {
153  int* ip = &r;
154}
155
156bool& operator,(X, Y);
157
158void test_comma(X x, Y y) {
159  bool& b1 = (x, y);
160  X& xr = (x, x); // expected-warning {{expression result unused}}
161}
162
163struct Callable {
164  int& operator()(int, double = 2.71828); // expected-note{{candidate function}}
165  float& operator()(int, double, long, ...); // expected-note{{candidate function}}
166
167  double& operator()(float); // expected-note{{candidate function}}
168};
169
170struct Callable2 {
171  int& operator()(int i = 0);
172  double& operator()(...) const;
173};
174
175struct DerivesCallable : public Callable {
176};
177
178void test_callable(Callable c, Callable2 c2, const Callable2& c2c,
179                   DerivesCallable dc) {
180  int &ir = c(1);
181  float &fr = c(1, 3.14159, 17, 42);
182
183  c(); // expected-error{{no matching function for call to object of type 'Callable'}}
184
185  double &dr = c(1.0f);
186
187  int &ir2 = c2();
188  int &ir3 = c2(1);
189  double &fr2 = c2c();
190
191  int &ir4 = dc(17);
192  double &fr3 = dc(3.14159f);
193}
194
195typedef float FLOAT;
196typedef int& INTREF;
197typedef INTREF Func1(FLOAT, double);
198typedef float& Func2(int, double);
199
200struct ConvertToFunc {
201  operator Func1*(); // expected-note 2{{conversion candidate of type 'INTREF (*)(FLOAT, double)'}}
202  operator Func2&(); // expected-note 2{{conversion candidate of type 'float &(&)(int, double)'}}
203  void operator()();
204};
205
206struct ConvertToFuncDerived : ConvertToFunc { };
207
208void test_funcptr_call(ConvertToFunc ctf, ConvertToFuncDerived ctfd) {
209  int &i1 = ctf(1.0f, 2.0);
210  float &f1 = ctf((short int)1, 1.0f);
211  ctf((long int)17, 2.0); // expected-error{{call to object of type 'ConvertToFunc' is ambiguous}}
212  ctf();
213
214  int &i2 = ctfd(1.0f, 2.0);
215  float &f2 = ctfd((short int)1, 1.0f);
216  ctfd((long int)17, 2.0); // expected-error{{call to object of type 'ConvertToFuncDerived' is ambiguous}}
217  ctfd();
218}
219
220struct HasMember {
221  int m;
222};
223
224struct Arrow1 {
225  HasMember* operator->();
226};
227
228struct Arrow2 {
229  Arrow1 operator->(); // expected-note{{candidate function}}
230};
231
232void test_arrow(Arrow1 a1, Arrow2 a2, const Arrow2 a3) {
233  int &i1 = a1->m;
234  int &i2 = a2->m;
235  a3->m; // expected-error{{no viable overloaded 'operator->'; candidate is}}
236}
237
238struct CopyConBase {
239};
240
241struct CopyCon : public CopyConBase {
242  CopyCon(const CopyConBase &Base);
243
244  CopyCon(const CopyConBase *Base) {
245    *this = *Base;
246  }
247};
248
249namespace N {
250  struct X { };
251}
252
253namespace M {
254  N::X operator+(N::X, N::X);
255}
256
257namespace M {
258  void test_X(N::X x) {
259    (void)(x + x);
260  }
261}
262
263struct AA { bool operator!=(AA&); };
264struct BB : AA {};
265bool x(BB y, BB z) { return y != z; }
266
267
268struct AX {
269  AX& operator ->();	 // expected-note {{declared here}}
270  int b;
271};
272
273void m() {
274  AX a;
275  a->b = 0; // expected-error {{circular pointer delegation detected}}
276}
277
278struct CircA {
279  struct CircB& operator->(); // expected-note {{declared here}}
280  int val;
281};
282struct CircB {
283  struct CircC& operator->(); // expected-note {{declared here}}
284};
285struct CircC {
286  struct CircA& operator->(); // expected-note {{declared here}}
287};
288
289void circ() {
290  CircA a;
291  a->val = 0; // expected-error {{circular pointer delegation detected}}
292}
293
294// PR5360: Arrays should lead to built-in candidates for subscript.
295typedef enum {
296  LastReg = 23,
297} Register;
298class RegAlloc {
299  int getPriority(Register r) {
300    return usepri[r];
301  }
302  int usepri[LastReg + 1];
303};
304
305// PR5546: Don't generate incorrect and ambiguous overloads for multi-level
306// arrays.
307namespace pr5546
308{
309  enum { X };
310  extern const char *const sMoveCommands[][2][2];
311  const char* a() { return sMoveCommands[X][0][0]; }
312  const char* b() { return (*(sMoveCommands+X))[0][0]; }
313}
314
315// PR5512 and its discussion
316namespace pr5512 {
317  struct Y {
318    operator short();
319    operator float();
320  };
321  void g_test(Y y) {
322    short s = 0;
323    // DR507, this should be ambiguous, but we special-case assignment
324    s = y;
325    // Note: DR507, this is ambiguous as specified
326    //s += y;
327  }
328
329  struct S {};
330  void operator +=(int&, S);
331  void f(S s) {
332    int i = 0;
333    i += s;
334  }
335
336  struct A {operator int();};
337  int a;
338  void b(A x) {
339    a += x;
340  }
341}
342
343// PR5900
344namespace pr5900 {
345  struct NotAnArray {};
346  void test0() {
347    NotAnArray x;
348    x[0] = 0; // expected-error {{does not provide a subscript operator}}
349  }
350
351  struct NonConstArray {
352    int operator[](unsigned); // expected-note {{candidate}}
353  };
354  int test1() {
355    const NonConstArray x = NonConstArray();
356    return x[0]; // expected-error {{no viable overloaded operator[] for type}}
357  }
358
359  // Not really part of this PR, but implemented at the same time.
360  struct NotAFunction {};
361  void test2() {
362    NotAFunction x;
363    x(); // expected-error {{does not provide a call operator}}
364  }
365}
366
367// Operator lookup through using declarations.
368namespace N {
369  struct X2 { };
370}
371
372namespace N2 {
373  namespace M {
374    namespace Inner {
375      template<typename T>
376      N::X2 &operator<<(N::X2&, const T&);
377    }
378    using Inner::operator<<;
379  }
380}
381
382void test_lookup_through_using() {
383  using namespace N2::M;
384  N::X2 x;
385  x << 17;
386}
387
388namespace rdar9136502 {
389  struct X {
390    int i();
391    int i(int);
392  };
393
394  struct Y {
395    Y &operator<<(int); // expected-note{{candidate function not viable: no known conversion from '<bound member function type>' to 'int'}}
396  };
397
398  void f(X x, Y y) {
399    y << x.i; // expected-error{{a bound member function may only be called}}
400  }
401}
402
403namespace rdar9222009 {
404class StringRef {
405  inline bool operator==(StringRef LHS, StringRef RHS) { // expected-error{{overloaded 'operator==' must be a binary operator (has 3 parameters)}}
406    return !(LHS == RHS); // expected-error{{invalid operands to binary expression ('rdar9222009::StringRef' and 'rdar9222009::StringRef')}}
407  }
408};
409
410}
411