2012-01-18 06:49:42 +08:00
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
2012-01-24 06:09:39 +08:00
// This must obviously come before the definition of std::initializer_list.
void missing_initializerlist ( ) {
auto l = { 1 , 2 , 3 , 4 } ; // expected-error {{std::initializer_list was not found}}
}
2012-01-18 06:49:42 +08:00
namespace std {
typedef decltype ( sizeof ( int ) ) size_t ;
// libc++'s implementation
template < class _E >
class initializer_list
{
const _E * __begin_ ;
size_t __size_ ;
initializer_list ( const _E * __b , size_t __s )
: __begin_ ( __b ) ,
__size_ ( __s )
{ }
public :
typedef _E value_type ;
typedef const _E & reference ;
typedef const _E & const_reference ;
typedef size_t size_type ;
typedef const _E * iterator ;
typedef const _E * const_iterator ;
initializer_list ( ) : __begin_ ( nullptr ) , __size_ ( 0 ) { }
size_t size ( ) const { return __size_ ; }
const _E * begin ( ) const { return __begin_ ; }
const _E * end ( ) const { return __begin_ + __size_ ; }
} ;
}
2012-01-18 06:49:58 +08:00
template < typename T , typename U >
struct same_type { static const bool value = false ; } ;
template < typename T >
struct same_type < T , T > { static const bool value = true ; } ;
2012-01-18 06:49:42 +08:00
struct one { char c [ 1 ] ; } ;
struct two { char c [ 2 ] ; } ;
struct A {
int a , b ;
} ;
struct B {
B ( ) ;
B ( int , int ) ;
} ;
void simple_list ( ) {
std : : initializer_list < int > il = { 1 , 2 , 3 } ;
std : : initializer_list < double > dl = { 1.0 , 2.0 , 3 } ;
std : : initializer_list < A > al = { { 1 , 2 } , { 2 , 3 } , { 3 , 4 } } ;
std : : initializer_list < B > bl = { { 1 , 2 } , { 2 , 3 } , { } } ;
}
void function_call ( ) {
void f ( std : : initializer_list < int > ) ;
f ( { 1 , 2 , 3 } ) ;
void g ( std : : initializer_list < B > ) ;
g ( { { 1 , 2 } , { 2 , 3 } , { } } ) ;
}
2012-01-18 06:49:48 +08:00
struct C {
C ( int ) ;
} ;
struct D {
D ( ) ;
operator int ( ) ;
operator C ( ) ;
} ;
void overloaded_call ( ) {
one overloaded ( std : : initializer_list < int > ) ;
two overloaded ( std : : initializer_list < B > ) ;
static_assert ( sizeof ( overloaded ( { 1 , 2 , 3 } ) ) = = sizeof ( one ) , " bad overload " ) ;
static_assert ( sizeof ( overloaded ( { { 1 , 2 } , { 2 , 3 } , { } } ) ) = = sizeof ( two ) , " bad overload " ) ;
void ambiguous ( std : : initializer_list < A > ) ; // expected-note {{candidate}}
void ambiguous ( std : : initializer_list < B > ) ; // expected-note {{candidate}}
ambiguous ( { { 1 , 2 } , { 2 , 3 } , { 3 , 4 } } ) ; // expected-error {{ambiguous}}
one ov2 ( std : : initializer_list < int > ) ; // expected-note {{candidate}}
two ov2 ( std : : initializer_list < C > ) ; // expected-note {{candidate}}
// Worst sequence to int is identity, whereas to C it's user-defined.
static_assert ( sizeof ( ov2 ( { 1 , 2 , 3 } ) ) = = sizeof ( one ) , " bad overload " ) ;
// But here, user-defined is worst in both cases.
ov2 ( { 1 , 2 , D ( ) } ) ; // expected-error {{ambiguous}}
}
2012-01-18 06:49:58 +08:00
template < typename T >
T deduce ( std : : initializer_list < T > ) ; // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
template < typename T >
T deduce_ref ( const std : : initializer_list < T > & ) ; // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
2017-01-04 10:59:16 +08:00
template < typename T , typename U > struct pair { pair ( . . . ) ; } ;
2017-01-05 03:48:07 +08:00
template < typename T > void deduce_pairs ( std : : initializer_list < pair < T , typename T : : type > > ) ;
2017-01-06 07:02:44 +08:00
// expected-note@-1 {{deduced type 'pair<[...], typename WithIntType::type>' of element of 1st parameter does not match adjusted type 'pair<[...], float>' of element of argument [with T = WithIntType]}}
2017-01-04 10:59:16 +08:00
struct WithIntType { typedef int type ; } ;
template < typename . . . T > void deduce_after_init_list_in_pack ( void ( * ) ( T . . . ) , T . . . ) ; // expected-note {{<int, int> vs. <(no value), double>}}
2012-01-18 06:49:58 +08:00
void argument_deduction ( ) {
static_assert ( same_type < decltype ( deduce ( { 1 , 2 , 3 } ) ) , int > : : value , " bad deduction " ) ;
static_assert ( same_type < decltype ( deduce ( { 1.0 , 2.0 , 3.0 } ) ) , double > : : value , " bad deduction " ) ;
deduce ( { 1 , 2.0 } ) ; // expected-error {{no matching function}}
static_assert ( same_type < decltype ( deduce_ref ( { 1 , 2 , 3 } ) ) , int > : : value , " bad deduction " ) ;
static_assert ( same_type < decltype ( deduce_ref ( { 1.0 , 2.0 , 3.0 } ) ) , double > : : value , " bad deduction " ) ;
deduce_ref ( { 1 , 2.0 } ) ; // expected-error {{no matching function}}
2017-01-04 10:59:16 +08:00
pair < WithIntType , int > pi ;
pair < WithIntType , float > pf ;
deduce_pairs ( { pi , pi , pi } ) ; // ok
2017-01-06 07:02:44 +08:00
deduce_pairs ( { pi , pf , pi } ) ; // expected-error {{no matching function}}
2017-01-04 10:59:16 +08:00
deduce_after_init_list_in_pack ( ( void ( * ) ( int , int ) ) 0 , { } , 0 ) ;
deduce_after_init_list_in_pack ( ( void ( * ) ( int , int ) ) 0 , { } , 0.0 ) ; // expected-error {{no matching function}}
2012-01-18 06:49:58 +08:00
}
2012-01-18 06:50:08 +08:00
void auto_deduction ( ) {
auto l = { 1 , 2 , 3 , 4 } ;
2015-11-11 09:36:17 +08:00
auto l2 { 1 , 2 , 3 , 4 } ; // expected-error {{initializer for variable 'l2' with type 'auto' contains multiple expressions}}
auto l3 { 1 } ;
2012-01-18 06:50:08 +08:00
static_assert ( same_type < decltype ( l ) , std : : initializer_list < int > > : : value , " " ) ;
2015-11-11 09:36:17 +08:00
static_assert ( same_type < decltype ( l3 ) , int > : : value , " " ) ;
2017-08-30 08:44:08 +08:00
auto bl = { 1 , 2.0 } ; // expected-error {{deduced conflicting types ('int' vs 'double') for initializer list element type}}
void f1 ( int ) , f1 ( float ) , f2 ( int ) , f3 ( float ) ;
auto fil = { f1 , f2 } ;
auto ffl = { f1 , f3 } ;
auto fl = { f1 , f2 , f3 } ; // expected-error {{deduced conflicting types ('void (*)(int)' vs 'void (*)(float)') for initializer list element type}}
2012-01-18 06:50:08 +08:00
for ( int i : { 1 , 2 , 3 , 4 } ) { }
2017-08-30 08:44:08 +08:00
for ( int j : { 1.0 , 2.0 , 3.0f , 4.0 } ) { } // expected-error {{deduced conflicting types ('double' vs 'float') for initializer list element type}}
2012-01-18 06:50:08 +08:00
}
2012-02-13 02:41:05 +08:00
void dangle ( ) {
2017-12-12 02:29:54 +08:00
new auto { 1 , 2 , 3 } ; // expected-error {{new expression for type 'auto' contains multiple constructor arguments}}
2012-02-13 02:41:05 +08:00
new std : : initializer_list < int > { 1 , 2 , 3 } ; // expected-warning {{at the end of the full-expression}}
}
2012-02-20 00:31:05 +08:00
struct haslist1 {
2018-07-18 06:24:09 +08:00
std : : initializer_list < int > il // expected-note {{declared here}}
= { 1 , 2 , 3 } ; // ok, unused
2018-07-24 05:21:22 +08:00
std : : initializer_list < int > jl { 1 , 2 , 3 } ; // expected-note {{default member init}}
2012-02-20 00:31:05 +08:00
haslist1 ( ) ;
} ;
2018-07-24 05:21:22 +08:00
haslist1 : : haslist1 ( ) // expected-error {{backing array for 'std::initializer_list' member 'jl' is a temporary object}}
2018-07-18 06:24:09 +08:00
: il { 1 , 2 , 3 } // expected-error {{backing array for 'std::initializer_list' member 'il' is a temporary object}}
2012-02-20 00:31:05 +08:00
{ }
2012-03-16 05:40:51 +08:00
namespace PR12119 {
// Deduction with nested initializer lists.
template < typename T > void f ( std : : initializer_list < T > ) ;
template < typename T > void g ( std : : initializer_list < std : : initializer_list < T > > ) ;
void foo ( ) {
2013-06-13 06:31:48 +08:00
f ( { 0 , { 1 } } ) ; // expected-warning{{braces around scalar initializer}}
2012-03-16 05:40:51 +08:00
g ( { { 0 , 1 } , { 2 , 3 } } ) ;
std : : initializer_list < int > il = { 1 , 2 } ;
g ( { il , { 2 , 3 } } ) ;
}
}
2012-04-04 13:10:53 +08:00
namespace Decay {
template < typename T >
void f ( std : : initializer_list < T > ) {
T x = 1 ; // expected-error{{cannot initialize a variable of type 'const char *' with an rvalue of type 'int'}}
}
void g ( ) {
f ( { " A " , " BB " , " CCC " } ) ; // expected-note{{in instantiation of function template specialization 'Decay::f<const char *>' requested here}}
auto x = { " A " , " BB " , " CCC " } ;
std : : initializer_list < const char * > * il = & x ;
for ( auto s : { " A " , " BB " , " CCC " , " DDD " } ) { }
}
}
2012-04-05 07:09:20 +08:00
namespace PR12436 {
struct X {
template < typename T >
X ( std : : initializer_list < int > , T ) ;
} ;
X x ( { } , 17 ) ;
}
2012-08-01 06:15:04 +08:00
namespace rdar11948732 {
template < typename T > struct X { } ;
struct XCtorInit {
XCtorInit ( std : : initializer_list < X < int > > ) ;
} ;
void f ( X < int > & xi ) {
XCtorInit xc = { xi , xi } ;
}
}
2012-11-07 07:56:42 +08:00
namespace PR14272 {
2015-11-11 09:36:17 +08:00
auto x { { 0 , 0 } } ; // expected-error {{cannot deduce type for variable 'x' with type 'auto' from nested initializer list}}
2012-11-07 07:56:42 +08:00
}
2012-12-09 14:48:56 +08:00
namespace initlist_of_array {
void f ( std : : initializer_list < int [ 2 ] > ) { }
void f ( std : : initializer_list < int [ 2 ] [ 2 ] > ) = delete ;
void h ( ) {
f ( { { 1 , 2 } , { 3 , 4 } } ) ;
}
}
2013-01-31 12:03:12 +08:00
namespace init_list_deduction_failure {
void f ( ) ;
void f ( int ) ;
2017-01-05 06:03:59 +08:00
// FIXME: It'd be nice to track that 'T' became a non-deduced context due to
// overload resolution failure for 'f'.
2013-01-31 12:03:12 +08:00
template < typename T > void g ( std : : initializer_list < T > ) ;
2017-01-05 06:03:59 +08:00
// expected-note@-1 {{candidate template ignored: couldn't infer template argument 'T'}}
void h ( ) {
g ( { f } ) ; // expected-error {{no matching function for call to 'g'}}
g ( { f , h } ) ; // ok
}
2013-01-31 12:03:12 +08:00
}
2013-05-24 07:20:04 +08:00
namespace deleted_copy {
struct X {
X ( int i ) { }
X ( const X & x ) = delete ; // expected-note {{here}}
void operator = ( const X & x ) = delete ;
} ;
std : : initializer_list < X > x { 1 } ; // expected-error {{invokes deleted constructor}}
}
2013-09-06 09:22:42 +08:00
namespace RefVersusInitList {
struct S { } ;
void f ( const S & ) = delete ;
void f ( std : : initializer_list < S > ) ;
void g ( S s ) { f ( { S ( ) } ) ; }
}
2013-11-22 07:30:57 +08:00
namespace PR18013 {
int f ( ) ;
std : : initializer_list < long ( * ) ( ) > x = { f } ; // expected-error {{cannot initialize an array element of type 'long (*const)()' with an lvalue of type 'int ()': different return type ('long' vs 'int')}}
}
2014-06-03 16:26:00 +08:00
namespace DR1070 {
struct S {
S ( std : : initializer_list < int > ) ;
} ;
S s [ 3 ] = { { 1 , 2 , 3 } , { 4 , 5 } } ; // ok
S * p = new S [ 3 ] { { 1 , 2 , 3 } , { 4 , 5 } } ; // ok
}
2014-07-17 05:33:43 +08:00
namespace ListInitInstantiate {
struct A {
A ( std : : initializer_list < A > ) ;
2014-07-17 13:12:35 +08:00
A ( std : : initializer_list < int > ) ;
2014-07-17 05:33:43 +08:00
} ;
struct B : A {
B ( int ) ;
} ;
template < typename T > struct X {
X ( ) ;
A a ;
} ;
template < typename T > X < T > : : X ( ) : a { B { 0 } , B { 1 } } { }
X < int > x ;
2014-07-17 13:12:35 +08:00
int f ( const A & ) ;
template < typename T > void g ( ) { int k = f ( { 0 } ) ; }
template void g < int > ( ) ;
2014-07-17 05:33:43 +08:00
}
2015-01-29 06:06:01 +08:00
namespace TemporaryInitListSourceRange_PR22367 {
struct A {
constexpr A ( ) { }
A ( std : : initializer_list < int > ) ; // expected-note {{here}}
} ;
constexpr int f ( A ) { return 0 ; }
constexpr int k = f ( // expected-error {{must be initialized by a constant expression}}
// The point of this test is to check that the caret points to
// 'std::initializer_list', not to '{0}'.
std : : initializer_list // expected-note {{constructor}}
< int >
{ 0 }
) ;
}
2015-06-25 08:25:49 +08:00
namespace ParameterPackNestedInitializerLists_PR23904c3 {
template < typename . . . T >
2017-01-06 07:02:44 +08:00
void f ( std : : initializer_list < std : : initializer_list < T > > . . . tt ) ; // expected-note 2{{conflicting}} expected-note {{incomplete pack}}
2015-06-25 08:25:49 +08:00
2017-01-06 07:02:44 +08:00
void foo ( ) {
f ( { { 0 } } , { { ' \0 ' } } ) ; // ok, T = <int, char>
f ( { { 0 } , { ' \0 ' } } ) ; // expected-error {{no match}}
f ( { { 0 , ' \0 ' } } ) ; // expected-error {{no match}}
f ( { { 0 } } , { { { } } } ) ; // expected-error {{no match}}
f ( { { 0 } } , { { { } , ' \0 ' } } ) ; // ok, T = <int, char>
f ( { { 0 } , { { } } } ) ; // ok, T = <int>
f ( { { 0 , { } } } ) ; // ok, T = <int>
}
2015-06-25 08:25:49 +08:00
}
2015-12-10 07:18:38 +08:00
namespace update_rbrace_loc_crash {
// We used to crash-on-invalid on this example when updating the right brace
// location.
template < typename T , T >
struct A { } ;
template < typename T , typename F , int . . . I >
std : : initializer_list < T > ExplodeImpl ( F p1 , A < int , I . . . > ) {
2019-02-02 06:06:02 +08:00
// expected-error@+1 {{reference to incomplete type 'const update_rbrace_loc_crash::Incomplete' could not bind to an rvalue of type 'void'}}
2015-12-10 07:18:38 +08:00
return { p1 ( I ) . . . } ;
}
template < typename T , int N , typename F >
void Explode ( F p1 ) {
// expected-note@+1 {{in instantiation of function template specialization}}
ExplodeImpl < T > ( p1 , A < int , N > ( ) ) ;
}
class Incomplete ;
struct ContainsIncomplete {
const Incomplete & obstacle ;
} ;
void f ( ) {
// expected-note@+1 {{in instantiation of function template specialization}}
Explode < ContainsIncomplete , 4 > ( [ ] ( int ) { } ) ;
}
}
2017-01-06 07:12:16 +08:00
namespace no_conversion_after_auto_list_deduction {
// We used to deduce 'auto' == 'std::initializer_list<X>' here, and then
// incorrectly accept the declaration of 'x'.
struct X { using T = std : : initializer_list < X > X : : * ; operator T ( ) ; } ;
auto X : : * x = { X ( ) } ; // expected-error {{from initializer list}}
struct Y { using T = std : : initializer_list < Y > ( * ) ( ) ; operator T ( ) ; } ;
auto ( * y ) ( ) = { Y ( ) } ; // expected-error {{from initializer list}}
}