[cfe-commits] r74578 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Tue Jun 30 17:28:38 PDT 2009


Author: dgregor
Date: Tue Jun 30 19:28:38 2009
New Revision: 74578

URL: http://llvm.org/viewvc/llvm-project?rev=74578&view=rev
Log:
Cope with explicitly-specified function template arguments when there
are fewer template arguments than there are template parameters for
that function.

Added:
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp
Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=74578&r1=74577&r2=74578&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Jun 30 19:28:38 2009
@@ -2162,6 +2162,7 @@
                                  const TemplateArgument *TemplateArgs,
                                  unsigned NumTemplateArgs,
                                  SourceLocation RAngleLoc,
+                                 bool PartialTemplateArgs,
                                  TemplateArgumentListBuilder &Converted);
 
   bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, 

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=74578&r1=74577&r2=74578&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jun 30 19:28:38 2009
@@ -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() == 

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=74578&r1=74577&r2=74578&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jun 30 19:28:38 2009
@@ -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 

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=74578&r1=74577&r2=74578&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Jun 30 19:28:38 2009
@@ -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();

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp?rev=74578&r1=74577&r2=74578&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateExpr.cpp Tue Jun 30 19:28:38 2009
@@ -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)

Added: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp?rev=74578&view=auto

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp Tue Jun 30 19:28:38 2009
@@ -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





More information about the cfe-commits mailing list