1// RUN: %clang_cc1 -fsyntax-only -fshow-overloads=best -verify -triple x86_64-linux-gnu %s
2
3struct yes;
4struct no;
5
6struct Short {
7  operator short();
8};
9
10struct Long {
11  operator long();
12};
13
14enum E1 { };
15struct Enum1 {
16  operator E1();
17};
18
19enum E2 { };
20struct Enum2 {
21  operator E2();
22};
23
24
25struct X {
26  void f();
27};
28
29typedef void (X::*pmf)();
30struct Xpmf {
31  operator pmf();
32};
33
34yes& islong(long);
35yes& islong(unsigned long); // FIXME: shouldn't be needed
36no& islong(int);
37
38void f(Short s, Long l, Enum1 e1, Enum2 e2, Xpmf pmf) {
39  // C++ [over.built]p8
40  int i1 = +e1;
41  int i2 = -e2;
42
43  // C++  [over.built]p10:
44  int i3 = ~s;
45  bool b1 = !s;
46
47  // C++ [over.built]p12
48  (void)static_cast<yes&>(islong(s + l));
49  (void)static_cast<no&>(islong(s + s));
50
51  // C++ [over.built]p16
52  (void)(pmf == &X::f);
53  (void)(pmf == 0);
54
55  // C++ [over.built]p17
56  (void)static_cast<yes&>(islong(s % l));
57  (void)static_cast<yes&>(islong(l << s));
58  (void)static_cast<no&>(islong(s << l));
59  (void)static_cast<yes&>(islong(e1 % l));
60  // FIXME: should pass (void)static_cast<no&>(islong(e1 % e2));
61}
62
63struct ShortRef { // expected-note{{candidate function (the implicit copy assignment operator)}}
64  operator short&();
65};
66
67struct LongRef {
68  operator volatile long&();
69};
70
71struct XpmfRef { // expected-note{{candidate function (the implicit copy assignment operator)}}
72  operator pmf&();
73};
74
75struct E2Ref {
76  operator E2&();
77};
78
79void g(ShortRef sr, LongRef lr, E2Ref e2_ref, XpmfRef pmf_ref) {
80  // C++ [over.built]p3
81  short s1 = sr++;
82
83  // C++ [over.built]p3
84  long l1 = lr--;
85
86  // C++ [over.built]p18
87  short& sr1 = (sr *= lr);
88  volatile long& lr1 = (lr *= sr);
89
90  // C++ [over.built]p20:
91  E2 e2r2;
92  e2r2 = e2_ref;
93
94  pmf &pmr = (pmf_ref = &X::f); // expected-error{{no viable overloaded '='}}
95  pmf pmr2;
96  pmr2 = pmf_ref;
97
98  // C++ [over.built]p22
99  short& sr2 = (sr %= lr);
100  volatile long& lr2 = (lr <<= sr);
101
102  bool b1 = (sr && lr) || (sr || lr);
103}
104
105struct VolatileIntPtr {
106  operator int volatile *();
107};
108
109struct ConstIntPtr {
110  operator int const *();
111};
112
113struct VolatileIntPtrRef {
114  operator int volatile *&();
115};
116
117struct ConstIntPtrRef {
118  operator int const *&();
119};
120
121void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr,
122                    VolatileIntPtrRef vipr, ConstIntPtrRef cipr) {
123  const int& cir1 = cip[sr];
124  const int& cir2 = sr[cip];
125  volatile int& vir1 = vip[sr];
126  volatile int& vir2 = sr[vip];
127  bool b1 = (vip == cip);
128  long p1 = vip - cip;
129
130  // C++ [over.built]p5:
131  int volatile *vip1 = vipr++;
132  int const *cip1 = cipr++;
133  int volatile *&vipr1 = ++vipr;
134  int const *&cipr1 = --cipr;
135
136  // C++ [over.built]p6:
137  int volatile &ivr = *vip;
138
139  // C++ [over.built]p8:
140  int volatile *vip2 = +vip;
141  int i1 = +sr;
142  int i2 = -sr;
143
144  // C++ [over.built]p13:
145  int volatile &ivr2 = vip[17];
146  int const &icr2 = 17[cip];
147}
148
149// C++ [over.match.open]p4
150
151void test_assign_restrictions(ShortRef& sr) {
152  sr = (short)0; // expected-error{{no viable overloaded '='}}
153}
154
155struct Base { };
156struct Derived1 : Base { };
157struct Derived2 : Base { };
158
159template<typename T>
160struct ConvertibleToPtrOf {
161  operator T*();
162};
163
164bool test_with_base_ptrs(ConvertibleToPtrOf<Derived1> d1,
165                         ConvertibleToPtrOf<Derived2> d2) {
166  return d1 == d2; // expected-error{{invalid operands}}
167}
168
169// DR425
170struct A {
171  template< typename T > operator T() const;
172};
173
174void test_dr425(A a) {
175  // FIXME: lots of candidates here!
176  (void)(1.0f * a); // expected-error{{ambiguous}} \
177                    // expected-note 4{{candidate}} \
178                    // expected-note {{remaining 117 candidates omitted; pass -fshow-overloads=all to show them}}
179}
180
181// pr5432
182enum e {X};
183
184const int a[][2] = {{1}};
185
186int test_pr5432() {
187  return a[X][X];
188}
189
190void f() {
191  (void)__extension__(A());
192}
193
194namespace PR7319 {
195  typedef enum { Enum1, Enum2, Enum3 } MyEnum;
196
197  template<typename X> bool operator>(const X &inX1, const X &inX2);
198
199  void f() {
200    MyEnum e1, e2;
201    if (e1 > e2) {}
202  }
203}
204
205namespace PR8477 {
206  struct Foo {
207    operator bool();
208    operator const char *();
209  };
210
211  bool doit() {
212    Foo foo;
213    long long zero = 0;
214    (void)(foo + zero);
215    (void)(foo - zero);
216    (void)(zero + foo);
217    (void)(zero[foo]);
218    (void)(foo - foo); // expected-error{{use of overloaded operator '-' is ambiguous}} \
219    // expected-note 4{{built-in candidate operator-}} \
220    // expected-note{{candidates omitted}}
221    return foo[zero] == zero;
222  }
223}
224
225namespace PR7851 {
226  struct X {
227    operator const void *() const;
228    operator void *();
229
230    operator const unsigned *() const;
231    operator unsigned *();
232  };
233
234  void f() {
235    X x;
236    x[0] = 1;
237    *x = 0;
238    (void)(x - x);
239  }
240}
241
242namespace PR12854 {
243  enum { size = 1 };
244  void plus_equals() {
245    int* __restrict py;
246    py += size;
247  }
248
249  struct RestrictInt {
250    operator int* __restrict &();
251  };
252
253  void user_conversions(RestrictInt ri) {
254    ++ri;
255    --ri;
256    ri++;
257    ri--;
258  }
259}
260
261namespace PR12964 {
262  struct X { operator  __int128() const; } x;
263  bool a = x == __int128(0);
264  bool b = x == 0;
265
266  struct Y { operator unsigned __int128() const; } y;
267  bool c = y == __int128(0);
268  bool d = y == 0;
269
270  bool e = x == y;
271}
272