aboutsummaryrefslogtreecommitdiff
path: root/test/SemaTemplate
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r--test/SemaTemplate/default-arguments.cpp9
-rw-r--r--test/SemaTemplate/dependent-names.cpp16
-rw-r--r--test/SemaTemplate/example-typelist.cpp98
-rw-r--r--test/SemaTemplate/instantiate-declref-ice.cpp7
-rw-r--r--test/SemaTemplate/instantiate-dependent-nested-name.cpp7
-rw-r--r--test/SemaTemplate/instantiate-function-1.cpp8
-rw-r--r--test/SemaTemplate/instantiate-member-pointers.cpp27
-rw-r--r--test/SemaTemplate/metafun-apply.cpp6
-rw-r--r--test/SemaTemplate/right-angle-brackets-0x.cpp22
-rw-r--r--test/SemaTemplate/right-angle-brackets-98.cpp12
-rw-r--r--test/SemaTemplate/temp_class_spec.cpp127
-rw-r--r--test/SemaTemplate/temp_class_spec_blocks.cpp34
-rw-r--r--test/SemaTemplate/temp_class_spec_neg.cpp45
-rw-r--r--test/SemaTemplate/temp_param.cpp90
-rw-r--r--test/SemaTemplate/typename-specifier-3.cpp19
-rw-r--r--test/SemaTemplate/variadic-class-template-1.cpp4
-rw-r--r--test/SemaTemplate/variadic-class-template-2.cpp19
-rw-r--r--test/SemaTemplate/variadic-parse.cpp6
-rw-r--r--test/SemaTemplate/variadic-unsupported.cpp5
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}}
+