1 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -fcxx-exceptions %s -Wno-unreachable-code
2 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -fcxx-exceptions -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