| // RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s -Wno-unreachable-code |
| |
| namespace test0 { |
| struct D { ~D(); }; |
| |
| int f(bool b) { |
| if (b) { |
| D d; |
| goto end; |
| } |
| |
| end: |
| return 1; |
| } |
| } |
| |
| namespace test1 { |
| struct C { C(); }; |
| |
| int f(bool b) { |
| if (b) |
| goto foo; // expected-error {{illegal goto into protected scope}} |
| C c; // expected-note {{jump bypasses variable initialization}} |
| foo: |
| return 1; |
| } |
| } |
| |
| namespace test2 { |
| struct C { C(); }; |
| |
| int f(void **ip) { |
| static void *ips[] = { &&lbl1, &&lbl2 }; |
| |
| C c; |
| goto *ip; |
| lbl1: |
| return 0; |
| lbl2: |
| return 1; |
| } |
| } |
| |
| namespace test3 { |
| struct C { C(); }; |
| |
| int f(void **ip) { |
| static void *ips[] = { &&lbl1, &&lbl2 }; |
| |
| goto *ip; |
| lbl1: { |
| C c; |
| return 0; |
| } |
| lbl2: |
| return 1; |
| } |
| } |
| |
| namespace test4 { |
| struct C { C(); }; |
| struct D { ~D(); }; |
| |
| int f(void **ip) { |
| static void *ips[] = { &&lbl1, &&lbl2 }; |
| |
| C c0; |
| |
| goto *ip; // expected-warning {{indirect goto might cross protected scopes}} |
| C c1; // expected-note {{jump bypasses variable initialization}} |
| lbl1: // expected-note {{possible target of indirect goto}} |
| return 0; |
| lbl2: |
| return 1; |
| } |
| } |
| |
| namespace test5 { |
| struct C { C(); }; |
| struct D { ~D(); }; |
| |
| int f(void **ip) { |
| static void *ips[] = { &&lbl1, &&lbl2 }; |
| C c0; |
| |
| goto *ip; |
| lbl1: // expected-note {{possible target of indirect goto}} |
| return 0; |
| lbl2: |
| if (ip[1]) { |
| D d; // expected-note {{jump exits scope of variable with non-trivial destructor}} |
| ip += 2; |
| goto *ip; // expected-warning {{indirect goto might cross protected scopes}} |
| } |
| return 1; |
| } |
| } |
| |
| namespace test6 { |
| struct C { C(); }; |
| |
| unsigned f(unsigned s0, unsigned s1, void **ip) { |
| static void *ips[] = { &&lbl1, &&lbl2, &&lbl3, &&lbl4 }; |
| C c0; |
| |
| goto *ip; |
| lbl1: |
| s0++; |
| goto *++ip; |
| lbl2: |
| s0 -= s1; |
| goto *++ip; |
| lbl3: { |
| unsigned tmp = s0; |
| s0 = s1; |
| s1 = tmp; |
| goto *++ip; |
| } |
| lbl4: |
| return s0; |
| } |
| } |
| |
| // C++0x says it's okay to skip non-trivial initializers on static |
| // locals, and we implement that in '03 as well. |
| namespace test7 { |
| struct C { C(); }; |
| |
| void test() { |
| goto foo; |
| static C c; |
| foo: |
| return; |
| } |
| } |
| |
| // PR7789 |
| namespace test8 { |
| void test1(int c) { |
| switch (c) { |
| case 0: |
| int x = 56; // expected-note {{jump bypasses variable initialization}} |
| case 1: // expected-error {{switch case is in protected scope}} |
| x = 10; |
| } |
| } |
| |
| void test2() { |
| goto l2; // expected-error {{goto into protected scope}} |
| l1: int x = 5; // expected-note {{jump bypasses variable initialization}} |
| l2: x++; |
| } |
| } |