WIP implementation of explicit instantiation of function templates,
member functions of class template specializations, and static data
members. The mechanics are (mostly) present, but the semantic analysis
is very weak.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82789 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Parser/cxx-template-decl.cpp b/test/Parser/cxx-template-decl.cpp
index 94b7069..7f1ff3d 100644
--- a/test/Parser/cxx-template-decl.cpp
+++ b/test/Parser/cxx-template-decl.cpp
@@ -2,7 +2,8 @@
 
 // Errors
 export class foo { };   // expected-error {{expected template}}
-template  x;            // expected-error {{C++ requires a type specifier for all declarations}}
+template  x;            // expected-error {{C++ requires a type specifier for all declarations}} \
+                        // expected-error {{does not refer}}
 export template x;      // expected-error {{expected '<' after 'template'}}
 export template<class T> class x0; // expected-note {{exported templates are unsupported}}
 template < ;            // expected-error {{parse error}} expected-error {{declaration does not declare anything}}
diff --git a/test/SemaTemplate/explicit-instantiation.cpp b/test/SemaTemplate/explicit-instantiation.cpp
new file mode 100644
index 0000000..f92c463
--- /dev/null
+++ b/test/SemaTemplate/explicit-instantiation.cpp
@@ -0,0 +1,57 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template void *; // expected-error{{expected unqualified-id}}
+
+template typedef void f0; // expected-error{{explicit instantiation of typedef}}
+
+int v0; // expected-note{{refers here}}
+template int v0; // expected-error{{does not refer}}
+
+template<typename T>
+struct X0 {
+  static T value;
+  
+  T f0(T x) {
+    return x + 1;  // expected-error{{invalid operands}}
+  } 
+  T* f0(T*, T*);
+  
+  template<typename U>
+  T f0(T, U);
+};
+
+template int X0<int>::value;
+
+struct NotDefaultConstructible {
+  NotDefaultConstructible(int);
+};
+
+template NotDefaultConstructible X0<NotDefaultConstructible>::value;
+
+template int X0<int>::f0(int);
+template int* X0<int>::f0(int*, int*);
+template int X0<int>::f0(int, float);
+
+template int X0<int>::f0(int) const; // expected-error{{does not refer}}
+template int* X0<int>::f0(int*, float*); // expected-error{{does not refer}}
+
+struct X1 { };
+typedef int X1::*MemPtr;
+
+template MemPtr X0<MemPtr>::f0(MemPtr); // expected-note{{requested here}}
+
+struct X2 {
+  int f0(int); // expected-note{{refers here}}
+  
+  template<typename T> T f1(T);
+  template<typename T> T* f1(T*);
+
+  template<typename T, typename U> void f2(T, U*); // expected-note{{candidate}}
+  template<typename T, typename U> void f2(T*, U); // expected-note{{candidate}}
+};
+
+template int X2::f0(int); // expected-error{{not an instantiation}}
+
+template int *X2::f1(int *); // okay
+
+template void X2::f2(int *, int *); // expected-error{{ambiguous}}