For template argument deduction from class template partial
specializations, separate out the deduction part from the checking and
substitution of the deduced arguments.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@102600 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index e7a12d6..0312092 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -961,6 +961,115 @@
   return TemplateParameter(cast<TemplateTemplateParmDecl>(D));
 }
 
+/// Complete template argument deduction for a class template partial
+/// specialization.
+static Sema::TemplateDeductionResult
+FinishTemplateArgumentDeduction(Sema &S, 
+                                ClassTemplatePartialSpecializationDecl *Partial,
+                                const TemplateArgumentList &TemplateArgs,
+                      llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
+                                Sema::TemplateDeductionInfo &Info) {
+  // Trap errors.
+  Sema::SFINAETrap Trap(S);
+  
+  Sema::ContextRAII SavedContext(S, Partial);
+
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  TemplateArgumentListBuilder Builder(Partial->getTemplateParameters(),
+                                      Deduced.size());
+  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+    if (Deduced[I].isNull()) {
+      Decl *Param
+      = const_cast<NamedDecl *>(
+                                Partial->getTemplateParameters()->getParam(I));
+      Info.Param = makeTemplateParameter(Param);
+      return Sema::TDK_Incomplete;
+    }
+    
+    Builder.Append(Deduced[I]);
+  }
+  
+  // Form the template argument list from the deduced template arguments.
+  TemplateArgumentList *DeducedArgumentList
+    = new (S.Context) TemplateArgumentList(S.Context, Builder, 
+                                           /*TakeArgs=*/true);
+  Info.reset(DeducedArgumentList);
+
+  // Substitute the deduced template arguments into the template
+  // arguments of the class template partial specialization, and
+  // verify that the instantiated template arguments are both valid
+  // and are equivalent to the template arguments originally provided
+  // to the class template.
+  // FIXME: Do we have to correct the types of deduced non-type template 
+  // arguments (in particular, integral non-type template arguments?).
+  Sema::LocalInstantiationScope InstScope(S);
+  ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
+  const TemplateArgumentLoc *PartialTemplateArgs
+    = Partial->getTemplateArgsAsWritten();
+  unsigned N = Partial->getNumTemplateArgsAsWritten();
+
+  // Note that we don't provide the langle and rangle locations.
+  TemplateArgumentListInfo InstArgs;
+
+  for (unsigned I = 0; I != N; ++I) {
+    Decl *Param = const_cast<NamedDecl *>(
+                    ClassTemplate->getTemplateParameters()->getParam(I));
+    TemplateArgumentLoc InstArg;
+    if (S.Subst(PartialTemplateArgs[I], InstArg,
+                MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
+      Info.Param = makeTemplateParameter(Param);
+      Info.FirstArg = PartialTemplateArgs[I].getArgument();
+      return Sema::TDK_SubstitutionFailure;
+    }
+    InstArgs.addArgument(InstArg);
+  }
+
+  TemplateArgumentListBuilder ConvertedInstArgs(
+                                  ClassTemplate->getTemplateParameters(), N);
+
+  if (S.CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
+                                InstArgs, false, ConvertedInstArgs)) {
+    // FIXME: fail with more useful information?
+    return Sema::TDK_SubstitutionFailure;
+  }
+  
+  for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
+    TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I];
+
+    Decl *Param = const_cast<NamedDecl *>(
+                    ClassTemplate->getTemplateParameters()->getParam(I));
+
+    if (InstArg.getKind() == TemplateArgument::Expression) {
+      // When the argument is an expression, check the expression result
+      // against the actual template parameter to get down to the canonical
+      // template argument.
+      Expr *InstExpr = InstArg.getAsExpr();
+      if (NonTypeTemplateParmDecl *NTTP
+            = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
+        if (S.CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
+          Info.Param = makeTemplateParameter(Param);
+          Info.FirstArg = Partial->getTemplateArgs()[I];
+          return Sema::TDK_SubstitutionFailure;
+        }
+      }
+    }
+
+    if (!isSameTemplateArg(S.Context, TemplateArgs[I], InstArg)) {
+      Info.Param = makeTemplateParameter(Param);
+      Info.FirstArg = TemplateArgs[I];
+      Info.SecondArg = InstArg;
+      return Sema::TDK_NonDeducedMismatch;
+    }
+  }
+
+  if (Trap.hasErrorOccurred())
+    return Sema::TDK_SubstitutionFailure;
+
+  return Sema::TDK_Success;
+}
+
 /// \brief Perform template argument deduction to determine whether
 /// the given template arguments match the given class template
 /// partial specialization per C++ [temp.class.spec.match].
@@ -988,101 +1097,11 @@
   if (Inst)
     return TDK_InstantiationDepth;
 
-  ContextRAII SavedContext(*this, Partial);
-
-  // C++ [temp.deduct.type]p2:
-  //   [...] or if any template argument remains neither deduced nor
-  //   explicitly specified, template argument deduction fails.
-  TemplateArgumentListBuilder Builder(Partial->getTemplateParameters(),
-                                      Deduced.size());
-  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
-    if (Deduced[I].isNull()) {
-      Decl *Param
-        = const_cast<NamedDecl *>(
-                                Partial->getTemplateParameters()->getParam(I));
-      Info.Param = makeTemplateParameter(Param);
-      return TDK_Incomplete;
-    }
-
-    Builder.Append(Deduced[I]);
-  }
-
-  // Form the template argument list from the deduced template arguments.
-  TemplateArgumentList *DeducedArgumentList
-    = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
-  Info.reset(DeducedArgumentList);
-
-  // Substitute the deduced template arguments into the template
-  // arguments of the class template partial specialization, and
-  // verify that the instantiated template arguments are both valid
-  // and are equivalent to the template arguments originally provided
-  // to the class template.
-  // FIXME: Do we have to correct the types of deduced non-type template 
-  // arguments (in particular, integral non-type template arguments?).
-  Sema::LocalInstantiationScope InstScope(*this);
-  ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
-  const TemplateArgumentLoc *PartialTemplateArgs
-    = Partial->getTemplateArgsAsWritten();
-  unsigned N = Partial->getNumTemplateArgsAsWritten();
-
-  // Note that we don't provide the langle and rangle locations.
-  TemplateArgumentListInfo InstArgs;
-
-  for (unsigned I = 0; I != N; ++I) {
-    Decl *Param = const_cast<NamedDecl *>(
-                    ClassTemplate->getTemplateParameters()->getParam(I));
-    TemplateArgumentLoc InstArg;
-    if (Subst(PartialTemplateArgs[I], InstArg,
-              MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
-      Info.Param = makeTemplateParameter(Param);
-      Info.FirstArg = PartialTemplateArgs[I].getArgument();
-      return TDK_SubstitutionFailure;
-    }
-    InstArgs.addArgument(InstArg);
-  }
-
-  TemplateArgumentListBuilder ConvertedInstArgs(
-                                  ClassTemplate->getTemplateParameters(), N);
-
-  if (CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
-                                InstArgs, false, ConvertedInstArgs)) {
-    // FIXME: fail with more useful information?
-    return TDK_SubstitutionFailure;
-  }
-  
-  for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
-    TemplateArgument InstArg = ConvertedInstArgs.getFlatArguments()[I];
-
-    Decl *Param = const_cast<NamedDecl *>(
-                    ClassTemplate->getTemplateParameters()->getParam(I));
-
-    if (InstArg.getKind() == TemplateArgument::Expression) {
-      // When the argument is an expression, check the expression result
-      // against the actual template parameter to get down to the canonical
-      // template argument.
-      Expr *InstExpr = InstArg.getAsExpr();
-      if (NonTypeTemplateParmDecl *NTTP
-            = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
-        if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
-          Info.Param = makeTemplateParameter(Param);
-          Info.FirstArg = Partial->getTemplateArgs()[I];
-          return TDK_SubstitutionFailure;
-        }
-      }
-    }
-
-    if (!isSameTemplateArg(Context, TemplateArgs[I], InstArg)) {
-      Info.Param = makeTemplateParameter(Param);
-      Info.FirstArg = TemplateArgs[I];
-      Info.SecondArg = InstArg;
-      return TDK_NonDeducedMismatch;
-    }
-  }
-
   if (Trap.hasErrorOccurred())
-    return TDK_SubstitutionFailure;
-
-  return TDK_Success;
+    return Sema::TDK_SubstitutionFailure;
+ 
+  return ::FinishTemplateArgumentDeduction(*this, Partial, TemplateArgs, 
+                                           Deduced, Info);
 }
 
 /// \brief Determine whether the given type T is a simple-template-id type.
@@ -2341,12 +2360,15 @@
   //       whose type is a class template specialization with the template 
   //       arguments of the second partial specialization.
   //
-  // Rather than synthesize function templates, we merely perform the 
-  // equivalent partial ordering by performing deduction directly on the
-  // template arguments of the class template partial specializations. This
-  // computation is slightly simpler than the general problem of function
-  // template partial ordering, because class template partial specializations
-  // are more constrained. We know that every template parameter is deduc
+  // Rather than synthesize function templates, we merely perform the
+  // equivalent partial ordering by performing deduction directly on
+  // the template arguments of the class template partial
+  // specializations. This computation is slightly simpler than the
+  // general problem of function template partial ordering, because
+  // class template partial specializations are more constrained. We
+  // know that every template parameter is deducible from the class
+  // template partial specialization's template arguments, for
+  // example.
   llvm::SmallVector<DeducedTemplateArgument, 4> Deduced;
   Sema::TemplateDeductionInfo Info(Context, Loc);