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

View File

@ -199,9 +199,9 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
} }
static bool calculateConstraintSatisfaction( static bool calculateConstraintSatisfaction(
Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL, const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) { ConstraintSatisfaction &Satisfaction) {
return calculateConstraintSatisfaction( return calculateConstraintSatisfaction(
S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) { S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
EnterExpressionEvaluationContext ConstantEvaluated( EnterExpressionEvaluationContext ConstantEvaluated(
@ -268,36 +268,35 @@ static bool calculateConstraintSatisfaction(
}); });
} }
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, static bool CheckConstraintSatisfaction(
ArrayRef<const Expr *> ConstraintExprs, Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs, const MultiLevelTemplateArgumentList &TemplateArgsLists,
SourceRange TemplateIDRange, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
ConstraintSatisfaction &Satisfaction) {
if (ConstraintExprs.empty()) { if (ConstraintExprs.empty()) {
Satisfaction.IsSatisfied = true; Satisfaction.IsSatisfied = true;
return false; return false;
} }
for (auto& Arg : TemplateArgs) if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
if (Arg.isInstantiationDependent()) {
// No need to check satisfaction for dependent constraint expressions. // No need to check satisfaction for dependent constraint expressions.
Satisfaction.IsSatisfied = true; Satisfaction.IsSatisfied = true;
return false; return false;
} }
ArrayRef<TemplateArgument> TemplateArgs =
TemplateArgsLists.getNumSubstitutedLevels() > 0
? TemplateArgsLists.getOutermost()
: ArrayRef<TemplateArgument> {};
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{}, Sema::InstantiatingTemplate::ConstraintsCheck{},
const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
if (Inst.isInvalid()) if (Inst.isInvalid())
return true; return true;
MultiLevelTemplateArgumentList MLTAL;
MLTAL.addOuterTemplateArguments(TemplateArgs);
for (const Expr *ConstraintExpr : ConstraintExprs) { for (const Expr *ConstraintExpr : ConstraintExprs) {
if (calculateConstraintSatisfaction(S, Template, TemplateArgs, if (calculateConstraintSatisfaction(S, Template, TemplateIDRange.getBegin(),
TemplateIDRange.getBegin(), MLTAL, TemplateArgsLists, ConstraintExpr,
ConstraintExpr, Satisfaction)) Satisfaction))
return true; return true;
if (!Satisfaction.IsSatisfied) if (!Satisfaction.IsSatisfied)
// [temp.constr.op] p2 // [temp.constr.op] p2
@ -311,28 +310,37 @@ static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
bool Sema::CheckConstraintSatisfaction( bool Sema::CheckConstraintSatisfaction(
const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange, const MultiLevelTemplateArgumentList &TemplateArgsLists,
ConstraintSatisfaction &OutSatisfaction) { SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
if (ConstraintExprs.empty()) { if (ConstraintExprs.empty()) {
OutSatisfaction.IsSatisfied = true; OutSatisfaction.IsSatisfied = true;
return false; return false;
} }
if (!Template) { if (!Template) {
return ::CheckConstraintSatisfaction(*this, nullptr, ConstraintExprs, return ::CheckConstraintSatisfaction(*this, nullptr, ConstraintExprs,
TemplateArgs, TemplateIDRange, TemplateArgsLists, TemplateIDRange,
OutSatisfaction); 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; llvm::FoldingSetNodeID ID;
ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs); ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
void *InsertPos; void *InsertPos;
if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
OutSatisfaction = *Cached; OutSatisfaction = *Cached;
return false; return false;
} }
auto Satisfaction = auto Satisfaction =
std::make_unique<ConstraintSatisfaction>(Template, TemplateArgs); std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
TemplateArgs, TemplateIDRange, TemplateArgsLists, TemplateIDRange,
*Satisfaction)) { *Satisfaction)) {
return true; return true;
} }
@ -379,12 +387,12 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
} }
bool Sema::EnsureTemplateArgumentListConstraints( bool Sema::EnsureTemplateArgumentListConstraints(
TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs, TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
SourceRange TemplateIDRange) { SourceRange TemplateIDRange) {
ConstraintSatisfaction Satisfaction; ConstraintSatisfaction Satisfaction;
llvm::SmallVector<const Expr *, 3> AssociatedConstraints; llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
TD->getAssociatedConstraints(AssociatedConstraints); TD->getAssociatedConstraints(AssociatedConstraints);
if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs, if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
TemplateIDRange, Satisfaction)) TemplateIDRange, Satisfaction))
return true; return true;
@ -392,7 +400,8 @@ bool Sema::EnsureTemplateArgumentListConstraints(
SmallString<128> TemplateArgString; SmallString<128> TemplateArgString;
TemplateArgString = " "; TemplateArgString = " ";
TemplateArgString += getTemplateArgumentBindingsText( TemplateArgString += getTemplateArgumentBindingsText(
TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size()); TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
TemplateArgsLists.getInnermost().size());
Diag(TemplateIDRange.getBegin(), Diag(TemplateIDRange.getBegin(),
diag::err_template_arg_list_constraints_not_satisfied) diag::err_template_arg_list_constraints_not_satisfied)
@ -423,6 +432,10 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
// PushDeclContext because we don't have a scope. // PushDeclContext because we don't have a scope.
Sema::ContextRAII savedContext(*this, Decl); Sema::ContextRAII savedContext(*this, Decl);
LocalInstantiationScope Scope(*this); 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 // 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 // version of the template arguments and add them to scope for the
@ -446,7 +459,7 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints(
Record = Method->getParent(); Record = Method->getParent();
} }
CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs, return CheckConstraintSatisfaction(Template, TemplateAC, MLTAL,
PointOfInstantiation, Satisfaction); PointOfInstantiation, Satisfaction);
} }

View File

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

View File

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