Basic nested-template implementation.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@79504 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4d164ea..45214bf 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -568,6 +568,38 @@
   return Invalid;
 }
 
+/// \brief Force a template's pattern class to be instantiated.
+///
+/// \returns true if an error occurred
+bool Sema::InstantiateTemplatePattern(SourceLocation PointOfInstantiation,
+                                      CXXRecordDecl *Pattern) {
+  if (Pattern->getDefinition(Context)) return false;
+
+  ClassTemplateDecl *PatternTemp = Pattern->getDescribedClassTemplate();
+  if (!PatternTemp) return false;
+
+  // Check whether this template is a lazy instantiation of a
+  // dependent member template, e.g. Inner<U> in
+  // Outer<int>::Inner<U>.
+  ClassTemplateDecl *PatternPatternTemp
+    = PatternTemp->getInstantiatedFromMemberTemplate();
+  if (!PatternPatternTemp) return false;
+  
+  ClassTemplateSpecializationDecl *Spec = 0;
+  for (DeclContext *Parent = Pattern->getDeclContext();
+       Parent && !Spec; Parent = Parent->getParent())
+    Spec = dyn_cast<ClassTemplateSpecializationDecl>(Parent);
+  assert(Spec && "Not a member of a class template specialization?");
+
+  // TODO: the error message from a nested failure here is probably
+  // not ideal.
+  return InstantiateClass(PointOfInstantiation,
+                          Pattern,
+                          PatternPatternTemp->getTemplatedDecl(),
+                          Spec->getTemplateArgs(),
+                          /* ExplicitInstantiation = */ false);
+}
+
 /// \brief Instantiate the definition of a class from a given pattern.
 ///
 /// \param PointOfInstantiation The point of instantiation within the
@@ -591,6 +623,10 @@
                        const TemplateArgumentList &TemplateArgs,
                        bool ExplicitInstantiation) {
   bool Invalid = false;
+
+  // Lazily instantiate member templates here.
+  if (InstantiateTemplatePattern(PointOfInstantiation, Pattern))
+    return true;
   
   CXXRecordDecl *PatternDef 
     = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));