diff options
Diffstat (limited to 'test/SemaTemplate')
19 files changed, 432 insertions, 129 deletions
diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp index 5b6ab7d1552c..f9bb44ecb9c0 100644 --- a/test/SemaTemplate/default-arguments.cpp +++ b/test/SemaTemplate/default-arguments.cpp @@ -13,3 +13,12 @@ X<> *x4; template<typename T = int> struct Z { }; template struct Z<>; + +// PR4362 +template<class T> struct a { }; +template<> struct a<int> { static const bool v = true; }; + +template<class T, bool = a<T>::v> struct p { }; // expected-error {{no member named 'v'}} + +template struct p<bool>; // expected-note {{in instantiation of default argument for 'p<bool>' required here}} +template struct p<int>; diff --git a/test/SemaTemplate/dependent-names.cpp b/test/SemaTemplate/dependent-names.cpp new file mode 100644 index 000000000000..95ee2d2b9d1f --- /dev/null +++ b/test/SemaTemplate/dependent-names.cpp @@ -0,0 +1,16 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +typedef double A; +template<typename T> class B { + typedef int A; +}; + +template<typename T> struct X : B<T> { + static A a; +}; + +int a0[sizeof(X<int>::a) == sizeof(double) ? 1 : -1]; + +// PR4365. +template<class T> class Q; +template<class T> class R : Q<T> {T current;}; diff --git a/test/SemaTemplate/example-typelist.cpp b/test/SemaTemplate/example-typelist.cpp new file mode 100644 index 000000000000..4a2aeb20e730 --- /dev/null +++ b/test/SemaTemplate/example-typelist.cpp @@ -0,0 +1,98 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// A simple cons-style typelist +struct nil { }; + +template<typename Head, typename Tail = nil> +struct cons { + typedef Head head; + typedef Tail tail; +}; + +// is_same trait, for testing +template<typename T, typename U> +struct is_same { + static const bool value = false; +}; + +template<typename T> +struct is_same<T, T> { + static const bool value = true; +}; + +// metaprogram that computes the length of a list +template<typename T> struct length; + +template<typename Head, typename Tail> +struct length<cons<Head, Tail> > { + static const unsigned value = length<Tail>::value + 1; +}; + +template<> +struct length<nil> { + static const unsigned value = 0; +}; + +typedef cons<unsigned char, + cons<unsigned short, + cons<unsigned int, + cons<unsigned long> > > > unsigned_inttypes; +int length0[length<unsigned_inttypes>::value == 4? 1 : -1]; + +// metaprogram that reverses a list + +// FIXME: I would prefer that this be a partial specialization, but +// that requires partial ordering of class template partial +// specializations. +template<typename T> +class reverse { + typedef typename reverse<typename T::tail>::type reversed_tail; + + typedef typename reverse<typename reversed_tail::tail>::type most_of_tail; + +public: + typedef cons<typename reversed_tail::head, + typename reverse<cons<typename T::head, most_of_tail> >::type> type; +}; + +template<typename Head> +class reverse<cons<Head> > { +public: + typedef cons<Head> type; +}; + +template<> +class reverse<nil> { +public: + typedef nil type; +}; + +int reverse0[is_same<reverse<unsigned_inttypes>::type, + cons<unsigned long, + cons<unsigned int, + cons<unsigned short, + cons<unsigned char> > > > >::value? 1 : -1]; + +// metaprogram that finds a type within a list + +// FIXME: I would prefer that this be a partial specialization, but +// that requires partial ordering of class template partial +// specializations. +template<typename List, typename T> +struct find : find<typename List::tail, T> { }; + +template<typename Tail, typename T> +struct find<cons<T, Tail>, T> { + typedef cons<T, Tail> type; +}; + +template<typename T> +struct find<nil, T> { + typedef nil type; +}; + +int find0[is_same<find<unsigned_inttypes, unsigned int>::type, + cons<unsigned int, cons<unsigned long> > >::value? + 1 : -1]; +int find1[is_same<find<unsigned_inttypes, int>::type, nil>::value? 1 : -1]; + diff --git a/test/SemaTemplate/instantiate-declref-ice.cpp b/test/SemaTemplate/instantiate-declref-ice.cpp new file mode 100644 index 000000000000..21ee87202797 --- /dev/null +++ b/test/SemaTemplate/instantiate-declref-ice.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<int i> struct x { + static const int j = i; + x<j>* y; +}; + diff --git a/test/SemaTemplate/instantiate-dependent-nested-name.cpp b/test/SemaTemplate/instantiate-dependent-nested-name.cpp new file mode 100644 index 000000000000..2b1d29878a54 --- /dev/null +++ b/test/SemaTemplate/instantiate-dependent-nested-name.cpp @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s +// PR4382 +template<typename T> struct X { static const T A = 1; }; +template<typename T, bool = X<T>::A> struct Y { typedef T A; }; +template<typename T> struct Z { typedef typename Y<T>::A A; }; +extern int x; +extern Z<int>::A x; diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp index 5b3a6d998404..023cc5437f69 100644 --- a/test/SemaTemplate/instantiate-function-1.cpp +++ b/test/SemaTemplate/instantiate-function-1.cpp @@ -140,7 +140,7 @@ template<typename T> struct Member0 { tp->f; this->f; - this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}} + this.f; // expected-error{{member reference base type 'Member0<T> *const' is not a structure or union}} } }; @@ -209,3 +209,9 @@ struct Abstract { template struct TryCatch0<int>; // okay template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}} template struct TryCatch0<Abstract>; // expected-note{{instantiation}} + +// PR4383 +template<typename T> struct X; +template<typename T> struct Y : public X<T> { + Y& x() { return *this; } +}; diff --git a/test/SemaTemplate/instantiate-member-pointers.cpp b/test/SemaTemplate/instantiate-member-pointers.cpp new file mode 100644 index 000000000000..b3ddb3fafa31 --- /dev/null +++ b/test/SemaTemplate/instantiate-member-pointers.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct Y { + int x; +}; + +template<typename T> +struct X1 { + int f(T* ptr, int T::*pm) { // expected-error{{member pointer}} + return ptr->*pm; + } +}; + +template struct X1<Y>; +template struct X1<int>; // expected-note{{instantiation}} + +template<typename T, typename Class> +struct X2 { + T f(Class &obj, T Class::*pm) { // expected-error{{to a reference}} \ + // expected-error{{member pointer to void}} + return obj.*pm; + } +}; + +template struct X2<int, Y>; +template struct X2<int&, Y>; // expected-note{{instantiation}} +template struct X2<const void, Y>; // expected-note{{instantiation}} diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp index 7bc971f24b59..9261ed6a6c96 100644 --- a/test/SemaTemplate/metafun-apply.cpp +++ b/test/SemaTemplate/metafun-apply.cpp @@ -23,8 +23,7 @@ struct bogus { template<typename MetaFun, typename T> struct apply1 { typedef typename MetaFun::template apply<T>::type type; // expected-note{{in instantiation of template class 'struct add_reference::apply<void>' requested here}} \ - // expected-error{{'apply' following the 'template' keyword does not refer to a template}} \ - // FIXME: expected-error{{type 'MetaFun::template apply<int>' cannot be used prior to '::' because it has no members}} + // expected-error{{'apply' following the 'template' keyword does not refer to a template}} }; int i; @@ -36,8 +35,7 @@ void test() { apply1<add_reference, void>::type t; // expected-note{{in instantiation of template class 'struct apply1<struct add_reference, void>' requested here}} \ // FIXME: expected-error{{unexpected type name 'type': expected expression}} - apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} \ - // FIXME: expected-error{{unexpected type name 'type': expected expression}} + apply1<bogus, int>::type t2; // expected-note{{in instantiation of template class 'struct apply1<struct bogus, int>' requested here}} } diff --git a/test/SemaTemplate/right-angle-brackets-0x.cpp b/test/SemaTemplate/right-angle-brackets-0x.cpp deleted file mode 100644 index 57b6ee22410c..000000000000 --- a/test/SemaTemplate/right-angle-brackets-0x.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s -template<typename T> struct X; -template<int I> struct Y; - -X<X<int>> *x1; - -Y<(1 >> 2)> *y1; -Y<1 >> 2> *y2; // FIXME: expected-error{{expected unqualified-id}} - -X<X<X<X<X<int>>>>> *x2; - -template<> struct X<int> { }; -typedef X<int> X_int; -struct Z : X_int { }; - -void f(const X<int> x) { - (void)reinterpret_cast<X<int>>(x); // expected-error{{reinterpret_cast from}} - (void)reinterpret_cast<X<X<X<int>>>>(x); // expected-error{{reinterpret_cast from}} - - X<X<int>> *x1; -} - diff --git a/test/SemaTemplate/right-angle-brackets-98.cpp b/test/SemaTemplate/right-angle-brackets-98.cpp deleted file mode 100644 index 764bb7bae073..000000000000 --- a/test/SemaTemplate/right-angle-brackets-98.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: clang-cc -fsyntax-only -std=c++98 -verify %s -template<typename T> struct X; -template<int I> struct Y; - -X<X<int> > *x1; -X<X<int>> *x2; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} - -X<X<X<X<int>> // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} - >> *x3; // expected-error{{a space is required between consecutive right angle brackets (use '> >')}} - -Y<(1 >> 2)> *y1; -Y<1 >> 2> *y2; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++0x}} diff --git a/test/SemaTemplate/temp_class_spec.cpp b/test/SemaTemplate/temp_class_spec.cpp index 4e4f5560aef3..1a534236c8eb 100644 --- a/test/SemaTemplate/temp_class_spec.cpp +++ b/test/SemaTemplate/temp_class_spec.cpp @@ -134,3 +134,130 @@ int is_unary_function6[is_unary_function_with_same_return_type_as_argument_type< int is_unary_function7[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, bool)>::value ? -1 : 1]; int is_unary_function8[is_unary_function_with_same_return_type_as_argument_type<int (*)(bool)>::value ? -1 : 1]; int is_unary_function9[is_unary_function_with_same_return_type_as_argument_type<int (*)(int)>::value ? 1 : -1]; +int is_unary_function10[is_unary_function_with_same_return_type_as_argument_type<int (*)(int, ...)>::value ? -1 : 1]; +int is_unary_function11[is_unary_function_with_same_return_type_as_argument_type<int (* const)(int)>::value ? -1 : 1]; + +template<typename T> +struct is_binary_function { + static const bool value = false; +}; + +template<typename R, typename T1, typename T2> +struct is_binary_function<R(T1, T2)> { + static const bool value = true; +}; + +int is_binary_function0[is_binary_function<int(float, double)>::value? 1 : -1]; + +template<typename T> +struct is_member_pointer { + static const bool value = false; +}; + +template<typename T, typename Class> +struct is_member_pointer<T Class::*> { + static const bool value = true; +}; + +struct X { }; + +int is_member_pointer0[is_member_pointer<int X::*>::value? 1 : -1]; +int is_member_pointer1[is_member_pointer<const int X::*>::value? 1 : -1]; +int is_member_pointer2[is_member_pointer<int (X::*)()>::value? 1 : -1]; +int is_member_pointer3[is_member_pointer<int (X::*)(int) const>::value? 1 : -1]; +int is_member_pointer4[is_member_pointer<int (X::**)(int) const>::value? -1 : 1]; +int is_member_pointer5[is_member_pointer<int>::value? -1 : 1]; + +template<typename T> +struct is_member_function_pointer { + static const bool value = false; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)()> { + static const bool value = true; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)() const> { + static const bool value = true; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)() volatile> { + static const bool value = true; +}; + +template<typename T, typename Class> +struct is_member_function_pointer<T (Class::*)() const volatile> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1)> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1) const> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1) volatile> { + static const bool value = true; +}; + +template<typename T, typename Class, typename A1> +struct is_member_function_pointer<T (Class::*)(A1) const volatile> { + static const bool value = true; +}; + +int is_member_function_pointer0[ + is_member_function_pointer<int X::*>::value? -1 : 1]; +int is_member_function_pointer1[ + is_member_function_pointer<int (X::*)()>::value? 1 : -1]; +int is_member_function_pointer2[ + is_member_function_pointer<X (X::*)(X&)>::value? 1 : -1]; +int is_member_function_pointer3[ + is_member_function_pointer<int (X::*)() const>::value? 1 : -1]; +int is_member_function_pointer4[ + is_member_function_pointer<int (X::*)(float) const>::value? 1 : -1]; + +// Test substitution of non-dependent arguments back into the template +// argument list of the class template partial specialization. +template<typename T, typename ValueType = T> +struct is_nested_value_type_identity { + static const bool value = false; +}; + +template<typename T> +struct is_nested_value_type_identity<T, typename T::value_type> { + static const bool value = true; +}; + +template<typename T> +struct HasValueType { + typedef T value_type; +}; + +struct HasIdentityValueType { + typedef HasIdentityValueType value_type; +}; + +struct NoValueType { }; + +int is_nested_value_type_identity0[ + is_nested_value_type_identity<HasValueType<int> >::value? -1 : 1]; +int is_nested_value_type_identity1[ + is_nested_value_type_identity<HasIdentityValueType>::value? 1 : -1]; +int is_nested_value_type_identity2[ + is_nested_value_type_identity<NoValueType>::value? -1 : 1]; + + +// C++ [temp.class.spec]p4: +template<class T1, class T2, int I> class A { }; //#1 +template<class T, int I> class A<T, T*, I> { }; //#2 +template<class T1, class T2, int I> class A<T1*, T2, I> { }; //#3 +template<class T> class A<int, T*, 5> { }; //#4 +template<class T1, class T2, int I> class A<T1, T2*, I> { }; //#5 diff --git a/test/SemaTemplate/temp_class_spec_blocks.cpp b/test/SemaTemplate/temp_class_spec_blocks.cpp new file mode 100644 index 000000000000..920d9c8b0cbd --- /dev/null +++ b/test/SemaTemplate/temp_class_spec_blocks.cpp @@ -0,0 +1,34 @@ +// RUN: clang-cc -fsyntax-only -verify %s -fblocks +template<typename T> +struct is_unary_block { + static const bool value = false; +}; + +template<typename T, typename U> +struct is_unary_block<T (^)(U)> { + static const bool value = true; +}; + +int is_unary_block0[is_unary_block<int>::value ? -1 : 1]; +int is_unary_block1[is_unary_block<int (^)()>::value ? -1 : 1]; +int is_unary_block2[is_unary_block<int (^)(int, bool)>::value ? -1 : 1]; +int is_unary_block3[is_unary_block<int (^)(bool)>::value ? 1 : -1]; +int is_unary_block4[is_unary_block<int (^)(int)>::value ? 1 : -1]; + +template<typename T> +struct is_unary_block_with_same_return_type_as_argument_type { + static const bool value = false; +}; + +template<typename T> +struct is_unary_block_with_same_return_type_as_argument_type<T (^)(T)> { + static const bool value = true; +}; + +int is_unary_block5[is_unary_block_with_same_return_type_as_argument_type<int>::value ? -1 : 1]; +int is_unary_block6[is_unary_block_with_same_return_type_as_argument_type<int (^)()>::value ? -1 : 1]; +int is_unary_block7[is_unary_block_with_same_return_type_as_argument_type<int (^)(int, bool)>::value ? -1 : 1]; +int is_unary_block8[is_unary_block_with_same_return_type_as_argument_type<int (^)(bool)>::value ? -1 : 1]; +int is_unary_block9[is_unary_block_with_same_return_type_as_argument_type<int (^)(int)>::value ? 1 : -1]; +int is_unary_block10[is_unary_block_with_same_return_type_as_argument_type<int (^)(int, ...)>::value ? -1 : 1]; +int is_unary_block11[is_unary_block_with_same_return_type_as_argument_type<int (^ const)(int)>::value ? -1 : 1]; diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp new file mode 100644 index 000000000000..b50bd8f634aa --- /dev/null +++ b/test/SemaTemplate/temp_class_spec_neg.cpp @@ -0,0 +1,45 @@ +// RUN: clang-cc -fsyntax-only -verify %s +template<typename T> struct vector; + +// C++ [temp.class.spec]p6: +namespace N { + namespace M { + template<typename T> struct A; // expected-note{{here}} + } +} + +template<typename T> +struct N::M::A<T*> { }; // expected-error{{not in namespace}} + +// C++ [temp.class.spec]p9 +// bullet 1 +template <int I, int J> struct A {}; +template <int I> struct A<I+5, I*2> {}; // expected-error{{depends on}} +template <int I, int J> struct B {}; +template <int I> struct B<I, I> {}; //OK + +// bullet 2 +template <class T, T t> struct C {}; // expected-note{{declared here}} +template <class T> struct C<T, 1>; // expected-error{{specializes}} +template <class T, T* t> struct C<T*, t>; // okay + +template< int X, int (*array_ptr)[X] > class A2 {}; // expected-note{{here}} +int array[5]; +template< int X > class A2<X,&array> { }; // expected-error{{specializes}} + +template<typename T, int N, template<typename X> class TT> +struct Test0; + +// bullet 3 +template<typename T, int N, template<typename X> class TT> +struct Test0<T, N, TT>; // expected-error{{does not specialize}} + +// C++ [temp.class.spec]p10 +template<typename T = int, // expected-error{{default template argument}} + int N = 17, // expected-error{{default template argument}} + template<typename X> class TT = ::vector> // expected-error{{default template argument}} + struct Test0<T*, N, TT> { }; + +template<typename T> struct Test1; +template<typename T, typename U> // expected-note{{non-deducible}} + struct Test1<T*> { }; // expected-warning{{never be used}} diff --git a/test/SemaTemplate/temp_param.cpp b/test/SemaTemplate/temp_param.cpp deleted file mode 100644 index c042f0849a04..000000000000 --- a/test/SemaTemplate/temp_param.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// RUN: clang-cc -fsyntax-only -verify %s - -class X; - -// C++ [temp.param]p4 -typedef int INT; -enum E { enum1, enum2 }; -template<int N> struct A1; -template<INT N, INT M> struct A2; -template<enum E x, E y> struct A3; -template<int &X> struct A4; -template<int *Ptr> struct A5; -template<int (&f)(int, int)> struct A6; -template<int (*fp)(float, double)> struct A7; -template<int X::*pm> struct A8; -template<float (X::*pmf)(float, int)> struct A9; -template<typename T, T x> struct A10; - -template<float f> struct A11; // expected-error{{a non-type template parameter cannot have type 'float'}} - -template<void *Ptr> struct A12; // expected-error{{a non-type template parameter cannot have type 'void *'}} - -// C++ [temp.param]p8 -template<int X[10]> struct A5; -template<int f(float, double)> struct A7; - -// C++ [temp.param]p11: -template<typename> struct Y1; // expected-note{{too few template parameters in template template argument}} -template<typename, int> struct Y2; - -template<class T1 = int, // expected-note{{previous default template argument defined here}} - class T2> // expected-error{{template parameter missing a default argument}} - class B1; - -template<template<class> class = Y1, // expected-note{{previous default template argument defined here}} - template<class> class> // expected-error{{template parameter missing a default argument}} - class B1t; - -template<int N = 5, // expected-note{{previous default template argument defined here}} - int M> // expected-error{{template parameter missing a default argument}} - class B1n; - -// Check for bogus template parameter shadow warning. -template<template<class T> class, - template<class T> class> - class B1noshadow; - -// C++ [temp.param]p10: -template<class T1, class T2 = int> class B2; -template<class T1 = int, class T2> class B2; - -template<template<class, int> class, template<class> class = Y1> class B2t; -template<template<class, int> class = Y2, template<class> class> class B2t; - -template<int N, int M = 5> class B2n; -template<int N = 5, int M> class B2n; - -// C++ [temp.param]p12: -template<class T1, - class T2 = int> // expected-note{{previous default template argument defined here}} - class B3; -template<class T1, typename T2> class B3; -template<class T1, - typename T2 = float> // expected-error{{template parameter redefines default argument}} - class B3; - -template<template<class, int> class, - template<class> class = Y1> // expected-note{{previous default template argument defined here}} - class B3t; - -template<template<class, int> class, template<class> class> class B3t; - -template<template<class, int> class, - template<class> class = Y1> // expected-error{{template parameter redefines default argument}} - class B3t; - -template<int N, - int M = 5> // expected-note{{previous default template argument defined here}} - class B3n; - -template<int N, int M> class B3n; - -template<int N, - int M = 7> // expected-error{{template parameter redefines default argument}} - class B3n; - -// Check validity of default arguments -template<template<class, int> class // expected-note{{previous template template parameter is here}} - = Y1> // expected-error{{template template argument has different template parameters than its corresponding template template parameter}} - class C1; diff --git a/test/SemaTemplate/typename-specifier-3.cpp b/test/SemaTemplate/typename-specifier-3.cpp new file mode 100644 index 000000000000..8dde6095e533 --- /dev/null +++ b/test/SemaTemplate/typename-specifier-3.cpp @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// PR4364 +template<class T> struct a { + T b() { + return typename T::x(); + } +}; +struct B { + typedef B x; +}; +B c() { + a<B> x; + return x.b(); +} + +// Some extra tests for invalid cases +template<class T> struct test2 { T b() { return typename T::a; } }; // expected-error{{expected '(' for function-style cast or type construction}} +template<class T> struct test3 { T b() { return typename a; } }; // expected-error{{expected a qualified name after 'typename'}} diff --git a/test/SemaTemplate/variadic-class-template-1.cpp b/test/SemaTemplate/variadic-class-template-1.cpp new file mode 100644 index 000000000000..6df905006692 --- /dev/null +++ b/test/SemaTemplate/variadic-class-template-1.cpp @@ -0,0 +1,4 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +template<typename ... Args = int> struct S1 { }; // expected-error{{template parameter pack cannot have a default argument}} +template<typename ... Args, typename T> struct S2 { }; // expected-error{{template parameter pack must be the last template parameter}} diff --git a/test/SemaTemplate/variadic-class-template-2.cpp b/test/SemaTemplate/variadic-class-template-2.cpp new file mode 100644 index 000000000000..eadea901c7fe --- /dev/null +++ b/test/SemaTemplate/variadic-class-template-2.cpp @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +// Type parameters packs +template <typename ...> struct TS1 {}; // expected-note{{template parameter is declared here}} +template struct TS1<>; +template struct TS1<int>; +template struct TS1<int, int>; +template struct TS1<int, 10>; // expected-error{{template argument for template type parameter must be a type}} + +template <typename, typename ...> struct TS2 {}; // expected-note{{template is declared here}} +template struct TS2<>; // expected-error{{too few template arguments for class template 'TS2'}} +template struct TS2<int>; +template struct TS2<int, int>; + +template <typename = int, typename ...> struct TS3 {}; // expected-note{{template parameter is declared here}} +template struct TS3<>; // expected-note{{previous explicit instantiation is here}} +template struct TS3<int>; // expected-error{{duplicate explicit instantiation of 'TS3<>'}} +template struct TS3<int, int>; +template struct TS3<10>; // expected-error{{template argument for template type parameter must be a type}} diff --git a/test/SemaTemplate/variadic-parse.cpp b/test/SemaTemplate/variadic-parse.cpp new file mode 100644 index 000000000000..e1d1b1f98db2 --- /dev/null +++ b/test/SemaTemplate/variadic-parse.cpp @@ -0,0 +1,6 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +// Parsing type parameter packs. +template <typename ... Args> struct T1 {}; +template <typename ... > struct T2 {}; + diff --git a/test/SemaTemplate/variadic-unsupported.cpp b/test/SemaTemplate/variadic-unsupported.cpp new file mode 100644 index 000000000000..98f217c76891 --- /dev/null +++ b/test/SemaTemplate/variadic-unsupported.cpp @@ -0,0 +1,5 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Type parameter packs. +template <typename ... > struct T1 {}; // expected-error{{variadic templates are only allowed in C++0x}} + |