1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
2 namespace Constructor {
3 struct A {
4   A(int);
5 };
6 
7 struct B {
8   explicit B(int);
9 };
10 
11 B::B(int) { }
12 
13 struct C {
14   void f(const A&);
15   void f(const B&);
16 };
17 
18 void f(C c) {
19   c.f(10);
20 }
21 }
22 
23 namespace Conversion {
24   struct A {
25     operator int();
26     explicit operator bool();
27   };
28 
29   A::operator bool() { return false; }
30 
31   struct B {
32     void f(int);
33     void f(bool);
34   };
35 
36   void f(A a, B b) {
37     b.f(a);
38   }
39 
40   void testExplicit()
41   {
42     // Taken from 12.3.2p2
43     class Y { }; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \
44 					          expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} \
45                     expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y &' for 1st argument}} \
46                     expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \
47 					expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \
48 					expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \
49 					expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \
50 					expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \
51 					expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y' for 1st argument}} \
52 					expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}} \
53 					expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'Conversion::Z' to 'const Conversion::Y' for 1st argument}} \
54           expected-note {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'Conversion::Z' to 'Conversion::Y &&' for 1st argument}} \
55 					expected-note {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
56     struct Z {
57       explicit operator Y() const;
58       explicit operator int() const;
59     };
60 
61     Z z;
62     // 13.3.1.4p1 & 8.5p16:
63     Y y2 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'Conversion::Y'}}
64     // FIXME: These are well-formed per C++0x 13.3.1.4p1 (see DR899).
65     Y y3 = (Y)z; // expected-error {{no matching conversion for C-style cast from 'Conversion::Z' to 'Conversion::Y'}}
66     Y y4 = Y(z); // expected-error {{no matching conversion for functional-style cast from 'Conversion::Z' to 'Conversion::Y'}}
67     Y y5 = static_cast<Y>(z); // expected-error {{no matching conversion for static_cast from 'Conversion::Z' to 'Conversion::Y'}}
68     // 13.3.1.5p1 & 8.5p16:
69     int i1 = (int)z;
70     int i2 = int(z);
71     int i3 = static_cast<int>(z);
72     int i4(z);
73     // 13.3.1.6p1 & 8.5.3p5:
74     const Y& y6 = z; // expected-error {{no viable conversion from 'Conversion::Z' to 'const Conversion::Y'}}
75     const int& y7(z);
76   }
77 
78   void testBool() {
79     struct Bool {
80       operator bool();
81     };
82 
83     struct NotBool {
84       explicit operator bool(); // expected-note {{conversion to integral type 'bool'}}
85     };
86     Bool    b;
87     NotBool n;
88 
89     (void) (1 + b);
90     (void) (1 + n); // expected-error {{invalid operands to binary expression ('int' and 'Conversion::NotBool')}}
91 
92     // 5.3.1p9:
93     (void) (!b);
94     (void) (!n);
95 
96     // 5.14p1:
97     (void) (b && true);
98     (void) (n && true);
99 
100     // 5.15p1:
101     (void) (b || true);
102     (void) (n || true);
103 
104     // 5.16p1:
105     (void) (b ? 0 : 1);
106     (void) (n ? 0: 1);
107 
108     // 5.19p5:
109     // TODO: After constexpr has been implemented
110 
111     // 6.4p4:
112     if (b) {}
113     if (n) {}
114 
115     // 6.4.2p2:
116     switch (b) {} // expected-warning {{switch condition has boolean value}}
117     switch (n) {} // expected-error {{switch condition type 'Conversion::NotBool' requires explicit conversion to 'bool'}} \
118                      expected-warning {{switch condition has boolean value}}
119 
120     // 6.5.1:
121     while (b) {}
122     while (n) {}
123 
124     // 6.5.2p1:
125     do {} while (b);
126     do {} while (n);
127 
128     // 6.5.3:
129     for (;b;) {}
130     for (;n;) {}
131   }
132 
133   void testNew()
134   {
135     // 5.3.4p6:
136     struct Int {
137       operator int();
138     };
139     struct NotInt {
140       explicit operator int(); // expected-note {{conversion to integral type 'int' declared here}}
141     };
142 
143     Int    i;
144     NotInt ni;
145 
146     new int[i];
147     new int[ni]; // expected-error {{array size expression of type 'Conversion::NotInt' requires explicit conversion to type 'int'}}
148   }
149 
150   void testDelete()
151   {
152     // 5.3.5pp2:
153     struct Ptr {
154       operator int*();
155     };
156     struct NotPtr {
157       explicit operator int*();
158     };
159 
160     Ptr    p;
161     NotPtr np;
162 
163     delete p;
164     delete np; // expected-error {{cannot delete expression of type 'Conversion::NotPtr'}}
165   }
166 
167   void testFunctionPointer()
168   {
169     // 13.3.1.1.2p2:
170     using Func = void(*)(int);
171 
172     struct FP {
173       operator Func();
174     };
175     struct NotFP {
176       explicit operator Func();
177     };
178 
179     FP    fp;
180     NotFP nfp;
181     fp(1);
182     nfp(1); // expected-error {{type 'Conversion::NotFP' does not provide a call operator}}
183   }
184 }
185