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 test0 {
5   struct D { ~D(); };
6 
7   int f(bool b) {
8     if (b) {
9       D d;
10       goto end;
11     }
12 
13   end:
14     return 1;
15   }
16 }
17 
18 namespace test1 {
19   struct C { C(); };
20 
21   int f(bool b) {
22     if (b)
23       goto foo; // expected-error {{goto into protected scope}}
24     C c; // expected-note {{jump bypasses variable initialization}}
25   foo:
26     return 1;
27   }
28 }
29 
30 namespace test2 {
31   struct C { C(); };
32 
33   int f(void **ip) {
34     static void *ips[] = { &&lbl1, &&lbl2 };
35 
36     C c;
37     goto *ip;
38   lbl1:
39     return 0;
40   lbl2:
41     return 1;
42   }
43 }
44 
45 namespace test3 {
46   struct C { C(); };
47 
48   int f(void **ip) {
49     static void *ips[] = { &&lbl1, &&lbl2 };
50 
51     goto *ip;
52   lbl1: {
53     C c;
54     return 0;
55   }
56   lbl2:
57     return 1;
58   }
59 }
60 
61 namespace test4 {
62   struct C { C(); };
63   struct D { ~D(); };
64 
65   int f(void **ip) {
66     static void *ips[] = { &&lbl1, &&lbl2 };
67 
68     C c0;
69 
70     goto *ip; // expected-error {{indirect goto might cross protected scopes}}
71     C c1; // expected-note {{jump bypasses variable initialization}}
72   lbl1: // expected-note {{possible target of indirect goto}}
73     return 0;
74   lbl2:
75     return 1;
76   }
77 }
78 
79 namespace test5 {
80   struct C { C(); };
81   struct D { ~D(); };
82 
83   int f(void **ip) {
84     static void *ips[] = { &&lbl1, &&lbl2 };
85     C c0;
86 
87     goto *ip;
88   lbl1: // expected-note {{possible target of indirect goto}}
89     return 0;
90   lbl2:
91     if (ip[1]) {
92       D d; // expected-note {{jump exits scope of variable with non-trivial destructor}}
93       ip += 2;
94       goto *ip; // expected-error {{indirect goto might cross protected scopes}}
95     }
96     return 1;
97   }
98 }
99 
100 namespace test6 {
101   struct C { C(); };
102 
103   unsigned f(unsigned s0, unsigned s1, void **ip) {
104     static void *ips[] = { &&lbl1, &&lbl2, &&lbl3, &&lbl4 };
105     C c0;
106 
107     goto *ip;
108   lbl1:
109     s0++;
110     goto *++ip;
111   lbl2:
112     s0 -= s1;
113     goto *++ip;
114   lbl3: {
115     unsigned tmp = s0;
116     s0 = s1;
117     s1 = tmp;
118     goto *++ip;
119   }
120   lbl4:
121     return s0;
122   }
123 }
124 
125 // C++0x says it's okay to skip non-trivial initializers on static
126 // locals, and we implement that in '03 as well.
127 namespace test7 {
128   struct C { C(); };
129 
130   void test() {
131     goto foo;
132     static C c;
133   foo:
134     return;
135   }
136 }
137 
138 // PR7789
139 namespace test8 {
140   void test1(int c) {
141     switch (c) {
142     case 0:
143       int x = 56; // expected-note {{jump bypasses variable initialization}}
144     case 1:       // expected-error {{switch case is in protected scope}}
145       x = 10;
146     }
147   }
148 
149   void test2() {
150     goto l2;     // expected-error {{goto into protected scope}}
151   l1: int x = 5; // expected-note {{jump bypasses variable initialization}}
152   l2: x++;
153   }
154 }
155 
156 namespace test9 {
157   struct S { int i; };
158   void test1() {
159     goto foo;
160     S s;
161   foo:
162     return;
163   }
164   unsigned test2(unsigned x, unsigned y) {
165     switch (x) {
166     case 2:
167       S s;
168       if (y > 42) return x + y;
169     default:
170       return x - 2;
171     }
172   }
173 }
174 
175 // http://llvm.org/PR10462
176 namespace PR10462 {
177   enum MyEnum {
178     something_valid,
179     something_invalid
180   };
181 
182   bool recurse() {
183     MyEnum K;
184     switch (K) { // expected-warning {{enumeration value 'something_invalid' not handled in switch}}
185     case something_valid:
186     case what_am_i_thinking: // expected-error {{use of undeclared identifier}}
187       int *X = 0;
188       if (recurse()) {
189       }
190 
191       break;
192     }
193   }
194 }
195 
196 namespace test10 {
197   int test() {
198     static void *ps[] = { &&a0 };
199     goto *&&a0; // expected-error {{goto into protected scope}}
200     int a = 3; // expected-note {{jump bypasses variable initialization}}
201   a0:
202     return 0;
203   }
204 }
205 
206 // pr13812
207 namespace test11 {
208   struct C {
209     C(int x);
210     ~C();
211   };
212   void f(void **ip) {
213     static void *ips[] = { &&l0 };
214   l0:  // expected-note {{possible target of indirect goto}}
215     C c0 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}}
216     goto *ip; // expected-error {{indirect goto might cross protected scopes}}
217   }
218 }
219 
220 namespace test12 {
221   struct C {
222     C(int x);
223     ~C();
224   };
225   void f(void **ip) {
226     static void *ips[] = { &&l0 };
227     const C c0 = 17;
228   l0: // expected-note {{possible target of indirect goto}}
229     const C &c1 = 42; // expected-note {{jump exits scope of variable with non-trivial destructor}}
230     const C &c2 = c0;
231     goto *ip; // expected-error {{indirect goto might cross protected scopes}}
232   }
233 }
234 
235 namespace test13 {
236   struct C {
237     C(int x);
238     ~C();
239     int i;
240   };
241   void f(void **ip) {
242     static void *ips[] = { &&l0 };
243   l0: // expected-note {{possible target of indirect goto}}
244     const int &c1 = C(1).i; // expected-note {{jump exits scope of variable with non-trivial destructor}}
245     goto *ip;  // expected-error {{indirect goto might cross protected scopes}}
246   }
247 }
248 
249 namespace test14 {
250   struct C {
251     C(int x);
252     ~C();
253     operator int&() const;
254   };
255   void f(void **ip) {
256     static void *ips[] = { &&l0 };
257   l0:
258     // no warning since the C temporary is destructed before the goto.
259     const int &c1 = C(1);
260     goto *ip;
261   }
262 }
263 
264 // PR14225
265 namespace test15 {
266   void f1() try {
267     goto x; // expected-error {{goto into protected scope}}
268   } catch(...) {  // expected-note {{jump bypasses initialization of catch block}}
269     x: ;
270   }
271   void f2() try {  // expected-note {{jump bypasses initialization of try block}}
272     x: ;
273   } catch(...) {
274     goto x; // expected-error {{goto into protected scope}}
275   }
276 }
277 
278 namespace test16 {
279   struct S { int n; };
280   int f() {
281     goto x; // expected-error {{goto into protected scope}}
282     const S &s = S(); // expected-note {{jump bypasses variable initialization}}
283 x:  return s.n;
284   }
285 }
286 
287 #if __cplusplus >= 201103L
288 namespace test17 {
289   struct S { int get(); private: int n; };
290   int f() {
291     goto x; // expected-error {{goto into protected scope}}
292     S s = {}; // expected-note {{jump bypasses variable initialization}}
293 x:  return s.get();
294   }
295 }
296 #endif
297 
298 // This test must be last, because the error prohibits further jump diagnostics.
299 namespace testInvalid {
300 Invalid inv; // expected-error {{unknown type name}}
301 // Make sure this doesn't assert.
302 void fn()
303 {
304     int c = 0;
305     if (inv)
306 Here: ;
307     goto Here;
308 }
309 }
310