2017-10-28 09:15:00 +08:00
// RUN: %clang_cc1 -std=c++1z -verify %s -DERRORS -Wundefined-func-template
// RUN: %clang_cc1 -std=c++1z -verify %s -UERRORS -Wundefined-func-template
2017-08-04 03:24:27 +08:00
// This test is split into two because we only produce "undefined internal"
// warnings if we didn't produce any errors.
# if ERRORS
2017-02-10 03:17:44 +08:00
namespace std {
using size_t = decltype ( sizeof ( 0 ) ) ;
template < typename T > struct initializer_list {
const T * p ;
size_t n ;
initializer_list ( ) ;
} ;
// FIXME: This should probably not be necessary.
template < typename T > initializer_list ( initializer_list < T > ) - > initializer_list < T > ;
}
template < typename T > constexpr bool has_type ( . . . ) { return false ; }
template < typename T > constexpr bool has_type ( T ) { return true ; }
std : : initializer_list il = { 1 , 2 , 3 , 4 , 5 } ;
template < typename T > struct vector {
template < typename Iter > vector ( Iter , Iter ) ;
vector ( std : : initializer_list < T > ) ;
} ;
template < typename T > vector ( std : : initializer_list < T > ) - > vector < T > ;
template < typename Iter > explicit vector ( Iter , Iter ) - > vector < typename Iter : : value_type > ;
template < typename T > explicit vector ( std : : size_t , T ) - > vector < T > ;
vector v1 = { 1 , 2 , 3 , 4 } ;
static_assert ( has_type < vector < int > > ( v1 ) ) ;
struct iter { typedef char value_type ; } it , end ;
vector v2 ( it , end ) ;
static_assert ( has_type < vector < char > > ( v2 ) ) ;
vector v3 ( 5 , 5 ) ;
static_assert ( has_type < vector < int > > ( v3 ) ) ;
2017-02-10 10:19:05 +08:00
vector v4 = { it , end } ;
static_assert ( has_type < vector < iter > > ( v4 ) ) ;
vector v5 { it , end } ;
static_assert ( has_type < vector < iter > > ( v5 ) ) ;
2017-02-10 03:17:44 +08:00
template < typename . . . T > struct tuple { tuple ( T . . . ) ; } ;
2017-02-10 10:19:05 +08:00
template < typename . . . T > explicit tuple ( T . . . t ) - > tuple < T . . . > ; // expected-note {{declared}}
2017-02-10 03:17:44 +08:00
// FIXME: Remove
template < typename . . . T > tuple ( tuple < T . . . > ) - > tuple < T . . . > ;
const int n = 4 ;
tuple ta = tuple { 1 , ' a ' , " foo " , n } ;
static_assert ( has_type < tuple < int , char , const char * , int > > ( ta ) ) ;
tuple tb { ta } ;
2017-02-10 10:19:05 +08:00
static_assert ( has_type < tuple < int , char , const char * , int > > ( tb ) ) ;
2017-02-10 03:17:44 +08:00
2017-02-10 10:19:05 +08:00
// FIXME: This should be tuple<tuple<...>>; when the above guide is removed.
2017-02-10 03:17:44 +08:00
tuple tc = { ta } ;
2017-02-10 10:19:05 +08:00
static_assert ( has_type < tuple < int , char , const char * , int > > ( tc ) ) ;
2017-02-10 03:17:44 +08:00
2017-02-10 10:19:05 +08:00
tuple td = { 1 , 2 , 3 } ; // expected-error {{selected an explicit deduction guide}}
static_assert ( has_type < tuple < int , char , const char * , int > > ( td ) ) ;
2017-02-10 03:17:44 +08:00
// FIXME: This is a GCC extension for now; if CWG don't allow this, at least
// add a warning for it.
namespace new_expr {
tuple < int > * p = new tuple { 0 } ;
tuple < float , float > * q = new tuple ( 1.0f , 2.0f ) ;
}
namespace ambiguity {
template < typename T > struct A { } ;
A ( unsigned short ) - > A < int > ; // expected-note {{candidate}}
A ( short ) - > A < int > ; // expected-note {{candidate}}
A a = 0 ; // expected-error {{ambiguous deduction for template arguments of 'A'}}
template < typename T > struct B { } ;
template < typename T > B ( T ( & ) ( int ) ) - > B < int > ; // expected-note {{candidate function [with T = int]}}
template < typename T > B ( int ( & ) ( T ) ) - > B < int > ; // expected-note {{candidate function [with T = int]}}
int f ( int ) ;
B b = f ; // expected-error {{ambiguous deduction for template arguments of 'B'}}
}
// FIXME: Revisit this once CWG decides if attributes, and [[deprecated]] in
// particular, should be permitted here.
namespace deprecated {
template < typename T > struct A { A ( int ) ; } ;
[[deprecated]] A ( int ) - > A < void > ; // expected-note {{marked deprecated here}}
A a = 0 ; // expected-warning {{'<deduction guide for A>' is deprecated}}
}
2017-02-11 07:10:17 +08:00
namespace dependent {
template < template < typename . . . > typename A > decltype ( auto ) a = A { 1 , 2 , 3 } ;
static_assert ( has_type < vector < int > > ( a < vector > ) ) ;
static_assert ( has_type < tuple < int , int , int > > ( a < tuple > ) ) ;
struct B {
template < typename T > struct X { X ( T ) ; } ;
X ( int ) - > X < int > ;
template < typename T > using Y = X < T > ; // expected-note {{template}}
} ;
template < typename T > void f ( ) {
typename T : : X tx = 0 ;
typename T : : Y ty = 0 ; // expected-error {{alias template 'Y' requires template arguments; argument deduction only allowed for class templates}}
}
template void f < B > ( ) ; // expected-note {{in instantiation of}}
template < typename T > struct C { C ( T ) ; } ;
template < typename T > C ( T ) - > C < T > ;
template < typename T > void g ( T a ) {
C b = 0 ;
C c = a ;
using U = decltype ( b ) ; // expected-note {{previous}}
using U = decltype ( c ) ; // expected-error {{different types ('C<const char *>' vs 'C<int>')}}
}
void h ( ) {
g ( 0 ) ;
g ( " foo " ) ; // expected-note {{instantiation of}}
}
}
2017-02-14 08:55:25 +08:00
namespace look_into_current_instantiation {
template < typename U > struct Q { } ;
template < typename T > struct A {
using U = T ;
template < typename > using V = Q < A < T > : : U > ;
template < typename W = int > A ( V < W > ) ;
} ;
A a = Q < float > ( ) ; // ok, can look through class-scope typedefs and alias
// templates, and members of the current instantiation
A < float > & r = a ;
template < typename T > struct B { // expected-note {{could not match 'B<T>' against 'int'}}
struct X {
typedef T type ;
} ;
B ( typename X : : type ) ; // expected-note {{couldn't infer template argument 'T'}}
} ;
B b = 0 ; // expected-error {{no viable}}
2017-02-14 09:49:59 +08:00
// We should have a substitution failure in the immediate context of
// deduction when using the C(T, U) constructor (probably; core wording
// unclear).
template < typename T > struct C {
using U = typename T : : type ;
C ( T , U ) ;
} ;
struct R { R ( int ) ; typedef R type ; } ;
C ( . . . ) - > C < R > ;
C c = { 1 , 2 } ;
2017-02-14 08:55:25 +08:00
}
2017-02-16 08:36:47 +08:00
namespace nondeducible {
template < typename A , typename B > struct X { } ;
template < typename A > // expected-note {{non-deducible template parameter 'A'}}
X ( ) - > X < A , int > ; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
template < typename A > // expected-note {{non-deducible template parameter 'A'}}
X ( typename X < A , int > : : type ) - > X < A , int > ; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
template < typename A = int ,
typename B > // expected-note {{non-deducible template parameter 'B'}}
X ( int ) - > X < A , B > ; // expected-error {{deduction guide template contains a template parameter that cannot be deduced}}
template < typename A = int ,
typename . . . B >
X ( float ) - > X < A , B . . . > ; // ok
}
2017-02-17 05:29:21 +08:00
namespace default_args_from_ctor {
template < class A > struct S { S ( A = 0 ) { } } ;
S s ( 0 ) ;
template < class A > struct T { template < typename B > T ( A = 0 , B = 0 ) { } } ;
T t ( 0 , 0 ) ;
}
2017-02-21 14:30:38 +08:00
namespace transform_params {
template < typename T , T N , template < T ( * v ) [ N ] > typename U , T ( * X ) [ N ] >
2017-04-14 05:37:24 +08:00
struct A {
2017-02-21 14:30:38 +08:00
template < typename V , V M , V ( * Y ) [ M ] , template < V ( * v ) [ M ] > typename W >
2017-04-14 05:37:24 +08:00
A ( U < X > , W < Y > ) ;
2017-02-21 14:30:38 +08:00
static constexpr T v = N ;
} ;
int n [ 12 ] ;
template < int ( * ) [ 12 ] > struct Q { } ;
Q < & n > qn ;
2017-04-14 05:37:24 +08:00
A a ( qn , qn ) ;
2017-02-21 14:30:38 +08:00
static_assert ( a . v = = 12 ) ;
2017-02-21 16:42:39 +08:00
template < typename . . . T > struct B {
template < T . . . V > B ( const T ( & . . . p ) [ V ] ) {
constexpr int Vs [ ] = { V . . . } ;
static_assert ( Vs [ 0 ] = = 3 & & Vs [ 1 ] = = 4 & & Vs [ 2 ] = = 4 ) ;
}
static constexpr int ( * p ) ( T . . . ) = ( int ( * ) ( int , char , char ) ) nullptr ;
2017-02-21 14:30:38 +08:00
} ;
2017-02-21 16:42:39 +08:00
B b ( { 1 , 2 , 3 } , " foo " , { ' x ' , ' y ' , ' z ' , ' w ' } ) ; // ok
2017-04-14 05:37:24 +08:00
template < typename . . . T > struct C {
2017-02-21 16:42:39 +08:00
template < T . . . V , template < T . . . > typename X >
2017-04-14 05:37:24 +08:00
C ( X < V . . . > ) ;
2017-02-21 16:42:39 +08:00
} ;
template < int . . . > struct Y { } ;
2017-04-14 05:37:24 +08:00
C c ( Y < 0 , 1 , 2 > { } ) ;
2017-02-22 07:49:18 +08:00
template < typename . . . T > struct D {
template < T . . . V > D ( Y < V . . . > ) ;
} ;
D d ( Y < 0 , 1 , 2 > { } ) ;
2017-02-21 14:30:38 +08:00
}
2017-04-20 09:15:31 +08:00
namespace variadic {
int arr3 [ 3 ] , arr4 [ 4 ] ;
// PR32673
template < typename T > struct A {
template < typename . . . U > A ( T , U . . . ) ;
} ;
A a ( 1 , 2 , 3 ) ;
template < typename T > struct B {
template < int . . . N > B ( T , int ( & . . . r ) [ N ] ) ;
} ;
B b ( 1 , arr3 , arr4 ) ;
template < typename T > struct C {
template < template < typename > typename . . . U > C ( T , U < int > . . . ) ;
} ;
C c ( 1 , a , b ) ;
template < typename . . . U > struct X {
template < typename T > X ( T , U . . . ) ;
} ;
X x ( 1 , 2 , 3 ) ;
template < int . . . N > struct Y {
template < typename T > Y ( T , int ( & . . . r ) [ N ] ) ;
} ;
Y y ( 1 , arr3 , arr4 ) ;
template < template < typename > typename . . . U > struct Z {
template < typename T > Z ( T , U < int > . . . ) ;
} ;
Z z ( 1 , a , b ) ;
}
2017-06-07 10:42:27 +08:00
namespace tuple_tests {
// The converting n-ary constructor appears viable, deducing T as an empty
// pack (until we check its SFINAE constraints).
namespace libcxx_1 {
template < class . . . T > struct tuple {
template < class . . . Args > struct X { static const bool value = false ; } ;
template < class . . . U , bool Y = X < U . . . > : : value > tuple ( U & & . . . u ) ;
} ;
tuple a = { 1 , 2 , 3 } ;
}
// Don't get caught by surprise when X<...> doesn't even exist in the
// selected specialization!
namespace libcxx_2 {
template < class . . . T > struct tuple { // expected-note {{candidate}}
template < class . . . Args > struct X { static const bool value = false ; } ;
template < class . . . U , bool Y = X < U . . . > : : value > tuple ( U & & . . . u ) ;
// expected-note@-1 {{substitution failure [with T = <>, U = <int, int, int>]: cannot reference member of primary template because deduced class template specialization 'tuple<>' is an explicit specialization}}
} ;
template < > class tuple < > { } ;
tuple a = { 1 , 2 , 3 } ; // expected-error {{no viable constructor or deduction guide}}
}
2017-06-08 09:08:50 +08:00
namespace libcxx_3 {
template < typename . . . T > struct scoped_lock {
scoped_lock ( T . . . ) ;
} ;
template < > struct scoped_lock < > { } ;
scoped_lock l = { } ;
}
2017-06-07 10:42:27 +08:00
}
2017-08-04 03:24:27 +08:00
2017-08-11 10:04:19 +08:00
namespace dependent {
template < typename T > struct X {
X ( T ) ;
} ;
template < typename T > int Var ( T t ) {
X x ( t ) ;
return X ( x ) + 1 ; // expected-error {{invalid operands}}
}
template < typename T > int Cast ( T t ) {
return X ( X ( t ) ) + 1 ; // expected-error {{invalid operands}}
}
template < typename T > int New ( T t ) {
return X ( new X ( t ) ) + 1 ; // expected-error {{invalid operands}}
} ;
template int Var ( float ) ; // expected-note {{instantiation of}}
template int Cast ( float ) ; // expected-note {{instantiation of}}
template int New ( float ) ; // expected-note {{instantiation of}}
template < typename T > int operator + ( X < T > , int ) ;
template int Var ( int ) ;
template int Cast ( int ) ;
template int New ( int ) ;
}
2018-01-04 09:24:17 +08:00
namespace injected_class_name {
template < typename T = void > struct A {
A ( ) ;
template < typename U > A ( A < U > ) ;
} ;
A < int > a ;
A b = a ;
using T = decltype ( a ) ;
using T = decltype ( b ) ;
}
2017-08-04 03:24:27 +08:00
# else
// expected-no-diagnostics
namespace undefined_warnings {
// Make sure we don't get an "undefined but used internal symbol" warning for the deduction guide here.
namespace {
template < typename T >
struct TemplDObj {
explicit TemplDObj ( T func ) noexcept { }
} ;
auto test1 = TemplDObj ( 0 ) ;
TemplDObj ( float ) - > TemplDObj < double > ;
auto test2 = TemplDObj ( .0f ) ;
}
}
# endif