forked from OSchip/llvm-project
When explicit template arguments are provided for a function call,
substitute those template arguments into the function parameter types prior to template argument deduction. There's still a bit of work to do to make this work properly when only some of the template arguments are specified. llvm-svn: 74576
This commit is contained in:
parent
1938fb1954
commit
89026b5018
|
@ -701,6 +701,9 @@ public:
|
||||||
bool SuppressUserConversions = false,
|
bool SuppressUserConversions = false,
|
||||||
bool ForceRValue = false);
|
bool ForceRValue = false);
|
||||||
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
Expr **Args, unsigned NumArgs,
|
Expr **Args, unsigned NumArgs,
|
||||||
OverloadCandidateSet& CandidateSet,
|
OverloadCandidateSet& CandidateSet,
|
||||||
bool SuppressUserConversions = false,
|
bool SuppressUserConversions = false,
|
||||||
|
@ -747,6 +750,9 @@ public:
|
||||||
|
|
||||||
FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||||
DeclarationName UnqualifiedName,
|
DeclarationName UnqualifiedName,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
SourceLocation LParenLoc,
|
SourceLocation LParenLoc,
|
||||||
Expr **Args, unsigned NumArgs,
|
Expr **Args, unsigned NumArgs,
|
||||||
SourceLocation *CommaLocs,
|
SourceLocation *CommaLocs,
|
||||||
|
@ -2247,7 +2253,10 @@ public:
|
||||||
TDK_TooManyArguments,
|
TDK_TooManyArguments,
|
||||||
/// \brief When performing template argument deduction for a class
|
/// \brief When performing template argument deduction for a class
|
||||||
/// template, there were too few call arguments.
|
/// template, there were too few call arguments.
|
||||||
TDK_TooFewArguments
|
TDK_TooFewArguments,
|
||||||
|
/// \brief The explicitly-specified template arguments were not valid
|
||||||
|
/// template arguments for the given template.
|
||||||
|
TDK_InvalidExplicitArguments
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Provides information about an attempted template argument
|
/// \brief Provides information about an attempted template argument
|
||||||
|
@ -2329,6 +2338,9 @@ public:
|
||||||
|
|
||||||
TemplateDeductionResult
|
TemplateDeductionResult
|
||||||
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
Expr **Args, unsigned NumArgs,
|
Expr **Args, unsigned NumArgs,
|
||||||
FunctionDecl *&Specialization,
|
FunctionDecl *&Specialization,
|
||||||
TemplateDeductionInfo &Info);
|
TemplateDeductionInfo &Info);
|
||||||
|
|
|
@ -2635,8 +2635,13 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're directly calling a function, get the appropriate declaration.
|
// If we're directly calling a function, get the appropriate declaration.
|
||||||
|
// Also, in C++, keep track of whether we should perform argument-dependent
|
||||||
|
// lookup and whether there were any explicitly-specified template arguments.
|
||||||
Expr *FnExpr = Fn;
|
Expr *FnExpr = Fn;
|
||||||
bool ADL = true;
|
bool ADL = true;
|
||||||
|
bool HasExplicitTemplateArgs = 0;
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs = 0;
|
||||||
|
unsigned NumExplicitTemplateArgs = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr))
|
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr))
|
||||||
FnExpr = IcExpr->getSubExpr();
|
FnExpr = IcExpr->getSubExpr();
|
||||||
|
@ -2661,6 +2666,28 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
||||||
} else if (TemplateIdRefExpr *TemplateIdRef
|
} else if (TemplateIdRefExpr *TemplateIdRef
|
||||||
= dyn_cast<TemplateIdRefExpr>(FnExpr)) {
|
= dyn_cast<TemplateIdRefExpr>(FnExpr)) {
|
||||||
NDecl = TemplateIdRef->getTemplateName().getAsTemplateDecl();
|
NDecl = TemplateIdRef->getTemplateName().getAsTemplateDecl();
|
||||||
|
HasExplicitTemplateArgs = true;
|
||||||
|
ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs();
|
||||||
|
NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs();
|
||||||
|
|
||||||
|
// C++ [temp.arg.explicit]p6:
|
||||||
|
// [Note: For simple function names, argument dependent lookup (3.4.2)
|
||||||
|
// applies even when the function name is not visible within the
|
||||||
|
// scope of the call. This is because the call still has the syntactic
|
||||||
|
// form of a function call (3.4.1). But when a function template with
|
||||||
|
// explicit template arguments is used, the call does not have the
|
||||||
|
// correct syntactic form unless there is a function template with
|
||||||
|
// that name visible at the point of the call. If no such name is
|
||||||
|
// visible, the call is not syntactically well-formed and
|
||||||
|
// argument-dependent lookup does not apply. If some such name is
|
||||||
|
// visible, argument dependent lookup applies and additional function
|
||||||
|
// templates may be found in other namespaces.
|
||||||
|
//
|
||||||
|
// The summary of this paragraph is that, if we get to this point and the
|
||||||
|
// template-id was not a qualified name, then argument-dependent lookup
|
||||||
|
// is still possible.
|
||||||
|
if (TemplateIdRef->getQualifier())
|
||||||
|
ADL = false;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Any kind of name that does not refer to a declaration (or
|
// Any kind of name that does not refer to a declaration (or
|
||||||
|
@ -2692,8 +2719,12 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
||||||
ADL = false;
|
ADL = false;
|
||||||
|
|
||||||
if (Ovl || FunctionTemplate || ADL) {
|
if (Ovl || FunctionTemplate || ADL) {
|
||||||
FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, LParenLoc,
|
FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName,
|
||||||
Args, NumArgs, CommaLocs, RParenLoc, ADL);
|
HasExplicitTemplateArgs,
|
||||||
|
ExplicitTemplateArgs,
|
||||||
|
NumExplicitTemplateArgs,
|
||||||
|
LParenLoc, Args, NumArgs, CommaLocs,
|
||||||
|
RParenLoc, ADL);
|
||||||
if (!FDecl)
|
if (!FDecl)
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
|
||||||
|
|
|
@ -2166,8 +2166,9 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
|
||||||
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
|
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
|
||||||
SuppressUserConversions);
|
SuppressUserConversions);
|
||||||
else
|
else
|
||||||
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F), Args,
|
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F),
|
||||||
NumArgs, CandidateSet,
|
/*FIXME: explicit args */false, 0, 0,
|
||||||
|
Args, NumArgs, CandidateSet,
|
||||||
SuppressUserConversions);
|
SuppressUserConversions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2273,6 +2274,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
|
||||||
/// template specialization.
|
/// template specialization.
|
||||||
void
|
void
|
||||||
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
Expr **Args, unsigned NumArgs,
|
Expr **Args, unsigned NumArgs,
|
||||||
OverloadCandidateSet& CandidateSet,
|
OverloadCandidateSet& CandidateSet,
|
||||||
bool SuppressUserConversions,
|
bool SuppressUserConversions,
|
||||||
|
@ -2289,8 +2293,9 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
||||||
TemplateDeductionInfo Info(Context);
|
TemplateDeductionInfo Info(Context);
|
||||||
FunctionDecl *Specialization = 0;
|
FunctionDecl *Specialization = 0;
|
||||||
if (TemplateDeductionResult Result
|
if (TemplateDeductionResult Result
|
||||||
= DeduceTemplateArguments(FunctionTemplate, Args, NumArgs,
|
= DeduceTemplateArguments(FunctionTemplate, HasExplicitTemplateArgs,
|
||||||
Specialization, Info)) {
|
ExplicitTemplateArgs, NumExplicitTemplateArgs,
|
||||||
|
Args, NumArgs, Specialization, Info)) {
|
||||||
// FIXME: Record what happened with template argument deduction, so
|
// FIXME: Record what happened with template argument deduction, so
|
||||||
// that we can give the user a beautiful diagnostic.
|
// that we can give the user a beautiful diagnostic.
|
||||||
(void)Result;
|
(void)Result;
|
||||||
|
@ -3438,8 +3443,9 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
|
||||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func))
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func))
|
||||||
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet);
|
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet);
|
||||||
else
|
else
|
||||||
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), Args,
|
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func),
|
||||||
NumArgs, CandidateSet);
|
/*FIXME: explicit args */false, 0, 0,
|
||||||
|
Args, NumArgs, CandidateSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3758,6 +3764,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
|
||||||
/// arguments and Fn, and returns NULL.
|
/// arguments and Fn, and returns NULL.
|
||||||
FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||||
DeclarationName UnqualifiedName,
|
DeclarationName UnqualifiedName,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
SourceLocation LParenLoc,
|
SourceLocation LParenLoc,
|
||||||
Expr **Args, unsigned NumArgs,
|
Expr **Args, unsigned NumArgs,
|
||||||
SourceLocation *CommaLocs,
|
SourceLocation *CommaLocs,
|
||||||
|
@ -3790,11 +3799,17 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||||
Func != FuncEnd; ++Func) {
|
Func != FuncEnd; ++Func) {
|
||||||
DeclContext *Ctx = 0;
|
DeclContext *Ctx = 0;
|
||||||
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Func)) {
|
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Func)) {
|
||||||
|
if (HasExplicitTemplateArgs)
|
||||||
|
continue;
|
||||||
|
|
||||||
AddOverloadCandidate(FunDecl, Args, NumArgs, CandidateSet);
|
AddOverloadCandidate(FunDecl, Args, NumArgs, CandidateSet);
|
||||||
Ctx = FunDecl->getDeclContext();
|
Ctx = FunDecl->getDeclContext();
|
||||||
} else {
|
} else {
|
||||||
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*Func);
|
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*Func);
|
||||||
AddTemplateOverloadCandidate(FunTmpl, Args, NumArgs, CandidateSet);
|
AddTemplateOverloadCandidate(FunTmpl, HasExplicitTemplateArgs,
|
||||||
|
ExplicitTemplateArgs,
|
||||||
|
NumExplicitTemplateArgs,
|
||||||
|
Args, NumArgs, CandidateSet);
|
||||||
Ctx = FunTmpl->getDeclContext();
|
Ctx = FunTmpl->getDeclContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3803,6 +3818,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||||
ArgumentDependentLookup = false;
|
ArgumentDependentLookup = false;
|
||||||
}
|
}
|
||||||
} else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) {
|
} else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) {
|
||||||
|
assert(!HasExplicitTemplateArgs && "Explicit template arguments?");
|
||||||
AddOverloadCandidate(Func, Args, NumArgs, CandidateSet);
|
AddOverloadCandidate(Func, Args, NumArgs, CandidateSet);
|
||||||
|
|
||||||
if (Func->getDeclContext()->isRecord() ||
|
if (Func->getDeclContext()->isRecord() ||
|
||||||
|
@ -3810,7 +3826,10 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||||
ArgumentDependentLookup = false;
|
ArgumentDependentLookup = false;
|
||||||
} else if (FunctionTemplateDecl *FuncTemplate
|
} else if (FunctionTemplateDecl *FuncTemplate
|
||||||
= dyn_cast_or_null<FunctionTemplateDecl>(Callee)) {
|
= dyn_cast_or_null<FunctionTemplateDecl>(Callee)) {
|
||||||
AddTemplateOverloadCandidate(FuncTemplate, Args, NumArgs, CandidateSet);
|
AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs,
|
||||||
|
ExplicitTemplateArgs,
|
||||||
|
NumExplicitTemplateArgs,
|
||||||
|
Args, NumArgs, CandidateSet);
|
||||||
|
|
||||||
if (FuncTemplate->getDeclContext()->isRecord())
|
if (FuncTemplate->getDeclContext()->isRecord())
|
||||||
ArgumentDependentLookup = false;
|
ArgumentDependentLookup = false;
|
||||||
|
@ -3819,6 +3838,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||||
if (Callee)
|
if (Callee)
|
||||||
UnqualifiedName = Callee->getDeclName();
|
UnqualifiedName = Callee->getDeclName();
|
||||||
|
|
||||||
|
// FIXME: Pass explicit template arguments through for ADL
|
||||||
if (ArgumentDependentLookup)
|
if (ArgumentDependentLookup)
|
||||||
AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs,
|
AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs,
|
||||||
CandidateSet);
|
CandidateSet);
|
||||||
|
|
|
@ -868,6 +868,16 @@ static bool isSimpleTemplateIdType(QualType T) {
|
||||||
/// \param FunctionTemplate the function template for which we are performing
|
/// \param FunctionTemplate the function template for which we are performing
|
||||||
/// template argument deduction.
|
/// 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 Args the function call arguments
|
/// \param Args the function call arguments
|
||||||
///
|
///
|
||||||
/// \param NumArgs the number of arguments in Args
|
/// \param NumArgs the number of arguments in Args
|
||||||
|
@ -880,22 +890,22 @@ static bool isSimpleTemplateIdType(QualType T) {
|
||||||
/// about template argument deduction.
|
/// about template argument deduction.
|
||||||
///
|
///
|
||||||
/// \returns the result of template argument deduction.
|
/// \returns the result of template argument deduction.
|
||||||
///
|
|
||||||
/// FIXME: We will also need to pass in any explicitly-specified template
|
|
||||||
/// arguments.
|
|
||||||
Sema::TemplateDeductionResult
|
Sema::TemplateDeductionResult
|
||||||
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
bool HasExplicitTemplateArgs,
|
||||||
|
const TemplateArgument *ExplicitTemplateArgs,
|
||||||
|
unsigned NumExplicitTemplateArgs,
|
||||||
Expr **Args, unsigned NumArgs,
|
Expr **Args, unsigned NumArgs,
|
||||||
FunctionDecl *&Specialization,
|
FunctionDecl *&Specialization,
|
||||||
TemplateDeductionInfo &Info) {
|
TemplateDeductionInfo &Info) {
|
||||||
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
|
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
|
||||||
|
|
||||||
// C++ [temp.deduct.call]p1:
|
// C++ [temp.deduct.call]p1:
|
||||||
// Template argument deduction is done by comparing each function template
|
// Template argument deduction is done by comparing each function template
|
||||||
// parameter type (call it P) with the type of the corresponding argument
|
// parameter type (call it P) with the type of the corresponding argument
|
||||||
// of the call (call it A) as described below.
|
// of the call (call it A) as described below.
|
||||||
unsigned CheckArgs = NumArgs;
|
unsigned CheckArgs = NumArgs;
|
||||||
if (NumArgs < Function->getNumParams())
|
if (NumArgs < Function->getMinRequiredArguments())
|
||||||
return TDK_TooFewArguments;
|
return TDK_TooFewArguments;
|
||||||
else if (NumArgs > Function->getNumParams()) {
|
else if (NumArgs > Function->getNumParams()) {
|
||||||
const FunctionProtoType *Proto
|
const FunctionProtoType *Proto
|
||||||
|
@ -905,18 +915,83 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
|
|
||||||
CheckArgs = Function->getNumParams();
|
CheckArgs = Function->getNumParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template argument deduction for function templates in a SFINAE context.
|
// Template argument deduction for function templates in a SFINAE context.
|
||||||
// Trap any errors that might occur.
|
// Trap any errors that might occur.
|
||||||
SFINAETrap Trap(*this);
|
SFINAETrap Trap(*this);
|
||||||
|
|
||||||
// Deduce template arguments from the function parameters.
|
// The types of the parameters from which we will perform template argument
|
||||||
llvm::SmallVector<TemplateArgument, 4> Deduced;
|
// deduction.
|
||||||
Deduced.resize(FunctionTemplate->getTemplateParameters()->size());
|
|
||||||
TemplateParameterList *TemplateParams
|
TemplateParameterList *TemplateParams
|
||||||
= FunctionTemplate->getTemplateParameters();
|
= FunctionTemplate->getTemplateParameters();
|
||||||
|
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);
|
||||||
|
if (CheckTemplateArgumentList(FunctionTemplate,
|
||||||
|
SourceLocation(), SourceLocation(),
|
||||||
|
ExplicitTemplateArgs,
|
||||||
|
NumExplicitTemplateArgs,
|
||||||
|
SourceLocation(),
|
||||||
|
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
|
||||||
|
= 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));
|
||||||
|
} 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) {
|
for (unsigned I = 0; I != CheckArgs; ++I) {
|
||||||
QualType ParamType = Function->getParamDecl(I)->getType();
|
QualType ParamType = ParamTypes[I];
|
||||||
QualType ArgType = Args[I]->getType();
|
QualType ArgType = Args[I]->getType();
|
||||||
|
|
||||||
// C++ [temp.deduct.call]p2:
|
// C++ [temp.deduct.call]p2:
|
||||||
|
@ -998,11 +1073,6 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
// FIXME: C++ [temp.deduct.call] paragraphs 6-9 deal with function
|
// FIXME: C++ [temp.deduct.call] paragraphs 6-9 deal with function
|
||||||
// pointer parameters.
|
// pointer parameters.
|
||||||
}
|
}
|
||||||
|
|
||||||
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
|
|
||||||
FunctionTemplate, Deduced.data(), Deduced.size());
|
|
||||||
if (Inst)
|
|
||||||
return TDK_InstantiationDepth;
|
|
||||||
|
|
||||||
// C++ [temp.deduct.type]p2:
|
// C++ [temp.deduct.type]p2:
|
||||||
// [...] or if any template argument remains neither deduced nor
|
// [...] or if any template argument remains neither deduced nor
|
||||||
|
@ -1030,6 +1100,13 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
= new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
|
= new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
|
||||||
Info.reset(DeducedArgumentList);
|
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());
|
||||||
|
if (Inst)
|
||||||
|
return TDK_InstantiationDepth;
|
||||||
|
|
||||||
// Substitute the deduced template arguments into the function template
|
// Substitute the deduced template arguments into the function template
|
||||||
// declaration to produce the function template specialization.
|
// declaration to produce the function template specialization.
|
||||||
Specialization = cast_or_null<FunctionDecl>(
|
Specialization = cast_or_null<FunctionDecl>(
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
template<typename T> struct A { };
|
template<typename T> struct A { };
|
||||||
|
|
||||||
template<typename T> T make(A<T>);
|
template<typename T> T make();
|
||||||
|
template<typename T> T make2(const T&);
|
||||||
|
|
||||||
void test_make() {
|
void test_make() {
|
||||||
int& ir0 = make<int&>(A<int&>());
|
int& ir0 = make<int&>();
|
||||||
A<int> a0 = make< A<int> >(A<A<int> >());
|
A<int> a0 = make< A<int> >();
|
||||||
|
A<int> a1 = make2< A<int> >(A<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue