diff options
Diffstat (limited to 'clang/lib/Sema/SemaConcept.cpp')
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 94 |
1 files changed, 50 insertions, 44 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index ebee599..e6117f9 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -567,11 +567,12 @@ static ExprResult calculateConstraintSatisfaction( } static bool CheckConstraintSatisfaction( - Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, + Sema &S, const NamedDecl *Template, + ArrayRef<AssociatedConstraint> AssociatedConstraints, llvm::SmallVectorImpl<Expr *> &Converted, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { - if (ConstraintExprs.empty()) { + if (AssociatedConstraints.empty()) { Satisfaction.IsSatisfied = true; return false; } @@ -592,10 +593,12 @@ static bool CheckConstraintSatisfaction( if (Inst.isInvalid()) return true; - for (const Expr *ConstraintExpr : ConstraintExprs) { + for (const AssociatedConstraint &AC : AssociatedConstraints) { + Sema::ArgumentPackSubstitutionIndexRAII _(S, + AC.ArgumentPackSubstitutionIndex); ExprResult Res = calculateConstraintSatisfaction( S, Template, TemplateIDRange.getBegin(), TemplateArgsLists, - ConstraintExpr, Satisfaction); + AC.ConstraintExpr, Satisfaction); if (Res.isInvalid()) return true; @@ -603,7 +606,8 @@ static bool CheckConstraintSatisfaction( if (!Satisfaction.IsSatisfied) { // Backfill the 'converted' list with nulls so we can keep the Converted // and unconverted lists in sync. - Converted.append(ConstraintExprs.size() - Converted.size(), nullptr); + Converted.append(AssociatedConstraints.size() - Converted.size(), + nullptr); // [temp.constr.op] p2 // [...] To determine if a conjunction is satisfied, the satisfaction // of the first operand is checked. If that is not satisfied, the @@ -615,17 +619,18 @@ static bool CheckConstraintSatisfaction( } bool Sema::CheckConstraintSatisfaction( - const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, + const NamedDecl *Template, + ArrayRef<AssociatedConstraint> AssociatedConstraints, llvm::SmallVectorImpl<Expr *> &ConvertedConstraints, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) { - if (ConstraintExprs.empty()) { + if (AssociatedConstraints.empty()) { OutSatisfaction.IsSatisfied = true; return false; } if (!Template) { return ::CheckConstraintSatisfaction( - *this, nullptr, ConstraintExprs, ConvertedConstraints, + *this, nullptr, AssociatedConstraints, ConvertedConstraints, TemplateArgsLists, TemplateIDRange, OutSatisfaction); } // Invalid templates could make their way here. Substituting them could result @@ -654,7 +659,7 @@ bool Sema::CheckConstraintSatisfaction( auto Satisfaction = std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs); - if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, + if (::CheckConstraintSatisfaction(*this, Template, AssociatedConstraints, ConvertedConstraints, TemplateArgsLists, TemplateIDRange, *Satisfaction)) { OutSatisfaction = *Satisfaction; @@ -923,8 +928,10 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, ForOverloadResolution); return CheckConstraintSatisfaction( - FD, {FD->getTrailingRequiresClause()}, *MLTAL, - SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), + FD, + AssociatedConstraint(FD->getTrailingRequiresClause(), + ArgumentPackSubstitutionIndex), + *MLTAL, SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), Satisfaction); } @@ -1099,13 +1106,13 @@ bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { assert(FD->getDescribedFunctionTemplate() && "Non-function templates don't need to be checked"); - SmallVector<const Expr *, 3> ACs; + SmallVector<AssociatedConstraint, 3> ACs; FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); - for (const Expr *Constraint : ACs) + for (const AssociatedConstraint &AC : ACs) if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, - Constraint)) + AC.ConstraintExpr)) return true; return false; @@ -1115,7 +1122,7 @@ bool Sema::EnsureTemplateArgumentListConstraints( TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange) { ConstraintSatisfaction Satisfaction; - llvm::SmallVector<const Expr *, 3> AssociatedConstraints; + llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints; TD->getAssociatedConstraints(AssociatedConstraints); if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists, TemplateIDRange, Satisfaction)) @@ -1146,7 +1153,7 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); // Note - code synthesis context for the constraints check is created // inside CheckConstraintsSatisfaction. - SmallVector<const Expr *, 3> TemplateAC; + SmallVector<AssociatedConstraint, 3> TemplateAC; Template->getAssociatedConstraints(TemplateAC); if (TemplateAC.empty()) { Satisfaction.IsSatisfied = true; @@ -1438,7 +1445,7 @@ void Sema::DiagnoseUnsatisfiedConstraint( const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints( const NamedDecl *ConstrainedDecl, - ArrayRef<const Expr *> AssociatedConstraints) { + ArrayRef<AssociatedConstraint> AssociatedConstraints) { // In case the ConstrainedDecl comes from modules, it is necessary to use // the canonical decl to avoid different atomic constraints with the 'same' // declarations. @@ -1446,9 +1453,8 @@ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints( auto CacheEntry = NormalizationCache.find(ConstrainedDecl); if (CacheEntry == NormalizationCache.end()) { - auto Normalized = - NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl, - AssociatedConstraints); + auto Normalized = NormalizedConstraint::fromAssociatedConstraints( + *this, ConstrainedDecl, AssociatedConstraints); CacheEntry = NormalizationCache .try_emplace(ConstrainedDecl, @@ -1463,7 +1469,7 @@ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints( const NormalizedConstraint *clang::getNormalizedAssociatedConstraints( Sema &S, const NamedDecl *ConstrainedDecl, - ArrayRef<const Expr *> AssociatedConstraints) { + ArrayRef<AssociatedConstraint> AssociatedConstraints) { return S.getNormalizedAssociatedConstraints(ConstrainedDecl, AssociatedConstraints); } @@ -1593,14 +1599,14 @@ NormalizedConstraint &NormalizedConstraint::getRHS() const { } std::optional<NormalizedConstraint> -NormalizedConstraint::fromConstraintExprs(Sema &S, const NamedDecl *D, - ArrayRef<const Expr *> E) { - assert(E.size() != 0); - auto Conjunction = fromConstraintExpr(S, D, E[0]); +NormalizedConstraint::fromAssociatedConstraints( + Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) { + assert(ACs.size() != 0); + auto Conjunction = fromConstraintExpr(S, D, ACs[0].ConstraintExpr); if (!Conjunction) return std::nullopt; - for (unsigned I = 1; I < E.size(); ++I) { - auto Next = fromConstraintExpr(S, D, E[I]); + for (unsigned I = 1; I < ACs.size(); ++I) { + auto Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr); if (!Next) return std::nullopt; *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), @@ -1655,8 +1661,8 @@ NormalizedConstraint::fromConstraintExpr(Sema &S, const NamedDecl *D, // expression, the program is ill-formed; no diagnostic is required. // [...] ConceptDecl *CD = CSE->getNamedConcept(); - SubNF = S.getNormalizedAssociatedConstraints(CD, - {CD->getConstraintExpr()}); + SubNF = S.getNormalizedAssociatedConstraints( + CD, AssociatedConstraint(CD->getConstraintExpr())); if (!SubNF) return std::nullopt; } @@ -1731,9 +1737,9 @@ bool FoldExpandedConstraint::AreCompatibleForSubsumption( } bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1, - MutableArrayRef<const Expr *> AC1, + MutableArrayRef<AssociatedConstraint> AC1, const NamedDecl *D2, - MutableArrayRef<const Expr *> AC2, + MutableArrayRef<AssociatedConstraint> AC2, bool &Result) { #ifndef NDEBUG if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) { @@ -1771,13 +1777,15 @@ bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1, for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { if (Depth2 > Depth1) { - AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1) - .TransformExpr(const_cast<Expr *>(AC1[I])) - .get(); + AC1[I].ConstraintExpr = + AdjustConstraintDepth(*this, Depth2 - Depth1) + .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr)) + .get(); } else if (Depth1 > Depth2) { - AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2) - .TransformExpr(const_cast<Expr *>(AC2[I])) - .get(); + AC2[I].ConstraintExpr = + AdjustConstraintDepth(*this, Depth1 - Depth2) + .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr)) + .get(); } } @@ -1793,9 +1801,8 @@ bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1, } bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic( - const NamedDecl *D1, ArrayRef<const Expr *> AC1, const NamedDecl *D2, - ArrayRef<const Expr *> AC2) { - + const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1, + const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2) { if (isSFINAEContext()) // No need to work here because our notes would be discarded. return false; @@ -2106,10 +2113,9 @@ void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) { F.push_back(C); } -std::optional<bool> SubsumptionChecker::Subsumes(const NamedDecl *DP, - ArrayRef<const Expr *> P, - const NamedDecl *DQ, - ArrayRef<const Expr *> Q) { +std::optional<bool> SubsumptionChecker::Subsumes( + const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ, + ArrayRef<AssociatedConstraint> Q) { const NormalizedConstraint *PNormalized = getNormalizedAssociatedConstraints(SemaRef, DP, P); if (!PNormalized) |