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);
|
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
|
/// Complete template argument deduction for a class template partial
|
||||||
/// specialization.
|
/// specialization.
|
||||||
static Sema::TemplateDeductionResult
|
static Sema::TemplateDeductionResult
|
||||||
|
@ -2232,25 +2356,9 @@ FinishTemplateArgumentDeduction(Sema &S,
|
||||||
// [...] or if any template argument remains neither deduced nor
|
// [...] or if any template argument remains neither deduced nor
|
||||||
// explicitly specified, template argument deduction fails.
|
// explicitly specified, template argument deduction fails.
|
||||||
SmallVector<TemplateArgument, 4> Builder;
|
SmallVector<TemplateArgument, 4> Builder;
|
||||||
TemplateParameterList *PartialParams = Partial->getTemplateParameters();
|
if (auto Result = ConvertDeducedTemplateArguments(S, Partial, Deduced,
|
||||||
for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
|
Info, Builder))
|
||||||
NamedDecl *Param = PartialParams->getParam(I);
|
return Result;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form the template argument list from the deduced template arguments.
|
// Form the template argument list from the deduced template arguments.
|
||||||
TemplateArgumentList *DeducedArgumentList
|
TemplateArgumentList *DeducedArgumentList
|
||||||
|
@ -2372,24 +2480,9 @@ static Sema::TemplateDeductionResult FinishTemplateArgumentDeduction(
|
||||||
// [...] or if any template argument remains neither deduced nor
|
// [...] or if any template argument remains neither deduced nor
|
||||||
// explicitly specified, template argument deduction fails.
|
// explicitly specified, template argument deduction fails.
|
||||||
SmallVector<TemplateArgument, 4> Builder;
|
SmallVector<TemplateArgument, 4> Builder;
|
||||||
TemplateParameterList *PartialParams = Partial->getTemplateParameters();
|
if (auto Result = ConvertDeducedTemplateArguments(S, Partial, Deduced,
|
||||||
for (unsigned I = 0, N = PartialParams->size(); I != N; ++I) {
|
Info, Builder))
|
||||||
NamedDecl *Param = PartialParams->getParam(I);
|
return Result;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form the template argument list from the deduced template arguments.
|
// Form the template argument list from the deduced template arguments.
|
||||||
TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
|
TemplateArgumentList *DeducedArgumentList = TemplateArgumentList::CreateCopy(
|
||||||
|
@ -2819,9 +2912,6 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
||||||
TemplateDeductionInfo &Info,
|
TemplateDeductionInfo &Info,
|
||||||
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
|
SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs,
|
||||||
bool PartialOverloading) {
|
bool PartialOverloading) {
|
||||||
TemplateParameterList *TemplateParams
|
|
||||||
= FunctionTemplate->getTemplateParameters();
|
|
||||||
|
|
||||||
// Unevaluated SFINAE context.
|
// Unevaluated SFINAE context.
|
||||||
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
|
EnterExpressionEvaluationContext Unevaluated(*this, Sema::Unevaluated);
|
||||||
SFINAETrap Trap(*this);
|
SFINAETrap Trap(*this);
|
||||||
|
@ -2842,114 +2932,11 @@ Sema::FinishTemplateArgumentDeduction(FunctionTemplateDecl *FunctionTemplate,
|
||||||
// [...] or if any template argument remains neither deduced nor
|
// [...] or if any template argument remains neither deduced nor
|
||||||
// explicitly specified, template argument deduction fails.
|
// explicitly specified, template argument deduction fails.
|
||||||
SmallVector<TemplateArgument, 4> Builder;
|
SmallVector<TemplateArgument, 4> Builder;
|
||||||
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
|
if (auto Result = ConvertDeducedTemplateArguments(
|
||||||
NamedDecl *Param = TemplateParams->getParam(I);
|
*this, FunctionTemplate, Deduced, Info, Builder,
|
||||||
|
CurrentInstantiationScope, NumExplicitlySpecified,
|
||||||
if (!Deduced[I].isNull()) {
|
PartialOverloading))
|
||||||
if (I < NumExplicitlySpecified) {
|
return Result;
|
||||||
// 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.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Form the template argument list from the deduced template arguments.
|
// Form the template argument list from the deduced template arguments.
|
||||||
TemplateArgumentList *DeducedArgumentList
|
TemplateArgumentList *DeducedArgumentList
|
||||||
|
|
Loading…
Reference in New Issue