forked from OSchip/llvm-project
Factor out checking of template arguments after deduction into a separate
function. (This change would also allow us to handle default template arguments in partial specializations if the standard ever permits them.) llvm-svn: 290225
This commit is contained in:
parent
d9af48a931
commit
1f5be4d5b6
|
@ -2214,6 +2214,130 @@ ConvertDeducedTemplateArgument(Sema &S, NamedDecl *Param,
|
|||
return ConvertArg(Arg, 0);
|
||||
}
|
||||
|
||||
// FIXME: This should not be a template, but
|
||||
// ClassTemplatePartialSpecializationDecl sadly does not derive from
|
||||
// TemplateDecl.
|
||||
template<typename TemplateDeclT>
|
||||
static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
|
||||
Sema &S, TemplateDeclT *Template,
|
||||
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
|
||||
TemplateDeductionInfo &Info, SmallVectorImpl<TemplateArgument> &Builder,
|
||||
LocalInstantiationScope *CurrentInstantiationScope = nullptr,
|
||||
unsigned NumAlreadyConverted = 0, bool PartialOverloading = false) {
|
||||
TemplateParameterList *TemplateParams = Template->getTemplateParameters();
|
||||
|
||||
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
|
||||
NamedDecl *Param = TemplateParams->getParam(I);
|
||||
|
||||
if (!Deduced[I].isNull()) {
|
||||
if (I < NumAlreadyConverted) {
|
||||
// We have already fully type-checked and converted this
|
||||
// argument, because it was explicitly-specified. Just record the
|
||||
// presence of this argument.
|
||||
Builder.push_back(Deduced[I]);
|
||||
// We may have had explicitly-specified template arguments for a
|
||||
// template parameter pack (that may or may not have been extended
|
||||
// via additional deduced arguments).
|
||||
if (Param->isParameterPack() && CurrentInstantiationScope) {
|
||||
if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
|
||||
Param) {
|
||||
// Forget the partially-substituted pack; its substitution is now
|
||||
// complete.
|
||||
CurrentInstantiationScope->ResetPartiallySubstitutedPack();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have deduced this argument, so it still needs to be
|
||||
// checked and converted.
|
||||
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Template, Info,
|
||||
isa<FunctionTemplateDecl>(Template),
|
||||
Builder)) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
|
||||
return Sema::TDK_SubstitutionFailure;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// C++0x [temp.arg.explicit]p3:
|
||||
// A trailing template parameter pack (14.5.3) not otherwise deduced will
|
||||
// be deduced to an empty sequence of template arguments.
|
||||
// FIXME: Where did the word "trailing" come from?
|
||||
if (Param->isTemplateParameterPack()) {
|
||||
// We may have had explicitly-specified template arguments for this
|
||||
// template parameter pack. If so, our empty deduction extends the
|
||||
// explicitly-specified set (C++0x [temp.arg.explicit]p9).
|
||||
const TemplateArgument *ExplicitArgs;
|
||||
unsigned NumExplicitArgs;
|
||||
if (CurrentInstantiationScope &&
|
||||
CurrentInstantiationScope->getPartiallySubstitutedPack(
|
||||
&ExplicitArgs, &NumExplicitArgs) == Param) {
|
||||
Builder.push_back(TemplateArgument(
|
||||
llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
|
||||
|
||||
// Forget the partially-substituted pack; its substitution is now
|
||||
// complete.
|
||||
CurrentInstantiationScope->ResetPartiallySubstitutedPack();
|
||||
} else {
|
||||
// Go through the motions of checking the empty argument pack against
|
||||
// the parameter pack.
|
||||
DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack());
|
||||
if (ConvertDeducedTemplateArgument(
|
||||
S, Param, DeducedPack, Template, Info,
|
||||
isa<FunctionTemplateDecl>(Template), Builder)) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
|
||||
return Sema::TDK_SubstitutionFailure;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substitute into the default template argument, if available.
|
||||
bool HasDefaultArg = false;
|
||||
TemplateDecl *TD = dyn_cast<TemplateDecl>(Template);
|
||||
if (!TD) {
|
||||
assert(isa<ClassTemplatePartialSpecializationDecl>(Template));
|
||||
return Sema::TDK_Incomplete;
|
||||
}
|
||||
|
||||
TemplateArgumentLoc DefArg = S.SubstDefaultTemplateArgumentIfAvailable(
|
||||
TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder,
|
||||
HasDefaultArg);
|
||||
|
||||
// If there was no default argument, deduction is incomplete.
|
||||
if (DefArg.getArgument().isNull()) {
|
||||
Info.Param = makeTemplateParameter(
|
||||
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
|
||||
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
|
||||
if (PartialOverloading) break;
|
||||
|
||||
return HasDefaultArg ? Sema::TDK_SubstitutionFailure
|
||||
: Sema::TDK_Incomplete;
|
||||
}
|
||||
|
||||
// Check whether we can actually use the default argument.
|
||||
if (S.CheckTemplateArgument(Param, DefArg, TD, TD->getLocation(),
|
||||
TD->getSourceRange().getEnd(), 0, Builder,
|
||||
Sema::CTAK_Specified)) {
|
||||
Info.Param = makeTemplateParameter(
|
||||
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
|
||||
return Sema::TDK_SubstitutionFailure;
|
||||
}
|
||||
|
||||
// If we get here, we successfully used the default template argument.
|
||||
}
|
||||
|
||||
return Sema::TDK_Success;
|
||||
}
|
||||
|
||||
/// Complete template argument deduction for a class template partial
|
||||
/// specialization.
|
||||
static Sema::TemplateDeductionResult
|
||||
|
@ -2232,25 +2356,9 @@ FinishTemplateArgumentDeduction(Sema &S,
|
|||
// [...] or if any template argument remains neither deduced nor
|
||||
// explicitly specified, template argument deduction fails.
|
||||
SmallVector<TemplateArgument, 4> Builder;
|
||||
TemplateParameterList *PartialParams = Partial->getTemplateParameters();
|
||||
for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
|
||||
NamedDecl *Param = PartialParams->getParam(I);
|
||||
if (Deduced[I].isNull()) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
return Sema::TDK_Incomplete;
|
||||
}
|
||||
|
||||
// We have deduced this argument, so it still needs to be
|
||||
// checked and converted.
|
||||
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I],
|
||||
Partial, Info, false,
|
||||
Builder)) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
|
||||
return Sema::TDK_SubstitutionFailure;
|
||||
}
|
||||
}
|
||||
if (auto Result = ConvertDeducedTemplateArguments(S, Partial, Deduced,
|
||||
Info, Builder))
|
||||
return Result;
|
||||
|
||||
// Form the template argument list from the deduced template arguments.
|
||||
TemplateArgumentList *DeducedArgumentList
|
||||
|
@ -2372,24 +2480,9 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
|
|||
// [...] or if any template argument remains neither deduced nor
|
||||
// explicitly specified, template argument deduction fails.
|
||||
SmallVector<TemplateArgument, 4> Builder;
|
||||
TemplateParameterList *PartialParams = Partial->getTemplateParameters();
|
||||
for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
|
||||
NamedDecl *Param = PartialParams->getParam(I);
|
||||
if (Deduced[I].isNull()) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
return Sema::TDK_Incomplete;
|
||||
}
|
||||
|
||||
// We have deduced this argument, so it still needs to be
|
||||
// checked and converted.
|
||||
if (ConvertDeducedTemplateArgument(S, Param, Deduced[I], Partial,
|
||||
Info, false, Builder)) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(S.Context, Builder));
|
||||
return Sema::TDK_SubstitutionFailure;
|
||||
}
|
||||
}
|
||||
if (auto Result = ConvertDeducedTemplateArguments(S, Partial, Deduced,
|
||||
Info, Builder))
|
||||
return Result;
|
||||
|
||||
// Form the template argument list from the deduced template arguments.
|
||||
TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
|
||||
|
@ -2819,9 +2912,6 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
|||
TemplateDeductionInfo &Info,
|
||||
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
|
||||
bool PartialOverloading) {
|
||||
TemplateParameterList *TemplateParams
|
||||
= FunctionTemplate->getTemplateParameters();
|
||||
|
||||
// Unevaluated SFINAE context.
|
||||
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
|
||||
SFINAETrap Trap(*this);
|
||||
|
@ -2842,114 +2932,11 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
|||
// [...] or if any template argument remains neither deduced nor
|
||||
// explicitly specified, template argument deduction fails.
|
||||
SmallVector<TemplateArgument, 4> Builder;
|
||||
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
|
||||
NamedDecl *Param = TemplateParams->getParam(I);
|
||||
|
||||
if (!Deduced[I].isNull()) {
|
||||
if (I < NumExplicitlySpecified) {
|
||||
// We have already fully type-checked and converted this
|
||||
// argument, because it was explicitly-specified. Just record the
|
||||
// presence of this argument.
|
||||
Builder.push_back(Deduced[I]);
|
||||
// We may have had explicitly-specified template arguments for a
|
||||
// template parameter pack (that may or may not have been extended
|
||||
// via additional deduced arguments).
|
||||
if (Param->isParameterPack() && CurrentInstantiationScope) {
|
||||
if (CurrentInstantiationScope->getPartiallySubstitutedPack() ==
|
||||
Param) {
|
||||
// Forget the partially-substituted pack; its substitution is now
|
||||
// complete.
|
||||
CurrentInstantiationScope->ResetPartiallySubstitutedPack();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// We have deduced this argument, so it still needs to be
|
||||
// checked and converted.
|
||||
if (ConvertDeducedTemplateArgument(*this, Param, Deduced[I],
|
||||
FunctionTemplate, Info,
|
||||
true, Builder)) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
|
||||
return TDK_SubstitutionFailure;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// C++0x [temp.arg.explicit]p3:
|
||||
// A trailing template parameter pack (14.5.3) not otherwise deduced will
|
||||
// be deduced to an empty sequence of template arguments.
|
||||
// FIXME: Where did the word "trailing" come from?
|
||||
if (Param->isTemplateParameterPack()) {
|
||||
// We may have had explicitly-specified template arguments for this
|
||||
// template parameter pack. If so, our empty deduction extends the
|
||||
// explicitly-specified set (C++0x [temp.arg.explicit]p9).
|
||||
const TemplateArgument *ExplicitArgs;
|
||||
unsigned NumExplicitArgs;
|
||||
if (CurrentInstantiationScope &&
|
||||
CurrentInstantiationScope->getPartiallySubstitutedPack(&ExplicitArgs,
|
||||
&NumExplicitArgs)
|
||||
== Param) {
|
||||
Builder.push_back(TemplateArgument(
|
||||
llvm::makeArrayRef(ExplicitArgs, NumExplicitArgs)));
|
||||
|
||||
// Forget the partially-substituted pack; its substitution is now
|
||||
// complete.
|
||||
CurrentInstantiationScope->ResetPartiallySubstitutedPack();
|
||||
} else {
|
||||
// Go through the motions of checking the empty argument pack against
|
||||
// the parameter pack.
|
||||
DeducedTemplateArgument DeducedPack(TemplateArgument::getEmptyPack());
|
||||
if (ConvertDeducedTemplateArgument(*this, Param, DeducedPack,
|
||||
FunctionTemplate, Info, true,
|
||||
Builder)) {
|
||||
Info.Param = makeTemplateParameter(Param);
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
|
||||
return TDK_SubstitutionFailure;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substitute into the default template argument, if available.
|
||||
bool HasDefaultArg = false;
|
||||
TemplateArgumentLoc DefArg
|
||||
= SubstDefaultTemplateArgumentIfAvailable(FunctionTemplate,
|
||||
FunctionTemplate->getLocation(),
|
||||
FunctionTemplate->getSourceRange().getEnd(),
|
||||
Param,
|
||||
Builder, HasDefaultArg);
|
||||
|
||||
// If there was no default argument, deduction is incomplete.
|
||||
if (DefArg.getArgument().isNull()) {
|
||||
Info.Param = makeTemplateParameter(
|
||||
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
|
||||
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
|
||||
if (PartialOverloading) break;
|
||||
|
||||
return HasDefaultArg ? TDK_SubstitutionFailure : TDK_Incomplete;
|
||||
}
|
||||
|
||||
// Check whether we can actually use the default argument.
|
||||
if (CheckTemplateArgument(Param, DefArg,
|
||||
FunctionTemplate,
|
||||
FunctionTemplate->getLocation(),
|
||||
FunctionTemplate->getSourceRange().getEnd(),
|
||||
0, Builder,
|
||||
CTAK_Specified)) {
|
||||
Info.Param = makeTemplateParameter(
|
||||
const_cast<NamedDecl *>(TemplateParams->getParam(I)));
|
||||
// FIXME: These template arguments are temporary. Free them!
|
||||
Info.reset(TemplateArgumentList::CreateCopy(Context, Builder));
|
||||
return TDK_SubstitutionFailure;
|
||||
}
|
||||
|
||||
// If we get here, we successfully used the default template argument.
|
||||
}
|
||||
if (auto Result = ConvertDeducedTemplateArguments(
|
||||
*this, FunctionTemplate, Deduced, Info, Builder,
|
||||
CurrentInstantiationScope, NumExplicitlySpecified,
|
||||
PartialOverloading))
|
||||
return Result;
|
||||
|
||||
// Form the template argument list from the deduced template arguments.
|
||||
TemplateArgumentList *DeducedArgumentList
|
||||
|
|
Loading…
Reference in New Issue