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,
FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
DeclarationName UnqualifiedName,
+ bool HasExplicitTemplateArgs,
+ const TemplateArgument *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
SourceLocation LParenLoc,
Expr **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
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
TemplateDeductionResult
DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
+ bool HasExplicitTemplateArgs,
+ const TemplateArgument *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
FunctionDecl *&Specialization,
TemplateDeductionInfo &Info);
}
// 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();
} 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
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();
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);
}
}
/// template specialization.
void
Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
+ bool HasExplicitTemplateArgs,
+ const TemplateArgument *ExplicitTemplateArgs,
+ unsigned NumExplicitTemplateArgs,
Expr **Args, unsigned NumArgs,
OverloadCandidateSet& CandidateSet,
bool SuppressUserConversions,
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;
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);
}
}
/// 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,
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();
}
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() ||
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;
if (Callee)
UnqualifiedName = Callee->getDeclName();
+ // FIXME: Pass explicit template arguments through for ADL
if (ArgumentDependentLookup)
AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs,
CandidateSet);
/// \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
/// 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
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:
// 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
= 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>(
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>());
}
-