forked from OSchip/llvm-project
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. llvm-svn: 75044
This commit is contained in:
parent
fb8d6d5b58
commit
9b14658713
|
@ -635,7 +635,8 @@ static bool DeclCanBeLvalue(const NamedDecl *Decl, ASTContext &Ctx) {
|
|||
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 @@ Expr::isLvalueResult Expr::isLvalue(ASTContext &Ctx) const {
|
|||
|
||||
// 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).
|
||||
|
|
|
@ -2350,7 +2350,22 @@ public:
|
|||
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 @@ public:
|
|||
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);
|
||||
|
|
|
@ -4684,7 +4684,8 @@ QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
|
|||
<< "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.
|
||||
|
|
|
@ -3702,7 +3702,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
|||
}
|
||||
|
||||
// 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 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
|||
}
|
||||
|
||||
// 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 @@ void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {
|
|||
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)) {
|
||||
|
|
|
@ -956,7 +956,220 @@ static bool isSimpleTemplateIdType(QualType T) {
|
|||
|
||||
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 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
|||
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 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
|||
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 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
|||
// 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();
|
||||
|
||||
// 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;
|
||||
return FinishTemplateArgumentDeduction(FunctionTemplate, Deduced,
|
||||
Specialization, Info);
|
||||
}
|
||||
|
||||
/// \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);
|
||||
|
||||
// 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,
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue