diff options
Diffstat (limited to 'clang/lib/Sema/SemaConcept.cpp')
-rw-r--r-- | clang/lib/Sema/SemaConcept.cpp | 70 |
1 files changed, 43 insertions, 27 deletions
diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 81601b09ce0d..290e4cbff4fd 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -167,9 +167,8 @@ calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, return false; } -template <typename TemplateDeclT> static bool calculateConstraintSatisfaction( - Sema &S, TemplateDeclT *Template, ArrayRef<TemplateArgument> TemplateArgs, + Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) { return calculateConstraintSatisfaction( @@ -182,8 +181,9 @@ static bool calculateConstraintSatisfaction( { TemplateDeductionInfo Info(TemplateNameLoc); Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(), - Sema::InstantiatingTemplate::ConstraintSubstitution{}, Template, - Info, AtomicExpr->getSourceRange()); + Sema::InstantiatingTemplate::ConstraintSubstitution{}, + const_cast<NamedDecl *>(Template), Info, + AtomicExpr->getSourceRange()); if (Inst.isInvalid()) return ExprError(); // We do not want error diagnostics escaping here. @@ -230,8 +230,7 @@ static bool calculateConstraintSatisfaction( }); } -template<typename TemplateDeclT> -static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template, +static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange, @@ -249,8 +248,8 @@ static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template, } Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), - Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs, - TemplateIDRange); + Sema::InstantiatingTemplate::ConstraintsCheck{}, + const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); if (Inst.isInvalid()) return true; @@ -273,7 +272,7 @@ static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template, } bool Sema::CheckConstraintSatisfaction( - NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, + const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs, ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) { if (ConstraintExprs.empty()) { @@ -284,7 +283,8 @@ bool Sema::CheckConstraintSatisfaction( llvm::FoldingSetNodeID ID; void *InsertPos; ConstraintSatisfaction *Satisfaction = nullptr; - if (LangOpts.ConceptSatisfactionCaching) { + bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template; + if (ShouldCache) { ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs); Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos); if (Satisfaction) { @@ -295,27 +295,15 @@ bool Sema::CheckConstraintSatisfaction( } else { Satisfaction = &OutSatisfaction; } - bool Failed; - if (auto *T = dyn_cast<TemplateDecl>(Template)) - Failed = ::CheckConstraintSatisfaction(*this, T, ConstraintExprs, - TemplateArgs, TemplateIDRange, - *Satisfaction); - else if (auto *P = - dyn_cast<ClassTemplatePartialSpecializationDecl>(Template)) - Failed = ::CheckConstraintSatisfaction(*this, P, ConstraintExprs, - TemplateArgs, TemplateIDRange, - *Satisfaction); - else - Failed = ::CheckConstraintSatisfaction( - *this, cast<VarTemplatePartialSpecializationDecl>(Template), - ConstraintExprs, TemplateArgs, TemplateIDRange, *Satisfaction); - if (Failed) { - if (LangOpts.ConceptSatisfactionCaching) + if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs, + TemplateArgs, TemplateIDRange, + *Satisfaction)) { + if (ShouldCache) delete Satisfaction; return true; } - if (LangOpts.ConceptSatisfactionCaching) { + if (ShouldCache) { // We cannot use InsertNode here because CheckConstraintSatisfaction might // have invalidated it. SatisfactionCache.InsertNode(Satisfaction); @@ -333,6 +321,30 @@ bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr, }); } +bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, + ConstraintSatisfaction &Satisfaction, + SourceLocation UsageLoc) { + const Expr *RC = FD->getTrailingRequiresClause(); + if (RC->isInstantiationDependent()) { + Satisfaction.IsSatisfied = true; + return false; + } + Qualifiers ThisQuals; + CXXRecordDecl *Record = nullptr; + if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { + ThisQuals = Method->getMethodQualifiers(); + Record = const_cast<CXXRecordDecl *>(Method->getParent()); + } + CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); + // We substitute with empty arguments in order to rebuild the atomic + // constraint in a constant-evaluated context. + // FIXME: Should this be a dedicated TreeTransform? + return CheckConstraintSatisfaction( + FD, {RC}, /*TemplateArgs=*/{}, + SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), + Satisfaction); +} + bool Sema::EnsureTemplateArgumentListConstraints( TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange) { @@ -671,6 +683,10 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ArgsAsWritten->arguments().back().getSourceRange().getEnd())); if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) return true; + Atomic.ParameterMapping.emplace( + MutableArrayRef<TemplateArgumentLoc>( + new (S.Context) TemplateArgumentLoc[SubstArgs.size()], + SubstArgs.size())); std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), N.getAtomicConstraint()->ParameterMapping->begin()); return false; |