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