2012-02-09 08:47:04 +08:00
// RUN: %clang_cc1 -std=c++0x -Wno-unused-value -fsyntax-only -verify -fblocks %s
2012-01-07 09:08:17 +08:00
2012-01-07 12:59:52 +08:00
namespace std { class type_info ; } ;
2012-01-07 09:08:17 +08:00
namespace ExplicitCapture {
class C {
2012-01-07 12:59:52 +08:00
int Member ;
static void Overload ( int ) ;
void Overload ( ) ;
virtual C & Overload ( float ) ;
2012-01-07 09:08:17 +08:00
2012-01-07 12:59:52 +08:00
void ImplicitThisCapture ( ) {
2012-02-09 16:26:42 +08:00
[ ] ( ) { ( void ) Member ; } ; // expected-error {{'this' cannot be implicitly captured in this context}}
[ & ] ( ) { ( void ) Member ; } ;
[ this ] ( ) { ( void ) Member ; } ;
[ this ] { [ this ] { } ; } ;
[ ] { [ this ] { } ; } ; // expected-error {{'this' cannot be implicitly captured in this context}}
2012-06-05 04:07:46 +08:00
[ ] { Overload ( 3 ) ; } ;
[ ] { Overload ( ) ; } ; // expected-error {{'this' cannot be implicitly captured in this context}}
2012-02-09 16:26:42 +08:00
[ ] { ( void ) typeid ( Overload ( ) ) ; } ;
2012-06-05 04:07:46 +08:00
[ ] { ( void ) typeid ( Overload ( .5f ) ) ; } ; // expected-error {{'this' cannot be implicitly captured in this context}}
2012-01-07 12:59:52 +08:00
}
2012-01-07 09:08:17 +08:00
} ;
void f ( ) {
2012-06-05 04:07:46 +08:00
[ this ] ( ) { } ; // expected-error {{'this' cannot be captured in this context}}
2012-01-07 09:08:17 +08:00
}
}
2012-01-26 11:00:14 +08:00
namespace ReturnDeduction {
void test ( ) {
2012-06-05 04:07:46 +08:00
[ ] ( ) { return 1 ; } ;
[ ] ( ) { return 1 ; } ;
[ ] ( ) { return ( { return 1 ; 1 ; } ) ; } ;
[ ] ( ) { return ( { return ' c ' ; 1 ; } ) ; } ; // expected-error {{must match previous return type}}
[ ] ( ) - > int { return ' c ' ; return 1 ; } ;
2012-02-09 16:26:42 +08:00
[ ] ( ) { return ' c ' ; return 1 ; } ; // expected-error {{must match previous return type}}
2012-06-05 04:07:46 +08:00
[ ] ( ) { return ; return ( void ) 0 ; } ;
[ ] ( ) { return 1 ; return 1 ; } ;
2012-01-26 11:00:14 +08:00
}
}
2012-02-04 06:47:37 +08:00
namespace ImplicitCapture {
void test ( ) {
2012-02-04 07:06:43 +08:00
int a = 0 ; // expected-note 5 {{declared}}
2012-06-05 04:07:46 +08:00
[ ] ( ) { return a ; } ; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}}
[ & ] ( ) { return a ; } ;
[ = ] ( ) { return a ; } ;
[ = ] ( ) { int * b = & a ; } ; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}}
2012-02-09 16:26:42 +08:00
[ = ] ( ) { return [ & ] ( ) { return a ; } ; } ;
2012-06-05 04:07:46 +08:00
[ ] ( ) { return [ & ] ( ) { return a ; } ; } ; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
[ ] ( ) { return ^ { return a ; } ; } ; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
[ ] ( ) { return [ & a ] { return a ; } ; } ; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}}
[ = ] ( ) { return [ & a ] { return a ; } ; } ; //
2012-02-04 06:47:37 +08:00
const int b = 2 ;
2012-06-05 04:07:46 +08:00
[ ] ( ) { return b ; } ;
2012-02-04 06:47:37 +08:00
union { // expected-note {{declared}}
int c ;
float d ;
} ;
d = 3 ;
2012-06-05 04:07:46 +08:00
[ = ] ( ) { return c ; } ; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}}
2012-02-04 06:47:37 +08:00
2012-02-04 07:06:43 +08:00
__block int e ; // expected-note 3 {{declared}}
2012-06-05 04:07:46 +08:00
[ & ] ( ) { return e ; } ; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}}
[ & e ] ( ) { return e ; } ; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}}
2012-02-04 06:47:37 +08:00
int f [ 10 ] ; // expected-note {{declared}}
2012-06-05 04:07:46 +08:00
[ & ] ( ) { return f [ 2 ] ; } ;
2012-02-13 02:42:33 +08:00
( void ) ^ { return [ ] ( ) { return f [ 2 ] ; } ; } ; / / expected - error { { variable ' f ' cannot be implicitly captured in a lambda with no capture - default specified } } \
// expected-note{{lambda expression begins here}}
2012-02-04 06:47:37 +08:00
struct G { G ( ) ; G ( G & ) ; int a ; } ; // expected-note 6 {{not viable}}
G g ;
2012-06-05 04:07:46 +08:00
[ = ] ( ) { const G * gg = & g ; return gg - > a ; } ;
2012-10-25 04:28:18 +08:00
[ = ] ( ) { return [ = ] { const G * gg = & g ; return gg - > a ; } ( ) ; } ; // expected-error {{no matching constructor for initialization of 'G'}}
( void ) ^ { return [ = ] { const G * gg = & g ; return gg - > a ; } ( ) ; } ; // expected-error 2 {{no matching constructor for initialization of 'const G'}}
2012-02-07 05:50:18 +08:00
const int h = a ; // expected-note {{declared}}
2012-06-05 04:07:46 +08:00
[ ] ( ) { return h ; } ; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
2012-03-02 12:14:40 +08:00
2012-10-20 09:38:33 +08:00
// References can appear in constant expressions if they are initialized by
// reference constant expressions.
int i ;
int & ref_i = i ; // expected-note {{declared}}
2012-03-02 12:14:40 +08:00
[ ] { return ref_i ; } ; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}}
2012-10-20 09:38:33 +08:00
static int j ;
int & ref_j = j ;
[ ] { return ref_j ; } ; // ok
2012-02-04 06:47:37 +08:00
}
}
2012-02-22 04:05:31 +08:00
namespace PR12031 {
struct X {
template < typename T >
X ( const T & ) ;
~ X ( ) ;
} ;
void f ( int i , X x ) ;
void g ( ) {
const int v = 10 ;
f ( v , [ ] ( ) { } ) ;
}
}
2012-02-25 06:12:32 +08:00
namespace NullPtr {
int & f ( int * p ) ;
char & f ( . . . ) ;
void g ( ) {
int n = 0 ;
[ = ] {
char & k = f ( n ) ; // not a null pointer constant
} ( ) ;
const int m = 0 ;
[ = ] {
2012-08-09 01:33:31 +08:00
int & k = f ( m ) ; // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
2012-02-25 06:12:32 +08:00
} ( ) ;
[ = ] ( ) - > bool {
2012-08-09 01:33:31 +08:00
int & k = f ( m ) ; // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
2012-02-25 07:21:24 +08:00
return & m = = 0 ;
2012-02-25 06:12:32 +08:00
} ( ) ;
[ m ] {
2012-08-09 01:33:31 +08:00
int & k = f ( m ) ; // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
2012-02-25 06:12:32 +08:00
} ( ) ;
}
}
2012-03-13 04:57:19 +08:00
void PR12248 ( )
{
unsigned int result = 0 ;
auto l = [ & ] ( ) { + + result ; } ;
}
2012-03-13 08:37:01 +08:00
namespace ModifyingCapture {
void test ( ) {
int n = 0 ;
[ = ] {
2012-03-13 09:10:51 +08:00
n = 1 ; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}}
2012-03-13 08:37:01 +08:00
} ;
}
}
2012-07-25 11:56:55 +08:00
namespace VariadicPackExpansion {
template < typename T , typename U > using Fst = T ;
template < typename . . . Ts > bool g ( Fst < bool , Ts > . . . bools ) ;
template < typename . . . Ts > bool f ( Ts & & . . . ts ) {
return g < Ts . . . > ( [ & ts ] {
if ( ! ts )
return false ;
- - ts ;
return true ;
} ( ) . . . ) ;
}
void h ( ) {
int a = 5 , b = 2 , c = 3 ;
while ( f ( a , b , c ) ) {
}
}
struct sink {
template < typename . . . Ts > sink ( Ts & & . . . ) { }
} ;
template < typename . . . Ts > void local_class ( ) {
sink {
[ ] ( Ts t ) {
struct S : Ts {
void f ( Ts t ) {
Ts & that = * this ;
that = t ;
}
Ts g ( ) { return * this ; } ;
} ;
S s ;
s . f ( t ) ;
return s ;
} ( Ts ( ) ) . g ( ) . . .
} ;
} ;
struct X { } ; struct Y { } ;
template void local_class < X , Y > ( ) ;
template < typename . . . Ts > void nested ( Ts . . . ts ) {
f (
// Each expansion of this lambda implicitly captures all of 'ts', because
// the inner lambda also expands 'ts'.
[ & ] {
return ts + [ & ] { return f ( ts . . . ) ; } ( ) ;
} ( ) . . .
) ;
}
template void nested ( int , int , int ) ;
template < typename . . . Ts > void nested2 ( Ts . . . ts ) { // expected-note 2{{here}}
// Capture all 'ts', use only one.
f ( [ & ts . . . ] { return ts ; } ( ) . . . ) ;
// Capture each 'ts', use it.
f ( [ & ts ] { return ts ; } ( ) . . . ) ;
// Capture all 'ts', use all of them.
f ( [ & ts . . . ] { return ( int ) f ( ts . . . ) ; } ( ) ) ;
// Capture each 'ts', use all of them. Ill-formed. In more detail:
//
// We instantiate two lambdas here; the first captures ts$0, the second
// captures ts$1. Both of them reference both ts parameters, so both are
// ill-formed because ts can't be implicitly captured.
//
// FIXME: This diagnostic does not explain what's happening. We should
// specify which 'ts' we're referring to in its diagnostic name. We should
// also say which slice of the pack expansion is being performed in the
// instantiation backtrace.
f ( [ & ts ] { return ( int ) f ( ts . . . ) ; } ( ) . . . ) ; / / \
/ / expected - error 2 { { ' ts ' cannot be implicitly captured } } \
// expected-note 2{{lambda expression begins here}}
}
template void nested2 ( int ) ; // ok
template void nested2 ( int , int ) ; // expected-note {{in instantiation of}}
}
2012-09-19 05:11:30 +08:00
namespace PR13860 {
void foo ( ) {
auto x = PR13860UndeclaredIdentifier ( ) ; // expected-error {{use of undeclared identifier 'PR13860UndeclaredIdentifier'}}
auto y = [ x ] ( ) { } ;
static_assert ( sizeof ( y ) , " " ) ;
}
}
2012-09-20 09:40:23 +08:00
namespace PR13854 {
auto l = [ ] ( void ) { } ;
}
2012-12-06 23:42:21 +08:00
namespace PR14518 {
auto f = [ ] ( void ) { return __func__ ; } ; // no-warning
}