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