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. |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
142 | void test() { |
143 | goto foo; |
144 | static C c; |
145 | foo: |
146 | return; |
147 | } |
148 | } |
149 | |
150 | // PR7789 |
151 | namespace test8 { |
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 | |
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; }; |
170 | void test1() { |
171 | goto foo; |
172 | S s; |
173 | foo: |
174 | return; |
175 | } |
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 | |
194 | bool recurse() { |
195 | MyEnum K; |
196 | switch (K) { // do not warn that 'something_invalid' is not listed; |
197 | // 'what_am_i_thinking' might have been intended to be that case. |
198 | case something_valid: |
199 | case what_am_i_thinking: // expected-error {{use of undeclared identifier}} |
200 | int *X = 0; |
201 | if (recurse()) { |
202 | } |
203 | |
204 | break; |
205 | } |
206 | } |
207 | } |
208 | |
209 | namespace test10 { |
210 | int test() { |
211 | static void *ps[] = { &&a0 }; |
212 | goto *&&a0; // expected-error {{cannot jump}} |
213 | int a = 3; // expected-note {{jump bypasses variable initialization}} |
214 | a0: |
215 | return 0; |
216 | } |
217 | } |
218 | |
219 | // pr13812 |
220 | namespace test11 { |
221 | struct C { |
222 | C(int x); |
223 | ~C(); |
224 | }; |
225 | void f(void **ip) { |
226 | static void *ips[] = { &&l0 }; |
227 | l0: // expected-note {{possible target of indirect goto}} |
228 | C c0 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}} |
229 | goto *ip; // expected-error {{cannot jump}} |
230 | } |
231 | } |
232 | |
233 | namespace test12 { |
234 | struct C { |
235 | C(int x); |
236 | ~C(); |
237 | }; |
238 | void f(void **ip) { |
239 | static void *ips[] = { &&l0 }; |
240 | const C c0 = 17; |
241 | l0: // expected-note {{possible target of indirect goto}} |
242 | const C &c1 = 42; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} |
243 | const C &c2 = c0; |
244 | goto *ip; // expected-error {{cannot jump}} |
245 | } |
246 | } |
247 | |
248 | namespace test13 { |
249 | struct C { |
250 | C(int x); |
251 | ~C(); |
252 | int i; |
253 | }; |
254 | void f(void **ip) { |
255 | static void *ips[] = { &&l0 }; |
256 | l0: // expected-note {{possible target of indirect goto}} |
257 | const int &c1 = C(1).i; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} |
258 | goto *ip; // expected-error {{cannot jump}} |
259 | } |
260 | } |
261 | |
262 | namespace test14 { |
263 | struct C { |
264 | C(int x); |
265 | ~C(); |
266 | operator int&() const; |
267 | }; |
268 | void f(void **ip) { |
269 | static void *ips[] = { &&l0 }; |
270 | l0: |
271 | // no warning since the C temporary is destructed before the goto. |
272 | const int &c1 = C(1); |
273 | goto *ip; |
274 | } |
275 | } |
276 | |
277 | // PR14225 |
278 | namespace test15 { |
279 | void f1() try { |
280 | goto x; // expected-error {{cannot jump}} |
281 | } catch(...) { // expected-note {{jump bypasses initialization of catch block}} |
282 | x: ; |
283 | } |
284 | void f2() try { // expected-note {{jump bypasses initialization of try block}} |
285 | x: ; |
286 | } catch(...) { |
287 | goto x; // expected-error {{cannot jump}} |
288 | } |
289 | } |
290 | |
291 | namespace test16 { |
292 | struct S { int n; }; |
293 | int f() { |
294 | goto x; // expected-error {{cannot jump}} |
295 | const S &s = S(); // expected-note {{jump bypasses variable initialization}} |
296 | x: return s.n; |
297 | } |
298 | } |
299 | |
300 | #if __cplusplus >= 201103L |
301 | namespace test17 { |
302 | struct S { int get(); private: int n; }; |
303 | int f() { |
304 | goto x; // expected-error {{cannot jump}} |
305 | S s = {}; // expected-note {{jump bypasses variable initialization}} |
306 | x: return s.get(); |
307 | } |
308 | } |
309 | #endif |
310 | |
311 | namespace test18 { |
312 | struct A { ~A(); }; |
313 | struct B { const int &r; const A &a; }; |
314 | int f() { |
315 | void *p = &&x; |
316 | const A a = A(); |
317 | x: |
318 | B b = { 0, a }; // ok |
319 | goto *p; |
320 | } |
321 | int g() { |
322 | void *p = &&x; |
323 | x: // expected-note {{possible target of indirect goto}} |
324 | B b = { 0, A() }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} |
325 | goto *p; // expected-error {{cannot jump}} |
326 | } |
327 | } |
328 | |
329 | #if __cplusplus >= 201103L |
330 | namespace std { |
331 | typedef decltype(sizeof(int)) size_t; |
332 | template<typename T> struct initializer_list { |
333 | const T *begin; |
334 | size_t size; |
335 | initializer_list(const T *, size_t); |
336 | }; |
337 | } |
338 | namespace test19 { |
339 | struct A { ~A(); }; |
340 | |
341 | int f() { |
342 | void *p = &&x; |
343 | A a; |
344 | x: // expected-note {{possible target of indirect goto}} |
345 | std::initializer_list<A> il = { a }; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} |
346 | goto *p; // expected-error {{cannot jump}} |
347 | } |
348 | } |
349 | |
350 | namespace test20 { |
351 | struct A { ~A(); }; |
352 | struct B { |
353 | const A &a; |
354 | }; |
355 | |
356 | int f() { |
357 | void *p = &&x; |
358 | A a; |
359 | x: |
360 | std::initializer_list<B> il = { |
361 | a, |
362 | a |
363 | }; |
364 | goto *p; |
365 | } |
366 | int g() { |
367 | void *p = &&x; |
368 | A a; |
369 | x: // expected-note {{possible target of indirect goto}} |
370 | std::initializer_list<B> il = { |
371 | a, |
372 | { A() } // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}} |
373 | }; |
374 | goto *p; // expected-error {{cannot jump}} |
375 | } |
376 | } |
377 | #endif |
378 | |
379 | namespace test21 { |
380 | template<typename T> void f() { |
381 | goto x; // expected-error {{cannot jump}} |
382 | T t; // expected-note {{bypasses}} |
383 | x: return; |
384 | } |
385 | |
386 | template void f<int>(); |
387 | struct X { ~X(); }; |
388 | template void f<X>(); // expected-note {{instantiation of}} |
389 | } |
390 | |
391 | namespace PR18217 { |
392 | typedef int *X; |
393 | |
394 | template <typename T> |
395 | class MyCl { |
396 | T mem; |
397 | }; |
398 | |
399 | class Source { |
400 | MyCl<X> m; |
401 | public: |
402 | int getKind() const; |
403 | }; |
404 | |
405 | bool b; |
406 | template<typename TT> |
407 | static void foo(const Source &SF, MyCl<TT *> Source::*m) { |
408 | switch (SF.getKind()) { |
409 | case 1: return; |
410 | case 2: break; |
411 | case 3: |
412 | case 4: return; |
413 | }; |
414 | if (b) { |
415 | auto &y = const_cast<MyCl<TT *> &>(SF.*m); // expected-warning 0-1{{extension}} |
416 | } |
417 | } |
418 | |
419 | int Source::getKind() const { |
420 | foo(*this, &Source::m); |
421 | return 0; |
422 | } |
423 | } |
424 | |
425 | namespace test_recovery { |
426 | // Test that jump scope checking recovers when there are unspecified errors |
427 | // in the function declaration or body. |
428 | |
429 | void test(nexist, int c) { // expected-error {{}} |
430 | nexist_fn(); // expected-error {{}} |
431 | goto nexist_label; // expected-error {{use of undeclared label}} |
432 | goto a0; // expected-error {{cannot jump}} |
433 | int a = 0; // expected-note {{jump bypasses variable initialization}} |
434 | a0:; |
435 | |
436 | switch (c) { |
437 | case $: // expected-error {{}} |
438 | case 0: |
439 | int x = 56; // expected-note {{jump bypasses variable initialization}} |
440 | case 1: // expected-error {{cannot jump}} |
441 | x = 10; |
442 | } |
443 | } |
444 | } |
445 | |
446 | namespace seh { |
447 | |
448 | // Jumping into SEH try blocks is not permitted. |
449 | |
450 | void jump_into_except() { |
451 | goto into_try_except_try; // expected-error {{cannot jump from this goto statement to its label}} |
452 | __try { // expected-note {{jump bypasses initialization of __try block}} |
453 | into_try_except_try: |
454 | ; |
455 | } __except(0) { |
456 | } |
457 | |
458 | goto into_try_except_except; // expected-error {{cannot jump from this goto statement to its label}} |
459 | __try { |
460 | } __except(0) { // expected-note {{jump bypasses initialization of __except block}} |
461 | into_try_except_except: |
462 | ; |
463 | } |
464 | } |
465 | |
466 | void jump_into_finally() { |
467 | goto into_try_except_try; // expected-error {{cannot jump from this goto statement to its label}} |
468 | __try { // expected-note {{jump bypasses initialization of __try block}} |
469 | into_try_except_try: |
470 | ; |
471 | } __finally { |
472 | } |
473 | |
474 | goto into_try_except_finally; // expected-error {{cannot jump from this goto statement to its label}} |
475 | __try { |
476 | } __finally { // expected-note {{jump bypasses initialization of __finally block}} |
477 | into_try_except_finally: |
478 | ; |
479 | } |
480 | } |
481 | |
482 | // Jumping out of SEH try blocks ok in general. (Jumping out of a __finally |
483 | // has undefined behavior.) |
484 | |
485 | void jump_out_of_except() { |
486 | __try { |
487 | goto out_of_except_try; |
488 | } __except(0) { |
489 | } |
490 | out_of_except_try: |
491 | ; |
492 | |
493 | __try { |
494 | } __except(0) { |
495 | goto out_of_except_except; |
496 | } |
497 | out_of_except_except: |
498 | ; |
499 | } |
500 | |
501 | void jump_out_of_finally() { |
502 | __try { |
503 | goto out_of_finally_try; |
504 | } __finally { |
505 | } |
506 | out_of_finally_try: |
507 | ; |
508 | |
509 | __try { |
510 | } __finally { |
511 | goto out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}} |
512 | } |
513 | |
514 | __try { |
515 | } __finally { |
516 | goto *&&out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}} |
517 | } |
518 | out_of_finally_finally: |
519 | ; |
520 | } |
521 | |
522 | // Jumping between protected scope and handler is not permitted. |
523 | |
524 | void jump_try_except() { |
525 | __try { |
526 | goto from_try_to_except; // expected-error {{cannot jump from this goto statement to its label}} |
527 | } __except(0) { // expected-note {{jump bypasses initialization of __except block}} |
528 | from_try_to_except: |
529 | ; |
530 | } |
531 | |
532 | __try { // expected-note {{jump bypasses initialization of __try block}} |
533 | from_except_to_try: |
534 | ; |
535 | } __except(0) { |
536 | goto from_except_to_try; // expected-error {{cannot jump from this goto statement to its label}} |
537 | } |
538 | } |
539 | |
540 | void jump_try_finally() { |
541 | __try { |
542 | goto from_try_to_finally; // expected-error {{cannot jump from this goto statement to its label}} |
543 | } __finally { // expected-note {{jump bypasses initialization of __finally block}} |
544 | from_try_to_finally: |
545 | ; |
546 | } |
547 | |
548 | __try { // expected-note {{jump bypasses initialization of __try block}} |
549 | from_finally_to_try: |
550 | ; |
551 | } __finally { |
552 | 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}} |
553 | } |
554 | } |
555 | |
556 | void nested() { |
557 | // These are not permitted. |
558 | __try { |
559 | __try { |
560 | } __finally { |
561 | goto outer_except; // expected-error {{cannot jump from this goto statement to its label}} |
562 | } |
563 | } __except(0) { // expected-note {{jump bypasses initialization of __except bloc}} |
564 | outer_except: |
565 | ; |
566 | } |
567 | |
568 | __try { |
569 | __try{ |
570 | } __except(0) { |
571 | goto outer_finally; // expected-error {{cannot jump from this goto statement to its label}} |
572 | } |
573 | } __finally { // expected-note {{jump bypasses initialization of __finally bloc}} |
574 | outer_finally: |
575 | ; |
576 | } |
577 | |
578 | // These are permitted. |
579 | __try { |
580 | __try { |
581 | } __finally { |
582 | goto after_outer_except; // expected-warning {{jump out of __finally block has undefined behavior}} |
583 | } |
584 | } __except(0) { |
585 | } |
586 | after_outer_except: |
587 | ; |
588 | |
589 | __try { |
590 | __try{ |
591 | } __except(0) { |
592 | goto after_outer_finally; |
593 | } |
594 | } __finally { |
595 | } |
596 | after_outer_finally: |
597 | ; |
598 | } |
599 | |
600 | // This section is academic, as MSVC doesn't support indirect gotos. |
601 | |
602 | void indirect_jumps(void **ip) { |
603 | static void *ips[] = { &&l }; |
604 | |
605 | __try { // expected-note {{jump exits __try block}} |
606 | // FIXME: Should this be allowed? Jumping out of the guarded section of a |
607 | // __try/__except doesn't require unwinding. |
608 | goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}} |
609 | } __except(0) { |
610 | } |
611 | |
612 | __try { |
613 | } __except(0) { // expected-note {{jump exits __except block}} |
614 | // FIXME: What about here? |
615 | goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}} |
616 | } |
617 | |
618 | __try { // expected-note {{jump exits __try block}} |
619 | goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}} |
620 | } __finally { |
621 | } |
622 | |
623 | __try { |
624 | } __finally { // expected-note {{jump exits __finally block}} |
625 | goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}} |
626 | } |
627 | l: // expected-note 4 {{possible target of indirect goto statement}} |
628 | ; |
629 | } |
630 | |
631 | } // namespace seh |
632 | |