xref: /aosp_15_r20/external/clang/test/SemaCXX/scope-check.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify -fblocks -fcxx-exceptions -fms-extensions %s -Wno-unreachable-code
2*67e74705SXin Li // RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify -fblocks -fcxx-exceptions -fms-extensions -std=gnu++11 %s -Wno-unreachable-code
3*67e74705SXin Li 
4*67e74705SXin Li namespace testInvalid {
5*67e74705SXin Li Invalid inv; // expected-error {{unknown type name}}
6*67e74705SXin Li // Make sure this doesn't assert.
fn()7*67e74705SXin Li void fn()
8*67e74705SXin Li {
9*67e74705SXin Li     int c = 0;
10*67e74705SXin Li     if (inv)
11*67e74705SXin Li Here: ;
12*67e74705SXin Li     goto Here;
13*67e74705SXin Li }
14*67e74705SXin Li }
15*67e74705SXin Li 
16*67e74705SXin Li namespace test0 {
17*67e74705SXin Li   struct D { ~D(); };
18*67e74705SXin Li 
f(bool b)19*67e74705SXin Li   int f(bool b) {
20*67e74705SXin Li     if (b) {
21*67e74705SXin Li       D d;
22*67e74705SXin Li       goto end;
23*67e74705SXin Li     }
24*67e74705SXin Li 
25*67e74705SXin Li   end:
26*67e74705SXin Li     return 1;
27*67e74705SXin Li   }
28*67e74705SXin Li }
29*67e74705SXin Li 
30*67e74705SXin Li namespace test1 {
31*67e74705SXin Li   struct C { C(); };
32*67e74705SXin Li 
f(bool b)33*67e74705SXin Li   int f(bool b) {
34*67e74705SXin Li     if (b)
35*67e74705SXin Li       goto foo; // expected-error {{cannot jump}}
36*67e74705SXin Li     C c; // expected-note {{jump bypasses variable initialization}}
37*67e74705SXin Li   foo:
38*67e74705SXin Li     return 1;
39*67e74705SXin Li   }
40*67e74705SXin Li }
41*67e74705SXin Li 
42*67e74705SXin Li namespace test2 {
43*67e74705SXin Li   struct C { C(); };
44*67e74705SXin Li 
f(void ** ip)45*67e74705SXin Li   int f(void **ip) {
46*67e74705SXin Li     static void *ips[] = { &&lbl1, &&lbl2 };
47*67e74705SXin Li 
48*67e74705SXin Li     C c;
49*67e74705SXin Li     goto *ip;
50*67e74705SXin Li   lbl1:
51*67e74705SXin Li     return 0;
52*67e74705SXin Li   lbl2:
53*67e74705SXin Li     return 1;
54*67e74705SXin Li   }
55*67e74705SXin Li }
56*67e74705SXin Li 
57*67e74705SXin Li namespace test3 {
58*67e74705SXin Li   struct C { C(); };
59*67e74705SXin Li 
f(void ** ip)60*67e74705SXin Li   int f(void **ip) {
61*67e74705SXin Li     static void *ips[] = { &&lbl1, &&lbl2 };
62*67e74705SXin Li 
63*67e74705SXin Li     goto *ip;
64*67e74705SXin Li   lbl1: {
65*67e74705SXin Li     C c;
66*67e74705SXin Li     return 0;
67*67e74705SXin Li   }
68*67e74705SXin Li   lbl2:
69*67e74705SXin Li     return 1;
70*67e74705SXin Li   }
71*67e74705SXin Li }
72*67e74705SXin Li 
73*67e74705SXin Li namespace test4 {
74*67e74705SXin Li   struct C { C(); };
75*67e74705SXin Li   struct D { ~D(); };
76*67e74705SXin Li 
f(void ** ip)77*67e74705SXin Li   int f(void **ip) {
78*67e74705SXin Li     static void *ips[] = { &&lbl1, &&lbl2 };
79*67e74705SXin Li 
80*67e74705SXin Li     C c0;
81*67e74705SXin Li 
82*67e74705SXin Li     goto *ip; // expected-error {{cannot jump}}
83*67e74705SXin Li     C c1; // expected-note {{jump bypasses variable initialization}}
84*67e74705SXin Li   lbl1: // expected-note {{possible target of indirect goto}}
85*67e74705SXin Li     return 0;
86*67e74705SXin Li   lbl2:
87*67e74705SXin Li     return 1;
88*67e74705SXin Li   }
89*67e74705SXin Li }
90*67e74705SXin Li 
91*67e74705SXin Li namespace test5 {
92*67e74705SXin Li   struct C { C(); };
93*67e74705SXin Li   struct D { ~D(); };
94*67e74705SXin Li 
f(void ** ip)95*67e74705SXin Li   int f(void **ip) {
96*67e74705SXin Li     static void *ips[] = { &&lbl1, &&lbl2 };
97*67e74705SXin Li     C c0;
98*67e74705SXin Li 
99*67e74705SXin Li     goto *ip;
100*67e74705SXin Li   lbl1: // expected-note {{possible target of indirect goto}}
101*67e74705SXin Li     return 0;
102*67e74705SXin Li   lbl2:
103*67e74705SXin Li     if (ip[1]) {
104*67e74705SXin Li       D d; // expected-note {{jump exits scope of variable with non-trivial destructor}}
105*67e74705SXin Li       ip += 2;
106*67e74705SXin Li       goto *ip; // expected-error {{cannot jump}}
107*67e74705SXin Li     }
108*67e74705SXin Li     return 1;
109*67e74705SXin Li   }
110*67e74705SXin Li }
111*67e74705SXin Li 
112*67e74705SXin Li namespace test6 {
113*67e74705SXin Li   struct C { C(); };
114*67e74705SXin Li 
f(unsigned s0,unsigned s1,void ** ip)115*67e74705SXin Li   unsigned f(unsigned s0, unsigned s1, void **ip) {
116*67e74705SXin Li     static void *ips[] = { &&lbl1, &&lbl2, &&lbl3, &&lbl4 };
117*67e74705SXin Li     C c0;
118*67e74705SXin Li 
119*67e74705SXin Li     goto *ip;
120*67e74705SXin Li   lbl1:
121*67e74705SXin Li     s0++;
122*67e74705SXin Li     goto *++ip;
123*67e74705SXin Li   lbl2:
124*67e74705SXin Li     s0 -= s1;
125*67e74705SXin Li     goto *++ip;
126*67e74705SXin Li   lbl3: {
127*67e74705SXin Li     unsigned tmp = s0;
128*67e74705SXin Li     s0 = s1;
129*67e74705SXin Li     s1 = tmp;
130*67e74705SXin Li     goto *++ip;
131*67e74705SXin Li   }
132*67e74705SXin Li   lbl4:
133*67e74705SXin Li     return s0;
134*67e74705SXin Li   }
135*67e74705SXin Li }
136*67e74705SXin Li 
137*67e74705SXin Li // C++0x says it's okay to skip non-trivial initializers on static
138*67e74705SXin Li // locals, and we implement that in '03 as well.
139*67e74705SXin Li namespace test7 {
140*67e74705SXin Li   struct C { C(); };
141*67e74705SXin Li 
test()142*67e74705SXin Li   void test() {
143*67e74705SXin Li     goto foo;
144*67e74705SXin Li     static C c;
145*67e74705SXin Li   foo:
146*67e74705SXin Li     return;
147*67e74705SXin Li   }
148*67e74705SXin Li }
149*67e74705SXin Li 
150*67e74705SXin Li // PR7789
151*67e74705SXin Li namespace test8 {
test1(int c)152*67e74705SXin Li   void test1(int c) {
153*67e74705SXin Li     switch (c) {
154*67e74705SXin Li     case 0:
155*67e74705SXin Li       int x = 56; // expected-note {{jump bypasses variable initialization}}
156*67e74705SXin Li     case 1:       // expected-error {{cannot jump}}
157*67e74705SXin Li       x = 10;
158*67e74705SXin Li     }
159*67e74705SXin Li   }
160*67e74705SXin Li 
test2()161*67e74705SXin Li   void test2() {
162*67e74705SXin Li     goto l2;     // expected-error {{cannot jump}}
163*67e74705SXin Li   l1: int x = 5; // expected-note {{jump bypasses variable initialization}}
164*67e74705SXin Li   l2: x++;
165*67e74705SXin Li   }
166*67e74705SXin Li }
167*67e74705SXin Li 
168*67e74705SXin Li namespace test9 {
169*67e74705SXin Li   struct S { int i; };
test1()170*67e74705SXin Li   void test1() {
171*67e74705SXin Li     goto foo;
172*67e74705SXin Li     S s;
173*67e74705SXin Li   foo:
174*67e74705SXin Li     return;
175*67e74705SXin Li   }
test2(unsigned x,unsigned y)176*67e74705SXin Li   unsigned test2(unsigned x, unsigned y) {
177*67e74705SXin Li     switch (x) {
178*67e74705SXin Li     case 2:
179*67e74705SXin Li       S s;
180*67e74705SXin Li       if (y > 42) return x + y;
181*67e74705SXin Li     default:
182*67e74705SXin Li       return x - 2;
183*67e74705SXin Li     }
184*67e74705SXin Li   }
185*67e74705SXin Li }
186*67e74705SXin Li 
187*67e74705SXin Li // http://llvm.org/PR10462
188*67e74705SXin Li namespace PR10462 {
189*67e74705SXin Li   enum MyEnum {
190*67e74705SXin Li     something_valid,
191*67e74705SXin Li     something_invalid
192*67e74705SXin Li   };
193*67e74705SXin Li 
recurse()194*67e74705SXin Li   bool recurse() {
195*67e74705SXin Li     MyEnum K;
196*67e74705SXin Li     switch (K) { // expected-warning {{enumeration value 'something_invalid' not handled in switch}}
197*67e74705SXin Li     case something_valid:
198*67e74705SXin Li     case what_am_i_thinking: // expected-error {{use of undeclared identifier}}
199*67e74705SXin Li       int *X = 0;
200*67e74705SXin Li       if (recurse()) {
201*67e74705SXin Li       }
202*67e74705SXin Li 
203*67e74705SXin Li       break;
204*67e74705SXin Li     }
205*67e74705SXin Li   }
206*67e74705SXin Li }
207*67e74705SXin Li 
208*67e74705SXin Li namespace test10 {
test()209*67e74705SXin Li   int test() {
210*67e74705SXin Li     static void *ps[] = { &&a0 };
211*67e74705SXin Li     goto *&&a0; // expected-error {{cannot jump}}
212*67e74705SXin Li     int a = 3; // expected-note {{jump bypasses variable initialization}}
213*67e74705SXin Li   a0:
214*67e74705SXin Li     return 0;
215*67e74705SXin Li   }
216*67e74705SXin Li }
217*67e74705SXin Li 
218*67e74705SXin Li // pr13812
219*67e74705SXin Li namespace test11 {
220*67e74705SXin Li   struct C {
221*67e74705SXin Li     C(int x);
222*67e74705SXin Li     ~C();
223*67e74705SXin Li   };
f(void ** ip)224*67e74705SXin Li   void f(void **ip) {
225*67e74705SXin Li     static void *ips[] = { &&l0 };
226*67e74705SXin Li   l0:  // expected-note {{possible target of indirect goto}}
227*67e74705SXin Li     C c0 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}}
228*67e74705SXin Li     goto *ip; // expected-error {{cannot jump}}
229*67e74705SXin Li   }
230*67e74705SXin Li }
231*67e74705SXin Li 
232*67e74705SXin Li namespace test12 {
233*67e74705SXin Li   struct C {
234*67e74705SXin Li     C(int x);
235*67e74705SXin Li     ~C();
236*67e74705SXin Li   };
f(void ** ip)237*67e74705SXin Li   void f(void **ip) {
238*67e74705SXin Li     static void *ips[] = { &&l0 };
239*67e74705SXin Li     const C c0 = 17;
240*67e74705SXin Li   l0: // expected-note {{possible target of indirect goto}}
241*67e74705SXin Li     const C &c1 = 42; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
242*67e74705SXin Li     const C &c2 = c0;
243*67e74705SXin Li     goto *ip; // expected-error {{cannot jump}}
244*67e74705SXin Li   }
245*67e74705SXin Li }
246*67e74705SXin Li 
247*67e74705SXin Li namespace test13 {
248*67e74705SXin Li   struct C {
249*67e74705SXin Li     C(int x);
250*67e74705SXin Li     ~C();
251*67e74705SXin Li     int i;
252*67e74705SXin Li   };
f(void ** ip)253*67e74705SXin Li   void f(void **ip) {
254*67e74705SXin Li     static void *ips[] = { &&l0 };
255*67e74705SXin Li   l0: // expected-note {{possible target of indirect goto}}
256*67e74705SXin Li     const int &c1 = C(1).i; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
257*67e74705SXin Li     goto *ip;  // expected-error {{cannot jump}}
258*67e74705SXin Li   }
259*67e74705SXin Li }
260*67e74705SXin Li 
261*67e74705SXin Li namespace test14 {
262*67e74705SXin Li   struct C {
263*67e74705SXin Li     C(int x);
264*67e74705SXin Li     ~C();
265*67e74705SXin Li     operator int&() const;
266*67e74705SXin Li   };
f(void ** ip)267*67e74705SXin Li   void f(void **ip) {
268*67e74705SXin Li     static void *ips[] = { &&l0 };
269*67e74705SXin Li   l0:
270*67e74705SXin Li     // no warning since the C temporary is destructed before the goto.
271*67e74705SXin Li     const int &c1 = C(1);
272*67e74705SXin Li     goto *ip;
273*67e74705SXin Li   }
274*67e74705SXin Li }
275*67e74705SXin Li 
276*67e74705SXin Li // PR14225
277*67e74705SXin Li namespace test15 {
f1()278*67e74705SXin Li   void f1() try {
279*67e74705SXin Li     goto x; // expected-error {{cannot jump}}
280*67e74705SXin Li   } catch(...) {  // expected-note {{jump bypasses initialization of catch block}}
281*67e74705SXin Li     x: ;
282*67e74705SXin Li   }
f2()283*67e74705SXin Li   void f2() try {  // expected-note {{jump bypasses initialization of try block}}
284*67e74705SXin Li     x: ;
285*67e74705SXin Li   } catch(...) {
286*67e74705SXin Li     goto x; // expected-error {{cannot jump}}
287*67e74705SXin Li   }
288*67e74705SXin Li }
289*67e74705SXin Li 
290*67e74705SXin Li namespace test16 {
291*67e74705SXin Li   struct S { int n; };
f()292*67e74705SXin Li   int f() {
293*67e74705SXin Li     goto x; // expected-error {{cannot jump}}
294*67e74705SXin Li     const S &s = S(); // expected-note {{jump bypasses variable initialization}}
295*67e74705SXin Li x:  return s.n;
296*67e74705SXin Li   }
297*67e74705SXin Li }
298*67e74705SXin Li 
299*67e74705SXin Li #if __cplusplus >= 201103L
300*67e74705SXin Li namespace test17 {
301*67e74705SXin Li   struct S { int get(); private: int n; };
f()302*67e74705SXin Li   int f() {
303*67e74705SXin Li     goto x; // expected-error {{cannot jump}}
304*67e74705SXin Li     S s = {}; // expected-note {{jump bypasses variable initialization}}
305*67e74705SXin Li x:  return s.get();
306*67e74705SXin Li   }
307*67e74705SXin Li }
308*67e74705SXin Li #endif
309*67e74705SXin Li 
310*67e74705SXin Li namespace test18 {
311*67e74705SXin Li   struct A { ~A(); };
312*67e74705SXin Li   struct B { const int &r; const A &a; };
f()313*67e74705SXin Li   int f() {
314*67e74705SXin Li     void *p = &&x;
315*67e74705SXin Li     const A a = A();
316*67e74705SXin Li   x:
317*67e74705SXin Li     B b = { 0, a }; // ok
318*67e74705SXin Li     goto *p;
319*67e74705SXin Li   }
g()320*67e74705SXin Li   int g() {
321*67e74705SXin Li     void *p = &&x;
322*67e74705SXin Li   x: // expected-note {{possible target of indirect goto}}
323*67e74705SXin Li     B b = { 0, A() }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
324*67e74705SXin Li     goto *p; // expected-error {{cannot jump}}
325*67e74705SXin Li   }
326*67e74705SXin Li }
327*67e74705SXin Li 
328*67e74705SXin Li #if __cplusplus >= 201103L
329*67e74705SXin Li namespace std {
330*67e74705SXin Li   typedef decltype(sizeof(int)) size_t;
331*67e74705SXin Li   template<typename T> struct initializer_list {
332*67e74705SXin Li     const T *begin;
333*67e74705SXin Li     size_t size;
334*67e74705SXin Li     initializer_list(const T *, size_t);
335*67e74705SXin Li   };
336*67e74705SXin Li }
337*67e74705SXin Li namespace test19 {
338*67e74705SXin Li   struct A { ~A(); };
339*67e74705SXin Li 
f()340*67e74705SXin Li   int f() {
341*67e74705SXin Li     void *p = &&x;
342*67e74705SXin Li     A a;
343*67e74705SXin Li   x: // expected-note {{possible target of indirect goto}}
344*67e74705SXin Li     std::initializer_list<A> il = { a }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
345*67e74705SXin Li     goto *p; // expected-error {{cannot jump}}
346*67e74705SXin Li   }
347*67e74705SXin Li }
348*67e74705SXin Li 
349*67e74705SXin Li namespace test20 {
350*67e74705SXin Li   struct A { ~A(); };
351*67e74705SXin Li   struct B {
352*67e74705SXin Li     const A &a;
353*67e74705SXin Li   };
354*67e74705SXin Li 
f()355*67e74705SXin Li   int f() {
356*67e74705SXin Li     void *p = &&x;
357*67e74705SXin Li     A a;
358*67e74705SXin Li   x:
359*67e74705SXin Li     std::initializer_list<B> il = {
360*67e74705SXin Li       a,
361*67e74705SXin Li       a
362*67e74705SXin Li     };
363*67e74705SXin Li     goto *p;
364*67e74705SXin Li   }
g()365*67e74705SXin Li   int g() {
366*67e74705SXin Li     void *p = &&x;
367*67e74705SXin Li     A a;
368*67e74705SXin Li   x: // expected-note {{possible target of indirect goto}}
369*67e74705SXin Li     std::initializer_list<B> il = {
370*67e74705SXin Li       a,
371*67e74705SXin Li       { A() } // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
372*67e74705SXin Li     };
373*67e74705SXin Li     goto *p; // expected-error {{cannot jump}}
374*67e74705SXin Li   }
375*67e74705SXin Li }
376*67e74705SXin Li #endif
377*67e74705SXin Li 
378*67e74705SXin Li namespace test21 {
f()379*67e74705SXin Li   template<typename T> void f() {
380*67e74705SXin Li   goto x; // expected-error {{cannot jump}}
381*67e74705SXin Li     T t; // expected-note {{bypasses}}
382*67e74705SXin Li  x: return;
383*67e74705SXin Li   }
384*67e74705SXin Li 
385*67e74705SXin Li   template void f<int>();
386*67e74705SXin Li   struct X { ~X(); };
387*67e74705SXin Li   template void f<X>(); // expected-note {{instantiation of}}
388*67e74705SXin Li }
389*67e74705SXin Li 
390*67e74705SXin Li namespace PR18217 {
391*67e74705SXin Li   typedef int *X;
392*67e74705SXin Li 
393*67e74705SXin Li   template <typename T>
394*67e74705SXin Li   class MyCl {
395*67e74705SXin Li     T mem;
396*67e74705SXin Li   };
397*67e74705SXin Li 
398*67e74705SXin Li   class Source {
399*67e74705SXin Li     MyCl<X> m;
400*67e74705SXin Li   public:
401*67e74705SXin Li     int getKind() const;
402*67e74705SXin Li   };
403*67e74705SXin Li 
404*67e74705SXin Li   bool b;
405*67e74705SXin Li   template<typename TT>
foo(const Source & SF,MyCl<TT * > Source::* m)406*67e74705SXin Li   static void foo(const Source &SF, MyCl<TT *> Source::*m) {
407*67e74705SXin Li     switch (SF.getKind()) {
408*67e74705SXin Li       case 1: return;
409*67e74705SXin Li       case 2: break;
410*67e74705SXin Li       case 3:
411*67e74705SXin Li       case 4: return;
412*67e74705SXin Li     };
413*67e74705SXin Li     if (b) {
414*67e74705SXin Li       auto &y = const_cast<MyCl<TT *> &>(SF.*m); // expected-warning 0-1{{extension}}
415*67e74705SXin Li     }
416*67e74705SXin Li   }
417*67e74705SXin Li 
getKind() const418*67e74705SXin Li   int Source::getKind() const {
419*67e74705SXin Li     foo(*this, &Source::m);
420*67e74705SXin Li     return 0;
421*67e74705SXin Li   }
422*67e74705SXin Li }
423*67e74705SXin Li 
424*67e74705SXin Li namespace test_recovery {
425*67e74705SXin Li   // Test that jump scope checking recovers when there are unspecified errors
426*67e74705SXin Li   // in the function declaration or body.
427*67e74705SXin Li 
test(nexist,int c)428*67e74705SXin Li   void test(nexist, int c) { // expected-error {{}}
429*67e74705SXin Li     nexist_fn(); // expected-error {{}}
430*67e74705SXin Li     goto nexist_label; // expected-error {{use of undeclared label}}
431*67e74705SXin Li     goto a0; // expected-error {{cannot jump}}
432*67e74705SXin Li     int a = 0; // expected-note {{jump bypasses variable initialization}}
433*67e74705SXin Li     a0:;
434*67e74705SXin Li 
435*67e74705SXin Li     switch (c) {
436*67e74705SXin Li     case $: // expected-error {{}}
437*67e74705SXin Li     case 0:
438*67e74705SXin Li       int x = 56; // expected-note {{jump bypasses variable initialization}}
439*67e74705SXin Li     case 1: // expected-error {{cannot jump}}
440*67e74705SXin Li       x = 10;
441*67e74705SXin Li     }
442*67e74705SXin Li   }
443*67e74705SXin Li }
444*67e74705SXin Li 
445*67e74705SXin Li namespace seh {
446*67e74705SXin Li 
447*67e74705SXin Li // Jumping into SEH try blocks is not permitted.
448*67e74705SXin Li 
jump_into_except()449*67e74705SXin Li void jump_into_except() {
450*67e74705SXin Li   goto into_try_except_try; // expected-error {{cannot jump from this goto statement to its label}}
451*67e74705SXin Li   __try { // expected-note {{jump bypasses initialization of __try block}}
452*67e74705SXin Li   into_try_except_try:
453*67e74705SXin Li     ;
454*67e74705SXin Li   } __except(0) {
455*67e74705SXin Li   }
456*67e74705SXin Li 
457*67e74705SXin Li   goto into_try_except_except; // expected-error {{cannot jump from this goto statement to its label}}
458*67e74705SXin Li   __try {
459*67e74705SXin Li   } __except(0) { // expected-note {{jump bypasses initialization of __except block}}
460*67e74705SXin Li   into_try_except_except:
461*67e74705SXin Li     ;
462*67e74705SXin Li   }
463*67e74705SXin Li }
464*67e74705SXin Li 
jump_into_finally()465*67e74705SXin Li void jump_into_finally() {
466*67e74705SXin Li   goto into_try_except_try; // expected-error {{cannot jump from this goto statement to its label}}
467*67e74705SXin Li   __try { // expected-note {{jump bypasses initialization of __try block}}
468*67e74705SXin Li   into_try_except_try:
469*67e74705SXin Li     ;
470*67e74705SXin Li   } __finally {
471*67e74705SXin Li   }
472*67e74705SXin Li 
473*67e74705SXin Li   goto into_try_except_finally; // expected-error {{cannot jump from this goto statement to its label}}
474*67e74705SXin Li   __try {
475*67e74705SXin Li   } __finally { // expected-note {{jump bypasses initialization of __finally block}}
476*67e74705SXin Li   into_try_except_finally:
477*67e74705SXin Li     ;
478*67e74705SXin Li   }
479*67e74705SXin Li }
480*67e74705SXin Li 
481*67e74705SXin Li // Jumping out of SEH try blocks ok in general. (Jumping out of a __finally
482*67e74705SXin Li // has undefined behavior.)
483*67e74705SXin Li 
jump_out_of_except()484*67e74705SXin Li void jump_out_of_except() {
485*67e74705SXin Li   __try {
486*67e74705SXin Li     goto out_of_except_try;
487*67e74705SXin Li   } __except(0) {
488*67e74705SXin Li   }
489*67e74705SXin Li out_of_except_try:
490*67e74705SXin Li   ;
491*67e74705SXin Li 
492*67e74705SXin Li   __try {
493*67e74705SXin Li   } __except(0) {
494*67e74705SXin Li     goto out_of_except_except;
495*67e74705SXin Li   }
496*67e74705SXin Li out_of_except_except:
497*67e74705SXin Li   ;
498*67e74705SXin Li }
499*67e74705SXin Li 
jump_out_of_finally()500*67e74705SXin Li void jump_out_of_finally() {
501*67e74705SXin Li   __try {
502*67e74705SXin Li   goto out_of_finally_try;
503*67e74705SXin Li   } __finally {
504*67e74705SXin Li   }
505*67e74705SXin Li out_of_finally_try:
506*67e74705SXin Li   ;
507*67e74705SXin Li 
508*67e74705SXin Li   __try {
509*67e74705SXin Li   } __finally {
510*67e74705SXin Li     goto out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}}
511*67e74705SXin Li   }
512*67e74705SXin Li 
513*67e74705SXin Li   __try {
514*67e74705SXin Li   } __finally {
515*67e74705SXin Li     goto *&&out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}}
516*67e74705SXin Li   }
517*67e74705SXin Li out_of_finally_finally:
518*67e74705SXin Li   ;
519*67e74705SXin Li }
520*67e74705SXin Li 
521*67e74705SXin Li // Jumping between protected scope and handler is not permitted.
522*67e74705SXin Li 
jump_try_except()523*67e74705SXin Li void jump_try_except() {
524*67e74705SXin Li   __try {
525*67e74705SXin Li     goto from_try_to_except; // expected-error {{cannot jump from this goto statement to its label}}
526*67e74705SXin Li   } __except(0) { // expected-note {{jump bypasses initialization of __except block}}
527*67e74705SXin Li   from_try_to_except:
528*67e74705SXin Li     ;
529*67e74705SXin Li   }
530*67e74705SXin Li 
531*67e74705SXin Li   __try { // expected-note {{jump bypasses initialization of __try block}}
532*67e74705SXin Li   from_except_to_try:
533*67e74705SXin Li     ;
534*67e74705SXin Li   } __except(0) {
535*67e74705SXin Li     goto from_except_to_try; // expected-error {{cannot jump from this goto statement to its label}}
536*67e74705SXin Li   }
537*67e74705SXin Li }
538*67e74705SXin Li 
jump_try_finally()539*67e74705SXin Li void jump_try_finally() {
540*67e74705SXin Li   __try {
541*67e74705SXin Li     goto from_try_to_finally; // expected-error {{cannot jump from this goto statement to its label}}
542*67e74705SXin Li   } __finally { // expected-note {{jump bypasses initialization of __finally block}}
543*67e74705SXin Li   from_try_to_finally:
544*67e74705SXin Li     ;
545*67e74705SXin Li   }
546*67e74705SXin Li 
547*67e74705SXin Li   __try { // expected-note {{jump bypasses initialization of __try block}}
548*67e74705SXin Li   from_finally_to_try:
549*67e74705SXin Li     ;
550*67e74705SXin Li   } __finally {
551*67e74705SXin Li     goto from_finally_to_try; // expected-error {{cannot jump from this goto statement to its label}} expected-warning {{jump out of __finally block has undefined behavior}}
552*67e74705SXin Li   }
553*67e74705SXin Li }
554*67e74705SXin Li 
nested()555*67e74705SXin Li void nested() {
556*67e74705SXin Li   // These are not permitted.
557*67e74705SXin Li   __try {
558*67e74705SXin Li     __try {
559*67e74705SXin Li     } __finally {
560*67e74705SXin Li       goto outer_except; // expected-error {{cannot jump from this goto statement to its label}}
561*67e74705SXin Li     }
562*67e74705SXin Li   } __except(0) { // expected-note {{jump bypasses initialization of __except bloc}}
563*67e74705SXin Li   outer_except:
564*67e74705SXin Li     ;
565*67e74705SXin Li   }
566*67e74705SXin Li 
567*67e74705SXin Li   __try {
568*67e74705SXin Li     __try{
569*67e74705SXin Li     } __except(0) {
570*67e74705SXin Li       goto outer_finally; // expected-error {{cannot jump from this goto statement to its label}}
571*67e74705SXin Li     }
572*67e74705SXin Li   } __finally { // expected-note {{jump bypasses initialization of __finally bloc}}
573*67e74705SXin Li   outer_finally:
574*67e74705SXin Li     ;
575*67e74705SXin Li   }
576*67e74705SXin Li 
577*67e74705SXin Li   // These are permitted.
578*67e74705SXin Li   __try {
579*67e74705SXin Li     __try {
580*67e74705SXin Li     } __finally {
581*67e74705SXin Li       goto after_outer_except; // expected-warning {{jump out of __finally block has undefined behavior}}
582*67e74705SXin Li     }
583*67e74705SXin Li   } __except(0) {
584*67e74705SXin Li   }
585*67e74705SXin Li after_outer_except:
586*67e74705SXin Li   ;
587*67e74705SXin Li 
588*67e74705SXin Li   __try {
589*67e74705SXin Li     __try{
590*67e74705SXin Li     } __except(0) {
591*67e74705SXin Li       goto after_outer_finally;
592*67e74705SXin Li     }
593*67e74705SXin Li   } __finally {
594*67e74705SXin Li   }
595*67e74705SXin Li after_outer_finally:
596*67e74705SXin Li   ;
597*67e74705SXin Li }
598*67e74705SXin Li 
599*67e74705SXin Li // This section is academic, as MSVC doesn't support indirect gotos.
600*67e74705SXin Li 
indirect_jumps(void ** ip)601*67e74705SXin Li void indirect_jumps(void **ip) {
602*67e74705SXin Li   static void *ips[] = { &&l };
603*67e74705SXin Li 
604*67e74705SXin Li   __try { // expected-note {{jump exits __try block}}
605*67e74705SXin Li     // FIXME: Should this be allowed? Jumping out of the guarded section of a
606*67e74705SXin Li     // __try/__except doesn't require unwinding.
607*67e74705SXin Li     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
608*67e74705SXin Li   } __except(0) {
609*67e74705SXin Li   }
610*67e74705SXin Li 
611*67e74705SXin Li   __try {
612*67e74705SXin Li   } __except(0) { // expected-note {{jump exits __except block}}
613*67e74705SXin Li     // FIXME: What about here?
614*67e74705SXin Li     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
615*67e74705SXin Li   }
616*67e74705SXin Li 
617*67e74705SXin Li   __try { // expected-note {{jump exits __try block}}
618*67e74705SXin Li     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
619*67e74705SXin Li   } __finally {
620*67e74705SXin Li   }
621*67e74705SXin Li 
622*67e74705SXin Li   __try {
623*67e74705SXin Li   } __finally { // expected-note {{jump exits __finally block}}
624*67e74705SXin Li     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
625*67e74705SXin Li   }
626*67e74705SXin Li l: // expected-note 4 {{possible target of indirect goto statement}}
627*67e74705SXin Li   ;
628*67e74705SXin Li }
629*67e74705SXin Li 
630*67e74705SXin Li } // namespace seh
631