Clang Project

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