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