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 ForceRValue = false);
|
||||
void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
||||
bool HasExplicitTemplateArgs,
|
||||
const TemplateArgument *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
OverloadCandidateSet& CandidateSet,
|
||||
bool SuppressUserConversions = false,
|
||||
|
@ -747,6 +750,9 @@ public:
|
|||
|
||||
FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||
DeclarationName UnqualifiedName,
|
||||
bool HasExplicitTemplateArgs,
|
||||
const TemplateArgument *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
SourceLocation LParenLoc,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
SourceLocation *CommaLocs,
|
||||
|
@ -2247,7 +2253,10 @@ public:
|
|||
TDK_TooManyArguments,
|
||||
/// \brief When performing template argument deduction for a class
|
||||
/// 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
|
||||
|
@ -2329,6 +2338,9 @@ public:
|
|||
|
||||
TemplateDeductionResult
|
||||
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||
bool HasExplicitTemplateArgs,
|
||||
const TemplateArgument *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
FunctionDecl *&Specialization,
|
||||
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.
|
||||
// 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;
|
||||
bool ADL = true;
|
||||
bool HasExplicitTemplateArgs = 0;
|
||||
const TemplateArgument *ExplicitTemplateArgs = 0;
|
||||
unsigned NumExplicitTemplateArgs = 0;
|
||||
while (true) {
|
||||
if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr))
|
||||
FnExpr = IcExpr->getSubExpr();
|
||||
|
@ -2661,6 +2666,28 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
|
|||
} else if (TemplateIdRefExpr *TemplateIdRef
|
||||
= dyn_cast<TemplateIdRefExpr>(FnExpr)) {
|
||||
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;
|
||||
} else {
|
||||
// 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;
|
||||
|
||||
if (Ovl || FunctionTemplate || ADL) {
|
||||
FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, LParenLoc,
|
||||
Args, NumArgs, CommaLocs, RParenLoc, ADL);
|
||||
FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName,
|
||||
HasExplicitTemplateArgs,
|
||||
ExplicitTemplateArgs,
|
||||
NumExplicitTemplateArgs,
|
||||
LParenLoc, Args, NumArgs, CommaLocs,
|
||||
RParenLoc, ADL);
|
||||
if (!FDecl)
|
||||
return ExprError();
|
||||
|
||||
|
|
|
@ -2166,8 +2166,9 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions,
|
|||
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet,
|
||||
SuppressUserConversions);
|
||||
else
|
||||
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F), Args,
|
||||
NumArgs, CandidateSet,
|
||||
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F),
|
||||
/*FIXME: explicit args */false, 0, 0,
|
||||
Args, NumArgs, CandidateSet,
|
||||
SuppressUserConversions);
|
||||
}
|
||||
}
|
||||
|
@ -2273,6 +2274,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object,
|
|||
/// template specialization.
|
||||
void
|
||||
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
||||
bool HasExplicitTemplateArgs,
|
||||
const TemplateArgument *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
OverloadCandidateSet& CandidateSet,
|
||||
bool SuppressUserConversions,
|
||||
|
@ -2289,8 +2293,9 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
|
|||
TemplateDeductionInfo Info(Context);
|
||||
FunctionDecl *Specialization = 0;
|
||||
if (TemplateDeductionResult Result
|
||||
= DeduceTemplateArguments(FunctionTemplate, Args, NumArgs,
|
||||
Specialization, Info)) {
|
||||
= DeduceTemplateArguments(FunctionTemplate, HasExplicitTemplateArgs,
|
||||
ExplicitTemplateArgs, NumExplicitTemplateArgs,
|
||||
Args, NumArgs, Specialization, Info)) {
|
||||
// FIXME: Record what happened with template argument deduction, so
|
||||
// that we can give the user a beautiful diagnostic.
|
||||
(void)Result;
|
||||
|
@ -3438,8 +3443,9 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
|
|||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func))
|
||||
AddOverloadCandidate(FD, Args, NumArgs, CandidateSet);
|
||||
else
|
||||
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), Args,
|
||||
NumArgs, CandidateSet);
|
||||
AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func),
|
||||
/*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.
|
||||
FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
||||
DeclarationName UnqualifiedName,
|
||||
bool HasExplicitTemplateArgs,
|
||||
const TemplateArgument *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
SourceLocation LParenLoc,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
SourceLocation *CommaLocs,
|
||||
|
@ -3790,11 +3799,17 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
|||
Func != FuncEnd; ++Func) {
|
||||
DeclContext *Ctx = 0;
|
||||
if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Func)) {
|
||||
if (HasExplicitTemplateArgs)
|
||||
continue;
|
||||
|
||||
AddOverloadCandidate(FunDecl, Args, NumArgs, CandidateSet);
|
||||
Ctx = FunDecl->getDeclContext();
|
||||
} else {
|
||||
FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*Func);
|
||||
AddTemplateOverloadCandidate(FunTmpl, Args, NumArgs, CandidateSet);
|
||||
AddTemplateOverloadCandidate(FunTmpl, HasExplicitTemplateArgs,
|
||||
ExplicitTemplateArgs,
|
||||
NumExplicitTemplateArgs,
|
||||
Args, NumArgs, CandidateSet);
|
||||
Ctx = FunTmpl->getDeclContext();
|
||||
}
|
||||
|
||||
|
@ -3803,6 +3818,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
|||
ArgumentDependentLookup = false;
|
||||
}
|
||||
} else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) {
|
||||
assert(!HasExplicitTemplateArgs && "Explicit template arguments?");
|
||||
AddOverloadCandidate(Func, Args, NumArgs, CandidateSet);
|
||||
|
||||
if (Func->getDeclContext()->isRecord() ||
|
||||
|
@ -3810,7 +3826,10 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
|||
ArgumentDependentLookup = false;
|
||||
} else if (FunctionTemplateDecl *FuncTemplate
|
||||
= dyn_cast_or_null<FunctionTemplateDecl>(Callee)) {
|
||||
AddTemplateOverloadCandidate(FuncTemplate, Args, NumArgs, CandidateSet);
|
||||
AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs,
|
||||
ExplicitTemplateArgs,
|
||||
NumExplicitTemplateArgs,
|
||||
Args, NumArgs, CandidateSet);
|
||||
|
||||
if (FuncTemplate->getDeclContext()->isRecord())
|
||||
ArgumentDependentLookup = false;
|
||||
|
@ -3819,6 +3838,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
|
|||
if (Callee)
|
||||
UnqualifiedName = Callee->getDeclName();
|
||||
|
||||
// FIXME: Pass explicit template arguments through for ADL
|
||||
if (ArgumentDependentLookup)
|
||||
AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs,
|
||||
CandidateSet);
|
||||
|
|
|
@ -868,6 +868,16 @@ static bool isSimpleTemplateIdType(QualType T) {
|
|||
/// \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 Args the function call arguments
|
||||
///
|
||||
/// \param NumArgs the number of arguments in Args
|
||||
|
@ -880,22 +890,22 @@ static bool isSimpleTemplateIdType(QualType T) {
|
|||
/// about 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::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||
bool HasExplicitTemplateArgs,
|
||||
const TemplateArgument *ExplicitTemplateArgs,
|
||||
unsigned NumExplicitTemplateArgs,
|
||||
Expr **Args, unsigned NumArgs,
|
||||
FunctionDecl *&Specialization,
|
||||
TemplateDeductionInfo &Info) {
|
||||
FunctionDecl *Function = FunctionTemplate->getTemplatedDecl();
|
||||
|
||||
|
||||
// C++ [temp.deduct.call]p1:
|
||||
// Template argument deduction is done by comparing each function template
|
||||
// parameter type (call it P) with the type of the corresponding argument
|
||||
// of the call (call it A) as described below.
|
||||
unsigned CheckArgs = NumArgs;
|
||||
if (NumArgs < Function->getNumParams())
|
||||
if (NumArgs < Function->getMinRequiredArguments())
|
||||
return TDK_TooFewArguments;
|
||||
else if (NumArgs > Function->getNumParams()) {
|
||||
const FunctionProtoType *Proto
|
||||
|
@ -905,18 +915,83 @@ 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);
|
||||
|
||||
// Deduce template arguments from the function parameters.
|
||||
llvm::SmallVector<TemplateArgument, 4> Deduced;
|
||||
Deduced.resize(FunctionTemplate->getTemplateParameters()->size());
|
||||
|
||||
// The types of the parameters from which we will perform template argument
|
||||
// deduction.
|
||||
TemplateParameterList *TemplateParams
|
||||
= 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) {
|
||||
QualType ParamType = Function->getParamDecl(I)->getType();
|
||||
QualType ParamType = ParamTypes[I];
|
||||
QualType ArgType = Args[I]->getType();
|
||||
|
||||
// C++ [temp.deduct.call]p2:
|
||||
|
@ -998,11 +1073,6 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
|||
// FIXME: C++ [temp.deduct.call] paragraphs 6-9 deal with function
|
||||
// pointer parameters.
|
||||
}
|
||||
|
||||
InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(),
|
||||
FunctionTemplate, Deduced.data(), Deduced.size());
|
||||
if (Inst)
|
||||
return TDK_InstantiationDepth;
|
||||
|
||||
// C++ [temp.deduct.type]p2:
|
||||
// [...] or if any template argument remains neither deduced nor
|
||||
|
@ -1030,6 +1100,13 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
|||
= 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());
|
||||
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>(
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
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() {
|
||||
int& ir0 = make<int&>(A<int&>());
|
||||
A<int> a0 = make< A<int> >(A<A<int> >());
|
||||
int& ir0 = make<int&>();
|
||||
A<int> a0 = make< A<int> >();
|
||||
A<int> a1 = make2< A<int> >(A<int>());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue