Clang Project

clang_source_code/test/SemaCXX/scope-check.cpp
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
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 {{cannot jump}}
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 {{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
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 {{cannot jump}}
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 {{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
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) { // 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
209namespace 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
220namespace 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
233namespace 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
248namespace 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
262namespace 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
278namespace 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
291namespace 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}}
296x:  return s.n;
297  }
298}
299
300#if __cplusplus >= 201103L
301namespace 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}}
306x:  return s.get();
307  }
308}
309#endif
310
311namespace 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
330namespace 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}
338namespace 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
350namespace 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
379namespace 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
391namespace 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
425namespace 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
446namespace seh {
447
448// Jumping into SEH try blocks is not permitted.
449
450void 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
466void 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
485void jump_out_of_except() {
486  __try {
487    goto out_of_except_try;
488  } __except(0) {
489  }
490out_of_except_try:
491  ;
492
493  __try {
494  } __except(0) {
495    goto out_of_except_except;
496  }
497out_of_except_except:
498  ;
499}
500
501void jump_out_of_finally() {
502  __try {
503  goto out_of_finally_try;
504  } __finally {
505  }
506out_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  }
518out_of_finally_finally:
519  ;
520}
521
522// Jumping between protected scope and handler is not permitted.
523
524void 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
540void 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
556void 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  }
586after_outer_except:
587  ;
588
589  __try {
590    __try{
591    } __except(0) {
592      goto after_outer_finally;
593    }
594  } __finally {
595  }
596after_outer_finally:
597  ;
598}
599
600// This section is academic, as MSVC doesn't support indirect gotos.
601
602void 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  }
627l: // expected-note 4 {{possible target of indirect goto statement}}
628  ;
629}
630
631} // namespace seh
632