aboutsummaryrefslogtreecommitdiff
path: root/test/SemaTemplate
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r--test/SemaTemplate/class-template-decl.cpp49
-rw-r--r--test/SemaTemplate/class-template-id-2.cpp24
-rw-r--r--test/SemaTemplate/class-template-id.cpp38
-rw-r--r--test/SemaTemplate/class-template-spec.cpp80
-rw-r--r--test/SemaTemplate/current-instantiation.cpp71
-rw-r--r--test/SemaTemplate/default-arguments.cpp12
-rw-r--r--test/SemaTemplate/dependent-type-identity.cpp72
-rw-r--r--test/SemaTemplate/enum-argument.cpp7
-rw-r--r--test/SemaTemplate/example-dynarray.cpp150
-rw-r--r--test/SemaTemplate/fibonacci.cpp66
-rw-r--r--test/SemaTemplate/fun-template-def.cpp43
-rw-r--r--test/SemaTemplate/injected-class-name.cpp40
-rw-r--r--test/SemaTemplate/instantiate-array.cpp28
-rw-r--r--test/SemaTemplate/instantiate-c99.cpp81
-rw-r--r--test/SemaTemplate/instantiate-call.cpp50
-rw-r--r--test/SemaTemplate/instantiate-cast.cpp109
-rw-r--r--test/SemaTemplate/instantiate-clang.cpp35
-rw-r--r--test/SemaTemplate/instantiate-complete.cpp47
-rw-r--r--test/SemaTemplate/instantiate-declref.cpp71
-rw-r--r--test/SemaTemplate/instantiate-enum.cpp11
-rw-r--r--test/SemaTemplate/instantiate-expr-1.cpp71
-rw-r--r--test/SemaTemplate/instantiate-expr-2.cpp132
-rw-r--r--test/SemaTemplate/instantiate-expr-3.cpp115
-rw-r--r--test/SemaTemplate/instantiate-expr-4.cpp289
-rw-r--r--test/SemaTemplate/instantiate-expr-basic.cpp17
-rw-r--r--test/SemaTemplate/instantiate-field.cpp28
-rw-r--r--test/SemaTemplate/instantiate-function-1.cpp211
-rw-r--r--test/SemaTemplate/instantiate-function-1.mm14
-rw-r--r--test/SemaTemplate/instantiate-function-2.cpp12
-rw-r--r--test/SemaTemplate/instantiate-member-class.cpp38
-rw-r--r--test/SemaTemplate/instantiate-method.cpp74
-rw-r--r--test/SemaTemplate/instantiate-static-var.cpp18
-rw-r--r--test/SemaTemplate/instantiate-subscript.cpp26
-rw-r--r--test/SemaTemplate/instantiate-template-template-parm.cpp21
-rw-r--r--test/SemaTemplate/instantiate-try-catch.cpp14
-rw-r--r--test/SemaTemplate/instantiate-type.cpp17
-rw-r--r--test/SemaTemplate/instantiate-typedef.cpp16
-rw-r--r--test/SemaTemplate/instantiation-backtrace.cpp32
-rw-r--r--test/SemaTemplate/instantiation-default-1.cpp102
-rw-r--r--test/SemaTemplate/instantiation-default-2.cpp18
-rw-r--r--test/SemaTemplate/instantiation-default-3.cpp21
-rw-r--r--test/SemaTemplate/instantiation-depth.cpp9
-rw-r--r--test/SemaTemplate/metafun-apply.cpp43
-rw-r--r--test/SemaTemplate/nested-name-spec-template.cpp61
-rw-r--r--test/SemaTemplate/nested-template.cpp16
-rw-r--r--test/SemaTemplate/qualified-names-diag.cpp16
-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.cpp5
-rw-r--r--test/SemaTemplate/temp_arg.cpp12
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp124
-rw-r--r--test/SemaTemplate/temp_arg_template.cpp38
-rw-r--r--test/SemaTemplate/temp_arg_type.cpp24
-rw-r--r--test/SemaTemplate/temp_class_spec.cpp20
-rw-r--r--test/SemaTemplate/temp_explicit.cpp111
-rw-r--r--test/SemaTemplate/temp_explicit_cxx0x.cpp24
-rw-r--r--test/SemaTemplate/temp_param.cpp90
-rw-r--r--test/SemaTemplate/typename-specifier-2.cpp30
-rw-r--r--test/SemaTemplate/typename-specifier.cpp74
59 files changed, 3101 insertions, 0 deletions
diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp
new file mode 100644
index 000000000000..c81267771297
--- /dev/null
+++ b/test/SemaTemplate/class-template-decl.cpp
@@ -0,0 +1,49 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> class A;
+
+extern "C++" {
+ template<typename T> class B;
+}
+
+namespace N {
+ template<typename T> class C;
+}
+
+extern "C" {
+ template<typename T> class D; // expected-error{{templates must have C++ linkage}}
+}
+
+template<class U> class A; // expected-note{{previous template declaration is here}}
+
+template<int N> class A; // expected-error{{template parameter has a different kind in template redeclaration}}
+
+template<int N> class NonTypeTemplateParm;
+
+typedef int INT;
+
+template<INT M> class NonTypeTemplateParm; // expected-note{{previous non-type template parameter with type 'INT' (aka 'int') is here}}
+
+template<long> class NonTypeTemplateParm; // expected-error{{template non-type parameter has a different type 'long' in template redeclaration}}
+
+template<template<typename T> class X> class TemplateTemplateParm;
+
+template<template<class> class Y> class TemplateTemplateParm; // expected-note{{previous template declaration is here}} \
+ // expected-note{{previous template template parameter is here}}
+
+template<typename> class TemplateTemplateParm; // expected-error{{template parameter has a different kind in template redeclaration}}
+
+template<template<typename T, int> class X> class TemplateTemplateParm; // expected-error{{too many template parameters in template template parameter redeclaration}}
+
+#if 0
+// FIXME: parse template declarations in these scopes, so that we can
+// complain about the one at function scope.
+class X {
+public:
+ template<typename T> class C;
+};
+
+void f() {
+ template<typename T> class X;
+}
+#endif
diff --git a/test/SemaTemplate/class-template-id-2.cpp b/test/SemaTemplate/class-template-id-2.cpp
new file mode 100644
index 000000000000..c4388a7c1556
--- /dev/null
+++ b/test/SemaTemplate/class-template-id-2.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+namespace N {
+ template<typename T> class A { };
+
+ template<> class A<int> { };
+
+ template<> class A<float>; // expected-note{{forward declaration of 'class N::A<float>'}}
+
+ class B : public A<int> { };
+}
+
+class C1 : public N::A<int> { };
+
+class C2 : public N::A<float> { }; // expected-error{{base class has incomplete type}}
+
+struct D1 {
+ operator N::A<int>();
+};
+
+namespace N {
+ struct D2 {
+ operator A<int>();
+ };
+}
diff --git a/test/SemaTemplate/class-template-id.cpp b/test/SemaTemplate/class-template-id.cpp
new file mode 100644
index 000000000000..e74a6f8dcca9
--- /dev/null
+++ b/test/SemaTemplate/class-template-id.cpp
@@ -0,0 +1,38 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T, typename U = float> struct A { };
+
+typedef A<int> A_int;
+
+typedef float FLOAT;
+
+A<int, FLOAT> *foo(A<int> *ptr, A<int> const *ptr2, A<int, double> *ptr3) {
+ if (ptr)
+ return ptr; // okay
+ else if (ptr2)
+ return ptr2; // expected-error{{incompatible type returning 'A<int> const *', expected 'A<int, FLOAT> *'}}
+ else {
+ return ptr3; // expected-error{{incompatible type returning 'A<int, double> *', expected 'A<int, FLOAT> *'}}
+ }
+}
+
+template<int I> struct B;
+
+const int value = 12;
+B<17 + 2> *bar(B<(19)> *ptr1, B< (::value + 7) > *ptr2, B<19 - 3> *ptr3) {
+ if (ptr1)
+ return ptr1;
+ else if (ptr2)
+ return ptr2;
+ else
+ return ptr3; // expected-error{{incompatible type returning 'B<19 - 3> *', expected 'B<17 + 2> *'}}
+}
+
+typedef B<5> B5;
+
+
+namespace N {
+ template<typename T> struct C {};
+}
+
+N::C<int> c1;
+typedef N::C<float> c2;
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
new file mode 100644
index 000000000000..71d8ea14be6b
--- /dev/null
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -0,0 +1,80 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T, typename U = int> struct A; // expected-note 2{{template is declared here}}
+
+template<> struct A<double, double>; // expected-note{{forward declaration}}
+
+template<> struct A<float, float> { // expected-note{{previous definition}}
+ int x;
+};
+
+template<> struct A<float> { // expected-note{{previous definition}}
+ int y;
+};
+
+int test_specs(A<float, float> *a1, A<float, int> *a2) {
+ return a1->x + a2->y;
+}
+
+int test_incomplete_specs(A<double, double> *a1,
+ A<double> *a2)
+{
+ (void)a1->x; // expected-error{{incomplete definition of type 'A<double, double>'}}
+ (void)a2->x; // expected-error{{implicit instantiation of undefined template 'struct A<double, int>'}}
+}
+
+typedef float FLOAT;
+
+template<> struct A<float, FLOAT>;
+
+template<> struct A<FLOAT, float> { }; // expected-error{{redefinition}}
+
+template<> struct A<float, int> { }; // expected-error{{redefinition}}
+
+template<typename T, typename U = int> struct X;
+
+template <> struct X<int, int> { int foo(); }; // #1
+template <> struct X<float> { int bar(); }; // #2
+
+typedef int int_type;
+void testme(X<int_type> *x1, X<float, int> *x2) {
+ (void)x1->foo(); // okay: refers to #1
+ (void)x2->bar(); // okay: refers to #2
+}
+
+// Make sure specializations are proper classes.
+template<>
+struct A<char> {
+ A();
+};
+
+A<char>::A() { }
+
+// Diagnose specialization errors
+struct A<double> { }; // expected-error{{template specialization requires 'template<>'}}
+
+template<> struct ::A<double>;
+
+namespace N {
+ template<typename T> struct B; // expected-note 2{{template is declared here}}
+
+ template<> struct ::N::B<char>; // okay
+ template<> struct ::N::B<short>; // okay
+ template<> struct ::N::B<int>; // okay
+
+ int f(int);
+}
+
+template<> struct N::B<int> { }; // okay
+
+template<> struct N::B<float> { }; // expected-error{{class template specialization of 'B' not in namespace 'N'}}
+
+namespace M {
+ template<> struct ::N::B<short> { }; // expected-error{{class template specialization of 'B' not in a namespace enclosing 'N'}}
+
+ template<> struct ::A<long double>; // expected-error{{class template specialization of 'A' must occur in the global scope}}
+}
+
+template<> struct N::B<char> {
+ int testf(int x) { return f(x); }
+};
+
diff --git a/test/SemaTemplate/current-instantiation.cpp b/test/SemaTemplate/current-instantiation.cpp
new file mode 100644
index 000000000000..603c14016fbc
--- /dev/null
+++ b/test/SemaTemplate/current-instantiation.cpp
@@ -0,0 +1,71 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// This test concerns the identity of dependent types within the
+// canonical type system, specifically focusing on the difference
+// between members of the current instantiation and membmers of an
+// unknown specialization. This considers C++ [temp.type], which
+// specifies type equivalence within a template, and C++0x
+// [temp.dep.type], which defines what it means to be a member of the
+// current instantiation.
+
+template<typename T, typename U>
+struct X0 {
+ typedef T T_type;
+ typedef U U_type;
+
+ void f0(T&); // expected-note{{previous}}
+ void f0(typename X0::U_type&);
+ void f0(typename X0::T_type&); // expected-error{{redecl}}
+
+ void f1(T&); // expected-note{{previous}}
+ void f1(typename X0::U_type&);
+ void f1(typename X0<T, U>::T_type&); // expected-error{{redecl}}
+
+ void f2(T&); // expected-note{{previous}}
+ void f2(typename X0::U_type&);
+ void f2(typename X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
+
+ void f3(T&); // expected-note{{previous}}
+ void f3(typename X0::U_type&);
+ void f3(typename ::X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
+
+ struct X1 {
+ typedef T my_T_type;
+
+ void g0(T&); // expected-note{{previous}}
+ void g0(typename X0::U_type&);
+ void g0(typename X0::T_type&); // expected-error{{redecl}}
+
+ void g1(T&); // expected-note{{previous}}
+ void g1(typename X0::U_type&);
+ void g1(typename X0<T, U>::T_type&); // expected-error{{redecl}}
+
+ void g2(T&); // expected-note{{previous}}
+ void g2(typename X0::U_type&);
+ void g2(typename X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
+
+ void g3(T&); // expected-note{{previous}}
+ void g3(typename X0::U_type&);
+ void g3(typename ::X0<T_type, U_type>::T_type&); // expected-error{{redecl}}
+
+ void g4(T&); // expected-note{{previous}}
+ void g4(typename X0::U_type&);
+ void g4(typename X1::my_T_type&); // expected-error{{redecl}}
+
+ void g5(T&); // expected-note{{previous}}
+ void g5(typename X0::U_type&);
+ void g5(typename X0::X1::my_T_type&); // expected-error{{redecl}}
+
+ void g6(T&); // expected-note{{previous}}
+ void g6(typename X0::U_type&);
+ void g6(typename X0<T, U>::X1::my_T_type&); // expected-error{{redecl}}
+
+ void g7(T&); // expected-note{{previous}}
+ void g7(typename X0::U_type&);
+ void g7(typename ::X0<typename X1::my_T_type, U_type>::X1::my_T_type&); // expected-error{{redecl}}
+
+ void g8(T&); // expected-note{{previous}}
+ void g8(typename X0<U, T_type>::T_type&);
+ void g8(typename ::X0<typename X0<T_type, U>::X1::my_T_type, U_type>::X1::my_T_type&); // expected-error{{redecl}}
+ };
+};
diff --git a/test/SemaTemplate/default-arguments.cpp b/test/SemaTemplate/default-arguments.cpp
new file mode 100644
index 000000000000..572227cb61de
--- /dev/null
+++ b/test/SemaTemplate/default-arguments.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, int N = 2> struct X; // expected-note{{template is declared here}}
+
+X<int, 1> *x1;
+X<int> *x2;
+
+X<> *x3; // expected-error{{too few template arguments for class template 'X'}}
+
+template<typename U = float, int M> struct X;
+
+X<> *x4;
diff --git a/test/SemaTemplate/dependent-type-identity.cpp b/test/SemaTemplate/dependent-type-identity.cpp
new file mode 100644
index 000000000000..739cb7f39fa3
--- /dev/null
+++ b/test/SemaTemplate/dependent-type-identity.cpp
@@ -0,0 +1,72 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// This test concerns the identity of dependent types within the
+// canonical type system. This corresponds to C++ [temp.type], which
+// specifies type equivalence within a template.
+//
+// FIXME: template template parameters
+
+namespace N {
+ template<typename T>
+ struct X2 {
+ template<typename U>
+ struct apply {
+ typedef U* type;
+ };
+ };
+}
+
+namespace Nalias = N;
+
+template<typename T>
+struct X0 { };
+
+using namespace N;
+
+template<typename T, typename U>
+struct X1 {
+ typedef T type;
+ typedef U U_type;
+
+ void f0(T); // expected-note{{previous}}
+ void f0(U);
+ void f0(type); // expected-error{{redeclar}}
+
+ void f1(T*); // expected-note{{previous}}
+ void f1(U*);
+ void f1(type*); // expected-error{{redeclar}}
+
+ void f2(X0<T>*); // expected-note{{previous}}
+ void f2(X0<U>*);
+ void f2(X0<type>*); // expected-error{{redeclar}}
+
+ void f3(X0<T>*); // expected-note{{previous}}
+ void f3(X0<U>*);
+ void f3(::X0<type>*); // expected-error{{redeclar}}
+
+ void f4(typename T::template apply<U>*); // expected-note{{previous}}
+ void f4(typename U::template apply<U>*);
+ void f4(typename type::template apply<T>*);
+ void f4(typename type::template apply<U_type>*); // expected-error{{redeclar}}
+
+ void f5(typename T::template apply<U>::type*); // expected-note{{previous}}
+ void f5(typename U::template apply<U>::type*);
+ void f5(typename U::template apply<T>::type*);
+ void f5(typename type::template apply<T>::type*);
+ void f5(typename type::template apply<U_type>::type*); // expected-error{{redeclar}}
+
+ void f6(typename N::X2<T>::template apply<U> *); // expected-note{{previous}}
+ void f6(typename N::X2<U>::template apply<U> *);
+ void f6(typename N::X2<U>::template apply<T> *);
+ void f6(typename ::N::X2<type>::template apply<U_type> *); // expected-error{{redeclar}}
+
+ void f7(typename N::X2<T>::template apply<U> *); // expected-note{{previous}}
+ void f7(typename N::X2<U>::template apply<U> *);
+ void f7(typename N::X2<U>::template apply<T> *);
+ void f7(typename X2<type>::template apply<U_type> *); // expected-error{{redeclar}}
+
+ void f8(typename N::X2<T>::template apply<U> *); // expected-note{{previous}}
+ void f8(typename N::X2<U>::template apply<U> *);
+ void f8(typename N::X2<U>::template apply<T> *);
+ void f8(typename ::Nalias::X2<type>::template apply<U_type> *); // expected-error{{redeclar}}
+};
diff --git a/test/SemaTemplate/enum-argument.cpp b/test/SemaTemplate/enum-argument.cpp
new file mode 100644
index 000000000000..101a1d0cd9da
--- /dev/null
+++ b/test/SemaTemplate/enum-argument.cpp
@@ -0,0 +1,7 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+enum Enum { val = 1 };
+template <Enum v> struct C {
+ typedef C<v> Self;
+};
+template struct C<val>;
diff --git a/test/SemaTemplate/example-dynarray.cpp b/test/SemaTemplate/example-dynarray.cpp
new file mode 100644
index 000000000000..cca3709bebbf
--- /dev/null
+++ b/test/SemaTemplate/example-dynarray.cpp
@@ -0,0 +1,150 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+#include <stddef.h>
+#include <stdlib.h>
+#include <assert.h>
+
+// Placement new requires <new> to be included, but we don't support that yet.
+void* operator new(size_t, void* ptr) throw() {
+ return ptr;
+}
+void operator delete(void*, void*) throw() {
+}
+
+template<typename T>
+class dynarray {
+public:
+ dynarray() { Start = Last = End = 0; }
+
+ dynarray(const dynarray &other) {
+ Start = (T*)malloc(sizeof(T) * other.size());
+ Last = End = Start + other.size();
+
+ for (unsigned I = 0, N = other.size(); I != N; ++I)
+ new (Start + I) T(other[I]);
+ }
+
+ ~dynarray() {
+ free(Start);
+ }
+
+ dynarray &operator=(const dynarray &other) {
+ T* NewStart = (T*)malloc(sizeof(T) * other.size());
+
+ for (unsigned I = 0, N = other.size(); I != N; ++I)
+ new (NewStart + I) T(other[I]);
+
+ // FIXME: destroy everything in Start
+ free(Start);
+ Start = NewStart;
+ Last = End = NewStart + other.size();
+ return *this;
+ }
+
+ unsigned size() const { return Last - Start; }
+ unsigned capacity() const { return End - Start; }
+
+ void push_back(const T& value) {
+ if (Last == End) {
+ unsigned NewCapacity = capacity() * 2;
+ if (NewCapacity == 0)
+ NewCapacity = 4;
+
+ T* NewStart = (T*)malloc(sizeof(T) * NewCapacity);
+
+ unsigned Size = size();
+ for (unsigned I = 0; I != Size; ++I)
+ new (NewStart + I) T(Start[I]);
+
+ // FIXME: destruct old values
+ free(Start);
+
+ Start = NewStart;
+ Last = Start + Size;
+ End = Start + NewCapacity;
+ }
+
+ new (Last) T(value);
+ ++Last;
+ }
+
+ void pop_back() {
+ // FIXME: destruct old value
+ --Last;
+ }
+
+ T& operator[](unsigned Idx) {
+ return Start[Idx];
+ }
+
+ const T& operator[](unsigned Idx) const {
+ return Start[Idx];
+ }
+
+ typedef T* iterator;
+ typedef const T* const_iterator;
+
+ iterator begin() { return Start; }
+ const_iterator begin() const { return Start; }
+
+ iterator end() { return Last; }
+ const_iterator end() const { return Last; }
+
+public:
+ T* Start, *Last, *End;
+};
+
+struct Point {
+ Point() { x = y = z = 0.0; }
+ Point(const Point& other) : x(other.x), y(other.y), z(other.z) { }
+
+ float x, y, z;
+};
+
+// FIXME: remove these when we have implicit instantiation for member
+// functions of class templates.
+template class dynarray<int>;
+template class dynarray<Point>;
+
+int main() {
+ dynarray<int> di;
+ di.push_back(0);
+ di.push_back(1);
+ di.push_back(2);
+ di.push_back(3);
+ di.push_back(4);
+ assert(di.size() == 5);
+ for (dynarray<int>::iterator I = di.begin(), IEnd = di.end(); I != IEnd; ++I)
+ assert(*I == I - di.begin());
+
+ for (int I = 0, N = di.size(); I != N; ++I)
+ assert(di[I] == I);
+
+ di.pop_back();
+ assert(di.size() == 4);
+ di.push_back(4);
+
+ dynarray<int> di2 = di;
+ assert(di2.size() == 5);
+ assert(di.begin() != di2.begin());
+ for (dynarray<int>::iterator I = di2.begin(), IEnd = di2.end();
+ I != IEnd; ++I)
+ assert(*I == I - di2.begin());
+
+ dynarray<int> di3(di);
+ assert(di3.size() == 5);
+ assert(di.begin() != di3.begin());
+ for (dynarray<int>::iterator I = di3.begin(), IEnd = di3.end();
+ I != IEnd; ++I)
+ assert(*I == I - di3.begin());
+
+ dynarray<int> di4;
+ assert(di4.size() == 0);
+ di4 = di;
+ assert(di4.size() == 5);
+ assert(di.begin() != di4.begin());
+ for (dynarray<int>::iterator I = di4.begin(), IEnd = di4.end();
+ I != IEnd; ++I)
+ assert(*I == I - di4.begin());
+
+ return 0;
+}
diff --git a/test/SemaTemplate/fibonacci.cpp b/test/SemaTemplate/fibonacci.cpp
new file mode 100644
index 000000000000..6cd50157e2bd
--- /dev/null
+++ b/test/SemaTemplate/fibonacci.cpp
@@ -0,0 +1,66 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<unsigned I>
+struct FibonacciEval;
+
+template<unsigned I>
+struct Fibonacci {
+ enum { value = FibonacciEval<I-1>::value + FibonacciEval<I-2>::value };
+};
+
+template<unsigned I>
+struct FibonacciEval {
+ enum { value = Fibonacci<I>::value };
+};
+
+template<> struct Fibonacci<0> {
+ enum { value = 0 };
+};
+
+template<> struct Fibonacci<1> {
+ enum { value = 1 };
+};
+
+int array5[Fibonacci<5>::value == 5? 1 : -1];
+int array10[Fibonacci<10>::value == 55? 1 : -1];
+
+template<unsigned I>
+struct FibonacciEval2;
+
+template<unsigned I>
+struct Fibonacci2 {
+ static const unsigned value
+ = FibonacciEval2<I-1>::value + FibonacciEval2<I-2>::value;
+};
+
+template<unsigned I>
+struct FibonacciEval2 {
+ static const unsigned value = Fibonacci2<I>::value;
+};
+
+template<> struct Fibonacci2<0> {
+ static const unsigned value = 0;
+};
+
+template<> struct Fibonacci2<1> {
+ static const unsigned value = 1;
+};
+
+int array5_2[Fibonacci2<5>::value == 5? 1 : -1];
+int array10_2[Fibonacci2<10>::value == 55? 1 : -1];
+
+template<unsigned I>
+struct Fibonacci3 {
+ static const unsigned value = Fibonacci3<I-1>::value + Fibonacci3<I-2>::value;
+};
+
+template<> struct Fibonacci3<0> {
+ static const unsigned value = 0;
+};
+
+template<> struct Fibonacci3<1> {
+ static const unsigned value = 1;
+};
+
+int array5_3[Fibonacci3<5>::value == 5? 1 : -1];
+int array10_3[Fibonacci3<10>::value == 55? 1 : -1];
diff --git a/test/SemaTemplate/fun-template-def.cpp b/test/SemaTemplate/fun-template-def.cpp
new file mode 100644
index 000000000000..8833ef4ddc1d
--- /dev/null
+++ b/test/SemaTemplate/fun-template-def.cpp
@@ -0,0 +1,43 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Tests that dependent expressions are always allowed, whereas non-dependent
+// are checked as usual.
+
+#include <stddef.h>
+
+// Fake typeid, lacking a typeinfo header.
+namespace std { class type_info {}; }
+
+struct dummy {};
+
+template <typename T, typename U>
+T f(T t1, U u1, int i1)
+{
+ T t2 = i1;
+ t2 = i1 + u1;
+ ++u1;
+ u1++;
+ int i2 = u1;
+
+ i1 = t1[u1];
+ i1 *= t1;
+
+ i1(u1, t1); // error
+ u1(i1, t1);
+
+ U u2 = (T)i1;
+ static_cast<void>(static_cast<U>(reinterpret_cast<T>(
+ dynamic_cast<U>(const_cast<T>(i1)))));
+
+ new U(i1, t1);
+ new int(t1, u1); // expected-error {{initializer of a builtin type can only take one argument}}
+ new (t1, u1) int;
+ delete t1;
+
+ dummy d1 = sizeof(t1); // FIXME: delayed checking okay?
+ dummy d2 = offsetof(T, foo); // expected-error {{cannot initialize 'd2'}}
+ dummy d3 = __alignof(u1); // FIXME: delayed checking okay?
+ i1 = typeid(t1); // expected-error {{incompatible type assigning}}
+
+ return u1;
+}
diff --git a/test/SemaTemplate/injected-class-name.cpp b/test/SemaTemplate/injected-class-name.cpp
new file mode 100644
index 000000000000..c5f826d849ca
--- /dev/null
+++ b/test/SemaTemplate/injected-class-name.cpp
@@ -0,0 +1,40 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T>
+struct X {
+ X<T*> *ptr;
+};
+
+X<int> x;
+
+template<>
+struct X<int***> {
+ typedef X<int***> *ptr;
+};
+
+// FIXME: EDG rejects this in their strict-conformance mode, but I
+// don't see any wording making this ill-formed. Actually,
+// [temp.local]p2 might make it ill-formed. Are we "in the scope of
+// the class template specialization?"
+X<float>::X<int> xi = x;
+
+// [temp.local]p1:
+
+// FIXME: test non-type and template template parameters
+template<typename T, typename U>
+struct X0 {
+ typedef T type;
+ typedef U U_type;
+ typedef U_type U_type2;
+
+ void f0(const X0&); // expected-note{{here}}
+ void f0(X0&);
+ void f0(const X0<T, U>&); // expected-error{{redecl}}
+
+ void f1(const X0&); // expected-note{{here}}
+ void f1(X0&);
+ void f1(const X0<type, U_type2>&); // expected-error{{redecl}}
+
+ void f2(const X0&); // expected-note{{here}}
+ void f2(X0&);
+ void f2(const ::X0<type, U_type2>&); // expected-error{{redecl}}
+};
diff --git a/test/SemaTemplate/instantiate-array.cpp b/test/SemaTemplate/instantiate-array.cpp
new file mode 100644
index 000000000000..29279b436899
--- /dev/null
+++ b/test/SemaTemplate/instantiate-array.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y)
+#define __CONCAT1(__X, __Y) __X ## __Y
+
+#define static_assert(__b, __m) \
+ typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1]
+#endif
+
+template <int N> class IntArray {
+ int elems[N];
+};
+
+static_assert(sizeof(IntArray<10>) == sizeof(int) * 10, "Array size mismatch");
+static_assert(sizeof(IntArray<1>) == sizeof(int) * 1, "Array size mismatch");
+
+template <typename T> class TenElementArray {
+ int elems[10];
+};
+
+static_assert(sizeof(TenElementArray<int>) == sizeof(int) * 10, "Array size mismatch");
+
+template<typename T, int N> class Array {
+ T elems[N];
+};
+
+static_assert(sizeof(Array<int, 10>) == sizeof(int) * 10, "Array size mismatch");
diff --git a/test/SemaTemplate/instantiate-c99.cpp b/test/SemaTemplate/instantiate-c99.cpp
new file mode 100644
index 000000000000..cf691cffad36
--- /dev/null
+++ b/test/SemaTemplate/instantiate-c99.cpp
@@ -0,0 +1,81 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Test template instantiation for C99-specific features.
+
+// ---------------------------------------------------------------------
+// Designated initializers
+// ---------------------------------------------------------------------
+template<typename T, typename XType, typename YType>
+struct DesigInit0 {
+ void f(XType x, YType y) {
+ T agg = {
+ .y = y, // expected-error{{does not refer}}
+ .x = x // expected-error{{does not refer}}
+ };
+ }
+};
+
+struct Point2D {
+ float x, y;
+};
+
+template struct DesigInit0<Point2D, int, double>;
+
+struct Point3D {
+ float x, y, z;
+};
+
+template struct DesigInit0<Point3D, int, double>;
+
+struct Color {
+ unsigned char red, green, blue;
+};
+
+struct ColorPoint3D {
+ Color color;
+ float x, y, z;
+};
+
+template struct DesigInit0<ColorPoint3D, int, double>;
+template struct DesigInit0<Color, int, double>; // expected-note{{instantiation}}
+
+template<typename T, int Subscript1, int Subscript2,
+ typename Val1, typename Val2>
+struct DesigArrayInit0 {
+ void f(Val1 val1, Val2 val2) {
+ T array = {
+ [Subscript1] = val1,
+ [Subscript2] = val2 // expected-error{{exceeds array bounds}}
+ };
+
+ int array2[10] = { [5] = 3 };
+ }
+};
+
+template struct DesigArrayInit0<int[8], 5, 3, float, int>;
+template struct DesigArrayInit0<int[8], 5, 13, float, int>; // expected-note{{instantiation}}
+
+template<typename T, int Subscript1, int Subscript2,
+ typename Val1>
+struct DesigArrayRangeInit0 {
+ void f(Val1 val1) {
+ T array = {
+ [Subscript1...Subscript2] = val1 // expected-error{{exceeds}}
+ };
+ }
+};
+
+template struct DesigArrayRangeInit0<int[8], 3, 5, float>;
+template struct DesigArrayRangeInit0<int[8], 5, 13, float>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// Compound literals
+// ---------------------------------------------------------------------
+template<typename T, typename Arg1, typename Arg2>
+struct CompoundLiteral0 {
+ T f(Arg1 a1, Arg2 a2) {
+ return (T){a1, a2};
+ }
+};
+
+template struct CompoundLiteral0<Point2D, int, float>;
diff --git a/test/SemaTemplate/instantiate-call.cpp b/test/SemaTemplate/instantiate-call.cpp
new file mode 100644
index 000000000000..a9c4bf481ded
--- /dev/null
+++ b/test/SemaTemplate/instantiate-call.cpp
@@ -0,0 +1,50 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N1 {
+ struct X0 { };
+
+ int& f0(X0);
+}
+
+namespace N2 {
+ char& f0(char);
+
+ template<typename T, typename Result>
+ struct call_f0 {
+ void test_f0(T t) {
+ Result result = f0(t);
+ }
+ };
+}
+
+template struct N2::call_f0<int, char&>;
+template struct N2::call_f0<N1::X0, int&>;
+
+namespace N3 {
+ template<typename T, typename Result>
+ struct call_f0 {
+ void test_f0(T t) {
+ Result &result = f0(t); // expected-error 2{{no matching}}
+ }
+ };
+}
+
+template struct N3::call_f0<int, char&>; // expected-note{{instantiation}}
+template struct N3::call_f0<N1::X0, int&>;
+
+short& f0(char);
+namespace N4 {
+ template<typename T, typename Result>
+ struct call_f0 {
+ void test_f0(T t) {
+ Result &result = f0(t);
+ }
+ };
+}
+
+template struct N4::call_f0<int, short&>;
+template struct N4::call_f0<N1::X0, int&>;
+template struct N3::call_f0<int, short&>; // expected-note{{instantiation}}
+
+// FIXME: test overloaded function call operators, calls to member
+// functions, etc.
diff --git a/test/SemaTemplate/instantiate-cast.cpp b/test/SemaTemplate/instantiate-cast.cpp
new file mode 100644
index 000000000000..d99f3e556602
--- /dev/null
+++ b/test/SemaTemplate/instantiate-cast.cpp
@@ -0,0 +1,109 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct A { int x; };
+
+class Base {
+public:
+ virtual void f();
+};
+
+class Derived : public Base { };
+
+struct ConvertibleToInt {
+ operator int() const;
+};
+
+struct Constructible {
+ Constructible(int, float);
+};
+
+// ---------------------------------------------------------------------
+// C-style casts
+// ---------------------------------------------------------------------
+template<typename T, typename U>
+struct CStyleCast0 {
+ void f(T t) {
+ (void)((U)t); // FIXME:ugly expected-error{{operand}}
+ }
+};
+
+template struct CStyleCast0<int, float>;
+template struct CStyleCast0<A, int>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// static_cast
+// ---------------------------------------------------------------------
+template<typename T, typename U>
+struct StaticCast0 {
+ void f(T t) {
+ (void)static_cast<U>(t); // expected-error{{static_cast}}
+ }
+};
+
+template struct StaticCast0<ConvertibleToInt, bool>;
+template struct StaticCast0<int, float>;
+template struct StaticCast0<int, A>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// dynamic_cast
+// ---------------------------------------------------------------------
+template<typename T, typename U>
+struct DynamicCast0 {
+ void f(T t) {
+ (void)dynamic_cast<U>(t); // expected-error{{not a reference or pointer}}
+ }
+};
+
+template struct DynamicCast0<Base*, Derived*>;
+template struct DynamicCast0<Base*, A>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// reinterpret_cast
+// ---------------------------------------------------------------------
+template<typename T, typename U>
+struct ReinterpretCast0 {
+ void f(T t) {
+ (void)reinterpret_cast<U>(t); // expected-error{{constness}}
+ }
+};
+
+template struct ReinterpretCast0<void (*)(int), void (*)(float)>;
+template struct ReinterpretCast0<int const *, float *>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// const_cast
+// ---------------------------------------------------------------------
+template<typename T, typename U>
+struct ConstCast0 {
+ void f(T t) {
+ (void)const_cast<U>(t); // expected-error{{not allowed}}
+ }
+};
+
+template struct ConstCast0<int const * *, int * *>;
+template struct ConstCast0<int const *, float *>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// C++ functional cast
+// ---------------------------------------------------------------------
+template<typename T, typename U>
+struct FunctionalCast1 {
+ void f(T t) {
+ (void)U(t); // FIXME:ugly expected-error{{operand}}
+ }
+};
+
+template struct FunctionalCast1<int, float>;
+template struct FunctionalCast1<A, int>; // expected-note{{instantiation}}
+
+#if 0
+// Generates temporaries, which we cannot handle yet.
+template<int N, long M>
+struct FunctionalCast2 {
+ void f() {
+ (void)Constructible(N, M);
+ }
+};
+
+template struct FunctionalCast2<1, 3>;
+#endif
diff --git a/test/SemaTemplate/instantiate-clang.cpp b/test/SemaTemplate/instantiate-clang.cpp
new file mode 100644
index 000000000000..a6c28d9e19db
--- /dev/null
+++ b/test/SemaTemplate/instantiate-clang.cpp
@@ -0,0 +1,35 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Test template instantiation for Clang-specific features.
+
+// ---------------------------------------------------------------------
+// Vector types
+// ---------------------------------------------------------------------
+typedef __attribute__(( ext_vector_type(2) )) double double2;
+typedef __attribute__(( ext_vector_type(4) )) double double4;
+
+template<typename T>
+struct ExtVectorAccess0 {
+ void f(T v1, double4 v2) {
+ v1.xy = v2.yx;
+ }
+};
+
+template struct ExtVectorAccess0<double2>;
+template struct ExtVectorAccess0<double4>;
+
+typedef __attribute__(( ext_vector_type(2) )) double double2;
+
+template<typename T, typename U, int N, int M>
+struct ShuffleVector0 {
+ void f(T t, U u, double2 a, double2 b) {
+ (void)__builtin_shufflevector(t, u, N, M); // expected-error{{index}}
+ (void)__builtin_shufflevector(a, b, N, M);
+ (void)__builtin_shufflevector(a, b, 2, 1);
+ }
+};
+
+template struct ShuffleVector0<double2, double2, 2, 1>;
+template struct ShuffleVector0<double2, double2, 4, 3>; // expected-note{{instantiation}}
+
+
diff --git a/test/SemaTemplate/instantiate-complete.cpp b/test/SemaTemplate/instantiate-complete.cpp
new file mode 100644
index 000000000000..babc55217a95
--- /dev/null
+++ b/test/SemaTemplate/instantiate-complete.cpp
@@ -0,0 +1,47 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// Tests various places where requiring a complete type involves
+// instantiation of that type.
+
+template<typename T>
+struct X {
+ X(T);
+
+ T f; // expected-error{{data member instantiated with function type 'float (int)'}} \
+ // expected-error{{data member instantiated with function type 'int (int)'}} \
+ // expected-error{{data member instantiated with function type 'char (char)'}} \
+ // expected-error{{data member instantiated with function type 'short (short)'}} \
+ // expected-error{{data member instantiated with function type 'float (float)'}}
+};
+
+X<int> f() { return 0; }
+
+struct XField {
+ X<float(int)> xf; // expected-note{{in instantiation of template class 'struct X<float (int)>' requested here}}
+};
+
+void test_subscript(X<double> *ptr1, X<int(int)> *ptr2, int i) {
+ (void)ptr1[i];
+ (void)ptr2[i]; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}}
+}
+
+void test_arith(X<signed char> *ptr1, X<unsigned char> *ptr2,
+ X<char(char)> *ptr3, X<short(short)> *ptr4) {
+ (void)(ptr1 + 5);
+ // FIXME: if I drop the ')' after void, below, it still parses (!)
+ (void)(5 + ptr2);
+ (void)(ptr3 + 5); // expected-note{{in instantiation of template class 'struct X<char (char)>' requested here}}
+ (void)(5 + ptr4); // expected-note{{in instantiation of template class 'struct X<short (short)>' requested here}}
+}
+
+void test_new() {
+ (void)new X<float>(0);
+ (void)new X<float(float)>; // expected-note{{in instantiation of template class 'struct X<float (float)>' requested here}}
+}
+
+void test_memptr(X<long> *p1, long X<long>::*pm1,
+ X<long(long)> *p2,
+ long (X<long(long)>::*pm2)(long)) {
+ (void)(p1->*pm1);
+ (void)((p2->*pm2)(0));
+}
diff --git a/test/SemaTemplate/instantiate-declref.cpp b/test/SemaTemplate/instantiate-declref.cpp
new file mode 100644
index 000000000000..051c6050abea
--- /dev/null
+++ b/test/SemaTemplate/instantiate-declref.cpp
@@ -0,0 +1,71 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+namespace N {
+ struct Outer {
+ struct Inner {
+ template<typename T>
+ struct InnerTemplate {
+ struct VeryInner {
+ typedef T type;
+
+ static enum K1 { K1Val = sizeof(T) } Kind1;
+ static enum { K2Val = sizeof(T)*2 } Kind2;
+ enum { K3Val = sizeof(T)*2 } Kind3;
+
+ void foo() {
+ K1 k1 = K1Val;
+ Kind1 = K1Val;
+ Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val;
+ Kind3 = K3Val;
+ }
+
+ struct UeberInner {
+ void bar() {
+ K1 k1 = K1Val;
+ Kind1 = K1Val;
+ Outer::Inner::InnerTemplate<type>::VeryInner::Kind2 = K2Val;
+
+ InnerTemplate t;
+ InnerTemplate<type> t2;
+ }
+ };
+ };
+ };
+ };
+ };
+}
+
+typedef int INT;
+template struct N::Outer::Inner::InnerTemplate<INT>::VeryInner;
+template struct N::Outer::Inner::InnerTemplate<INT>::UeberInner; // expected-error{{'UeberInner' does not name a tag member}}
+
+namespace N2 {
+ struct Outer2 {
+ template<typename T, typename U = T>
+ struct Inner {
+ void foo() {
+ enum { K1Val = sizeof(T) } k1;
+ enum K2 { K2Val = sizeof(T)*2 } k2a;
+
+ K2 k2b = K2Val;
+
+ struct S { T x, y; } s1;
+ struct { U x, y; } s2;
+ s1.x = s2.x; // expected-error{{incompatible}}
+
+ typedef T type;
+ type t2 = s1.x;
+
+ typedef struct { T z; } type2;
+ type2 t3 = { s1.x };
+
+ Inner i1;
+ i1.foo();
+ Inner<T> i2;
+ i2.foo();
+ }
+ };
+ };
+}
+
+template struct N2::Outer2::Inner<float>;
+template struct N2::Outer2::Inner<int*, float*>; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/instantiate-enum.cpp b/test/SemaTemplate/instantiate-enum.cpp
new file mode 100644
index 000000000000..a7acf22a45a1
--- /dev/null
+++ b/test/SemaTemplate/instantiate-enum.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T, T I, int J>
+struct adder {
+ enum {
+ value = I + J,
+ value2
+ };
+};
+
+int array1[adder<long, 3, 4>::value == 7? 1 : -1];
diff --git a/test/SemaTemplate/instantiate-expr-1.cpp b/test/SemaTemplate/instantiate-expr-1.cpp
new file mode 100644
index 000000000000..13ee3ab525ba
--- /dev/null
+++ b/test/SemaTemplate/instantiate-expr-1.cpp
@@ -0,0 +1,71 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<int I, int J>
+struct Bitfields {
+ int simple : I; // expected-error{{bit-field 'simple' has zero width}}
+ int parens : (J);
+};
+
+void test_Bitfields(Bitfields<0, 5> *b) {
+ (void)sizeof(Bitfields<10, 5>);
+ (void)sizeof(Bitfields<0, 1>); // expected-note{{in instantiation of template class 'struct Bitfields<0, 1>' requested here}}
+}
+
+template<int I, int J>
+struct BitfieldPlus {
+ int bitfield : I + J; // expected-error{{bit-field 'bitfield' has zero width}}
+};
+
+void test_BitfieldPlus() {
+ (void)sizeof(BitfieldPlus<0, 1>);
+ (void)sizeof(BitfieldPlus<-5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldPlus<-5, 5>' requested here}}
+}
+
+template<int I, int J>
+struct BitfieldMinus {
+ int bitfield : I - J; // expected-error{{bit-field 'bitfield' has negative width (-1)}} \
+ // expected-error{{bit-field 'bitfield' has zero width}}
+};
+
+void test_BitfieldMinus() {
+ (void)sizeof(BitfieldMinus<5, 1>);
+ (void)sizeof(BitfieldMinus<0, 1>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<0, 1>' requested here}}
+ (void)sizeof(BitfieldMinus<5, 5>); // expected-note{{in instantiation of template class 'struct BitfieldMinus<5, 5>' requested here}}
+}
+
+template<int I, int J>
+struct BitfieldDivide {
+ int bitfield : I / J; // expected-error{{expression is not an integer constant expression}} \
+ // expected-note{{division by zero}}
+};
+
+void test_BitfieldDivide() {
+ (void)sizeof(BitfieldDivide<5, 1>);
+ (void)sizeof(BitfieldDivide<5, 0>); // expected-note{{in instantiation of template class 'struct BitfieldDivide<5, 0>' requested here}}
+}
+
+template<typename T, T I, int J>
+struct BitfieldDep {
+ int bitfield : I + J;
+};
+
+void test_BitfieldDep() {
+ (void)sizeof(BitfieldDep<int, 1, 5>);
+}
+
+template<int I>
+struct BitfieldNeg {
+ int bitfield : (-I); // expected-error{{bit-field 'bitfield' has negative width (-5)}}
+};
+
+template<typename T, T I>
+struct BitfieldNeg2 {
+ int bitfield : (-I); // expected-error{{bit-field 'bitfield' has negative width (-5)}}
+};
+
+void test_BitfieldNeg() {
+ (void)sizeof(BitfieldNeg<-5>); // okay
+ (void)sizeof(BitfieldNeg<5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg<5>' requested here}}
+ (void)sizeof(BitfieldNeg2<int, -5>); // okay
+ (void)sizeof(BitfieldNeg2<int, 5>); // expected-note{{in instantiation of template class 'struct BitfieldNeg2<int, 5>' requested here}}
+}
diff --git a/test/SemaTemplate/instantiate-expr-2.cpp b/test/SemaTemplate/instantiate-expr-2.cpp
new file mode 100644
index 000000000000..80f403ed56fe
--- /dev/null
+++ b/test/SemaTemplate/instantiate-expr-2.cpp
@@ -0,0 +1,132 @@
+// RUN: clang-cc -fsyntax-only %s
+typedef char one_byte;
+typedef char (&two_bytes)[2];
+typedef char (&four_bytes)[4];
+typedef char (&eight_bytes)[8];
+
+template<int N> struct A { };
+
+namespace N1 {
+ struct X { };
+}
+
+namespace N2 {
+ struct Y { };
+
+ two_bytes operator+(Y, Y);
+}
+
+namespace N3 {
+ struct Z { };
+
+ eight_bytes operator+(Z, Z);
+}
+
+namespace N4 {
+ one_byte operator+(N1::X, N2::Y);
+
+ template<typename T, typename U>
+ struct BinOpOverload {
+ typedef A<sizeof(T() + U())> type;
+ };
+}
+
+namespace N1 {
+ four_bytes operator+(X, X);
+}
+
+namespace N3 {
+ eight_bytes operator+(Z, Z); // redeclaration
+}
+
+void test_bin_op_overload(A<1> *a1, A<2> *a2, A<4> *a4, A<8> *a8) {
+ typedef N4::BinOpOverload<N1::X, N2::Y>::type XY;
+ XY *xy = a1;
+ typedef N4::BinOpOverload<N1::X, N1::X>::type XX;
+ XX *xx = a4;
+ typedef N4::BinOpOverload<N2::Y, N2::Y>::type YY;
+ YY *yy = a2;
+ typedef N4::BinOpOverload<N3::Z, N3::Z>::type ZZ;
+ ZZ *zz = a8;
+}
+
+namespace N3 {
+ eight_bytes operator-(::N3::Z);
+}
+
+namespace N4 {
+ template<typename T>
+ struct UnaryOpOverload {
+ typedef A<sizeof(-T())> type;
+ };
+}
+
+void test_unary_op_overload(A<8> *a8) {
+ typedef N4::UnaryOpOverload<N3::Z>::type UZ;
+ UZ *uz = a8;
+}
+
+/*
+namespace N5 {
+ template<int I>
+ struct Lookup {
+ enum { val = I, more = val + 1 };
+ };
+
+ template<bool B>
+ struct Cond {
+ enum Junk { is = B ? Lookup<B>::more : Lookup<Lookup<B+1>::more>::val };
+ };
+
+ enum { resultT = Cond<true>::is,
+ resultF = Cond<false>::is };
+}
+*/
+
+namespace N6 {
+ // non-typedependent
+ template<int I>
+ struct Lookup {};
+
+ template<bool B, typename T, typename E>
+ struct Cond {
+ typedef Lookup<B ? sizeof(T) : sizeof(E)> True;
+ typedef Lookup<!B ? sizeof(T) : sizeof(E)> False;
+ };
+
+ typedef Cond<true, int, char>::True True;
+ typedef Cond<true, int, char>::False False;
+
+ // check that we have the right types
+ Lookup<1> const &L1(False());
+ Lookup<sizeof(int)> const &L2(True());
+}
+
+
+namespace N7 {
+ // type dependent
+ template<int I>
+ struct Lookup {};
+
+ template<bool B, typename T, typename E>
+ struct Cond {
+ T foo() { return B ? T() : E(); }
+ typedef Lookup<sizeof(B ? T() : E())> Type;
+ };
+
+ //Cond<true, int*, double> C; // Errors
+ //int V(C.foo()); // Errors
+ //typedef Cond<true, int*, double>::Type Type; // Errors
+ typedef Cond<true, int, double>::Type Type;
+}
+
+template<typename T, unsigned long N> struct IntegralConstant { };
+
+template<typename T>
+struct X0 {
+ void f(T x, IntegralConstant<T, sizeof(x)>);
+};
+
+void test_X0(X0<int> x, IntegralConstant<int, sizeof(int)> ic) {
+ x.f(5,ic);
+}
diff --git a/test/SemaTemplate/instantiate-expr-3.cpp b/test/SemaTemplate/instantiate-expr-3.cpp
new file mode 100644
index 000000000000..696b58325cd7
--- /dev/null
+++ b/test/SemaTemplate/instantiate-expr-3.cpp
@@ -0,0 +1,115 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// ---------------------------------------------------------------------
+// Imaginary literals
+// ---------------------------------------------------------------------
+template<typename T>
+struct ImaginaryLiteral0 {
+ void f(T &x) {
+ x = 3.0I; // expected-error{{incompatible type}}
+ }
+};
+
+template struct ImaginaryLiteral0<_Complex float>;
+template struct ImaginaryLiteral0<int*>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// Compound assignment operator
+// ---------------------------------------------------------------------
+namespace N1 {
+ struct X { };
+
+ int& operator+=(X&, int); // expected-note{{candidate}}
+}
+
+namespace N2 {
+ long& operator+=(N1::X&, long); // expected-note{{candidate}}
+
+ template<typename T, typename U, typename Result>
+ struct PlusEquals0 {
+ void f(T t, U u) {
+ Result r = t += u; // expected-error{{ambiguous}}
+ }
+ };
+}
+
+namespace N3 {
+ struct Y : public N1::X {
+ short& operator+=(long); // expected-note{{candidate}}
+ };
+}
+
+template struct N2::PlusEquals0<N1::X, int, int&>;
+template struct N2::PlusEquals0<N1::X, long, long&>;
+template struct N2::PlusEquals0<N3::Y, long, short&>;
+template struct N2::PlusEquals0<int, int, int&>;
+template struct N2::PlusEquals0<N3::Y, int, short&>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// Conditional operator
+// ---------------------------------------------------------------------
+template<typename T, typename U, typename Result>
+struct Conditional0 {
+ void f(T t, U u) {
+ Result result = t? : u;
+ }
+};
+
+template struct Conditional0<int, int, int>;
+
+// ---------------------------------------------------------------------
+// Statement expressions
+// ---------------------------------------------------------------------
+template<typename T>
+struct StatementExpr0 {
+ void f(T t) {
+ (void)({ if (t) t = t + 17; t + 12;}); // expected-error{{invalid}}
+ }
+};
+
+template struct StatementExpr0<int>;
+template struct StatementExpr0<N1::X>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// __builtin_choose_expr
+// ---------------------------------------------------------------------
+template<bool Cond, typename T, typename U, typename Result>
+struct Choose0 {
+ void f(T t, U u) {
+ Result r = __builtin_choose_expr(Cond, t, u); // expected-error{{lvalue}}
+ }
+};
+
+template struct Choose0<true, int, float, int&>;
+template struct Choose0<false, int, float, float&>;
+template struct Choose0<true, int, float, float&>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// __builtin_va_arg
+// ---------------------------------------------------------------------
+template<typename ArgType>
+struct VaArg0 {
+ void f(int n, ...) {
+ __builtin_va_list va;
+ __builtin_va_start(va, n);
+ for (int i = 0; i != n; ++i)
+ (void)__builtin_va_arg(va, ArgType);
+ __builtin_va_end(va);
+ }
+};
+
+template struct VaArg0<int>;
+
+template<typename VaList, typename ArgType>
+struct VaArg1 {
+ void f(int n, ...) {
+ VaList va;
+ __builtin_va_start(va, n); // expected-error{{int}}
+ for (int i = 0; i != n; ++i)
+ (void)__builtin_va_arg(va, ArgType);
+ __builtin_va_end(va);
+ }
+};
+
+template struct VaArg1<__builtin_va_list, int>;
+template struct VaArg1<int, int>; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp
new file mode 100644
index 000000000000..cd74a21d6dbc
--- /dev/null
+++ b/test/SemaTemplate/instantiate-expr-4.cpp
@@ -0,0 +1,289 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// ---------------------------------------------------------------------
+// C++ Functional Casts
+// ---------------------------------------------------------------------
+template<int N>
+struct ValueInit0 {
+ int f() {
+ return int();
+ }
+};
+
+template struct ValueInit0<5>;
+
+template<int N>
+struct FunctionalCast0 {
+ int f() {
+ return int(N);
+ }
+};
+
+template struct FunctionalCast0<5>;
+
+struct X { // expected-note 2 {{candidate function}}
+ X(int, int); // expected-note 2 {{candidate function}}
+};
+
+template<int N, int M>
+struct BuildTemporary0 {
+ X f() {
+ return X(N, M);
+ }
+};
+
+template struct BuildTemporary0<5, 7>;
+
+template<int N, int M>
+struct Temporaries0 {
+ void f() {
+ (void)X(N, M);
+ }
+};
+
+template struct Temporaries0<5, 7>;
+
+// ---------------------------------------------------------------------
+// new/delete expressions
+// ---------------------------------------------------------------------
+struct Y { };
+
+template<typename T>
+struct New0 {
+ T* f(bool x) {
+ if (x)
+ return new T; // expected-error{{no matching}}
+ else
+ return new T();
+ }
+};
+
+template struct New0<int>;
+template struct New0<Y>;
+template struct New0<X>; // expected-note{{instantiation}}
+
+template<typename T, typename Arg1>
+struct New1 {
+ T* f(bool x, Arg1 a1) {
+ return new T(a1); // expected-error{{no matching}}
+ }
+};
+
+template struct New1<int, float>;
+template struct New1<Y, Y>;
+template struct New1<X, Y>; // expected-note{{instantiation}}
+
+template<typename T, typename Arg1, typename Arg2>
+struct New2 {
+ T* f(bool x, Arg1 a1, Arg2 a2) {
+ return new T(a1, a2); // expected-error{{no matching}}
+ }
+};
+
+template struct New2<X, int, float>;
+template struct New2<X, int, int*>; // expected-note{{instantiation}}
+// FIXME: template struct New2<int, int, float>;
+
+template<typename T>
+struct Delete0 {
+ void f(T t) {
+ delete t; // expected-error{{cannot delete}}
+ ::delete [] t;
+ }
+};
+
+template struct Delete0<int*>;
+template struct Delete0<X*>;
+template struct Delete0<int>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// throw expressions
+// ---------------------------------------------------------------------
+template<typename T>
+struct Throw1 {
+ void f(T t) {
+ throw;
+ throw t; // expected-error{{incomplete type}}
+ }
+};
+
+struct Incomplete; // expected-note{{forward}}
+
+template struct Throw1<int>;
+template struct Throw1<int*>;
+template struct Throw1<Incomplete*>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// typeid expressions
+// ---------------------------------------------------------------------
+
+// FIXME: This should really include <typeinfo>, but we don't have that yet.
+namespace std {
+ class type_info;
+}
+
+template<typename T>
+struct TypeId0 {
+ const std::type_info &f(T* ptr) {
+ if (ptr)
+ return typeid(ptr);
+ else
+ return typeid(T);
+ }
+};
+
+struct Abstract {
+ virtual void f() = 0;
+};
+
+template struct TypeId0<int>;
+template struct TypeId0<Incomplete>;
+template struct TypeId0<Abstract>;
+
+// ---------------------------------------------------------------------
+// type traits
+// ---------------------------------------------------------------------
+template<typename T>
+struct is_pod {
+ static const bool value = __is_pod(T);
+};
+
+static const int is_pod0[is_pod<X>::value? -1 : 1];
+static const int is_pod1[is_pod<Y>::value? 1 : -1];
+
+// ---------------------------------------------------------------------
+// initializer lists
+// ---------------------------------------------------------------------
+template<typename T, typename Val1>
+struct InitList1 {
+ void f(Val1 val1) {
+ T x = { val1 };
+ }
+};
+
+struct APair {
+ int *x;
+ const float *y;
+};
+
+template struct InitList1<int[1], float>;
+template struct InitList1<APair, int*>;
+
+template<typename T, typename Val1, typename Val2>
+struct InitList2 {
+ void f(Val1 val1, Val2 val2) {
+ T x = { val1, val2 }; // expected-error{{incompatible}}
+ }
+};
+
+template struct InitList2<APair, int*, float*>;
+template struct InitList2<APair, int*, double*>; // expected-note{{instantiation}}
+
+// ---------------------------------------------------------------------
+// member references
+// ---------------------------------------------------------------------
+template<typename T, typename Result>
+struct DotMemRef0 {
+ void f(T t) {
+ Result result = t.m; // expected-error{{cannot be initialized}}
+ }
+};
+
+struct MemInt {
+ int m;
+};
+
+struct InheritsMemInt : MemInt { };
+
+struct MemIntFunc {
+ static int m(int);
+};
+
+template struct DotMemRef0<MemInt, int&>;
+template struct DotMemRef0<InheritsMemInt, int&>;
+template struct DotMemRef0<MemIntFunc, int (*)(int)>;
+template struct DotMemRef0<MemInt, float&>; // expected-note{{instantiation}}
+
+template<typename T, typename Result>
+struct ArrowMemRef0 {
+ void f(T t) {
+ Result result = t->m; // expected-error 2{{cannot be initialized}}
+ }
+};
+
+template<typename T>
+struct ArrowWrapper {
+ T operator->();
+};
+
+template struct ArrowMemRef0<MemInt*, int&>;
+template struct ArrowMemRef0<InheritsMemInt*, int&>;
+template struct ArrowMemRef0<MemIntFunc*, int (*)(int)>;
+template struct ArrowMemRef0<MemInt*, float&>; // expected-note{{instantiation}}
+
+template struct ArrowMemRef0<ArrowWrapper<MemInt*>, int&>;
+template struct ArrowMemRef0<ArrowWrapper<InheritsMemInt*>, int&>;
+template struct ArrowMemRef0<ArrowWrapper<MemIntFunc*>, int (*)(int)>;
+template struct ArrowMemRef0<ArrowWrapper<MemInt*>, float&>; // expected-note{{instantiation}}
+template struct ArrowMemRef0<ArrowWrapper<ArrowWrapper<MemInt*> >, int&>;
+
+// FIXME: we should be able to return a MemInt without the reference!
+MemInt &createMemInt(int);
+
+template<int N>
+struct NonDepMemberExpr0 {
+ void f() {
+ createMemInt(N).m = N;
+ }
+};
+
+template struct NonDepMemberExpr0<0>;
+
+template<typename T, typename Result>
+struct MemberFuncCall0 {
+ void f(T t) {
+ Result result = t.f();
+ }
+};
+
+template<typename T>
+struct HasMemFunc0 {
+ T f();
+};
+
+
+template struct MemberFuncCall0<HasMemFunc0<int&>, const int&>;
+
+template<typename Result>
+struct ThisMemberFuncCall0 {
+ Result g();
+
+ void f() {
+ Result r1 = g();
+ Result r2 = this->g();
+ }
+};
+
+template struct ThisMemberFuncCall0<int&>;
+
+template<typename T>
+struct NonDepMemberCall0 {
+ void foo(HasMemFunc0<int&> x) {
+ T result = x.f(); // expected-error{{initialized}}
+ }
+};
+
+template struct NonDepMemberCall0<int&>;
+template struct NonDepMemberCall0<const int&>;
+template struct NonDepMemberCall0<float&>; // expected-note{{instantiation}}
+
+
+template<typename T>
+struct QualifiedDeclRef0 {
+ T f() {
+ return is_pod<X>::value; // expected-error{{initialized}}
+ }
+};
+
+template struct QualifiedDeclRef0<bool>;
+template struct QualifiedDeclRef0<int&>; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/instantiate-expr-basic.cpp b/test/SemaTemplate/instantiate-expr-basic.cpp
new file mode 100644
index 000000000000..2b5fcaeb0454
--- /dev/null
+++ b/test/SemaTemplate/instantiate-expr-basic.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only -Wno-unused-value -std=c++0x %s
+
+template <typename T>
+struct S {
+ void f() {
+ __func__; // PredefinedExpr
+ 10; // IntegerLiteral
+ 10.5; // FloatingLiteral
+ 'c'; // CharacterLiteral
+ "hello"; // StringLiteral
+ true; // CXXBooleanLiteralExpr
+ nullptr; // CXXNullPtrLiteralExpr
+ __null; // GNUNullExpr
+ }
+};
+
+template struct S<int>;
diff --git a/test/SemaTemplate/instantiate-field.cpp b/test/SemaTemplate/instantiate-field.cpp
new file mode 100644
index 000000000000..8e2a3758b0d7
--- /dev/null
+++ b/test/SemaTemplate/instantiate-field.cpp
@@ -0,0 +1,28 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct X {
+ int x;
+ T y; // expected-error{{data member instantiated with function type}}
+ T* z;
+ T bitfield : 12; // expected-error{{bit-field 'bitfield' has non-integral type 'float'}} \
+ // expected-error{{data member instantiated with function type}}
+
+ mutable T x2; // expected-error{{data member instantiated with function type}}
+};
+
+void test1(const X<int> *xi) {
+ int i1 = xi->x;
+ const int &i2 = xi->y;
+ int* ip1 = xi->z;
+ int i3 = xi->bitfield;
+ xi->x2 = 17;
+}
+
+void test2(const X<float> *xf) {
+ (void)xf->x; // expected-note{{in instantiation of template class 'struct X<float>' requested here}}
+}
+
+void test3(const X<int(int)> *xf) {
+ (void)xf->x; // expected-note{{in instantiation of template class 'struct X<int (int)>' requested here}}
+}
diff --git a/test/SemaTemplate/instantiate-function-1.cpp b/test/SemaTemplate/instantiate-function-1.cpp
new file mode 100644
index 000000000000..5b3a6d998404
--- /dev/null
+++ b/test/SemaTemplate/instantiate-function-1.cpp
@@ -0,0 +1,211 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T, typename U>
+struct X0 {
+ void f(T x, U y) {
+ (void)(x + y); // expected-error{{invalid operands}}
+ }
+};
+
+struct X1 { };
+
+template struct X0<int, float>;
+template struct X0<int*, int>;
+template struct X0<int X1::*, int>; // expected-note{{instantiation of}}
+
+template<typename T>
+struct X2 {
+ void f(T);
+
+ T g(T x, T y) {
+ /* DeclStmt */;
+ T *xp = &x, &yr = y; // expected-error{{pointer to a reference}}
+ /* NullStmt */;
+ }
+};
+
+template struct X2<int>;
+template struct X2<int&>; // expected-note{{instantiation of}}
+
+template<typename T>
+struct X3 {
+ void f(T) {
+ Label:
+ T x;
+ goto Label;
+ }
+};
+
+template struct X3<int>;
+
+template <typename T> struct X4 {
+ T f() const {
+ return; // expected-warning{{non-void function 'f' should return a value}}
+ }
+
+ T g() const {
+ return 1; // expected-warning{{void function 'g' should not return a value}}
+ }
+};
+
+template struct X4<void>; // expected-note{{in instantiation of}}
+template struct X4<int>; // expected-note{{in instantiation of}}
+
+struct Incomplete; // expected-note 2{{forward declaration}}
+
+template<typename T> struct X5 {
+ T f() { } // expected-error{{incomplete result type}}
+};
+void test_X5(X5<Incomplete> x5); // okay!
+
+template struct X5<Incomplete>; // expected-note{{instantiation}}
+
+template<typename T, typename U, typename V> struct X6 {
+ U f(T t, U u, V v) {
+ // IfStmt
+ if (t > 0)
+ return u;
+ else {
+ if (t < 0)
+ return v; // expected-error{{incompatible type}}
+ }
+
+ if (T x = t) {
+ t = x;
+ }
+ return v;
+ }
+};
+
+struct ConvertibleToInt {
+ operator int() const;
+};
+
+template struct X6<ConvertibleToInt, float, char>;
+template struct X6<bool, int, int*>; // expected-note{{instantiation}}
+
+template <typename T> struct X7 {
+ void f() {
+ void *v = this;
+ }
+};
+
+template struct X7<int>;
+
+template<typename T> struct While0 {
+ void f(T t) {
+ while (t) {
+ }
+
+ while (T t2 = T()) ;
+ }
+};
+
+template struct While0<float>;
+
+template<typename T> struct Do0 {
+ void f(T t) {
+ do {
+ } while (t); // expected-error{{not contextually}}
+
+ do {
+ } while (T t2 = T());
+ }
+};
+
+struct NotConvertibleToBool { };
+template struct Do0<ConvertibleToInt>;
+template struct Do0<NotConvertibleToBool>; // expected-note{{instantiation}}
+
+template<typename T> struct For0 {
+ void f(T f, T l) {
+ for (; f != l; ++f) {
+ if (*f)
+ continue;
+ else if (*f == 17)
+ break;
+ }
+ }
+};
+
+template struct For0<int*>;
+
+template<typename T> struct Member0 {
+ void f(T t) {
+ t;
+ t.f;
+ t->f;
+
+ T* tp;
+ tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}}
+ tp->f;
+
+ this->f;
+ this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}}
+ }
+};
+
+template<typename T, typename U> struct Switch0 {
+ U f(T value, U v0, U v1, U v2) {
+ switch (value) {
+ case 0: return v0;
+
+ case 1: return v1;
+
+ case 2: // fall through
+
+ default:
+ return v2;
+ }
+ }
+};
+
+template struct Switch0<int, float>;
+
+template<typename T, int I1, int I2> struct Switch1 {
+ T f(T x, T y, T z) {
+ switch (x) {
+ case I1: return y; // expected-note{{previous}}
+ case I2: return z; // expected-error{{duplicate}}
+ default: return x;
+ }
+ }
+};
+
+template struct Switch1<int, 1, 2>;
+template struct Switch1<int, 2, 2>; // expected-note{{instantiation}}
+
+template<typename T> struct IndirectGoto0 {
+ void f(T x) {
+ // FIXME: crummy error message below
+ goto *x; // expected-error{{incompatible}}
+
+ prior:
+ T prior_label = &&prior;
+
+ T later_label = &&later;
+
+ later:
+ (void)(1+1);
+ }
+};
+
+template struct IndirectGoto0<void*>;
+template struct IndirectGoto0<int>; // expected-note{{instantiation}}
+
+template<typename T> struct TryCatch0 {
+ void f() {
+ try {
+ } catch (T t) { // expected-error{{incomplete type}} \
+ // expected-error{{abstract class}}
+ } catch (...) {
+ }
+ }
+};
+
+struct Abstract {
+ virtual void foo() = 0; // expected-note{{pure virtual}}
+};
+
+template struct TryCatch0<int>; // okay
+template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
+template struct TryCatch0<Abstract>; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/instantiate-function-1.mm b/test/SemaTemplate/instantiate-function-1.mm
new file mode 100644
index 000000000000..aef2d9dbb7eb
--- /dev/null
+++ b/test/SemaTemplate/instantiate-function-1.mm
@@ -0,0 +1,14 @@
+template<typename T> struct Member0 {
+ void f(T t) {
+ t;
+ t.f;
+ t->f;
+
+ T* tp;
+ tp.f;
+ tp->f;
+
+ this->f;
+ this.f; // expected-error{{member reference base type 'struct Member0 *const' is not a structure or union}}
+ }
+};
diff --git a/test/SemaTemplate/instantiate-function-2.cpp b/test/SemaTemplate/instantiate-function-2.cpp
new file mode 100644
index 000000000000..51a60146d46a
--- /dev/null
+++ b/test/SemaTemplate/instantiate-function-2.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template <typename T> struct S {
+ S() { }
+ S(T t);
+};
+
+template struct S<int>;
+
+void f() {
+ S<int> s1;
+ S<int> s2(10);
+}
diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp
new file mode 100644
index 000000000000..fab65cef2e45
--- /dev/null
+++ b/test/SemaTemplate/instantiate-member-class.cpp
@@ -0,0 +1,38 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+class X {
+public:
+ struct C { T &foo(); };
+
+ struct D {
+ struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}}
+ struct F; // expected-note{{member is declared here}}
+ };
+};
+
+X<int>::C *c1;
+X<float>::C *c2;
+
+X<int>::X *xi;
+X<float>::X *xf;
+
+void test_naming() {
+ c1 = c2; // expected-error{{incompatible type assigning 'X<float>::C *', expected 'X<int>::C *'}}
+ xi = xf; // expected-error{{incompatible type assigning}}
+ // FIXME: error above doesn't print the type X<int>::X cleanly!
+}
+
+void test_instantiation(X<double>::C *x,
+ X<float>::D::E *e,
+ X<float>::D::F *f) {
+ double &dr = x->foo();
+ float &fr = e->bar();
+ f->foo(); // expected-error{{implicit instantiation of undefined member 'struct X<float>::D::F'}}
+
+}
+
+
+X<void>::C *c3; // okay
+X<void>::D::E *e1; // okay
+X<void>::D::E e2; // expected-note{{in instantiation of member class 'struct X<void>::D::E' requested here}}
diff --git a/test/SemaTemplate/instantiate-method.cpp b/test/SemaTemplate/instantiate-method.cpp
new file mode 100644
index 000000000000..daea7465dc12
--- /dev/null
+++ b/test/SemaTemplate/instantiate-method.cpp
@@ -0,0 +1,74 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T>
+class X {
+public:
+ void f(T x); // expected-error{{argument may not have 'void' type}}
+ void g(T*);
+
+ static int h(T, T); // expected-error 2{{argument may not have 'void' type}}
+};
+
+int identity(int x) { return x; }
+
+void test(X<int> *xi, int *ip, X<int(int)> *xf) {
+ xi->f(17);
+ xi->g(ip);
+ xf->f(&identity);
+ xf->g(identity);
+ X<int>::h(17, 25);
+ X<int(int)>::h(identity, &identity);
+}
+
+void test_bad() {
+ X<void> xv; // expected-note{{in instantiation of template class 'class X<void>' requested here}}
+}
+
+template<typename T, typename U>
+class Overloading {
+public:
+ int& f(T, T); // expected-note{{previous declaration is here}}
+ float& f(T, U); // expected-error{{functions that differ only in their return type cannot be overloaded}}
+};
+
+void test_ovl(Overloading<int, long> *oil, int i, long l) {
+ int &ir = oil->f(i, i);
+ float &fr = oil->f(i, l);
+}
+
+void test_ovl_bad() {
+ Overloading<float, float> off; // expected-note{{in instantiation of template class 'class Overloading<float, float>' requested here}}
+}
+
+template<typename T>
+class HasDestructor {
+public:
+ virtual ~HasDestructor() = 0;
+};
+
+int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but
+ // the code below should probably instantiate by itself.
+int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1];
+
+
+template<typename T>
+class Constructors {
+public:
+ Constructors(const T&);
+ Constructors(const Constructors &other);
+};
+
+void test_constructors() {
+ Constructors<int> ci1(17);
+ Constructors<int> ci2 = ci1;
+}
+
+
+template<typename T>
+struct ConvertsTo {
+ operator T();
+};
+
+void test_converts_to(ConvertsTo<int> ci, ConvertsTo<int *> cip) {
+ int i = ci;
+ int *ip = cip;
+}
diff --git a/test/SemaTemplate/instantiate-static-var.cpp b/test/SemaTemplate/instantiate-static-var.cpp
new file mode 100644
index 000000000000..99e6b9cc06c3
--- /dev/null
+++ b/test/SemaTemplate/instantiate-static-var.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, T Divisor>
+class X {
+public:
+ static const T value = 10 / Divisor; // expected-error{{in-class initializer is not an integral constant expression}}
+};
+
+int array1[X<int, 2>::value == 5? 1 : -1];
+X<int, 0> xi0; // expected-note{{in instantiation of template class 'class X<int, 0>' requested here}}
+
+
+template<typename T>
+class Y {
+ static const T value = 0; // expected-error{{'value' can only be initialized if it is a static const integral data member}}
+};
+
+Y<float> fy; // expected-note{{in instantiation of template class 'class Y<float>' requested here}}
diff --git a/test/SemaTemplate/instantiate-subscript.cpp b/test/SemaTemplate/instantiate-subscript.cpp
new file mode 100644
index 000000000000..434d84e2b893
--- /dev/null
+++ b/test/SemaTemplate/instantiate-subscript.cpp
@@ -0,0 +1,26 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+
+struct Sub0 {
+ int &operator[](int);
+};
+
+struct Sub1 {
+ long &operator[](long);
+};
+
+struct ConvertibleToInt {
+ operator int();
+};
+
+template<typename T, typename U, typename Result>
+struct Subscript0 {
+ void test(T t, U u) {
+ Result &result = t[u]; // expected-error{{subscripted value is not}}
+ }
+};
+
+template struct Subscript0<int*, int, int&>;
+template struct Subscript0<Sub0, int, int&>;
+template struct Subscript0<Sub1, ConvertibleToInt, long&>;
+template struct Subscript0<Sub1, Sub0, long&>; // expected-note{{instantiation}}
diff --git a/test/SemaTemplate/instantiate-template-template-parm.cpp b/test/SemaTemplate/instantiate-template-template-parm.cpp
new file mode 100644
index 000000000000..b158251915a0
--- /dev/null
+++ b/test/SemaTemplate/instantiate-template-template-parm.cpp
@@ -0,0 +1,21 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<template<typename T> class MetaFun, typename Value>
+struct apply {
+ typedef typename MetaFun<Value>::type type;
+};
+
+template<class T>
+struct add_pointer {
+ typedef T* type;
+};
+
+template<class T>
+struct add_reference {
+ typedef T& type;
+};
+
+int i;
+apply<add_pointer, int>::type ip = &i;
+apply<add_reference, int>::type ir = i;
+apply<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a value of type 'int'}}
diff --git a/test/SemaTemplate/instantiate-try-catch.cpp b/test/SemaTemplate/instantiate-try-catch.cpp
new file mode 100644
index 000000000000..074afa9d173d
--- /dev/null
+++ b/test/SemaTemplate/instantiate-try-catch.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s
+
+template<typename T> struct TryCatch0 {
+ void f() {
+ try {
+ } catch (T&&) { // expected-error 2{{cannot catch exceptions by rvalue reference}}
+ }
+ }
+};
+
+template struct TryCatch0<int&>; // okay
+template struct TryCatch0<int&&>; // expected-note{{instantiation}}
+template struct TryCatch0<int>; // expected-note{{instantiation}}
+
diff --git a/test/SemaTemplate/instantiate-type.cpp b/test/SemaTemplate/instantiate-type.cpp
new file mode 100644
index 000000000000..48060c4e384e
--- /dev/null
+++ b/test/SemaTemplate/instantiate-type.cpp
@@ -0,0 +1,17 @@
+// RUN: clang-cc -fsyntax-only %s
+
+int* f(int);
+float *f(...);
+
+template<typename T>
+struct X {
+ typedef typeof(T*) typeof_type;
+ typedef typeof(f(T())) typeof_expr;
+};
+
+int *iptr0;
+float *fptr0;
+X<int>::typeof_type &iptr1 = iptr0;
+
+X<int>::typeof_expr &iptr2 = iptr0;
+X<float*>::typeof_expr &fptr1 = fptr0;
diff --git a/test/SemaTemplate/instantiate-typedef.cpp b/test/SemaTemplate/instantiate-typedef.cpp
new file mode 100644
index 000000000000..d30309cc86ca
--- /dev/null
+++ b/test/SemaTemplate/instantiate-typedef.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T>
+struct add_pointer {
+ typedef T* type; // expected-error{{'type' declared as a pointer to a reference}}
+};
+
+add_pointer<int>::type test1(int * ptr) { return ptr; }
+
+add_pointer<float>::type test2(int * ptr) {
+ return ptr; // expected-error{{incompatible type returning 'int *', expected 'add_pointer<float>::type' (aka 'float *')}}
+}
+
+add_pointer<int&>::type // expected-note{{in instantiation of template class 'struct add_pointer<int &>' requested here}} \
+// expected-error {{unknown type name 'type'}}
+test3();
diff --git a/test/SemaTemplate/instantiation-backtrace.cpp b/test/SemaTemplate/instantiation-backtrace.cpp
new file mode 100644
index 000000000000..869662268dd2
--- /dev/null
+++ b/test/SemaTemplate/instantiation-backtrace.cpp
@@ -0,0 +1,32 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T> struct A; // expected-note 4{{template is declared here}}
+
+template<typename T> struct B : A<T*> { }; // expected-error{{implicit instantiation of undefined template}} \
+// expected-error{{implicit instantiation of undefined template 'struct A<X *>'}}
+
+template<typename T> struct C : B<T> { } ; // expected-note{{instantiation of template class}}
+
+template<typename T> struct D : C<T> { }; // expected-note{{instantiation of template class}}
+
+template<typename T> struct E : D<T> { }; // expected-note{{instantiation of template class}}
+
+template<typename T> struct F : E<T(T)> { }; // expected-note{{instantiation of template class}}
+
+void f() {
+ (void)sizeof(F<int>); // expected-note{{instantiation of template class}}
+}
+
+typedef struct { } X;
+
+void g() {
+ (void)sizeof(B<X>); // expected-note{{in instantiation of template class 'struct B<X>' requested here}}
+}
+
+template<typename T>
+struct G : A<T>, // expected-error{{implicit instantiation of undefined template 'struct A<int>'}}
+ A<T*> // expected-error{{implicit instantiation of undefined template 'struct A<int *>'}}
+ { };
+
+void h() {
+ (void)sizeof(G<int>); // expected-note{{in instantiation of template class 'struct G<int>' requested here}}
+}
diff --git a/test/SemaTemplate/instantiation-default-1.cpp b/test/SemaTemplate/instantiation-default-1.cpp
new file mode 100644
index 000000000000..f0ce0d3cc669
--- /dev/null
+++ b/test/SemaTemplate/instantiation-default-1.cpp
@@ -0,0 +1,102 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T, typename U = const T> struct Def1;
+
+template<> struct Def1<int> {
+ void foo();
+};
+
+template<> struct Def1<const int> { // expected-note{{previous definition is here}}
+ void bar();
+};
+
+template<> struct Def1<int&> {
+ void wibble();
+};
+
+void test_Def1(Def1<int, const int> *d1, Def1<const int, const int> *d2,
+ Def1<int&, int&> *d3) {
+ d1->foo();
+ d2->bar();
+ d3->wibble();
+}
+
+template<typename T, // FIXME: bad error message below, needs better location info
+ typename T2 = const T*> // expected-error{{'T2' declared as a pointer to a reference}}
+ struct Def2;
+
+template<> struct Def2<int> {
+ void foo();
+};
+
+void test_Def2(Def2<int, int const*> *d2) {
+ d2->foo();
+}
+
+typedef int& int_ref_t;
+Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
+
+
+template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1<int const>'}}
+
+template<typename T, typename T2 = T&> struct Def3;
+
+template<> struct Def3<int> {
+ void foo();
+};
+
+template<> struct Def3<int&> {
+ void bar();
+};
+
+void test_Def3(Def3<int, int&> *d3a, Def3<int&, int&> *d3b) {
+ d3a->foo();
+ d3b->bar();
+}
+
+
+template<typename T, typename T2 = T[]> struct Def4;
+
+template<> struct Def4<int> {
+ void foo();
+};
+
+void test_Def4(Def4<int, int[]> *d4a) {
+ d4a->foo();
+}
+
+template<typename T, typename T2 = T const[12]> struct Def5;
+
+template<> struct Def5<int> {
+ void foo();
+};
+
+template<> struct Def5<int, int const[13]> {
+ void bar();
+};
+
+void test_Def5(Def5<int, const int[12]> *d5a, Def5<int, const int[13]> *d5b) {
+ d5a->foo();
+ d5b->bar();
+}
+
+template<typename R, typename Arg1, typename Arg2 = Arg1,
+ typename FuncType = R (*)(Arg1, Arg2)>
+ struct Def6;
+
+template<> struct Def6<int, float> {
+ void foo();
+};
+
+template<> struct Def6<bool, int[5], float(double, double)> {
+ void bar();
+};
+
+bool test_Def6(Def6<int, float, float> *d6a,
+ Def6<int, float, float, int (*)(float, float)> *d6b,
+ Def6<bool, int[5], float(double, double),
+ bool(*)(int*, float(*)(double, double))> *d6c) {
+ d6a->foo();
+ d6b->foo();
+ d6c->bar();
+ return d6a == d6b;
+}
diff --git a/test/SemaTemplate/instantiation-default-2.cpp b/test/SemaTemplate/instantiation-default-2.cpp
new file mode 100644
index 000000000000..740832c5ba39
--- /dev/null
+++ b/test/SemaTemplate/instantiation-default-2.cpp
@@ -0,0 +1,18 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, T Value> struct Constant; // expected-note{{template parameter is declared here}} \
+// FIXME: bad location expected-error{{a non-type template parameter cannot have type 'float'}}
+
+Constant<int, 5> *c1;
+
+int x;
+float f(int, double);
+
+Constant<int&, x> *c2;
+Constant<int*, &x> *c3;
+Constant<float (*)(int, double), f> *c4;
+Constant<float (*)(int, double), &f> *c5;
+
+Constant<float (*)(int, int), f> *c6; // expected-error{{non-type template argument of type 'float (*)(int, double)' cannot be converted to a value of type 'float (*)(int, int)'}}
+
+Constant<float, 0> *c7; // expected-note{{in instantiation of default argument for 'Constant<float>' required here}}
diff --git a/test/SemaTemplate/instantiation-default-3.cpp b/test/SemaTemplate/instantiation-default-3.cpp
new file mode 100644
index 000000000000..521edf66f24c
--- /dev/null
+++ b/test/SemaTemplate/instantiation-default-3.cpp
@@ -0,0 +1,21 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T> struct A { };
+
+template<typename T, typename U = A<T*> >
+ struct B : U { };
+
+template<>
+struct A<int*> {
+ void foo();
+};
+
+template<>
+struct A<float*> {
+ void bar();
+};
+
+void test(B<int> *b1, B<float> *b2) {
+ b1->foo();
+ b2->bar();
+}
diff --git a/test/SemaTemplate/instantiation-depth.cpp b/test/SemaTemplate/instantiation-depth.cpp
new file mode 100644
index 000000000000..522c4e1cbb5c
--- /dev/null
+++ b/test/SemaTemplate/instantiation-depth.cpp
@@ -0,0 +1,9 @@
+// RUN: clang-cc -fsyntax-only -ftemplate-depth=5 -verify %s
+
+template<typename T> struct X : X<T*> { }; // expected-error{{recursive template instantiation exceeded maximum depth of 5}} \
+// expected-note{{use -ftemplate-depth-N to increase recursive template instantiation depth}} \
+// expected-note 5 {{instantiation of template class}}
+
+void test() {
+ (void)sizeof(X<int>); // expected-note {{instantiation of template class}}
+}
diff --git a/test/SemaTemplate/metafun-apply.cpp b/test/SemaTemplate/metafun-apply.cpp
new file mode 100644
index 000000000000..7bc971f24b59
--- /dev/null
+++ b/test/SemaTemplate/metafun-apply.cpp
@@ -0,0 +1,43 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct add_pointer {
+ template<typename T>
+ struct apply {
+ typedef T* type;
+ };
+};
+
+struct add_reference {
+ template<typename T>
+ struct apply {
+ typedef T& type; // expected-error{{cannot form a reference to 'void'}}
+ };
+};
+
+struct bogus {
+ struct apply {
+ typedef int type;
+ };
+};
+
+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}}
+};
+
+int i;
+apply1<add_pointer, int>::type ip = &i;
+apply1<add_reference, int>::type ir = i;
+apply1<add_reference, float>::type fr = i; // expected-error{{non-const lvalue reference to type 'float' cannot be initialized with a value of type 'int'}}
+
+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}}
+}
+
+
diff --git a/test/SemaTemplate/nested-name-spec-template.cpp b/test/SemaTemplate/nested-name-spec-template.cpp
new file mode 100644
index 000000000000..a5aa2dcb527a
--- /dev/null
+++ b/test/SemaTemplate/nested-name-spec-template.cpp
@@ -0,0 +1,61 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace N {
+ namespace M {
+ template<typename T> struct Promote;
+
+ template<> struct Promote<short> {
+ typedef int type;
+ };
+
+ template<> struct Promote<int> {
+ typedef int type;
+ };
+
+ template<> struct Promote<float> {
+ typedef double type;
+ };
+
+ Promote<short>::type *ret_intptr(int* ip) { return ip; }
+ Promote<int>::type *ret_intptr2(int* ip) { return ip; }
+ }
+
+ M::Promote<int>::type *ret_intptr3(int* ip) { return ip; }
+ M::template Promote<int>::type *ret_intptr4(int* ip) { return ip; }
+}
+
+N::M::Promote<int>::type *ret_intptr5(int* ip) { return ip; }
+::N::M::Promote<int>::type *ret_intptr6(int* ip) { return ip; }
+
+
+N::M::template; // expected-error{{expected template name after 'template' keyword in nested name specifier}} \
+ // expected-error{{expected unqualified-id}}
+
+N::M::template Promote; // expected-error{{expected '<' after 'template Promote' in nested name specifier}} \
+// expected-error{{C++ requires a type specifier for all declarations}}
+
+namespace N {
+ template<typename T> struct A;
+
+ template<>
+ struct A<int> {
+ struct X;
+ };
+
+ struct B;
+}
+
+struct ::N::A<int>::X {
+ int foo;
+};
+
+#if 0
+// FIXME: the following crashes the parser, because Sema has no way to
+// communicate that the "dependent" template-name N::template B doesn't
+// actually refer to a template.
+template<typename T>
+struct TestA {
+ typedef typename N::template B<T>::type type; // xpected-error{{'B' following the 'template' keyword does not refer to a template}}
+ // FIXME: should show what B *does* refer to.
+};
+#endif
diff --git a/test/SemaTemplate/nested-template.cpp b/test/SemaTemplate/nested-template.cpp
new file mode 100644
index 000000000000..bd9e89f76a0a
--- /dev/null
+++ b/test/SemaTemplate/nested-template.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only %s
+
+class A;
+
+class S {
+public:
+ template<typename T> struct A {
+ struct Nested {
+ typedef T type;
+ };
+ };
+};
+
+int i;
+S::A<int>::Nested::type *ip = &i;
+
diff --git a/test/SemaTemplate/qualified-names-diag.cpp b/test/SemaTemplate/qualified-names-diag.cpp
new file mode 100644
index 000000000000..c875332905fb
--- /dev/null
+++ b/test/SemaTemplate/qualified-names-diag.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+namespace std {
+ template<typename T> class vector { };
+}
+
+typedef int INT;
+typedef float Real;
+
+void test() {
+ using namespace std;
+
+ std::vector<INT> v1;
+ vector<Real> v2;
+ v1 = v2; // expected-error{{no viable overloaded '='}}
+}
diff --git a/test/SemaTemplate/right-angle-brackets-0x.cpp b/test/SemaTemplate/right-angle-brackets-0x.cpp
new file mode 100644
index 000000000000..57b6ee22410c
--- /dev/null
+++ b/test/SemaTemplate/right-angle-brackets-0x.cpp
@@ -0,0 +1,22 @@
+// 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
new file mode 100644
index 000000000000..764bb7bae073
--- /dev/null
+++ b/test/SemaTemplate/right-angle-brackets-98.cpp
@@ -0,0 +1,12 @@
+// 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.cpp b/test/SemaTemplate/temp.cpp
new file mode 100644
index 000000000000..8be4739a741b
--- /dev/null
+++ b/test/SemaTemplate/temp.cpp
@@ -0,0 +1,5 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+
+// p3
+template<typename T> int foo(T), bar(T, T); // expected-error{{single entity}}
diff --git a/test/SemaTemplate/temp_arg.cpp b/test/SemaTemplate/temp_arg.cpp
new file mode 100644
index 000000000000..e873b8e2a61d
--- /dev/null
+++ b/test/SemaTemplate/temp_arg.cpp
@@ -0,0 +1,12 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T,
+ int I,
+ template<typename> class TT>
+ class A; // expected-note 2 {{template is declared here}}
+
+template<typename> class X;
+
+A<int, 0, X> * a1;
+
+A<float, 1, X, double> *a2; // expected-error{{too many template arguments for class template 'A'}}
+A<float, 1> *a3; // expected-error{{too few template arguments for class template 'A'}}
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
new file mode 100644
index 000000000000..fe18fe657c16
--- /dev/null
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -0,0 +1,124 @@
+// RUN: clang-cc -fsyntax-only -std=c++98 -verify %s
+template<int N> struct A; // expected-note 5{{template parameter is declared here}}
+
+A<0> *a0;
+
+A<int()> *a1; // expected-error{{template argument for non-type template parameter is treated as type 'int (void)'}}
+
+A<int> *a2; // expected-error{{template argument for non-type template parameter must be an expression}}
+
+A<1 >> 2> *a3; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++0x}}
+
+// C++ [temp.arg.nontype]p5:
+A<A> *a4; // expected-error{{must have an integral or enumeration type}} \
+ // FIXME: the error message above is a bit lame
+
+enum E { Enumerator = 17 };
+A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}}
+template<E Value> struct A1; // expected-note{{template parameter is declared here}}
+A1<Enumerator> *a6; // okay
+A1<17> *a7; // expected-error{{non-type template argument of type 'int' cannot be converted to a value of type 'enum E'}}
+
+const long LongValue = 12345678;
+A<LongValue> *a8;
+const short ShortValue = 17;
+A<ShortValue> *a9;
+
+int f(int);
+A<f(17)> *a10; // expected-error{{non-type template argument of type 'int' is not an integral constant expression}}
+
+class X {
+public:
+ X();
+ X(int, int);
+ operator int() const;
+};
+A<X(17, 42)> *a11; // expected-error{{non-type template argument of type 'class X' must have an integral or enumeration type}}
+
+template<X const *Ptr> struct A2;
+
+X *X_ptr;
+X an_X;
+X array_of_Xs[10];
+A2<X_ptr> *a12;
+A2<array_of_Xs> *a13;
+A2<&an_X> *a13_2;
+A2<(&an_X)> *a13_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}}
+
+float f(float);
+
+float g(float);
+double g(double);
+
+int h(int);
+float h2(float);
+
+template<int fp(int)> struct A3; // expected-note 2{{template parameter is declared here}}
+A3<h> *a14_1;
+A3<&h> *a14_2;
+A3<f> *a14_3;
+A3<&f> *a14_4;
+A3<h2> *a14_6; // expected-error{{non-type template argument of type 'float (*)(float)' cannot be converted to a value of type 'int (*)(int)'}}
+A3<g> *a14_7; // expected-error{{non-type template argument of type '<overloaded function type>' cannot be converted to a value of type 'int (*)(int)'}}
+// FIXME: the first error includes the string <overloaded function
+// type>, which makes Doug slightly unhappy.
+
+
+struct Y { } y;
+
+volatile X * X_volatile_ptr;
+template<X const &AnX> struct A4; // expected-note 2{{template parameter is declared here}}
+A4<an_X> *a15_1; // okay
+A4<*X_volatile_ptr> *a15_2; // expected-error{{reference binding of non-type template parameter of type 'class X const &' to template argument of type 'class X volatile' ignores qualifiers}}
+A4<y> *15_3; // expected-error{{non-type template parameter of reference type 'class X const &' cannot bind to template argument of type 'struct Y'}} \
+ // FIXME: expected-error{{expected unqualified-id}}
+
+template<int (&fr)(int)> struct A5; // expected-note 2{{template parameter is declared here}}
+A5<h> *a16_1;
+A5<f> *a16_3;
+A5<h2> *a16_6; // expected-error{{non-type template argument of type 'float (float)' cannot be converted to a value of type 'int (&)(int)'}}
+A5<g> *a14_7; // expected-error{{non-type template argument of type '<overloaded function type>' cannot be converted to a value of type 'int (&)(int)'}}
+// FIXME: the first error includes the string <overloaded function
+// type>, which makes Doug slightly unhappy.
+
+struct Z {
+ int foo(int);
+ float bar(float);
+ int bar(int);
+ double baz(double);
+
+ int int_member;
+ float float_member;
+};
+template<int (Z::*pmf)(int)> struct A6; // expected-note{{template parameter is declared here}}
+A6<&Z::foo> *a17_1;
+A6<&Z::bar> *a17_2;
+A6<&Z::baz> *a17_3; // expected-error{{non-type template argument of type 'double (struct Z::*)(double)' cannot be converted to a value of type 'int (struct Z::*)(int)'}}
+
+
+template<int Z::*pm> struct A7; // expected-note{{template parameter is declared here}}
+template<int Z::*pm> struct A7c;
+A7<&Z::int_member> *a18_1;
+A7c<&Z::int_member> *a18_2;
+A7<&Z::float_member> *a18_3; // expected-error{{non-type template argument of type 'float struct Z::*' cannot be converted to a value of type 'int struct Z::*'}}
+A7c<(&Z::int_member)> *a18_3; // expected-error{{non-type template argument cannot be surrounded by parentheses}}
+
+template<unsigned char C> struct Overflow; // expected-note{{template parameter is declared here}}
+
+Overflow<5> *overflow1; // okay
+Overflow<256> *overflow2; // expected-error{{non-type template argument value '256' is too large for template parameter of type 'unsigned char'}}
+
+
+template<unsigned> struct Signedness; // expected-note{{template parameter is declared here}}
+Signedness<10> *signedness1; // okay
+Signedness<-10> *signedness2; // expected-error{{non-type template argument provides negative value '-10' for unsigned template parameter of type 'unsigned int'}}
+
+// Check canonicalization of template arguments.
+template<int (*)(int, int)> struct FuncPtr0;
+int func0(int, int);
+extern FuncPtr0<&func0> *fp0;
+template<int (*)(int, int)> struct FuncPtr0;
+extern FuncPtr0<&func0> *fp0;
+int func0(int, int);
+extern FuncPtr0<&func0> *fp0;
+
diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp
new file mode 100644
index 000000000000..a5e9f75fa77a
--- /dev/null
+++ b/test/SemaTemplate/temp_arg_template.cpp
@@ -0,0 +1,38 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<template<typename T> class X> struct A; // expected-note 2{{previous template template parameter is here}}
+
+template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}}
+
+template<template<int I> class X> struct C; // expected-note{{previous non-type template parameter with type 'int' is here}}
+
+template<class> struct X; // expected-note{{too few template parameters in template template argument}}
+template<int N> struct Y; // expected-note{{template parameter has a different kind in template argument}}
+template<long N> struct Ylong; // expected-note{{template non-type parameter has a different type 'long' in template argument}}
+
+namespace N {
+ template<class> struct Z;
+}
+template<class, class> struct TooMany; // expected-note{{too many template parameters in template template argument}}
+
+
+A<X> *a1;
+A<N::Z> *a2;
+A< ::N::Z> *a3;
+
+A<Y> *a4; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
+A<TooMany> *a5; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
+B<X> *a6; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
+C<Y> *a7;
+C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
+
+template<typename T> void f(int);
+
+// FIXME: we're right to provide an error message, but it should say
+// that we need a class template. We won't get this right until name
+// lookup of 'f' returns a TemplateDecl.
+A<f> *a9; // expected-error{{template argument for template template parameter must be a template}}
+
+// FIXME: The code below is ill-formed, because of the evil digraph '<:'.
+// We should provide a much better error message than we currently do.
+// A<::N::Z> *a10;
diff --git a/test/SemaTemplate/temp_arg_type.cpp b/test/SemaTemplate/temp_arg_type.cpp
new file mode 100644
index 000000000000..b322dae98b90
--- /dev/null
+++ b/test/SemaTemplate/temp_arg_type.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T> class A; // expected-note 2 {{template parameter is declared here}}
+
+// [temp.arg.type]p1
+A<0> *a1; // expected-error{{template argument for template type parameter must be a type}}
+
+A<A> *a2; // expected-error{{template argument for template type parameter must be a type}}
+
+A<int> *a3;
+A<int()> *a4;
+A<int(float)> *a5;
+A<A<int> > *a6;
+
+// [temp.arg.type]p2
+void f() {
+ class X { };
+ A<X> * a = 0; // expected-error{{template argument uses local type 'class X'}}
+}
+
+struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}}
+A<__typeof__(Unnamed)> *a7; // expected-error{{template argument uses unnamed type}}
+
+// FIXME: [temp.arg.type]p3. The check doesn't really belong here (it
+// belongs somewhere in the template instantiation section).
diff --git a/test/SemaTemplate/temp_class_spec.cpp b/test/SemaTemplate/temp_class_spec.cpp
new file mode 100644
index 000000000000..df652b5ba38d
--- /dev/null
+++ b/test/SemaTemplate/temp_class_spec.cpp
@@ -0,0 +1,20 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+template<typename T>
+struct is_pointer {
+ static const bool value = false;
+};
+
+template<typename T>
+struct is_pointer<T*> {
+ static const bool value = true;
+};
+
+template<typename T>
+struct is_pointer<const T*> {
+ static const bool value = true;
+};
+
+int array0[is_pointer<int>::value? -1 : 1];
+int array1[is_pointer<int*>::value? 1 : -1];
+int array2[is_pointer<const int*>::value? 1 : -1]; // expected-error{{partial ordering}} \
+// expected-error{{negative}}
diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp
new file mode 100644
index 000000000000..0292964a1a76
--- /dev/null
+++ b/test/SemaTemplate/temp_explicit.cpp
@@ -0,0 +1,111 @@
+// RUN: clang-cc -fsyntax-only -pedantic -verify %s
+//
+// Tests explicit instantiation of templates.
+template<typename T, typename U = T> class X0 { };
+
+namespace N {
+ template<typename T, typename U = T> class X1 { };
+}
+
+// Check the syntax of explicit instantiations.
+template class X0<int, float>;
+template class X0<int>; // expected-note{{previous}}
+
+template class N::X1<int>;
+template class ::N::X1<int, float>;
+
+using namespace N;
+template class X1<float>;
+
+// Check for some bogus syntax that probably means that the user
+// wanted to write an explicit specialization, but forgot the '<>'
+// after 'template'.
+template class X0<double> { }; // expected-error{{explicit specialization}}
+
+// Check for explicit instantiations that come after other kinds of
+// instantiations or declarations.
+template class X0<int, int>; // expected-error{{duplicate}}
+
+template<> class X0<char> { }; // expected-note{{previous}}
+template class X0<char>; // expected-warning{{ignored}}
+
+void foo(X0<short>) { }
+template class X0<short>;
+
+// Check that explicit instantiations actually produce definitions. We
+// determine whether this happens by placing semantic errors in the
+// definition of the template we're instantiating.
+template<typename T> struct X2; // expected-note{{declared here}}
+
+template struct X2<float>; // expected-error{{undefined template}}
+
+template<typename T>
+struct X2 {
+ void f0(T*); // expected-error{{pointer to a reference}}
+};
+
+template struct X2<int>; // okay
+template struct X2<int&>; // expected-note{{in instantiation of}}
+
+// Check that explicit instantiations instantiate member classes.
+template<typename T> struct X3 {
+ struct Inner {
+ void f(T*); // expected-error{{pointer to a reference}}
+ };
+};
+
+void f1(X3<int&>); // okay, Inner, not instantiated
+
+template struct X3<int&>; // expected-note{{instantiation}}
+
+template<typename T> struct X4 {
+ struct Inner {
+ struct VeryInner {
+ void f(T*); // expected-error 2{{pointer to a reference}}
+ };
+ };
+};
+
+void f2(X4<int&>); // okay, Inner, not instantiated
+void f3(X4<int&>::Inner); // okay, Inner::VeryInner, not instantiated
+
+template struct X4<int&>; // expected-note{{instantiation}}
+template struct X4<float&>; // expected-note{{instantiation}}
+
+// Check explicit instantiation of member classes
+namespace N2 {
+
+template<typename T>
+struct X5 {
+ struct Inner1 {
+ void f(T&);
+ };
+
+ struct Inner2 {
+ struct VeryInner {
+ void g(T*); // expected-error 2{{pointer to a reference}}
+ };
+ };
+};
+
+}
+
+template struct N2::X5<void>::Inner2;
+
+using namespace N2;
+template struct X5<int&>::Inner2; // expected-note{{instantiation}}
+
+void f4(X5<float&>::Inner2);
+template struct X5<float&>::Inner2; // expected-note{{instantiation}}
+
+namespace N3 {
+ template struct N2::X5<int>::Inner2;
+}
+
+struct X6 {
+ struct Inner { // expected-note{{here}}
+ void f();
+ };
+};
+
+template struct X6::Inner; // expected-error{{non-templated}}
diff --git a/test/SemaTemplate/temp_explicit_cxx0x.cpp b/test/SemaTemplate/temp_explicit_cxx0x.cpp
new file mode 100644
index 000000000000..7045afc3032f
--- /dev/null
+++ b/test/SemaTemplate/temp_explicit_cxx0x.cpp
@@ -0,0 +1,24 @@
+// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s
+namespace N1 {
+
+ template<typename T> struct X0 { }; // expected-note{{here}}
+
+ namespace Inner {
+ template<typename T> struct X1 { };
+ }
+
+ template struct X0<int>;
+ template struct Inner::X1<int>;
+}
+
+template<typename T> struct X2 { }; // expected-note{{here}}
+
+template struct ::N1::Inner::X1<float>;
+
+namespace N2 {
+ using namespace N1;
+
+ template struct X0<double>; // expected-error{{not in a namespace enclosing}}
+
+ template struct X2<float>; // expected-error{{at global scope}}
+}
diff --git a/test/SemaTemplate/temp_param.cpp b/test/SemaTemplate/temp_param.cpp
new file mode 100644
index 000000000000..c042f0849a04
--- /dev/null
+++ b/test/SemaTemplate/temp_param.cpp
@@ -0,0 +1,90 @@
+// 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-2.cpp b/test/SemaTemplate/typename-specifier-2.cpp
new file mode 100644
index 000000000000..99e628523158
--- /dev/null
+++ b/test/SemaTemplate/typename-specifier-2.cpp
@@ -0,0 +1,30 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename MetaFun, typename T>
+struct bind_metafun {
+ typedef typename MetaFun::template apply<T> type;
+};
+
+struct add_pointer {
+ template<typename T>
+ struct apply {
+ typedef T* type;
+ };
+};
+
+int i;
+// FIXME: if we make the declarator below a pointer (e.g., with *ip),
+// the error message isn't so good because we don't get the handy
+// 'aka' telling us that we're dealing with an int**. Should we fix
+// getDesugaredType to dig through pointers and such?
+bind_metafun<add_pointer, int>::type::type ip = &i;
+bind_metafun<add_pointer, float>::type::type fp = &i; // expected-error{{incompatible type initializing 'int *', expected 'bind_metafun<add_pointer, float>::type::type' (aka 'float *')}}
+
+
+template<typename T>
+struct extract_type_type {
+ typedef typename T::type::type t;
+};
+
+double d;
+extract_type_type<bind_metafun<add_pointer, double> >::t dp = &d;
diff --git a/test/SemaTemplate/typename-specifier.cpp b/test/SemaTemplate/typename-specifier.cpp
new file mode 100644
index 000000000000..d3fca3eacad5
--- /dev/null
+++ b/test/SemaTemplate/typename-specifier.cpp
@@ -0,0 +1,74 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+namespace N {
+ struct A {
+ typedef int type;
+ };
+
+ struct B {
+ };
+
+ struct C {
+ struct type { };
+ int type; // expected-note 2{{referenced member 'type' is declared here}}
+ };
+}
+
+int i;
+
+typename N::A::type *ip1 = &i;
+typename N::B::type *ip2 = &i; // expected-error{{ no type named 'type' in 'B'}}
+typename N::C::type *ip3 = &i; // expected-error{{typename specifier refers to non-type member 'type'}}
+
+void test(double d) {
+ typename N::A::type f(typename N::A::type(a)); // expected-warning{{parentheses were disambiguated as a function declarator}}
+ int five = f(5);
+
+ using namespace N;
+ for (typename A::type i = 0; i < 10; ++i)
+ five += 1;
+
+ const typename N::A::type f2(d);
+}
+
+namespace N {
+ template<typename T>
+ struct X {
+ typedef typename T::type type; // expected-error 2{{no type named 'type' in 'B'}} \
+ // FIXME: location info for error above isn't very good \
+ // expected-error 2{{typename specifier refers to non-type member 'type'}} \
+ // expected-error{{type 'int' cannot be used prior to '::' because it has no members}}
+ };
+}
+
+N::X<N::A>::type *ip4 = &i;
+N::X<N::B>::type *ip5 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::B>' requested here}} \
+// expected-error{{unknown type name 'type'}}
+N::X<N::C>::type *ip6 = &i; // expected-note{{in instantiation of template class 'struct N::X<struct N::C>' requested here}} \
+// expected-error{{unknown type name 'type'}}
+
+N::X<int>::type fail1; // expected-note{{in instantiation of template class 'struct N::X<int>' requested here}} \
+// expected-error{{unknown type name 'type'}}
+
+template<typename T>
+struct Y {
+ typedef typename N::X<T>::type *type; // expected-note{{in instantiation of template class 'struct N::X<struct B>' requested here}} \
+ // expected-note{{in instantiation of template class 'struct N::X<struct C>' requested here}}
+};
+
+struct A {
+ typedef int type;
+};
+
+struct B {
+};
+
+struct C {
+ struct type { };
+ int type; // expected-note{{referenced member 'type' is declared here}}
+};
+
+::Y<A>::type ip7 = &i;
+::Y<B>::type ip8 = &i; // expected-note{{in instantiation of template class 'struct Y<struct B>' requested here}} \
+// expected-error{{unknown type name 'type'}}
+::Y<C>::type ip9 = &i; // expected-note{{in instantiation of template class 'struct Y<struct C>' requested here}} \
+// expected-error{{unknown type name 'type'}}