1// RUN: %clang_cc1 -fsyntax-only -verify %s
2class X {
3public:
4  operator bool();
5  operator int() const;
6
7  bool f() {
8    return operator bool();
9  }
10
11  float g() {
12    return operator float(); // expected-error{{use of undeclared 'operator float'}}
13  }
14
15  static operator short(); // expected-error{{conversion function must be a non-static member function}}
16};
17
18operator int(); // expected-error{{conversion function must be a non-static member function}}
19
20operator int; // expected-error{{'operator int' cannot be the name of a variable or data member}}
21
22typedef int func_type(int);
23typedef int array_type[10];
24
25class Y {
26public:
27  void operator bool(int, ...) const; // expected-error{{conversion function cannot have a return type}} \
28  // expected-error{{conversion function cannot have any parameters}}
29
30  operator bool(int a = 4, int b = 6) const; // expected-error{{conversion function cannot have any parameters}}
31
32
33  operator float(...) const;  // expected-error{{conversion function cannot be variadic}}
34
35
36  operator func_type(); // expected-error{{conversion function cannot convert to a function type}}
37  operator array_type(); // expected-error{{conversion function cannot convert to an array type}}
38};
39
40
41typedef int INT;
42typedef INT* INT_PTR;
43
44class Z {
45  operator int(); // expected-note {{previous declaration is here}}
46  operator int**(); // expected-note {{previous declaration is here}}
47
48  operator INT();  // expected-error{{conversion function cannot be redeclared}}
49  operator INT_PTR*(); // expected-error{{conversion function cannot be redeclared}}
50};
51
52
53class A { };
54
55class B : public A {
56public:
57  operator A&() const; // expected-warning{{conversion function converting 'B' to its base class 'A' will never be used}}
58  operator const void() const; // expected-warning{{conversion function converting 'B' to 'const void' will never be used}}
59  operator const B(); // expected-warning{{conversion function converting 'B' to itself will never be used}}
60};
61
62// This used to crash Clang.
63struct Flip;
64struct Flop {
65  Flop();
66  Flop(const Flip&); // expected-note{{candidate constructor}}
67};
68struct Flip {
69  operator Flop() const; // expected-note{{candidate function}}
70};
71Flop flop = Flip(); // expected-error {{conversion from 'Flip' to 'Flop' is ambiguous}}
72
73// This tests that we don't add the second conversion declaration to the list of user conversions
74struct C {
75  operator const char *() const;
76};
77
78C::operator const char*() const { return 0; }
79
80void f(const C& c) {
81  const char* v = c;
82}
83
84// Test. Conversion in base class is visible in derived class.
85class XB {
86public:
87  operator int(); // expected-note {{candidate function}}
88};
89
90class Yb : public XB {
91public:
92  operator char(); // expected-note {{candidate function}}
93};
94
95void f(Yb& a) {
96  if (a) { } // expected-error {{conversion from 'Yb' to 'bool' is ambiguous}}
97  int i = a; // OK. calls XB::operator int();
98  char ch = a;  // OK. calls Yb::operator char();
99}
100
101// Test conversion + copy construction.
102class AutoPtrRef { };
103
104class AutoPtr {
105  AutoPtr(AutoPtr &); // expected-note{{declared private here}}
106
107public:
108  AutoPtr();
109  AutoPtr(AutoPtrRef);
110
111  operator AutoPtrRef();
112};
113
114AutoPtr make_auto_ptr();
115
116AutoPtr test_auto_ptr(bool Cond) {
117  AutoPtr p1( make_auto_ptr() );
118
119  AutoPtr p;
120  if (Cond)
121    return p; // expected-error{{calling a private constructor}}
122
123  return AutoPtr();
124}
125
126struct A1 {
127  A1(const char *);
128  ~A1();
129
130private:
131  A1(const A1&); // expected-note 2 {{declared private here}}
132};
133
134A1 f() {
135  // FIXME: redundant diagnostics!
136  return "Hello"; // expected-error {{calling a private constructor}} expected-warning {{an accessible copy constructor}}
137}
138
139namespace source_locations {
140  template<typename T>
141  struct sneaky_int {
142    typedef int type;
143  };
144
145  template<typename T, typename U>
146  struct A { };
147
148  template<typename T>
149  struct A<T, T> : A<T, int> { };
150
151  struct E {
152    template<typename T>
153    operator A<T, typename sneaky_int<T>::type>&() const; // expected-note{{candidate function}}
154  };
155
156  void f() {
157    A<float, float> &af = E(); // expected-error{{no viable conversion}}
158    A<float, int> &af2 = E();
159    const A<float, int> &caf2 = E();
160  }
161
162  // Check
163  template<typename T>
164  struct E2 {
165    operator T
166    * // expected-error{{pointer to a reference}}
167    () const;
168  };
169
170  E2<int&> e2i; // expected-note{{in instantiation}}
171}
172
173namespace crazy_declarators {
174  struct A {
175    (&operator bool())(); // expected-error {{must use a typedef to declare a conversion to 'bool (&)()'}}
176
177    // FIXME: This diagnostic is misleading (the correct spelling
178    // would be 'operator int*'), but it's a corner case of a
179    // rarely-used syntax extension.
180    *operator int();  // expected-error {{must use a typedef to declare a conversion to 'int *'}}
181  };
182}
183
184namespace smart_ptr {
185  class Y {
186    class YRef { };
187
188    Y(Y&);
189
190  public:
191    Y();
192    Y(YRef);
193
194    operator YRef(); // expected-note{{candidate function}}
195  };
196
197  struct X { // expected-note{{candidate constructor (the implicit copy constructor) not}}
198    explicit X(Y);
199  };
200
201  Y make_Y();
202
203  X f() {
204    X x = make_Y(); // expected-error{{no viable conversion from 'smart_ptr::Y' to 'smart_ptr::X'}}
205    X x2(make_Y());
206    return X(Y());
207  }
208}
209
210struct Any {
211  Any(...);
212};
213
214struct Other {
215  Other(const Other &);
216  Other();
217};
218
219void test_any() {
220  Any any = Other(); // expected-error{{cannot pass object of non-POD type 'Other' through variadic constructor; call will abort at runtime}}
221}
222
223namespace PR7055 {
224  // Make sure that we don't allow too many conversions in an
225  // auto_ptr-like template. In particular, we can't create multiple
226  // temporary objects when binding to a reference.
227  struct auto_ptr {
228    struct auto_ptr_ref { };
229
230    auto_ptr(auto_ptr&);
231    auto_ptr(auto_ptr_ref);
232    explicit auto_ptr(int *);
233
234    operator auto_ptr_ref();
235  };
236
237  struct X {
238    X(auto_ptr);
239  };
240
241  X f() {
242    X x(auto_ptr(new int));
243    return X(auto_ptr(new int));
244  }
245
246  auto_ptr foo();
247
248  X e(foo());
249
250  struct Y {
251    Y(X);
252  };
253
254  Y f2(foo());
255}
256
257namespace PR7934 {
258  typedef unsigned char uint8;
259
260  struct MutablePtr {
261    MutablePtr() : ptr(0) {}
262    void *ptr;
263
264    operator void*() { return ptr; }
265
266  private:
267    operator uint8*() { return reinterpret_cast<uint8*>(ptr); }
268    operator const char*() const { return reinterpret_cast<const char*>(ptr); }
269  };
270
271  void fake_memcpy(const void *);
272
273  void use() {
274    MutablePtr ptr;
275    fake_memcpy(ptr);
276  }
277}
278
279namespace rdar8018274 {
280  struct X { };
281  struct Y {
282    operator const struct X *() const;
283  };
284
285  struct Z : Y {
286    operator struct X * ();
287  };
288
289  void test() {
290    Z x;
291    (void) (x != __null);
292  }
293
294
295  struct Base {
296    operator int();
297  };
298
299  struct Derived1 : Base { };
300
301  struct Derived2 : Base { };
302
303  struct SuperDerived : Derived1, Derived2 {
304    using Derived1::operator int;
305  };
306
307  struct UeberDerived : SuperDerived {
308    operator long();
309  };
310
311  void test2(UeberDerived ud) {
312    int i = ud; // expected-error{{ambiguous conversion from derived class 'rdar8018274::SuperDerived' to base class 'rdar8018274::Base'}}
313  }
314
315  struct Base2 {
316    operator int();
317  };
318
319  struct Base3 {
320    operator int();
321  };
322
323  struct Derived23 : Base2, Base3 {
324    using Base2::operator int;
325  };
326
327  struct ExtraDerived23 : Derived23 { };
328
329  void test3(ExtraDerived23 ed) {
330    int i = ed;
331  }
332}
333
334namespace PR8065 {
335  template <typename T> struct Iterator;
336  template <typename T> struct Container;
337
338  template<>
339  struct Iterator<int> {
340    typedef Container<int> container_type;
341  };
342
343  template <typename T>
344  struct Container {
345    typedef typename Iterator<T>::container_type X;
346    operator X(void) { return X(); }
347  };
348
349  Container<int> test;
350}
351
352namespace PR8034 {
353  struct C {
354    operator int();
355
356  private:
357    template <typename T> operator T();
358  };
359  int x = C().operator int();
360}
361
362namespace PR9336 {
363  template<class T>
364  struct generic_list
365  {
366    template<class Container>
367    operator Container()
368    {
369      Container ar;
370      T* i;
371      ar[0]=*i;
372      return ar;
373    }
374  };
375
376  template<class T>
377  struct array
378  {
379    T& operator[](int);
380    const T& operator[](int)const;
381  };
382
383  generic_list<generic_list<int> > l;
384  array<array<int> > a = l;
385}
386
387namespace PR8800 {
388  struct A;
389  struct C {
390    operator A&();
391  };
392  void f() {
393    C c;
394    A& a1(c);
395    A& a2 = c;
396    A& a3 = static_cast<A&>(c);
397    A& a4 = (A&)c;
398  }
399}
400
401namespace PR12712 {
402  struct A {};
403  struct B {
404    operator A();
405    operator A() const;
406  };
407  struct C : B {};
408
409  A f(const C c) { return c; }
410}
411
412namespace PR18234 {
413  struct A {
414    operator enum E { e } (); // expected-error {{'PR18234::A::E' cannot be defined in a type specifier}}
415    operator struct S { int n; } (); // expected-error {{'PR18234::A::S' cannot be defined in a type specifier}}
416  } a;
417  A::S s = a;
418  A::E e = a; // expected-note {{here}}
419  bool k1 = e == A::e; // expected-error {{no member named 'e'}}
420  bool k2 = e.n == 0;
421}
422