[cfe-commits] r75044 - in /cfe/trunk: lib/AST/Expr.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplateDeduction.cpp test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp

Douglas Gregor dgregor at apple.com
Wed Jul 8 13:55:53 PDT 2009


Author: dgregor
Date: Wed Jul  8 15:55:45 2009
New Revision: 75044

URL: http://llvm.org/viewvc/llvm-project?rev=75044&view=rev
Log:
Implement template argument deduction when taking the address of a
function template. Most of the change here is in factoring out the
common bits used for template argument deduction from a function call
and when taking the address of a function template.

Added:
    cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp
Modified:
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=75044&r1=75043&r2=75044&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Jul  8 15:55:45 2009
@@ -635,7 +635,8 @@
   return isa<VarDecl>(Decl) || isa<FieldDecl>(Decl) ||
     // C++ 3.10p2: An lvalue refers to an object or function.
     (Ctx.getLangOptions().CPlusPlus &&
-     (isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl)));
+     (isa<FunctionDecl>(Decl) || isa<OverloadedFunctionDecl>(Decl) ||
+      isa<FunctionTemplateDecl>(Decl)));
 }
 
 /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or an
@@ -659,7 +660,7 @@
 
   // first, check the type (C99 6.3.2.1). Expressions with function
   // type in C are not lvalues, but they can be lvalues in C++.
-  if (TR->isFunctionType())
+  if (TR->isFunctionType() || TR == Ctx.OverloadTy)
     return LV_NotObjectType;
 
   // Allow qualified void which is an incomplete type other than void (yuck).

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Jul  8 15:55:45 2009
@@ -2350,7 +2350,22 @@
   DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
                           const TemplateArgumentList &TemplateArgs,
                           TemplateDeductionInfo &Info);
-                   
+          
+  TemplateDeductionResult
+  SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                                const TemplateArgument *ExplicitTemplateArgs,
+                                      unsigned NumExplicitTemplateArgs,
+                            llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                 llvm::SmallVectorImpl<QualType> &ParamTypes,
+                                      QualType *FunctionType,
+                                      TemplateDeductionInfo &Info);
+                                      
+  TemplateDeductionResult 
+  FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+                             llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                  FunctionDecl *&Specialization,
+                                  TemplateDeductionInfo &Info);
+  
   TemplateDeductionResult
   DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
                           bool HasExplicitTemplateArgs,
@@ -2359,6 +2374,15 @@
                           Expr **Args, unsigned NumArgs,
                           FunctionDecl *&Specialization,
                           TemplateDeductionInfo &Info);
+
+  TemplateDeductionResult
+  DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                          bool HasExplicitTemplateArgs,
+                          const TemplateArgument *ExplicitTemplateArgs,
+                          unsigned NumExplicitTemplateArgs,
+                          QualType ArgFunctionType,
+                          FunctionDecl *&Specialization,
+                          TemplateDeductionInfo &Info);
   
   void MarkDeducedTemplateParameters(const TemplateArgumentList &TemplateArgs,
                                      llvm::SmallVectorImpl<bool> &Deduced);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jul  8 15:55:45 2009
@@ -4684,7 +4684,8 @@
           << "register variable" << op->getSourceRange();
         return QualType();
       }
-    } else if (isa<OverloadedFunctionDecl>(dcl)) {
+    } else if (isa<OverloadedFunctionDecl>(dcl) ||
+               isa<FunctionTemplateDecl>(dcl)) {
       return Context.OverloadTy;
     } else if (isa<FieldDecl>(dcl)) {
       // Okay: we can take the address of a field.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Jul  8 15:55:45 2009
@@ -3702,7 +3702,8 @@
   }
 
   // We only look at pointers or references to functions.
-  if (!FunctionType->isFunctionType()) 
+  FunctionType = Context.getCanonicalType(FunctionType.getUnqualifiedType());
+  if (!FunctionType->isFunctionType())
     return 0;
 
   // Find the actual overloaded function declaration.
@@ -3722,44 +3723,69 @@
   }
 
   // Try to dig out the overloaded function.
-  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr))
+  FunctionTemplateDecl *FunctionTemplate = 0;
+  if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) {
     Ovl = dyn_cast<OverloadedFunctionDecl>(DR->getDecl());
+    FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DR->getDecl());
+  }
 
-  // If there's no overloaded function declaration, we're done.
-  if (!Ovl)
+  // If there's no overloaded function declaration or function template, 
+  // we're done.
+  if (!Ovl && !FunctionTemplate)
     return 0;
  
+  OverloadIterator Fun;
+  if (Ovl)
+    Fun = Ovl;
+  else
+    Fun = FunctionTemplate;
+  
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
-  // FIXME: When templates or using declarations come along, we'll actually
-  // have to deal with duplicates, partial ordering, etc. For now, we 
-  // can just do a simple search.
-  FunctionType = Context.getCanonicalType(FunctionType.getUnqualifiedType());
-  for (OverloadedFunctionDecl::function_iterator Fun = Ovl->function_begin();
-       Fun != Ovl->function_end(); ++Fun) {
+  // FIXME: We still need to cope with duplicates, partial ordering, etc.
+  for (OverloadIterator FunEnd; Fun != FunEnd; ++Fun) {
     // C++ [over.over]p3:
     //   Non-member functions and static member functions match
     //   targets of type "pointer-to-function" or "reference-to-function."
     //   Nonstatic member functions match targets of
     //   type "pointer-to-member-function."
     // Note that according to DR 247, the containing class does not matter.
+
+    if (FunctionTemplateDecl *FunctionTemplate 
+          = dyn_cast<FunctionTemplateDecl>(*Fun)) {
+      // C++ [temp.deduct.funcaddr]p1:
+      //   Template arguments can be deduced from the type specified when 
+      //   taking the address of an overloaded function (13.4). The function 
+      //   template’s function type and the specified type are used as the 
+      //   types of P and A, and the deduction is done as described in 
+      //   14.8.2.4.
+      FunctionDecl *Specialization = 0;
+      TemplateDeductionInfo Info(Context);
+      if (TemplateDeductionResult Result
+            = DeduceTemplateArguments(FunctionTemplate, /*FIXME*/false,
+                                      /*FIXME:*/0, /*FIXME:*/0,
+                                      FunctionType, Specialization, Info)) {
+        // FIXME: make a note of the failed deduction for diagnostics.
+        (void)Result;
+      } else {
+        assert(FunctionType 
+                 == Context.getCanonicalType(Specialization->getType()));
+        return Specialization;
+      }
+    }
+    
     if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Fun)) {
       // Skip non-static functions when converting to pointer, and static
       // when converting to member pointer.
       if (Method->isStatic() == IsMember)
         continue;
-    } else if (IsMember)
+    } else if (IsMember) // FIXME: member templates
       continue;
 
     if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Fun)) {
       if (FunctionType == Context.getCanonicalType(FunDecl->getType()))
         return FunDecl;
-    } else {
-      unsigned DiagID 
-        = PP.getDiagnostics().getCustomDiagID(Diagnostic::Warning,
-                   "Clang does not yet support templated conversion functions");
-      Diag(From->getLocStart(), DiagID);
-    }
+    } 
   }
 
   return 0;
@@ -4614,8 +4640,9 @@
     FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn);
     E->setType(Context.getPointerType(UnOp->getSubExpr()->getType()));
   } else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {
-    assert(isa<OverloadedFunctionDecl>(DR->getDecl()) && 
-           "Expected overloaded function");
+    assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||
+            isa<FunctionTemplateDecl>(DR->getDecl())) && 
+           "Expected overloaded function or function template");
     DR->setDecl(Fn);
     E->setType(Fn->getType());
   } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Jul  8 15:55:45 2009
@@ -956,7 +956,220 @@
   
   return false;
 }
-                   
+
+/// \brief Substitute the explicitly-provided template arguments into the
+/// given function template according to C++ [temp.arg.explicit].
+///
+/// \param FunctionTemplate the function template into which the explicit
+/// template arguments will be substituted.
+///
+/// \param ExplicitTemplateArguments the explicitly-specified template 
+/// arguments.
+///
+/// \param NumExplicitTemplateArguments the number of explicitly-specified 
+/// template arguments in @p ExplicitTemplateArguments. This value may be zero.
+///
+/// \param Deduced the deduced template arguments, which will be populated 
+/// with the converted and checked explicit template arguments.
+///
+/// \param ParamTypes will be populated with the instantiated function 
+/// parameters.
+///
+/// \param FunctionType if non-NULL, the result type of the function template
+/// will also be instantiated and the pointed-to value will be updated with
+/// the instantiated function type.
+///
+/// \param Info if substitution fails for any reason, this object will be
+/// populated with more information about the failure.
+///
+/// \returns TDK_Success if substitution was successful, or some failure
+/// condition.
+Sema::TemplateDeductionResult
+Sema::SubstituteExplicitTemplateArguments(
+                                      FunctionTemplateDecl *FunctionTemplate,
+                                const TemplateArgument *ExplicitTemplateArgs,
+                                          unsigned NumExplicitTemplateArgs,
+                            llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                 llvm::SmallVectorImpl<QualType> &ParamTypes,
+                                          QualType *FunctionType,
+                                          TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+
+  if (NumExplicitTemplateArgs == 0) {
+    // No arguments to substitute; just copy over the parameter types and
+    // fill in the function type.
+    for (FunctionDecl::param_iterator P = Function->param_begin(),
+                                   PEnd = Function->param_end();
+         P != PEnd;
+         ++P)
+      ParamTypes.push_back((*P)->getType());
+    
+    if (FunctionType)
+      *FunctionType = Function->getType();
+    return TDK_Success;
+  }
+  
+  // Substitution of the explicit template arguments into a function template
+  /// is a SFINAE context. Trap any errors that might occur.
+  SFINAETrap Trap(*this);  
+  
+  // C++ [temp.arg.explicit]p3:
+  //   Template arguments that are present shall be specified in the 
+  //   declaration order of their corresponding template-parameters. The 
+  //   template argument list shall not specify more template-arguments than
+  //   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(),
+           ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
+  if (Inst)
+    return TDK_InstantiationDepth;
+  
+  if (CheckTemplateArgumentList(FunctionTemplate,
+                                SourceLocation(), SourceLocation(),
+                                ExplicitTemplateArgs,
+                                NumExplicitTemplateArgs,
+                                SourceLocation(),
+                                true,
+                                Builder) || Trap.hasErrorOccurred())
+    return TDK_InvalidExplicitArguments;
+  
+  // Form the template argument list from the explicitly-specified
+  // template arguments.
+  TemplateArgumentList *ExplicitArgumentList 
+    = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
+  Info.reset(ExplicitArgumentList);
+  
+  // Instantiate the types of each of the function parameters given the
+  // explicitly-specified template arguments.
+  for (FunctionDecl::param_iterator P = Function->param_begin(),
+                                PEnd = Function->param_end();
+       P != PEnd;
+       ++P) {
+    QualType ParamType = InstantiateType((*P)->getType(), 
+                                         *ExplicitArgumentList, 
+                                         (*P)->getLocation(), 
+                                         (*P)->getDeclName());
+    if (ParamType.isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+    
+    ParamTypes.push_back(ParamType);
+  }
+
+  // If the caller wants a full function type back, instantiate the return
+  // type and form that function type.
+  if (FunctionType) {
+    // FIXME: exception-specifications?
+    const FunctionProtoType *Proto 
+      = Function->getType()->getAsFunctionProtoType();
+    assert(Proto && "Function template does not have a prototype?");
+    
+    QualType ResultType = InstantiateType(Proto->getResultType(),
+                                          *ExplicitArgumentList,
+                                          Function->getTypeSpecStartLoc(),
+                                          Function->getDeclName());
+    if (ResultType.isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+    
+    *FunctionType = BuildFunctionType(ResultType, 
+                                      ParamTypes.data(), ParamTypes.size(),
+                                      Proto->isVariadic(),
+                                      Proto->getTypeQuals(),
+                                      Function->getLocation(),
+                                      Function->getDeclName());
+    if (FunctionType->isNull() || Trap.hasErrorOccurred())
+      return TDK_SubstitutionFailure;
+  }
+  
+  // C++ [temp.arg.explicit]p2:
+  //   Trailing template arguments that can be deduced (14.8.2) may be 
+  //   omitted from the list of explicit template-arguments. If all of the 
+  //   template arguments can be deduced, they may all be omitted; in this
+  //   case, the empty template argument list <> itself may also be omitted.
+  //
+  // Take all of the explicitly-specified arguments and put them into the
+  // set of deduced template arguments. 
+  Deduced.reserve(TemplateParams->size());
+  for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
+    Deduced.push_back(ExplicitArgumentList->get(I));  
+  
+  return TDK_Success;
+}
+
+/// \brief Finish template argument deduction for a function template, 
+/// checking the deduced template arguments for completeness and forming
+/// the function template specialization.
+Sema::TemplateDeductionResult 
+Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
+                            llvm::SmallVectorImpl<TemplateArgument> &Deduced,
+                                      FunctionDecl *&Specialization,
+                                      TemplateDeductionInfo &Info) {
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  
+  // C++ [temp.deduct.type]p2:
+  //   [...] or if any template argument remains neither deduced nor
+  //   explicitly specified, template argument deduction fails.
+  TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
+  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
+    if (Deduced[I].isNull()) {
+      Info.Param = makeTemplateParameter(
+                            const_cast<Decl *>(TemplateParams->getParam(I)));
+      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);
+  
+  // Template argument deduction for function templates in a SFINAE context.
+  // Trap any errors that might occur.
+  SFINAETrap Trap(*this);  
+  
+  // Enter a new template instantiation context while we instantiate the
+  // actual function declaration.
+  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), 
+                             FunctionTemplate, Deduced.data(), Deduced.size(),
+              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
+  if (Inst)
+    return TDK_InstantiationDepth; 
+  
+  // Substitute the deduced template arguments into the function template 
+  // declaration to produce the function template specialization.
+  Specialization = cast_or_null<FunctionDecl>(
+                      InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
+                                      FunctionTemplate->getDeclContext(),
+                                      *DeducedArgumentList));
+  if (!Specialization)
+    return TDK_SubstitutionFailure;
+  
+  // If the template argument list is owned by the function template 
+  // specialization, release it.
+  if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
+    Info.take();
+  
+  // There may have been an error that did not prevent us from constructing a
+  // declaration. Mark the declaration invalid and return with a substitution
+  // failure.
+  if (Trap.hasErrorOccurred()) {
+    Specialization->setInvalidDecl(true);
+    return TDK_SubstitutionFailure;
+  }
+  
+  return TDK_Success;  
+}
+
 /// \brief Perform template argument deduction from a function call
 /// (C++ [temp.deduct.call]).
 ///
@@ -1011,10 +1224,6 @@
     CheckArgs = Function->getNumParams();
   }
     
-  // Template argument deduction for function templates in a SFINAE context.
-  // Trap any errors that might occur.
-  SFINAETrap Trap(*this);
-
   // The types of the parameters from which we will perform template argument
   // deduction.
   TemplateParameterList *TemplateParams
@@ -1022,71 +1231,22 @@
   llvm::SmallVector<TemplateArgument, 4> Deduced;
   llvm::SmallVector<QualType, 4> ParamTypes;
   if (NumExplicitTemplateArgs) {
-    // C++ [temp.arg.explicit]p3:
-    //   Template arguments that are present shall be specified in the 
-    //   declaration order of their corresponding template-parameters. The 
-    //   template argument list shall not specify more template-arguments than
-    //   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(),
-             ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution);
-    if (Inst)
-      return TDK_InstantiationDepth;
-    
-    if (CheckTemplateArgumentList(FunctionTemplate,
-                                  SourceLocation(), SourceLocation(),
-                                  ExplicitTemplateArgs,
-                                  NumExplicitTemplateArgs,
-                                  SourceLocation(),
-                                  true,
-                                  Builder) || Trap.hasErrorOccurred())
-      return TDK_InvalidExplicitArguments;
-
-    // Form the template argument list from the explicitly-specified
-    // template arguments.
-    TemplateArgumentList *ExplicitArgumentList 
-      = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
-    Info.reset(ExplicitArgumentList);
-    
-    // Instantiate the types of each of the function parameters given the
-    // explicitly-specified template arguments.
-    for (FunctionDecl::param_iterator P = Function->param_begin(),
-                                   PEnd = Function->param_end();
-         P != PEnd;
-         ++P) {
-      QualType ParamType = InstantiateType((*P)->getType(), 
-                                           *ExplicitArgumentList, 
-                                           (*P)->getLocation(), 
-                                           (*P)->getDeclName());
-      if (ParamType.isNull() || Trap.hasErrorOccurred())
-        return TDK_SubstitutionFailure;
-      
-      ParamTypes.push_back(ParamType);
-    }
-    
-    // C++ [temp.arg.explicit]p2:
-    //   Trailing template arguments that can be deduced (14.8.2) may be 
-    //   omitted from the list of explicit template- arguments. If all of the 
-    //   template arguments can be deduced, they may all be omitted; in this
-    //   case, the empty template argument list <> itself may also be omitted.
-    //
-    // Take all of the explicitly-specified arguments and put them into the
-    // set of deduced template arguments. 
-    Deduced.reserve(TemplateParams->size());
-    for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I)
-      Deduced.push_back(ExplicitArgumentList->get(I));
+    TemplateDeductionResult Result =
+      SubstituteExplicitTemplateArguments(FunctionTemplate,
+                                          ExplicitTemplateArgs,
+                                          NumExplicitTemplateArgs,
+                                          Deduced,
+                                          ParamTypes,
+                                          0,
+                                          Info);
+    if (Result)
+      return Result;
   } else {
     // Just fill in the parameter types from the function declaration.
     for (unsigned I = 0; I != CheckArgs; ++I)
       ParamTypes.push_back(Function->getParamDecl(I)->getType());
   }
-  
+                                        
   // Deduce template arguments from the function parameters.
   Deduced.resize(TemplateParams->size());  
   for (unsigned I = 0; I != CheckArgs; ++I) {
@@ -1173,65 +1333,81 @@
     // pointer parameters. 
   }
   
-  // C++ [temp.deduct.type]p2:
-  //   [...] or if any template argument remains neither deduced nor
-  //   explicitly specified, template argument deduction fails.
-  TemplateArgumentListBuilder Builder(TemplateParams, Deduced.size());
-  for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
-    if (Deduced[I].isNull()) {
-      Decl *Param 
-      = const_cast<Decl *>(TemplateParams->getParam(I));
-      if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
-        Info.Param = TTP;
-      else if (NonTypeTemplateParmDecl *NTTP 
-               = dyn_cast<NonTypeTemplateParmDecl>(Param))
-        Info.Param = NTTP;
-      else
-        Info.Param = cast<TemplateTemplateParmDecl>(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);
-  
-  // Enter a new template instantiation context while we instantiate the
-  // actual function declaration.
-  InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), 
-                             FunctionTemplate, Deduced.data(), Deduced.size(),
-              ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution);
-  if (Inst)
-    return TDK_InstantiationDepth; 
-                                  
-  // Substitute the deduced template arguments into the function template 
-  // declaration to produce the function template specialization.
-  Specialization = cast_or_null<FunctionDecl>(
-                         InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
-                                         FunctionTemplate->getDeclContext(),
-                                         *DeducedArgumentList));
-  if (!Specialization)
-    return TDK_SubstitutionFailure;
-  
-  // If the template argument list is owned by the function template 
-  // specialization, release it.
-  if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
-    Info.take();
+  return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 
+                                         Specialization, Info);
+}
 
-  // There may have been an error that did not prevent us from constructing a
-  // declaration. Mark the declaration invalid and return with a substitution
-  // failure.
-  if (Trap.hasErrorOccurred()) {
-    Specialization->setInvalidDecl(true);
-    return TDK_SubstitutionFailure;
+/// \brief Deduce template arguments when taking the address of a function
+/// template (C++ [temp.deduct.funcaddr]).
+///
+/// \param FunctionTemplate the function template for which we are performing
+/// template argument deduction.
+///
+/// \param HasExplicitTemplateArgs whether any template arguments were 
+/// explicitly specified.
+///
+/// \param ExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
+/// the explicitly-specified template arguments.
+///
+/// \param NumExplicitTemplateArguments when @p HasExplicitTemplateArgs is true,
+/// the number of explicitly-specified template arguments in 
+/// @p ExplicitTemplateArguments. This value may be zero.
+///
+/// \param ArgFunctionType the function type that will be used as the
+/// "argument" type (A) when performing template argument deduction from the
+/// function template's function type.
+///
+/// \param Specialization if template argument deduction was successful,
+/// this will be set to the function template specialization produced by 
+/// template argument deduction.
+///
+/// \param Info the argument will be updated to provide additional information
+/// about template argument deduction.
+///
+/// \returns the result of template argument deduction.
+Sema::TemplateDeductionResult
+Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+                              bool HasExplicitTemplateArgs,
+                              const TemplateArgument *ExplicitTemplateArgs,
+                              unsigned NumExplicitTemplateArgs,
+                              QualType ArgFunctionType,
+                              FunctionDecl *&Specialization,
+                              TemplateDeductionInfo &Info) {
+  FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
+  TemplateParameterList *TemplateParams
+    = FunctionTemplate->getTemplateParameters();
+  QualType FunctionType = Function->getType();
+  
+  // Substitute any explicit template arguments.
+  llvm::SmallVector<TemplateArgument, 4> Deduced;
+  llvm::SmallVector<QualType, 4> ParamTypes;
+  if (HasExplicitTemplateArgs) {
+    if (TemplateDeductionResult Result 
+          = SubstituteExplicitTemplateArguments(FunctionTemplate, 
+                                                ExplicitTemplateArgs, 
+                                                NumExplicitTemplateArgs,
+                                                Deduced, ParamTypes, 
+                                                &FunctionType, Info))
+      return Result;
   }
+
+  // Template argument deduction for function templates in a SFINAE context.
+  // Trap any errors that might occur.
+  SFINAETrap Trap(*this);  
   
-  return TDK_Success;
+  // Deduce template arguments from the function type.
+  Deduced.resize(TemplateParams->size());  
+  if (TemplateDeductionResult Result
+        = ::DeduceTemplateArguments(Context, TemplateParams,
+                                    FunctionType, ArgFunctionType, Info, 
+                                    Deduced, 0))
+    return Result;
+  
+  return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced, 
+                                         Specialization, Info);
 }
 
+
 static void 
 MarkDeducedTemplateParameters(Sema &SemaRef,
                               const TemplateArgument &TemplateArg,

Added: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp?rev=75044&view=auto

==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.funcaddr/p1.cpp Wed Jul  8 15:55:45 2009
@@ -0,0 +1,22 @@
+// RUN: clang-cc -fsyntax-only %s
+
+template<typename T>
+  T f0(T, int);
+
+void test_f0() {
+  int (*f0a)(int, int) = f0;
+  int (*f0b)(int, int) = &f0;
+  float (*f0c)(float, int) = &f0;
+}
+
+template<typename T> T f1(T, int);
+template<typename T> T f1(T);
+
+void test_f1() {
+  float (*f1a)(float, int) = f1;
+  float (*f1b)(float, int) = &f1;
+  float (*f1c)(float) = f1;
+  float (*f1d)(float) = (f1);
+  float (*f1e)(float) = &f1;
+  float (*f1f)(float) = (&f1);
+}
\ No newline at end of file





More information about the cfe-commits mailing list