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