]> granicus.if.org Git - clang/commitdiff
Cope with explicitly-specified function template arguments when there
authorDouglas Gregor <dgregor@apple.com>
Wed, 1 Jul 2009 00:28:38 +0000 (00:28 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 1 Jul 2009 00:28:38 +0000 (00:28 +0000)
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

lib/Sema/Sema.h
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateDeduction.cpp
lib/Sema/SemaTemplateInstantiate.cpp
lib/Sema/SemaTemplateInstantiateExpr.cpp
test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp [new file with mode: 0644]

index 9b906aadbd5945be5c3c8ca2b279325ad1968a87..7576be8af14739916863ed000081b640aaf2c620 100644 (file)
@@ -2162,6 +2162,7 @@ public:
                                  const TemplateArgument *TemplateArgs,
                                  unsigned NumTemplateArgs,
                                  SourceLocation RAngleLoc,
+                                 bool PartialTemplateArgs,
                                  TemplateArgumentListBuilder &Converted);
 
   bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, 
index d72fcf8adcd61dff5c555493efb75e892c248ac6..568d68c9a7e82f714c1d1006d0832250051a9702 100644 (file)
@@ -852,7 +852,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
                                         NumTemplateArgs);
   if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, 
                                 TemplateArgs, NumTemplateArgs, RAngleLoc,
-                                Converted))
+                                false, Converted))
     return QualType();
 
   assert((Converted.structuredSize() == 
@@ -1055,6 +1055,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
                                      const TemplateArgument *TemplateArgs,
                                      unsigned NumTemplateArgs,
                                      SourceLocation RAngleLoc,
+                                     bool PartialTemplateArgs,
                                      TemplateArgumentListBuilder &Converted) {
   TemplateParameterList *Params = Template->getTemplateParameters();
   unsigned NumParams = Params->size();
@@ -1065,7 +1066,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
     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 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
   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 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
                                         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 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
                                         TemplateArgs.size());
   if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, 
                                 TemplateArgs.data(), TemplateArgs.size(),
-                                RAngleLoc, Converted))
+                                RAngleLoc, false, Converted))
     return true;
 
   assert((Converted.structuredSize() == 
index 810de048c2133a1a12e414f4d8a7e43ca956fdcb..ae0e7040654aec2663ddd8915b383c12ba2a1eb4 100644 (file)
@@ -934,21 +934,24 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
     //   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 
index ff01e41214cef6bb2925534ac5b9ec2f273bbc81..3bc1cf9504b8ccbc3f5f0f8915fe66e247303155 100644 (file)
@@ -584,6 +584,15 @@ InstantiateTemplateTypeParmType(const TemplateTypeParmType *T) const {
   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();
index 58896d48fa9260f7077df7a5e5233b11f3caea5a..c82e1a7da3c927eb5900d98cac7b86d588cb9eb3 100644 (file)
@@ -139,8 +139,17 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) {
   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)
diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp
new file mode 100644 (file)
index 0000000..f4970b8
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<class X, class Y, class Z> X f(Y,Z); 
+
+void g() {
+  f<int,char*,double>("aa",3.0); 
+  f<int,char*>("aa",3.0); // Z is deduced to be double 
+  f<int>("aa",3.0);       // Y is deduced to be char*, and
+                          // Z is deduced to be double 
+  f("aa",3.0); // expected-error{{no matching}}
+}
\ No newline at end of file