2009-12-16 04:14:24 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify %s
2009-03-27 12:21:56 +08:00
class A ;
class S {
public :
template < typename T > struct A {
struct Nested {
typedef T type ;
} ;
} ;
} ;
int i ;
S : : A < int > : : Nested : : type * ip = & i ;
2009-08-25 07:03:25 +08:00
template < typename T >
2009-08-26 01:23:04 +08:00
struct Outer {
template < typename U >
class Inner0 ;
2009-08-25 07:03:25 +08:00
template < typename U >
2009-08-26 01:23:04 +08:00
class Inner1 {
struct ReallyInner ;
T foo ( U ) ;
template < typename V > T bar ( V ) ;
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
template < typename V > T * bar ( V ) ;
2009-08-26 06:53:07 +08:00
static T value1 ;
static U value2 ;
2009-08-25 07:03:25 +08:00
} ;
} ;
2009-08-26 01:23:04 +08:00
template < typename X >
template < typename Y >
class Outer < X > : : Inner0 {
public :
void f ( X , Y ) ;
} ;
template < typename X >
template < typename Y >
void Outer < X > : : Inner0 < Y > : : f ( X , Y ) {
}
template < typename X >
template < typename Y >
struct Outer < X > : : Inner1 < Y > : : ReallyInner {
2009-08-26 06:54:02 +08:00
static Y value3 ;
2009-08-26 01:23:04 +08:00
void g ( X , Y ) ;
} ;
template < typename X >
template < typename Y >
void Outer < X > : : Inner1 < Y > : : ReallyInner : : g ( X , Y ) {
}
template < typename X >
template < typename Y >
X Outer < X > : : Inner1 < Y > : : foo ( Y ) {
return X ( ) ;
}
2009-08-25 07:03:25 +08:00
2009-08-26 01:23:04 +08:00
template < typename X >
template < typename Y >
template < typename Z >
X Outer < X > : : Inner1 < Y > : : bar ( Z ) {
return X ( ) ;
}
Improve support for out-of-line definitions of nested templates and
their members, including member class template, member function
templates, and member classes and functions of member templates.
To actually parse the nested-name-specifiers that qualify the name of
an out-of-line definition of a member template, e.g.,
template<typename X> template<typename Y>
X Outer<X>::Inner1<Y>::foo(Y) {
return X();
}
we need to look for the template names (e.g., "Inner1") as a member of
the current instantiation (Outer<X>), even before we have entered the
scope of the current instantiation. Since we can't do this in general
(i.e., we should not be looking into all dependent
nested-name-specifiers as if they were the current instantiation), we
rely on the parser to tell us when it is parsing a declaration
specifier sequence, and, therefore, when we should consider the
current scope specifier to be a current instantiation.
Printing of complicated, dependent nested-name-specifiers may be
somewhat broken by this commit; I'll add tests for this issue and fix
the problem (if it still exists) in a subsequent commit.
llvm-svn: 80044
2009-08-26 06:51:20 +08:00
template < typename X >
template < typename Y >
template < typename Z >
X * Outer < X > : : Inner1 < Y > : : bar ( Z ) {
return 0 ;
}
2009-08-26 06:53:07 +08:00
template < typename X >
template < typename Y >
X Outer < X > : : Inner1 < Y > : : value1 = 0 ;
template < typename X >
template < typename Y >
Y Outer < X > : : Inner1 < Y > : : value2 = Y ( ) ;
2009-08-26 06:54:02 +08:00
template < typename X >
template < typename Y >
Y Outer < X > : : Inner1 < Y > : : ReallyInner : : value3 = Y ( ) ;
2009-08-26 08:04:55 +08:00
template < typename X >
template < typename Y >
Y Outer < X > : : Inner1 < Y * > : : ReallyInner : : value4 ; // expected-error{{Outer<X>::Inner1<Y *>::ReallyInner::}}
2009-09-10 08:12:48 +08:00
template < typename T >
struct X0 { } ;
template < typename T >
struct X0 < T * > {
template < typename U >
void f ( U u = T ( ) ) { }
} ;
2009-10-24 07:25:44 +08:00
// PR5103
template < typename >
struct X1 {
template < typename , bool = false > struct B { } ;
} ;
template struct X1 < int > : : B < bool > ;
2009-11-12 00:58:32 +08:00
// Template template parameters
template < typename T >
struct X2 {
template < template < class U , T Value > class > / / expected - error { { cannot have type ' float ' } } \
// expected-note{{previous non-type template}}
struct Inner { } ;
} ;
template < typename T ,
int Value > // expected-note{{template non-type parameter}}
struct X2_arg ;
X2 < int > : : Inner < X2_arg > x2i1 ;
2009-11-12 03:13:48 +08:00
X2 < float > x2a ; // expected-note{{instantiation}}
2009-11-12 00:58:32 +08:00
X2 < long > : : Inner < X2_arg > x2i3 ; // expected-error{{template template argument has different}}
2011-09-21 22:40:46 +08:00
namespace PR10896 {
template < typename TN >
class Foo {
public :
void foo ( ) { }
private :
template < typename T >
T SomeField ; // expected-error {{member 'SomeField' declared as a template}}
2013-06-21 04:56:57 +08:00
template < > int SomeField2 ; // expected-error {{extraneous 'template<>' in declaration of member 'SomeField2'}}
2011-09-21 22:40:46 +08:00
} ;
2009-11-12 00:58:32 +08:00
2011-09-21 22:40:46 +08:00
void g ( ) {
Foo < int > f ;
f . foo ( ) ;
}
}
2011-11-02 05:35:16 +08:00
namespace PR10924 {
template < class Topology , class ctype >
struct ReferenceElement
{
} ;
template < class Topology , class ctype >
template < int codim >
class ReferenceElement < Topology , ctype > : : BaryCenterArray // expected-error{{out-of-line definition of 'BaryCenterArray' does not match any declaration in 'ReferenceElement<Topology, ctype>'}}
{
} ;
}
2012-09-07 02:32:18 +08:00
class Outer1 {
template < typename T > struct X ;
template < typename T > int X < T > : : func ( ) { } // expected-error{{out-of-line definition of 'func' from class 'X<T>' without definition}}
} ;
2018-02-14 10:07:53 +08:00
namespace RefPack {
template < const int & . . . N > struct A { template < typename . . . T > void f ( T ( & . . . t ) [ N ] ) ; } ;
constexpr int k = 10 ;
int arr [ 10 ] ;
void g ( ) { A < k > ( ) . f ( arr ) ; }
}