[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