2015-04-29 06:58:25 +08:00
// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify -fblocks -fcxx-exceptions -fms-extensions %s -Wno-unreachable-code
// RUN: %clang_cc1 -triple x86_64-windows -fsyntax-only -verify -fblocks -fcxx-exceptions -fms-extensions -std=gnu++11 %s -Wno-unreachable-code
2010-05-12 08:58:13 +08:00
2014-05-09 16:40:10 +08:00
namespace testInvalid {
Invalid inv ; // expected-error {{unknown type name}}
// Make sure this doesn't assert.
void fn ( )
{
int c = 0 ;
if ( inv )
Here : ;
goto Here ;
}
}
2010-05-12 08:58:13 +08:00
namespace test0 {
struct D { ~ D ( ) ; } ;
int f ( bool b ) {
if ( b ) {
D d ;
goto end ;
}
end :
return 1 ;
}
}
namespace test1 {
struct C { C ( ) ; } ;
int f ( bool b ) {
if ( b )
2014-09-06 08:24:58 +08:00
goto foo ; // expected-error {{cannot jump}}
2010-05-12 08:58:13 +08:00
C c ; // expected-note {{jump bypasses variable initialization}}
foo :
return 1 ;
}
}
namespace test2 {
struct C { C ( ) ; } ;
int f ( void * * ip ) {
static void * ips [ ] = { & & lbl1 , & & lbl2 } ;
C c ;
goto * ip ;
lbl1 :
return 0 ;
lbl2 :
return 1 ;
}
}
namespace test3 {
struct C { C ( ) ; } ;
int f ( void * * ip ) {
static void * ips [ ] = { & & lbl1 , & & lbl2 } ;
goto * ip ;
lbl1 : {
C c ;
return 0 ;
}
lbl2 :
return 1 ;
}
}
namespace test4 {
struct C { C ( ) ; } ;
struct D { ~ D ( ) ; } ;
int f ( void * * ip ) {
static void * ips [ ] = { & & lbl1 , & & lbl2 } ;
C c0 ;
2014-09-06 08:24:58 +08:00
goto * ip ; // expected-error {{cannot jump}}
2010-05-12 08:58:13 +08:00
C c1 ; // expected-note {{jump bypasses variable initialization}}
lbl1 : // expected-note {{possible target of indirect goto}}
return 0 ;
lbl2 :
return 1 ;
}
}
namespace test5 {
struct C { C ( ) ; } ;
struct D { ~ D ( ) ; } ;
int f ( void * * ip ) {
static void * ips [ ] = { & & lbl1 , & & lbl2 } ;
C c0 ;
goto * ip ;
lbl1 : // expected-note {{possible target of indirect goto}}
return 0 ;
lbl2 :
if ( ip [ 1 ] ) {
D d ; // expected-note {{jump exits scope of variable with non-trivial destructor}}
ip + = 2 ;
2014-09-06 08:24:58 +08:00
goto * ip ; // expected-error {{cannot jump}}
2010-05-12 08:58:13 +08:00
}
return 1 ;
}
}
namespace test6 {
struct C { C ( ) ; } ;
unsigned f ( unsigned s0 , unsigned s1 , void * * ip ) {
static void * ips [ ] = { & & lbl1 , & & lbl2 , & & lbl3 , & & lbl4 } ;
C c0 ;
goto * ip ;
lbl1 :
s0 + + ;
goto * + + ip ;
lbl2 :
s0 - = s1 ;
goto * + + ip ;
lbl3 : {
unsigned tmp = s0 ;
s0 = s1 ;
s1 = tmp ;
goto * + + ip ;
}
lbl4 :
return s0 ;
}
}
2010-08-01 09:24:59 +08:00
// C++0x says it's okay to skip non-trivial initializers on static
// locals, and we implement that in '03 as well.
namespace test7 {
struct C { C ( ) ; } ;
void test ( ) {
goto foo ;
static C c ;
foo :
return ;
}
}
2010-08-03 07:33:14 +08:00
// PR7789
namespace test8 {
void test1 ( int c ) {
switch ( c ) {
case 0 :
int x = 56 ; // expected-note {{jump bypasses variable initialization}}
2014-09-06 08:24:58 +08:00
case 1 : // expected-error {{cannot jump}}
2010-08-03 07:33:14 +08:00
x = 10 ;
}
}
void test2 ( ) {
2014-09-06 08:24:58 +08:00
goto l2 ; // expected-error {{cannot jump}}
2010-08-03 07:33:14 +08:00
l1 : int x = 5 ; // expected-note {{jump bypasses variable initialization}}
l2 : x + + ;
}
}
2011-04-23 03:01:39 +08:00
namespace test9 {
struct S { int i ; } ;
void test1 ( ) {
goto foo ;
S s ;
foo :
return ;
}
unsigned test2 ( unsigned x , unsigned y ) {
switch ( x ) {
case 2 :
S s ;
if ( y > 42 ) return x + y ;
default :
return x - 2 ;
}
}
}
2011-07-29 09:25:44 +08:00
// http://llvm.org/PR10462
namespace PR10462 {
2012-09-11 22:17:47 +08:00
enum MyEnum {
something_valid ,
something_invalid
} ;
bool recurse ( ) {
MyEnum K ;
2018-07-27 02:41:30 +08:00
switch ( K ) { // do not warn that 'something_invalid' is not listed;
// 'what_am_i_thinking' might have been intended to be that case.
2011-07-29 09:25:44 +08:00
case something_valid :
case what_am_i_thinking : // expected-error {{use of undeclared identifier}}
int * X = 0 ;
if ( recurse ( ) ) {
}
break ;
2012-09-11 22:17:47 +08:00
}
2011-07-29 09:25:44 +08:00
}
}
2011-09-17 07:15:32 +08:00
namespace test10 {
2012-09-11 22:17:47 +08:00
int test ( ) {
static void * ps [ ] = { & & a0 } ;
2014-09-06 08:24:58 +08:00
goto * & & a0 ; // expected-error {{cannot jump}}
2012-09-11 22:17:47 +08:00
int a = 3 ; // expected-note {{jump bypasses variable initialization}}
a0 :
return 0 ;
}
2011-09-17 07:15:32 +08:00
}
2012-10-28 10:44:03 +08:00
// pr13812
namespace test11 {
struct C {
C ( int x ) ;
~ C ( ) ;
} ;
void f ( void * * ip ) {
static void * ips [ ] = { & & l0 } ;
l0 : // expected-note {{possible target of indirect goto}}
C c0 = 42 ; // expected-note {{jump exits scope of variable with non-trivial destructor}}
2014-09-06 08:24:58 +08:00
goto * ip ; // expected-error {{cannot jump}}
2012-10-28 10:44:03 +08:00
}
}
namespace test12 {
struct C {
C ( int x ) ;
~ C ( ) ;
} ;
void f ( void * * ip ) {
static void * ips [ ] = { & & l0 } ;
const C c0 = 17 ;
l0 : // expected-note {{possible target of indirect goto}}
2013-12-12 09:27:02 +08:00
const C & c1 = 42 ; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
2012-10-28 10:44:03 +08:00
const C & c2 = c0 ;
2014-09-06 08:24:58 +08:00
goto * ip ; // expected-error {{cannot jump}}
2012-10-28 10:44:03 +08:00
}
}
namespace test13 {
struct C {
C ( int x ) ;
~ C ( ) ;
int i ;
} ;
void f ( void * * ip ) {
static void * ips [ ] = { & & l0 } ;
l0 : // expected-note {{possible target of indirect goto}}
2013-12-12 09:27:02 +08:00
const int & c1 = C ( 1 ) . i ; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
2014-09-06 08:24:58 +08:00
goto * ip ; // expected-error {{cannot jump}}
2012-10-28 10:44:03 +08:00
}
}
namespace test14 {
struct C {
C ( int x ) ;
~ C ( ) ;
operator int & ( ) const ;
} ;
void f ( void * * ip ) {
static void * ips [ ] = { & & l0 } ;
l0 :
// no warning since the C temporary is destructed before the goto.
const int & c1 = C ( 1 ) ;
goto * ip ;
}
}
2012-11-01 07:55:28 +08:00
// PR14225
namespace test15 {
void f1 ( ) try {
2014-09-06 08:24:58 +08:00
goto x ; // expected-error {{cannot jump}}
2012-11-01 07:55:28 +08:00
} catch ( . . . ) { // expected-note {{jump bypasses initialization of catch block}}
x : ;
}
void f2 ( ) try { // expected-note {{jump bypasses initialization of try block}}
x : ;
} catch ( . . . ) {
2014-09-06 08:24:58 +08:00
goto x ; // expected-error {{cannot jump}}
2012-11-01 07:55:28 +08:00
}
}
2013-02-16 02:34:13 +08:00
namespace test16 {
2013-06-03 09:05:37 +08:00
struct S { int n ; } ;
int f ( ) {
2014-09-06 08:24:58 +08:00
goto x ; // expected-error {{cannot jump}}
2013-06-03 09:05:37 +08:00
const S & s = S ( ) ; // expected-note {{jump bypasses variable initialization}}
x : return s . n ;
}
}
# if __cplusplus >= 201103L
namespace test17 {
struct S { int get ( ) ; private : int n ; } ;
int f ( ) {
2014-09-06 08:24:58 +08:00
goto x ; // expected-error {{cannot jump}}
2013-06-03 09:05:37 +08:00
S s = { } ; // expected-note {{jump bypasses variable initialization}}
x : return s . get ( ) ;
}
}
# endif
2013-12-12 09:27:02 +08:00
namespace test18 {
struct A { ~ A ( ) ; } ;
struct B { const int & r ; const A & a ; } ;
int f ( ) {
void * p = & & x ;
const A a = A ( ) ;
x :
B b = { 0 , a } ; // ok
goto * p ;
}
int g ( ) {
void * p = & & x ;
x : // expected-note {{possible target of indirect goto}}
B b = { 0 , A ( ) } ; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
2014-09-06 08:24:58 +08:00
goto * p ; // expected-error {{cannot jump}}
2013-12-12 09:27:02 +08:00
}
}
# if __cplusplus >= 201103L
namespace std {
typedef decltype ( sizeof ( int ) ) size_t ;
template < typename T > struct initializer_list {
const T * begin ;
size_t size ;
initializer_list ( const T * , size_t ) ;
} ;
}
namespace test19 {
struct A { ~ A ( ) ; } ;
int f ( ) {
void * p = & & x ;
A a ;
x : // expected-note {{possible target of indirect goto}}
std : : initializer_list < A > il = { a } ; // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
2014-09-06 08:24:58 +08:00
goto * p ; // expected-error {{cannot jump}}
2013-12-12 09:27:02 +08:00
}
}
namespace test20 {
struct A { ~ A ( ) ; } ;
struct B {
const A & a ;
} ;
int f ( ) {
void * p = & & x ;
A a ;
x :
std : : initializer_list < B > il = {
a ,
a
} ;
goto * p ;
}
int g ( ) {
void * p = & & x ;
A a ;
x : // expected-note {{possible target of indirect goto}}
std : : initializer_list < B > il = {
a ,
{ A ( ) } // expected-note {{jump exits scope of lifetime-extended temporary with non-trivial destructor}}
} ;
2014-09-06 08:24:58 +08:00
goto * p ; // expected-error {{cannot jump}}
2013-12-12 09:27:02 +08:00
}
}
# endif
namespace test21 {
template < typename T > void f ( ) {
2014-09-06 08:24:58 +08:00
goto x ; // expected-error {{cannot jump}}
2013-12-12 09:27:02 +08:00
T t ; // expected-note {{bypasses}}
x : return ;
}
template void f < int > ( ) ;
struct X { ~ X ( ) ; } ;
template void f < X > ( ) ; // expected-note {{instantiation of}}
}
namespace PR18217 {
typedef int * X ;
template < typename T >
class MyCl {
T mem ;
} ;
class Source {
MyCl < X > m ;
public :
int getKind ( ) const ;
} ;
bool b ;
template < typename TT >
static void foo ( const Source & SF , MyCl < TT * > Source : : * m ) {
switch ( SF . getKind ( ) ) {
case 1 : return ;
case 2 : break ;
case 3 :
case 4 : return ;
} ;
if ( b ) {
auto & y = const_cast < MyCl < TT * > & > ( SF . * m ) ; // expected-warning 0-1{{extension}}
}
}
int Source : : getKind ( ) const {
foo ( * this , & Source : : m ) ;
return 0 ;
}
}
2014-05-09 16:40:10 +08:00
namespace test_recovery {
// Test that jump scope checking recovers when there are unspecified errors
// in the function declaration or body.
void test ( nexist , int c ) { // expected-error {{}}
nexist_fn ( ) ; // expected-error {{}}
goto nexist_label ; // expected-error {{use of undeclared label}}
2014-09-06 08:24:58 +08:00
goto a0 ; // expected-error {{cannot jump}}
2014-05-09 16:40:10 +08:00
int a = 0 ; // expected-note {{jump bypasses variable initialization}}
a0 : ;
switch ( c ) {
case $ : // expected-error {{}}
case 0 :
int x = 56 ; // expected-note {{jump bypasses variable initialization}}
2014-09-06 08:24:58 +08:00
case 1 : // expected-error {{cannot jump}}
2014-05-09 16:40:10 +08:00
x = 10 ;
}
}
2013-02-16 02:34:13 +08:00
}
2015-02-04 01:06:08 +08:00
namespace seh {
// Jumping into SEH try blocks is not permitted.
void jump_into_except ( ) {
goto into_try_except_try ; // expected-error {{cannot jump from this goto statement to its label}}
__try { // expected-note {{jump bypasses initialization of __try block}}
into_try_except_try :
;
} __except ( 0 ) {
}
goto into_try_except_except ; // expected-error {{cannot jump from this goto statement to its label}}
__try {
} __except ( 0 ) { // expected-note {{jump bypasses initialization of __except block}}
into_try_except_except :
;
}
}
void jump_into_finally ( ) {
goto into_try_except_try ; // expected-error {{cannot jump from this goto statement to its label}}
__try { // expected-note {{jump bypasses initialization of __try block}}
into_try_except_try :
;
} __finally {
}
goto into_try_except_finally ; // expected-error {{cannot jump from this goto statement to its label}}
__try {
} __finally { // expected-note {{jump bypasses initialization of __finally block}}
into_try_except_finally :
;
}
}
// Jumping out of SEH try blocks ok in general. (Jumping out of a __finally
// has undefined behavior.)
void jump_out_of_except ( ) {
__try {
goto out_of_except_try ;
} __except ( 0 ) {
}
out_of_except_try :
;
__try {
} __except ( 0 ) {
goto out_of_except_except ;
}
out_of_except_except :
;
}
void jump_out_of_finally ( ) {
__try {
goto out_of_finally_try ;
} __finally {
}
out_of_finally_try :
;
__try {
} __finally {
2015-03-09 12:27:56 +08:00
goto out_of_finally_finally ; // expected-warning {{jump out of __finally block has undefined behavior}}
}
__try {
} __finally {
goto * & & out_of_finally_finally ; // expected-warning {{jump out of __finally block has undefined behavior}}
2015-02-04 01:06:08 +08:00
}
out_of_finally_finally :
;
}
// Jumping between protected scope and handler is not permitted.
void jump_try_except ( ) {
__try {
goto from_try_to_except ; // expected-error {{cannot jump from this goto statement to its label}}
} __except ( 0 ) { // expected-note {{jump bypasses initialization of __except block}}
from_try_to_except :
;
}
__try { // expected-note {{jump bypasses initialization of __try block}}
from_except_to_try :
;
} __except ( 0 ) {
goto from_except_to_try ; // expected-error {{cannot jump from this goto statement to its label}}
}
}
void jump_try_finally ( ) {
__try {
goto from_try_to_finally ; // expected-error {{cannot jump from this goto statement to its label}}
} __finally { // expected-note {{jump bypasses initialization of __finally block}}
from_try_to_finally :
;
}
__try { // expected-note {{jump bypasses initialization of __try block}}
from_finally_to_try :
;
} __finally {
2015-03-09 12:27:56 +08:00
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}}
2015-02-04 01:06:08 +08:00
}
}
void nested ( ) {
// These are not permitted.
__try {
__try {
} __finally {
goto outer_except ; // expected-error {{cannot jump from this goto statement to its label}}
}
} __except ( 0 ) { // expected-note {{jump bypasses initialization of __except bloc}}
outer_except :
;
}
__try {
__try {
} __except ( 0 ) {
goto outer_finally ; // expected-error {{cannot jump from this goto statement to its label}}
}
} __finally { // expected-note {{jump bypasses initialization of __finally bloc}}
outer_finally :
;
}
// These are permitted.
__try {
__try {
} __finally {
2015-03-09 12:27:56 +08:00
goto after_outer_except ; // expected-warning {{jump out of __finally block has undefined behavior}}
2015-02-04 01:06:08 +08:00
}
} __except ( 0 ) {
}
after_outer_except :
;
__try {
__try {
} __except ( 0 ) {
goto after_outer_finally ;
}
} __finally {
}
after_outer_finally :
;
}
// This section is academic, as MSVC doesn't support indirect gotos.
void indirect_jumps ( void * * ip ) {
static void * ips [ ] = { & & l } ;
__try { // expected-note {{jump exits __try block}}
// FIXME: Should this be allowed? Jumping out of the guarded section of a
// __try/__except doesn't require unwinding.
goto * ip ; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
} __except ( 0 ) {
}
__try {
} __except ( 0 ) { // expected-note {{jump exits __except block}}
// FIXME: What about here?
goto * ip ; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
}
__try { // expected-note {{jump exits __try block}}
goto * ip ; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
} __finally {
}
__try {
} __finally { // expected-note {{jump exits __finally block}}
goto * ip ; // expected-error {{cannot jump from this indirect goto statement to one of its possible targets}}
}
l : // expected-note 4 {{possible target of indirect goto statement}}
;
}
} // namespace seh