Home | History | Annotate | Download | only in SemaCXX
      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) { // 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 
    208 namespace test10 {
    209   int test() {
    210     static void *ps[] = { &&a0 };
    211     goto *&&a0; // expected-error {{cannot jump}}
    212     int a = 3; // expected-note {{jump bypasses variable initialization}}
    213   a0:
    214     return 0;
    215   }
    216 }
    217 
    218 // pr13812
    219 namespace 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 {{cannot jump}}
    229   }
    230 }
    231 
    232 namespace 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 {{cannot jump}}
    244   }
    245 }
    246 
    247 namespace 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 {{cannot jump}}
    258   }
    259 }
    260 
    261 namespace 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
    277 namespace test15 {
    278   void f1() try {
    279     goto x; // expected-error {{cannot jump}}
    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 {{cannot jump}}
    287   }
    288 }
    289 
    290 namespace test16 {
    291   struct S { int n; };
    292   int f() {
    293     goto x; // expected-error {{cannot jump}}
    294     const S &s = S(); // expected-note {{jump bypasses variable initialization}}
    295 x:  return s.n;
    296   }
    297 }
    298 
    299 #if __cplusplus >= 201103L
    300 namespace test17 {
    301   struct S { int get(); private: int n; };
    302   int f() {
    303     goto x; // expected-error {{cannot jump}}
    304     S s = {}; // expected-note {{jump bypasses variable initialization}}
    305 x:  return s.get();
    306   }
    307 }
    308 #endif
    309 
    310 namespace 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 {{cannot jump}}
    325   }
    326 }
    327 
    328 #if __cplusplus >= 201103L
    329 namespace 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 }
    337 namespace 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 {{cannot jump}}
    346   }
    347 }
    348 
    349 namespace 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 {{cannot jump}}
    374   }
    375 }
    376 #endif
    377 
    378 namespace test21 {
    379   template<typename T> void f() {
    380   goto x; // expected-error {{cannot jump}}
    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 
    390 namespace 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 
    424 namespace 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 {{cannot jump}}
    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 {{cannot jump}}
    440       x = 10;
    441     }
    442   }
    443 }
    444 
    445 namespace seh {
    446 
    447 // Jumping into SEH try blocks is not permitted.
    448 
    449 void jump_into_except() {
    450   goto into_try_except_try; // expected-error {{cannot jump from this goto statement to its label}}
    451   __try { // expected-note {{jump bypasses initialization of __try block}}
    452   into_try_except_try:
    453     ;
    454   } __except(0) {
    455   }
    456 
    457   goto into_try_except_except; // expected-error {{cannot jump from this goto statement to its label}}
    458   __try {
    459   } __except(0) { // expected-note {{jump bypasses initialization of __except block}}
    460   into_try_except_except:
    461     ;
    462   }
    463 }
    464 
    465 void jump_into_finally() {
    466   goto into_try_except_try; // expected-error {{cannot jump from this goto statement to its label}}
    467   __try { // expected-note {{jump bypasses initialization of __try block}}
    468   into_try_except_try:
    469     ;
    470   } __finally {
    471   }
    472 
    473   goto into_try_except_finally; // expected-error {{cannot jump from this goto statement to its label}}
    474   __try {
    475   } __finally { // expected-note {{jump bypasses initialization of __finally block}}
    476   into_try_except_finally:
    477     ;
    478   }
    479 }
    480 
    481 // Jumping out of SEH try blocks ok in general. (Jumping out of a __finally
    482 // has undefined behavior.)
    483 
    484 void jump_out_of_except() {
    485   __try {
    486     goto out_of_except_try;
    487   } __except(0) {
    488   }
    489 out_of_except_try:
    490   ;
    491 
    492   __try {
    493   } __except(0) {
    494     goto out_of_except_except;
    495   }
    496 out_of_except_except:
    497   ;
    498 }
    499 
    500 void jump_out_of_finally() {
    501   __try {
    502   goto out_of_finally_try;
    503   } __finally {
    504   }
    505 out_of_finally_try:
    506   ;
    507 
    508   __try {
    509   } __finally {
    510     goto out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}}
    511   }
    512 
    513   __try {
    514   } __finally {
    515     goto *&&out_of_finally_finally; // expected-warning {{jump out of __finally block has undefined behavior}}
    516   }
    517 out_of_finally_finally:
    518   ;
    519 }
    520 
    521 // Jumping between protected scope and handler is not permitted.
    522 
    523 void jump_try_except() {
    524   __try {
    525     goto from_try_to_except; // expected-error {{cannot jump from this goto statement to its label}}
    526   } __except(0) { // expected-note {{jump bypasses initialization of __except block}}
    527   from_try_to_except:
    528     ;
    529   }
    530 
    531   __try { // expected-note {{jump bypasses initialization of __try block}}
    532   from_except_to_try:
    533     ;
    534   } __except(0) {
    535     goto from_except_to_try; // expected-error {{cannot jump from this goto statement to its label}}
    536   }
    537 }
    538 
    539 void jump_try_finally() {
    540   __try {
    541     goto from_try_to_finally; // expected-error {{cannot jump from this goto statement to its label}}
    542   } __finally { // expected-note {{jump bypasses initialization of __finally block}}
    543   from_try_to_finally:
    544     ;
    545   }
    546 
    547   __try { // expected-note {{jump bypasses initialization of __try block}}
    548   from_finally_to_try:
    549     ;
    550   } __finally {
    551     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}}
    552   }
    553 }
    554 
    555 void nested() {
    556   // These are not permitted.
    557   __try {
    558     __try {
    559     } __finally {
    560       goto outer_except; // expected-error {{cannot jump from this goto statement to its label}}
    561     }
    562   } __except(0) { // expected-note {{jump bypasses initialization of __except bloc}}
    563   outer_except:
    564     ;
    565   }
    566 
    567   __try {
    568     __try{
    569     } __except(0) {
    570       goto outer_finally; // expected-error {{cannot jump from this goto statement to its label}}
    571     }
    572   } __finally { // expected-note {{jump bypasses initialization of __finally bloc}}
    573   outer_finally:
    574     ;
    575   }
    576 
    577   // These are permitted.
    578   __try {
    579     __try {
    580     } __finally {
    581       goto after_outer_except; // expected-warning {{jump out of __finally block has undefined behavior}}
    582     }
    583   } __except(0) {
    584   }
    585 after_outer_except:
    586   ;
    587 
    588   __try {
    589     __try{
    590     } __except(0) {
    591       goto after_outer_finally;
    592     }
    593   } __finally {
    594   }
    595 after_outer_finally:
    596   ;
    597 }
    598 
    599 // This section is academic, as MSVC doesn't support indirect gotos.
    600 
    601 void indirect_jumps(void **ip) {
    602   static void *ips[] = { &&l };
    603 
    604   __try { // expected-note {{jump exits __try block}}
    605     // FIXME: Should this be allowed? Jumping out of the guarded section of a
    606     // __try/__except doesn't require unwinding.
    607     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
    608   } __except(0) {
    609   }
    610 
    611   __try {
    612   } __except(0) { // expected-note {{jump exits __except block}}
    613     // FIXME: What about here?
    614     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
    615   }
    616 
    617   __try { // expected-note {{jump exits __try block}}
    618     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
    619   } __finally {
    620   }
    621 
    622   __try {
    623   } __finally { // expected-note {{jump exits __finally block}}
    624     goto *ip; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
    625   }
    626 l: // expected-note 4 {{possible target of indirect goto statement}}
    627   ;
    628 }
    629 
    630 } // namespace seh
    631