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
4namespace testInvalid {
5Invalid inv; // expected-error {{unknown type name}}
6// Make sure this doesn't assert.
7void fn()
8{
9    int c = 0;
10    if (inv)
11Here: ;
12    goto Here;
13}
14}
15
16namespace 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
30namespace test1 {
31  struct C { C(); };
32
33  int f(bool b) {
34    if (b)
35      goto foo; // expected-error {{goto into protected scope}}
36    C c; // expected-note {{jump bypasses variable initialization}}
37  foo:
38    return 1;
39  }
40}
41
42namespace 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
57namespace 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
73namespace 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 {{indirect goto might cross protected scopes}}
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
91namespace 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 {{indirect goto might cross protected scopes}}
107    }
108    return 1;
109  }
110}
111
112namespace 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.
139namespace 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
151namespace 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 {{switch case is in protected scope}}
157      x = 10;
158    }
159  }
160
161  void test2() {
162    goto l2;     // expected-error {{goto into protected scope}}
163  l1: int x = 5; // expected-note {{jump bypasses variable initialization}}
164  l2: x++;
165  }
166}
167
168namespace 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
188namespace PR10462 {
189  enum MyEnum {
190    something_valid,
191    something_invalid
192  };
193
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
208namespace test10 {
209  int test() {
210    static void *ps[] = { &&a0 };
211    goto *&&a0; // expected-error {{goto into protected scope}}
212    int a = 3; // expected-note {{jump bypasses variable initialization}}
213  a0:
214    return 0;
215  }
216}
217
218// pr13812
219namespace test11 {
220  struct C {
221    C(int x);
222    ~C();
223  };
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 {{indirect goto might cross protected scopes}}
229  }
230}
231
232namespace test12 {
233  struct C {
234    C(int x);
235    ~C();
236  };
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 {{indirect goto might cross protected scopes}}
244  }
245}
246
247namespace test13 {
248  struct C {
249    C(int x);
250    ~C();
251    int i;
252  };
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 {{indirect goto might cross protected scopes}}
258  }
259}
260
261namespace test14 {
262  struct C {
263    C(int x);
264    ~C();
265    operator int&() const;
266  };
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
277namespace test15 {
278  void f1() try {
279    goto x; // expected-error {{goto into protected scope}}
280  } catch(...) {  // expected-note {{jump bypasses initialization of catch block}}
281    x: ;
282  }
283  void f2() try {  // expected-note {{jump bypasses initialization of try block}}
284    x: ;
285  } catch(...) {
286    goto x; // expected-error {{goto into protected scope}}
287  }
288}
289
290namespace test16 {
291  struct S { int n; };
292  int f() {
293    goto x; // expected-error {{goto into protected scope}}
294    const S &s = S(); // expected-note {{jump bypasses variable initialization}}
295x:  return s.n;
296  }
297}
298
299#if __cplusplus >= 201103L
300namespace test17 {
301  struct S { int get(); private: int n; };
302  int f() {
303    goto x; // expected-error {{goto into protected scope}}
304    S s = {}; // expected-note {{jump bypasses variable initialization}}
305x:  return s.get();
306  }
307}
308#endif
309
310namespace test18 {
311  struct A { ~A(); };
312  struct B { const int &r; const A &a; };
313  int f() {
314    void *p = &&x;
315    const A a = A();
316  x:
317    B b = { 0, a }; // ok
318    goto *p;
319  }
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 {{indirect goto might cross protected scopes}}
325  }
326}
327
328#if __cplusplus >= 201103L
329namespace 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}
337namespace test19 {
338  struct A { ~A(); };
339
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 {{indirect goto might cross protected scopes}}
346  }
347}
348
349namespace test20 {
350  struct A { ~A(); };
351  struct B {
352    const A &a;
353  };
354
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  }
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 {{indirect goto might cross protected scopes}}
374  }
375}
376#endif
377
378namespace test21 {
379  template<typename T> void f() {
380  goto x; // expected-error {{protected scope}}
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
390namespace 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>
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
418  int Source::getKind() const {
419    foo(*this, &Source::m);
420    return 0;
421  }
422}
423
424namespace test_recovery {
425  // Test that jump scope checking recovers when there are unspecified errors
426  // in the function declaration or body.
427
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 {{goto into protected scope}}
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 {{switch case is in protected scope}}
440      x = 10;
441    }
442  }
443}
444