Collect multiple levels of template arguments into a new type,
MultiLevelTemplateArgumentList. This is a baby step toward
instantiating member templates; no intended functionality change yet.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80380 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4642251..b330ae9 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -28,30 +28,39 @@
 
 /// \brief Retrieve the template argument list that should be used to
 /// instantiate the given declaration.
-const TemplateArgumentList &
+MultiLevelTemplateArgumentList
 Sema::getTemplateInstantiationArgs(NamedDecl *D) {
-  // Template arguments for a class template specialization.
-  if (ClassTemplateSpecializationDecl *Spec 
-        = dyn_cast<ClassTemplateSpecializationDecl>(D))
-    return Spec->getTemplateInstantiationArgs();
-
-  // Template arguments for a function template specialization.
-  if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
-    if (const TemplateArgumentList *TemplateArgs
-          = Function->getTemplateSpecializationArgs())
-      return *TemplateArgs;
+  // Accumulate the set of template argument lists in this structure.
+  MultiLevelTemplateArgumentList Result;
+  
+  DeclContext *Ctx = dyn_cast<DeclContext>(D);
+  if (!Ctx)
+    Ctx = D->getDeclContext();
+  
+  for (; !Ctx->isFileContext(); Ctx = Ctx->getParent()) {
+    // Add template arguments from a class template instantiation.
+    if (ClassTemplateSpecializationDecl *Spec 
+          = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) {
+      // We're done when we hit an explicit specialization.
+      if (Spec->getSpecializationKind() == TSK_ExplicitSpecialization)
+        break;
       
-  // Template arguments for a member of a class template specialization.
-  DeclContext *EnclosingTemplateCtx = D->getDeclContext();
-  while (!isa<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx)) {
-    assert(!EnclosingTemplateCtx->isFileContext() &&
-           "Tried to get the instantiation arguments of a non-template");
-    EnclosingTemplateCtx = EnclosingTemplateCtx->getParent();
+      Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs());
+      continue;
+    } 
+    
+    // Add template arguments from a function template specialization.
+    if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) {
+      // FIXME: Check whether this is an explicit specialization.
+      if (const TemplateArgumentList *TemplateArgs
+            = Function->getTemplateSpecializationArgs())
+        Result.addOuterTemplateArguments(TemplateArgs);
+      
+      continue;
+    }
   }
-
-  ClassTemplateSpecializationDecl *EnclosingTemplate 
-    = cast<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx);
-  return EnclosingTemplate->getTemplateInstantiationArgs();
+  
+  return Result;
 }
 
 Sema::InstantiatingTemplate::