1 // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++98 %s
3 // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
4 
5 struct A; // expected-note 4 {{forward declaration of 'A'}}
6 
7 struct Abstract { virtual void f() = 0; }; // expected-note {{unimplemented pure virtual method 'f'}}
8 
trys()9 void trys() {
10   int k = 42;
11   try {
12   } catch(int i) { // expected-note {{previous definition}}
13     int j = i;
14     int i; // expected-error {{redefinition of 'i'}}
15   } catch(float i) {
16   } catch(void v) { // expected-error {{cannot catch incomplete type 'void'}}
17   } catch(A a) { // expected-error {{cannot catch incomplete type 'A'}}
18   } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'A'}}
19   } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'A'}}
20   } catch(Abstract) { // expected-error {{variable type 'Abstract' is an abstract class}}
21   } catch(...) {
22     int ref = k;
23     {
24       int ref = k;
25     }
26     int j = i; // expected-error {{use of undeclared identifier 'i'}}
27   }
28 
29   try {
30   } catch(...) { // expected-error {{catch-all handler must come last}}
31   } catch(int) {
32   }
33 }
34 
throws()35 void throws() {
36   throw;
37   throw 0;
38   throw throw; // expected-error {{cannot throw object of incomplete type 'void'}}
39   throw (A*)0; // expected-error {{cannot throw pointer to object of incomplete type 'A'}}
40 }
41 
jumps()42 void jumps() {
43 l1:
44   goto l5;
45   goto l4; // expected-error {{cannot jump}}
46   goto l3; // expected-error {{cannot jump}}
47   goto l2; // expected-error {{cannot jump}}
48   goto l1;
49   try { // expected-note 4 {{jump bypasses initialization of try block}}
50   l2:
51     goto l5;
52     goto l4; // expected-error {{cannot jump}}
53     goto l3; // expected-error {{cannot jump}}
54     goto l2;
55     goto l1;
56   } catch(int) { // expected-note 4 {{jump bypasses initialization of catch block}}
57   l3:
58     goto l5;
59     goto l4; // expected-error {{cannot jump}}
60     goto l3;
61     goto l2; // expected-error {{cannot jump}}
62     goto l1;
63   } catch(...) { // expected-note 4 {{jump bypasses initialization of catch block}}
64   l4:
65     goto l5;
66     goto l4;
67     goto l3; // expected-error {{cannot jump}}
68     goto l2; // expected-error {{cannot jump}}
69     goto l1;
70   }
71 l5:
72   goto l5;
73   goto l4; // expected-error {{cannot jump}}
74   goto l3; // expected-error {{cannot jump}}
75   goto l2; // expected-error {{cannot jump}}
76   goto l1;
77 }
78 
79 struct BadReturn {
BadReturnBadReturn80   BadReturn() try {
81   } catch(...) {
82     // Try to hide
83     try {
84     } catch(...) {
85       {
86         if (0)
87           return; // expected-error {{return in the catch of a function try block of a constructor is illegal}}
88       }
89     }
90   }
91   BadReturn(int);
92 };
93 
BadReturn(int)94 BadReturn::BadReturn(int) try {
95 } catch(...) {
96   // Try to hide
97   try {
98   } catch(int) {
99     return; // expected-error {{return in the catch of a function try block of a constructor is illegal}}
100   } catch(...) {
101     {
102       if (0)
103         return; // expected-error {{return in the catch of a function try block of a constructor is illegal}}
104     }
105   }
106 }
107 
108 // Cannot throw an abstract type.
109 class foo {
110 public:
foo()111   foo() {}
bar()112   void bar () {
113     throw *this; // expected-error{{cannot throw an object of abstract type 'foo'}}
114   }
115   virtual void test () = 0; // expected-note{{unimplemented pure virtual method 'test'}}
116 };
117 
118 namespace PR6831 {
119   namespace NA { struct S; }
120   namespace NB { struct S; }
121 
f()122   void f() {
123     using namespace NA;
124     using namespace NB;
125     try {
126     } catch (int S) {
127     }
128   }
129 }
130 
131 namespace Decay {
132   struct A {
133     void f() throw (A[10]);
134   };
135 
136   template<typename T> struct B {
137     void f() throw (B[10]);
138   };
139   template struct B<int>;
140 
141   void f() throw (int[10], int(*)());
142   void f() throw (int*, int());
143 
144   template<typename T> struct C {
145     void f() throw (T);
146 #if __cplusplus <= 199711L
147     // expected-error@-2 {{pointer to incomplete type 'Decay::E' is not allowed in exception specification}}
148 #endif
149   };
150   struct D {
151     C<D[10]> c;
152   };
153   struct E;
154 #if __cplusplus <= 199711L
155   // expected-note@-2 {{forward declaration of 'Decay::E'}}
156 #endif
157 
158   C<E[10]> e;
159 #if __cplusplus <= 199711L
160   // expected-note@-2 {{in instantiation of template class 'Decay::C<Decay::E [10]>' requested here}}
161 #endif
162 }
163 
164 void rval_ref() throw (int &&); // expected-error {{rvalue reference type 'int &&' is not allowed in exception specification}}
165 #if __cplusplus <= 199711L
166 // expected-warning@-2 {{rvalue references are a C++11 extension}}
167 #endif
168 
169 namespace HandlerInversion {
170 struct B {};
171 struct D : B {};
172 struct D2 : D {};
173 
f1()174 void f1() {
175   try {
176   } catch (B &b) { // expected-note {{for type 'HandlerInversion::B &'}}
177   } catch (D &d) { // expected-warning {{exception of type 'HandlerInversion::D &' will be caught by earlier handler}}
178   }
179 }
180 
f2()181 void f2() {
182   try {
183   } catch (B *b) { // expected-note {{for type 'HandlerInversion::B *'}}
184   } catch (D *d) { // expected-warning {{exception of type 'HandlerInversion::D *' will be caught by earlier handler}}
185   }
186 }
187 
f3()188 void f3() {
189   try {
190   } catch (D &d) { // Ok
191   } catch (B &b) {
192   }
193 }
194 
f4()195 void f4() {
196   try {
197   } catch (B &b) { // Ok
198   }
199 }
200 
f5()201 void f5() {
202   try {
203   } catch (int) {
204   } catch (float) {
205   }
206 }
207 
f6()208 void f6() {
209   try {
210   } catch (B &b) {  // expected-note {{for type 'HandlerInversion::B &'}}
211   } catch (D2 &d) {  // expected-warning {{exception of type 'HandlerInversion::D2 &' will be caught by earlier handler}}
212   }
213 }
214 
f7()215 void f7() {
216   try {
217   } catch (B *b) { // Ok
218   } catch (D &d) { // Ok
219   }
220 
221   try {
222   } catch (B b) { // Ok
223   } catch (D *d) { // Ok
224   }
225 }
226 
f8()227 void f8() {
228   try {
229   } catch (const B &b) {  // expected-note {{for type 'const HandlerInversion::B &'}}
230   } catch (D2 &d) {  // expected-warning {{exception of type 'HandlerInversion::D2 &' will be caught by earlier handler}}
231   }
232 
233   try {
234   } catch (B &b) {  // expected-note {{for type 'HandlerInversion::B &'}}
235   } catch (const D2 &d) {  // expected-warning {{exception of type 'const HandlerInversion::D2 &' will be caught by earlier handler}}
236   }
237 
238   try {
239   } catch (B b) { // expected-note {{for type 'HandlerInversion::B'}}
240   } catch (D &d) { // expected-warning {{exception of type 'HandlerInversion::D &' will be caught by earlier handler}}
241   }
242 }
243 }
244 
245 namespace ConstVolatileThrow {
246 struct S {
SConstVolatileThrow::S247   S() {}         // expected-note{{candidate constructor not viable}}
248   S(const S &s); // expected-note{{candidate constructor not viable}}
249 };
250 
251 typedef const volatile S CVS;
252 
f()253 void f() {
254   throw CVS(); // expected-error{{no matching constructor for initialization}}
255 }
256 }
257 
258 namespace ConstVolatileCatch {
259 struct S {
SConstVolatileCatch::S260   S() {}
261   S(const volatile S &s);
262 
263 private:
264   S(const S &s); // expected-note {{declared private here}}
265 };
266 
267 void f();
268 
g()269 void g() {
270   try {
271     f();
272   } catch (volatile S s) { // expected-error {{calling a private constructor}}
273   }
274 }
275 }
276 
277 namespace PR28047 {
test1(int i)278 void test1(int i) {
279   try {
280   } catch (int(*)[i]) { // expected-error{{cannot catch variably modified type}}
281   }
282 }
test2()283 void test2() {
284   int i;
285   try {
286   } catch (int(*)[i]) { // expected-error{{cannot catch variably modified type}}
287   }
288 }
289 }
290