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