648 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify -fblocks -fcxx-exceptions -fms-extensions %s -Wno-unreachable-code2// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify -fblocks -fcxx-exceptions -fms-extensions -std=gnu++11 %s -Wno-unreachable-code3 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 static138// 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// PR7789151namespace 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/PR10462188namespace PR10462 {189 enum MyEnum {190 something_valid,191 something_invalid192 };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// pr13812220namespace 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// PR14225278namespace 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 >= 201103L301namespace 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#endif310 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 }; // ok319 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 >= 201103L330namespace 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 a363 };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#endif378 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 errors427 // 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 __finally483// 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 a607 // __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 seh632 633void continue_scope_check() {634 // These are OK.635 for (; ({break; true;});) {}636 for (; ({continue; true;});) {}637 for (; int n = ({break; 0;});) {}638 for (; int n = 0; ({break;})) {}639 for (; int n = 0; ({continue;})) {}640 641 // This would jump past the initialization of 'n' to the increment (where 'n'642 // is in scope).643 for (; int n = ({continue; 0;});) {} // expected-error {{cannot jump from this continue statement to the loop increment; jump bypasses initialization of loop condition variable}}644 645 // An intervening loop makes it OK again.646 for (; int n = ({while (true) continue; 0;});) {}647}648