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