[NFCI] Propagate MLTAL through more concepts in prep of deferred inst.

In preperation of the deferred instantation progress, this patch
propagates the multi-level template argument lists further through the
API to reduce the size of that patch.
This commit is contained in:
Erich Keane 2022-07-29 05:52:40 -07:00
parent fbe022f189
commit b25902736c
4 changed files with 73 additions and 44 deletions

View File

@ -7153,7 +7153,7 @@ public:
/// false otherwise.
bool CheckConstraintSatisfaction(
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs,
const MultiLevelTemplateArgumentList &TemplateArgLists,
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
/// \brief Check whether the given non-dependent constraint expression is
@ -7189,9 +7189,10 @@ public:
///
/// \returns true if the constrains are not satisfied or could not be checked
/// for satisfaction, false if the constraints are satisfied.
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange TemplateIDRange);
bool EnsureTemplateArgumentListConstraints(
TemplateDecl *Template,
const MultiLevelTemplateArgumentList &TemplateArgs,
SourceRange TemplateIDRange);
/// \brief Emit diagnostics explaining why a constraint expression was deemed
/// unsatisfied.

View File

@ -199,9 +199,9 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
}
static bool calculateConstraintSatisfaction(
Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
ConstraintSatisfaction &Satisfaction) {
return calculateConstraintSatisfaction(
S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
EnterExpressionEvaluationContext ConstantEvaluated(
@ -268,36 +268,35 @@ static bool calculateConstraintSatisfaction(
});
}
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs,
SourceRange TemplateIDRange,
ConstraintSatisfaction &Satisfaction) {
static bool CheckConstraintSatisfaction(
Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
const MultiLevelTemplateArgumentList &TemplateArgsLists,
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
if (ConstraintExprs.empty()) {
Satisfaction.IsSatisfied = true;
return false;
}
for (auto& Arg : TemplateArgs)
if (Arg.isInstantiationDependent()) {
// No need to check satisfaction for dependent constraint expressions.
Satisfaction.IsSatisfied = true;
return false;
}
if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
// No need to check satisfaction for dependent constraint expressions.
Satisfaction.IsSatisfied = true;
return false;
}
ArrayRef<TemplateArgument> TemplateArgs =
TemplateArgsLists.getNumSubstitutedLevels() > 0
? TemplateArgsLists.getOutermost()
: ArrayRef<TemplateArgument> {};
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{},
const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
if (Inst.isInvalid())
return true;
MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(TemplateArgs);
for (const Expr *ConstraintExpr : ConstraintExprs) {
if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
TemplateIDRange.getBegin(), MLTAL,
ConstraintExpr, Satisfaction))
if (calculateConstraintSatisfaction(S, Template, TemplateIDRange.getBegin(),
TemplateArgsLists, ConstraintExpr,
Satisfaction))
return true;
if (!Satisfaction.IsSatisfied)
// [temp.constr.op] p2
@ -311,28 +310,37 @@ static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
bool Sema::CheckConstraintSatisfaction(
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
ConstraintSatisfaction &OutSatisfaction) {
const MultiLevelTemplateArgumentList &TemplateArgsLists,
SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
if (ConstraintExprs.empty()) {
OutSatisfaction.IsSatisfied = true;
return false;
}
if (!Template) {
return ::CheckConstraintSatisfaction(*this, nullptr, ConstraintExprs,
TemplateArgs, TemplateIDRange,
TemplateArgsLists, TemplateIDRange,
OutSatisfaction);
}
// A list of the template argument list flattened in a predictible manner for
// the purposes of caching. The ConstraintSatisfaction type is in AST so it
// has no access to the MultiLevelTemplateArgumentList, so this has to happen
// here.
llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
for (ArrayRef<TemplateArgument> List : TemplateArgsLists)
FlattenedArgs.insert(FlattenedArgs.end(), List.begin(), List.end());
llvm::FoldingSetNodeID ID;
ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
void *InsertPos;
if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
OutSatisfaction = *Cached;
return false;
}
auto Satisfaction =
std::make_unique<ConstraintSatisfaction>(Template, TemplateArgs);
std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
TemplateArgs, TemplateIDRange,
TemplateArgsLists, TemplateIDRange,
*Satisfaction)) {
return true;
}
@ -379,12 +387,12 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
}
bool Sema::EnsureTemplateArgumentListConstraints(
TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
SourceRange TemplateIDRange) {
ConstraintSatisfaction Satisfaction;
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
TD->getAssociatedConstraints(AssociatedConstraints);
if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
TemplateIDRange, Satisfaction))
return true;
@ -392,7 +400,8 @@ bool Sema::EnsureTemplateArgumentListConstraints(
SmallString<128> TemplateArgString;
TemplateArgString = " ";
TemplateArgString += getTemplateArgumentBindingsText(
TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
TemplateArgsLists.getInnermost().size());
Diag(TemplateIDRange.getBegin(),
diag::err_template_arg_list_constraints_not_satisfied)
@ -423,6 +432,10 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
// PushDeclContext because we don't have a scope.
Sema::ContextRAII savedContext(*this, Decl);
LocalInstantiationScope Scope(*this);
MultiLevelTemplateArgumentList MLTAL;
// FIXME: This will be replaced with some logic to get all the template
// arguments when we switch to deferred template instantiation.
MLTAL.addOuterTemplateArguments(TemplateArgs);
// If this is not an explicit specialization - we need to get the instantiated
// version of the template arguments and add them to scope for the
@ -446,7 +459,7 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
Record = Method->getParent();
}
CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs,
return CheckConstraintSatisfaction(Template, TemplateAC, MLTAL,
PointOfInstantiation, Satisfaction);
}

View File

@ -4751,9 +4751,12 @@ Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
bool AreArgsDependent =
TemplateSpecializationType::anyDependentTemplateArguments(*TemplateArgs,
Converted);
MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(Converted);
LocalInstantiationScope Scope(*this);
if (!AreArgsDependent &&
CheckConstraintSatisfaction(
NamedConcept, {NamedConcept->getConstraintExpr()}, Converted,
NamedConcept, {NamedConcept->getConstraintExpr()}, MLTAL,
SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameInfo.getLoc(),
TemplateArgs->getRAngleLoc()),
Satisfaction))
@ -5970,13 +5973,18 @@ bool Sema::CheckTemplateArgumentList(
if (UpdateArgsWithConversions)
TemplateArgs = std::move(NewArgs);
if (!PartialTemplateArgs &&
EnsureTemplateArgumentListConstraints(
Template, Converted, SourceRange(TemplateLoc,
TemplateArgs.getRAngleLoc()))) {
if (ConstraintsNotSatisfied)
*ConstraintsNotSatisfied = true;
return true;
if (!PartialTemplateArgs) {
// FIXME: This will be changed a bit once deferred concept instantiation is
// implemented.
MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(Converted);
if (EnsureTemplateArgumentListConstraints(
Template, MLTAL,
SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) {
if (ConstraintsNotSatisfied)
*ConstraintsNotSatisfied = true;
return true;
}
}
return false;

View File

@ -2791,8 +2791,13 @@ CheckDeducedArgumentConstraints(Sema& S, TemplateDeclT *Template,
TemplateDeductionInfo& Info) {
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
Template->getAssociatedConstraints(AssociatedConstraints);
// FIXME: This will change quite a bit once deferred concept instantiation is
// implemented.
MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(DeducedArgs);
if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints,
DeducedArgs, Info.getLocation(),
MLTAL, Info.getLocation(),
Info.AssociatedConstraintsSatisfaction) ||
!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
Info.reset(TemplateArgumentList::CreateCopy(S.Context, DeducedArgs));
@ -4572,8 +4577,10 @@ CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type,
if (S.CheckTemplateArgumentList(Concept, SourceLocation(), TemplateArgs,
/*PartialTemplateArgs=*/false, Converted))
return Sema::DAR_FailedAlreadyDiagnosed;
MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(Converted);
if (S.CheckConstraintSatisfaction(Concept, {Concept->getConstraintExpr()},
Converted, TypeLoc.getLocalSourceRange(),
MLTAL, TypeLoc.getLocalSourceRange(),
Satisfaction))
return Sema::DAR_FailedAlreadyDiagnosed;
if (!Satisfaction.IsSatisfied) {