Cope with explicitly-specified function template arguments when there
are fewer template arguments than there are template parameters for
that function.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74578 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 9b906aa..7576be8 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2162,6 +2162,7 @@
                                  const TemplateArgument *TemplateArgs,
                                  unsigned NumTemplateArgs,
                                  SourceLocation RAngleLoc,
+                                 bool PartialTemplateArgs,
                                  TemplateArgumentListBuilder &Converted);
 
   bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index d72fcf8..568d68c 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -852,7 +852,7 @@
                                         NumTemplateArgs);
   if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, 
                                 TemplateArgs, NumTemplateArgs, RAngleLoc,
-                                Converted))
+                                false, Converted))
     return QualType();
 
   assert((Converted.structuredSize() == 
@@ -1055,6 +1055,7 @@
                                      const TemplateArgument *TemplateArgs,
                                      unsigned NumTemplateArgs,
                                      SourceLocation RAngleLoc,
+                                     bool PartialTemplateArgs,
                                      TemplateArgumentListBuilder &Converted) {
   TemplateParameterList *Params = Template->getTemplateParameters();
   unsigned NumParams = Params->size();
@@ -1065,7 +1066,8 @@
     NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack();
   
   if ((NumArgs > NumParams && !HasParameterPack) ||
-      NumArgs < Params->getMinRequiredArguments()) {
+      (NumArgs < Params->getMinRequiredArguments() &&
+       !PartialTemplateArgs)) {
     // FIXME: point at either the first arg beyond what we can handle,
     // or the '>', depending on whether we have too many or too few
     // arguments.
@@ -1092,6 +1094,9 @@
   for (TemplateParameterList::iterator Param = Params->begin(),
                                        ParamEnd = Params->end();
        Param != ParamEnd; ++Param, ++ArgIdx) {
+    if (ArgIdx > NumArgs && PartialTemplateArgs)
+      break;
+    
     // Decode the template argument
     TemplateArgument Arg;
     if (ArgIdx >= NumArgs) {
@@ -2338,7 +2343,7 @@
                                         TemplateArgs.size());
   if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, 
                                 TemplateArgs.data(), TemplateArgs.size(),
-                                RAngleLoc, Converted))
+                                RAngleLoc, false, Converted))
     return true;
 
   assert((Converted.structuredSize() == 
@@ -2633,7 +2638,7 @@
                                         TemplateArgs.size());
   if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, 
                                 TemplateArgs.data(), TemplateArgs.size(),
-                                RAngleLoc, Converted))
+                                RAngleLoc, false, Converted))
     return true;
 
   assert((Converted.structuredSize() == 
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 810de04..ae0e704 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -934,21 +934,24 @@
     //   there are corresponding template-parameters. 
     TemplateArgumentListBuilder Builder(TemplateParams, 
                                         NumExplicitTemplateArgs);
+    
+    // Enter a new template instantiation context where we check the 
+    // explicitly-specified template arguments against this function template,
+    // and then substitute them into the function parameter types.
+    InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), 
+                               FunctionTemplate, Deduced.data(), Deduced.size());
+    if (Inst)
+      return TDK_InstantiationDepth;
+    
     if (CheckTemplateArgumentList(FunctionTemplate,
                                   SourceLocation(), SourceLocation(),
                                   ExplicitTemplateArgs,
                                   NumExplicitTemplateArgs,
                                   SourceLocation(),
+                                  true,
                                   Builder) || Trap.hasErrorOccurred())
       return TDK_InvalidExplicitArguments;
 
-    // Enter a new template instantiation context for the substitution of the
-    // explicitly-specified template arguments into the 
-    InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), 
-                               FunctionTemplate, Deduced.data(), Deduced.size());
-    if (Inst)
-      return TDK_InstantiationDepth;
-
     // Form the template argument list from the explicitly-specified
     // template arguments.
     TemplateArgumentList *ExplicitArgumentList 
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index ff01e41..3bc1cf9 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -584,6 +584,15 @@
   if (T->getDepth() == 0) {
     // Replace the template type parameter with its corresponding
     // template argument.
+    
+    // If the corresponding template argument is NULL or doesn't exist, it's 
+    // because we are performing instantiation from explicitly-specified 
+    // template arguments in a function template class, but there were some 
+    // arguments left unspecified.
+    if (T->getIndex() >= TemplateArgs.size() ||
+        TemplateArgs[T->getIndex()].isNull())
+      return QualType(T, 0); // Would be nice to keep the original type here
+        
     assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type &&
            "Template argument kind mismatch");
     return TemplateArgs[T->getIndex()].getAsType();
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index 58896d4..c82e1a7 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -139,8 +139,17 @@
   NamedDecl *D = E->getDecl();
   if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) {
     assert(NTTP->getDepth() == 0 && "No nested templates yet");
-    const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
 
+    // If the corresponding template argument is NULL or non-existent, it's 
+    // because we are performing instantiation from explicitly-specified 
+    // template arguments in a function template, but there were some
+    // arguments left unspecified.
+    if (NTTP->getPosition() >= TemplateArgs.size() ||
+        TemplateArgs[NTTP->getPosition()].isNull())
+      return SemaRef.Owned(E); // FIXME: Clone the expression!
+    
+    const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; 
+    
     // The template argument itself might be an expression, in which
     // case we just return that expression.
     if (Arg.getKind() == TemplateArgument::Expression)