brintos

brintos / llvm-project-archived public Read only

0
0
Text · 107.3 KiB · 883e341 Raw
2822 lines · cpp
1//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file implements semantic analysis for C++ constraints and concepts.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Sema/SemaConcept.h"14#include "TreeTransform.h"15#include "clang/AST/ASTConcept.h"16#include "clang/AST/ASTLambda.h"17#include "clang/AST/DeclCXX.h"18#include "clang/AST/ExprConcepts.h"19#include "clang/AST/RecursiveASTVisitor.h"20#include "clang/Basic/OperatorPrecedence.h"21#include "clang/Sema/EnterExpressionEvaluationContext.h"22#include "clang/Sema/Initialization.h"23#include "clang/Sema/Overload.h"24#include "clang/Sema/ScopeInfo.h"25#include "clang/Sema/Sema.h"26#include "clang/Sema/SemaInternal.h"27#include "clang/Sema/Template.h"28#include "clang/Sema/TemplateDeduction.h"29#include "llvm/ADT/DenseMap.h"30#include "llvm/ADT/PointerUnion.h"31#include "llvm/ADT/StringExtras.h"32#include "llvm/Support/SaveAndRestore.h"33 34using namespace clang;35using namespace sema;36 37namespace {38class LogicalBinOp {39  SourceLocation Loc;40  OverloadedOperatorKind Op = OO_None;41  const Expr *LHS = nullptr;42  const Expr *RHS = nullptr;43 44public:45  LogicalBinOp(const Expr *E) {46    if (auto *BO = dyn_cast<BinaryOperator>(E)) {47      Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());48      LHS = BO->getLHS();49      RHS = BO->getRHS();50      Loc = BO->getExprLoc();51    } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {52      // If OO is not || or && it might not have exactly 2 arguments.53      if (OO->getNumArgs() == 2) {54        Op = OO->getOperator();55        LHS = OO->getArg(0);56        RHS = OO->getArg(1);57        Loc = OO->getOperatorLoc();58      }59    }60  }61 62  bool isAnd() const { return Op == OO_AmpAmp; }63  bool isOr() const { return Op == OO_PipePipe; }64  explicit operator bool() const { return isAnd() || isOr(); }65 66  const Expr *getLHS() const { return LHS; }67  const Expr *getRHS() const { return RHS; }68  OverloadedOperatorKind getOp() const { return Op; }69 70  ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {71    return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));72  }73 74  ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,75                           ExprResult RHS) const {76    assert((isAnd() || isOr()) && "Not the right kind of op?");77    assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");78 79    if (!LHS.isUsable() || !RHS.isUsable())80      return ExprEmpty();81 82    // We should just be able to 'normalize' these to the builtin Binary83    // Operator, since that is how they are evaluated in constriant checks.84    return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),85                                  BinaryOperator::getOverloadedOpcode(Op),86                                  SemaRef.Context.BoolTy, VK_PRValue,87                                  OK_Ordinary, Loc, FPOptionsOverride{});88  }89};90} // namespace91 92bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,93                                     Token NextToken, bool *PossibleNonPrimary,94                                     bool IsTrailingRequiresClause) {95  // C++2a [temp.constr.atomic]p196  // ..E shall be a constant expression of type bool.97 98  ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();99 100  if (LogicalBinOp BO = ConstraintExpression) {101    return CheckConstraintExpression(BO.getLHS(), NextToken,102                                     PossibleNonPrimary) &&103           CheckConstraintExpression(BO.getRHS(), NextToken,104                                     PossibleNonPrimary);105  } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))106    return CheckConstraintExpression(C->getSubExpr(), NextToken,107                                     PossibleNonPrimary);108 109  QualType Type = ConstraintExpression->getType();110 111  auto CheckForNonPrimary = [&] {112    if (!PossibleNonPrimary)113      return;114 115    *PossibleNonPrimary =116        // We have the following case:117        // template<typename> requires func(0) struct S { };118        // The user probably isn't aware of the parentheses required around119        // the function call, and we're only going to parse 'func' as the120        // primary-expression, and complain that it is of non-bool type.121        //122        // However, if we're in a lambda, this might also be:123        // []<typename> requires var () {};124        // Which also looks like a function call due to the lambda parentheses,125        // but unlike the first case, isn't an error, so this check is skipped.126        (NextToken.is(tok::l_paren) &&127         (IsTrailingRequiresClause ||128          (Type->isDependentType() &&129           isa<UnresolvedLookupExpr>(ConstraintExpression) &&130           !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||131          Type->isFunctionType() ||132          Type->isSpecificBuiltinType(BuiltinType::Overload))) ||133        // We have the following case:134        // template<typename T> requires size_<T> == 0 struct S { };135        // The user probably isn't aware of the parentheses required around136        // the binary operator, and we're only going to parse 'func' as the137        // first operand, and complain that it is of non-bool type.138        getBinOpPrecedence(NextToken.getKind(),139                           /*GreaterThanIsOperator=*/true,140                           getLangOpts().CPlusPlus11) > prec::LogicalAnd;141  };142 143  // An atomic constraint!144  if (ConstraintExpression->isTypeDependent()) {145    CheckForNonPrimary();146    return true;147  }148 149  if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {150    Diag(ConstraintExpression->getExprLoc(),151         diag::err_non_bool_atomic_constraint)152        << Type << ConstraintExpression->getSourceRange();153    CheckForNonPrimary();154    return false;155  }156 157  if (PossibleNonPrimary)158    *PossibleNonPrimary = false;159  return true;160}161 162namespace {163struct SatisfactionStackRAII {164  Sema &SemaRef;165  bool Inserted = false;166  SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,167                        const llvm::FoldingSetNodeID &FSNID)168      : SemaRef(SemaRef) {169    if (ND) {170      SemaRef.PushSatisfactionStackEntry(ND, FSNID);171      Inserted = true;172    }173  }174  ~SatisfactionStackRAII() {175    if (Inserted)176      SemaRef.PopSatisfactionStackEntry();177  }178};179} // namespace180 181static bool DiagRecursiveConstraintEval(182    Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E,183    const MultiLevelTemplateArgumentList *MLTAL = nullptr) {184  E->Profile(ID, S.Context, /*Canonical=*/true);185  if (MLTAL) {186    for (const auto &List : *MLTAL)187      for (const auto &TemplateArg : List.Args)188        S.Context.getCanonicalTemplateArgument(TemplateArg)189            .Profile(ID, S.Context);190  }191  if (S.SatisfactionStackContains(Templ, ID)) {192    S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)193        << E << E->getSourceRange();194    return true;195  }196  return false;197}198 199// Figure out the to-translation-unit depth for this function declaration for200// the purpose of seeing if they differ by constraints. This isn't the same as201// getTemplateDepth, because it includes already instantiated parents.202static unsigned203CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,204                                     bool SkipForSpecialization = false) {205  MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(206      ND, ND->getLexicalDeclContext(), /*Final=*/false,207      /*Innermost=*/std::nullopt,208      /*RelativeToPrimary=*/true,209      /*Pattern=*/nullptr,210      /*ForConstraintInstantiation=*/true, SkipForSpecialization);211  return MLTAL.getNumLevels();212}213 214namespace {215class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {216  unsigned TemplateDepth = 0;217 218public:219  using inherited = TreeTransform<AdjustConstraintDepth>;220  AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)221      : inherited(SemaRef), TemplateDepth(TemplateDepth) {}222 223  using inherited::TransformTemplateTypeParmType;224  QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,225                                         TemplateTypeParmTypeLoc TL, bool) {226    const TemplateTypeParmType *T = TL.getTypePtr();227 228    TemplateTypeParmDecl *NewTTPDecl = nullptr;229    if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())230      NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(231          TransformDecl(TL.getNameLoc(), OldTTPDecl));232 233    QualType Result = getSema().Context.getTemplateTypeParmType(234        T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),235        NewTTPDecl);236    TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);237    NewTL.setNameLoc(TL.getNameLoc());238    return Result;239  }240 241  bool AlreadyTransformed(QualType T) {242    if (T.isNull())243      return true;244 245    if (T->isInstantiationDependentType() || T->isVariablyModifiedType() ||246        T->containsUnexpandedParameterPack())247      return false;248    return true;249  }250};251} // namespace252 253namespace {254 255// FIXME: Convert it to DynamicRecursiveASTVisitor256class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {257  using inherited = RecursiveASTVisitor<HashParameterMapping>;258  friend inherited;259 260  Sema &SemaRef;261  const MultiLevelTemplateArgumentList &TemplateArgs;262  llvm::FoldingSetNodeID &ID;263  llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;264 265  UnsignedOrNone OuterPackSubstIndex;266 267  bool shouldVisitTemplateInstantiations() const { return true; }268 269public:270  HashParameterMapping(Sema &SemaRef,271                       const MultiLevelTemplateArgumentList &TemplateArgs,272                       llvm::FoldingSetNodeID &ID,273                       UnsignedOrNone OuterPackSubstIndex)274      : SemaRef(SemaRef), TemplateArgs(TemplateArgs), ID(ID),275        OuterPackSubstIndex(OuterPackSubstIndex) {}276 277  bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {278    // A lambda expression can introduce template parameters that don't have279    // corresponding template arguments yet.280    if (T->getDepth() >= TemplateArgs.getNumLevels())281      return true;282 283    // There might not be a corresponding template argument before substituting284    // into the parameter mapping, e.g. a sizeof... expression.285    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))286      return true;287 288    TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());289 290    if (T->isParameterPack() && SemaRef.ArgPackSubstIndex) {291      assert(Arg.getKind() == TemplateArgument::Pack &&292             "Missing argument pack");293 294      Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);295    }296 297    UsedTemplateArgs.push_back(298        SemaRef.Context.getCanonicalTemplateArgument(Arg));299    return true;300  }301 302  bool VisitDeclRefExpr(DeclRefExpr *E) {303    NamedDecl *D = E->getDecl();304    NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);305    if (!NTTP)306      return TraverseDecl(D);307 308    if (NTTP->getDepth() >= TemplateArgs.getNumLevels())309      return true;310 311    if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), NTTP->getIndex()))312      return true;313 314    TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());315    if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {316      assert(Arg.getKind() == TemplateArgument::Pack &&317             "Missing argument pack");318      Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);319    }320 321    UsedTemplateArgs.push_back(322        SemaRef.Context.getCanonicalTemplateArgument(Arg));323    return true;324  }325 326  bool VisitTypedefType(TypedefType *TT) {327    return inherited::TraverseType(TT->desugar());328  }329 330  bool TraverseDecl(Decl *D) {331    if (auto *VD = dyn_cast<ValueDecl>(D)) {332      if (auto *Var = dyn_cast<VarDecl>(VD))333        TraverseStmt(Var->getInit());334      return TraverseType(VD->getType());335    }336 337    return inherited::TraverseDecl(D);338  }339 340  bool TraverseCallExpr(CallExpr *CE) {341    inherited::TraverseStmt(CE->getCallee());342 343    for (Expr *Arg : CE->arguments())344      inherited::TraverseStmt(Arg);345 346    return true;347  }348 349  bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {350    // We don't care about TypeLocs. So traverse Types instead.351    return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);352  }353 354  bool TraverseTagType(const TagType *T, bool TraverseQualifier) {355    // T's parent can be dependent while T doesn't have any template arguments.356    // We should have already traversed its qualifier.357    // FIXME: Add an assert to catch cases where we failed to profile the358    // concept.359    return true;360  }361 362  bool TraverseInjectedClassNameType(InjectedClassNameType *T,363                                     bool TraverseQualifier) {364    return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.Context));365  }366 367  bool TraverseTemplateArgument(const TemplateArgument &Arg) {368    if (!Arg.containsUnexpandedParameterPack() || Arg.isPackExpansion()) {369      // Act as if we are fully expanding this pack, if it is a PackExpansion.370      Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);371      llvm::SaveAndRestore<UnsignedOrNone> _2(OuterPackSubstIndex,372                                              std::nullopt);373      return inherited::TraverseTemplateArgument(Arg);374    }375 376    Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);377    return inherited::TraverseTemplateArgument(Arg);378  }379 380  bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {381    return TraverseDecl(SOPE->getPack());382  }383 384  bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {385    return inherited::TraverseStmt(E->getReplacement());386  }387 388  bool TraverseTemplateName(TemplateName Template) {389    if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(390            Template.getAsTemplateDecl());391        TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {392      if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),393                                            TTP->getPosition()))394        return true;395 396      TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());397      if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {398        assert(Arg.getKind() == TemplateArgument::Pack &&399               "Missing argument pack");400        Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);401      }402      assert(!Arg.getAsTemplate().isNull() &&403             "Null template template argument");404      UsedTemplateArgs.push_back(405          SemaRef.Context.getCanonicalTemplateArgument(Arg));406    }407    return inherited::TraverseTemplateName(Template);408  }409 410  void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {411    if (!Constraint.hasParameterMapping()) {412      for (const auto &List : TemplateArgs)413        for (const TemplateArgument &Arg : List.Args)414          SemaRef.Context.getCanonicalTemplateArgument(Arg).Profile(415              ID, SemaRef.Context);416      return;417    }418 419    llvm::ArrayRef<TemplateArgumentLoc> Mapping =420        Constraint.getParameterMapping();421    for (auto &ArgLoc : Mapping) {422      TemplateArgument Canonical =423          SemaRef.Context.getCanonicalTemplateArgument(ArgLoc.getArgument());424      // We don't want sugars to impede the profile of cache.425      UsedTemplateArgs.push_back(Canonical);426      TraverseTemplateArgument(Canonical);427    }428 429    for (auto &Used : UsedTemplateArgs) {430      llvm::FoldingSetNodeID R;431      Used.Profile(R, SemaRef.Context);432      ID.AddNodeID(R);433    }434  }435};436 437class ConstraintSatisfactionChecker {438  Sema &S;439  const NamedDecl *Template;440  SourceLocation TemplateNameLoc;441  UnsignedOrNone PackSubstitutionIndex;442  ConstraintSatisfaction &Satisfaction;443  bool BuildExpression;444 445private:446  ExprResult447  EvaluateAtomicConstraint(const Expr *AtomicExpr,448                           const MultiLevelTemplateArgumentList &MLTAL);449 450  UnsignedOrNone EvaluateFoldExpandedConstraintSize(451      const FoldExpandedConstraint &FE,452      const MultiLevelTemplateArgumentList &MLTAL);453 454  // XXX: It is SLOW! Use it very carefully.455  std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(456      const NormalizedConstraintWithParamMapping &Constraint,457      const MultiLevelTemplateArgumentList &MLTAL,458      llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);459 460  ExprResult EvaluateSlow(const AtomicConstraint &Constraint,461                          const MultiLevelTemplateArgumentList &MLTAL);462 463  ExprResult Evaluate(const AtomicConstraint &Constraint,464                      const MultiLevelTemplateArgumentList &MLTAL);465 466  ExprResult EvaluateSlow(const FoldExpandedConstraint &Constraint,467                          const MultiLevelTemplateArgumentList &MLTAL);468 469  ExprResult Evaluate(const FoldExpandedConstraint &Constraint,470                      const MultiLevelTemplateArgumentList &MLTAL);471 472  ExprResult EvaluateSlow(const ConceptIdConstraint &Constraint,473                          const MultiLevelTemplateArgumentList &MLTAL,474                          unsigned int Size);475 476  ExprResult Evaluate(const ConceptIdConstraint &Constraint,477                      const MultiLevelTemplateArgumentList &MLTAL);478 479  ExprResult Evaluate(const CompoundConstraint &Constraint,480                      const MultiLevelTemplateArgumentList &MLTAL);481 482public:483  ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template,484                                SourceLocation TemplateNameLoc,485                                UnsignedOrNone PackSubstitutionIndex,486                                ConstraintSatisfaction &Satisfaction,487                                bool BuildExpression)488      : S(SemaRef), Template(Template), TemplateNameLoc(TemplateNameLoc),489        PackSubstitutionIndex(PackSubstitutionIndex),490        Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}491 492  ExprResult Evaluate(const NormalizedConstraint &Constraint,493                      const MultiLevelTemplateArgumentList &MLTAL);494};495 496StringRef allocateStringFromConceptDiagnostic(const Sema &S,497                                              const PartialDiagnostic Diag) {498  SmallString<128> DiagString;499  DiagString = ": ";500  Diag.EmitToString(S.getDiagnostics(), DiagString);501  return S.getASTContext().backupStr(DiagString);502}503 504} // namespace505 506ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(507    const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL) {508  EnterExpressionEvaluationContext ConstantEvaluated(509      S, Sema::ExpressionEvaluationContext::ConstantEvaluated,510      Sema::ReuseLambdaContextDecl);511 512  llvm::FoldingSetNodeID ID;513  if (Template &&514      DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, &MLTAL)) {515    Satisfaction.IsSatisfied = false;516    Satisfaction.ContainsErrors = true;517    return ExprEmpty();518  }519  SatisfactionStackRAII StackRAII(S, Template, ID);520 521  // Atomic constraint - substitute arguments and check satisfaction.522  ExprResult SubstitutedExpression = const_cast<Expr *>(AtomicExpr);523  {524    TemplateDeductionInfo Info(TemplateNameLoc);525    Sema::InstantiatingTemplate Inst(526        S, AtomicExpr->getBeginLoc(),527        Sema::InstantiatingTemplate::ConstraintSubstitution{},528        // FIXME: improve const-correctness of InstantiatingTemplate529        const_cast<NamedDecl *>(Template), AtomicExpr->getSourceRange());530    if (Inst.isInvalid())531      return ExprError();532 533    // We do not want error diagnostics escaping here.534    Sema::SFINAETrap Trap(S, Info);535    SubstitutedExpression =536        S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);537 538    if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {539      // C++2a [temp.constr.atomic]p1540      //   ...If substitution results in an invalid type or expression, the541      //   constraint is not satisfied.542      if (!Trap.hasErrorOccurred())543        // A non-SFINAE error has occurred as a result of this544        // substitution.545        return ExprError();546 547      PartialDiagnosticAt SubstDiag{SourceLocation(),548                                    PartialDiagnostic::NullDiagnostic()};549      Info.takeSFINAEDiagnostic(SubstDiag);550      // FIXME: This is an unfortunate consequence of there551      //  being no serialization code for PartialDiagnostics and the fact552      //  that serializing them would likely take a lot more storage than553      //  just storing them as strings. We would still like, in the554      //  future, to serialize the proper PartialDiagnostic as serializing555      //  it as a string defeats the purpose of the diagnostic mechanism.556      Satisfaction.Details.emplace_back(557          new (S.Context) ConstraintSubstitutionDiagnostic{558              SubstDiag.first,559              allocateStringFromConceptDiagnostic(S, SubstDiag.second)});560      Satisfaction.IsSatisfied = false;561      return ExprEmpty();562    }563  }564 565  if (!S.CheckConstraintExpression(SubstitutedExpression.get()))566    return ExprError();567 568  // [temp.constr.atomic]p3: To determine if an atomic constraint is569  // satisfied, the parameter mapping and template arguments are first570  // substituted into its expression.  If substitution results in an571  // invalid type or expression, the constraint is not satisfied.572  // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,573  // and E shall be a constant expression of type bool.574  //575  // Perform the L to R Value conversion if necessary. We do so for all576  // non-PRValue categories, else we fail to extend the lifetime of577  // temporaries, and that fails the constant expression check.578  if (!SubstitutedExpression.get()->isPRValue())579    SubstitutedExpression = ImplicitCastExpr::Create(580        S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,581        SubstitutedExpression.get(),582        /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());583 584  return SubstitutedExpression;585}586 587std::optional<MultiLevelTemplateArgumentList>588ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(589    const NormalizedConstraintWithParamMapping &Constraint,590    const MultiLevelTemplateArgumentList &MLTAL,591    llvm::SmallVector<TemplateArgument> &SubstitutedOutermost) {592 593  if (!Constraint.hasParameterMapping())594    return std::move(MLTAL);595 596  // The mapping is empty, meaning no template arguments are needed for597  // evaluation.598  if (Constraint.getParameterMapping().empty())599    return MultiLevelTemplateArgumentList();600 601  TemplateDeductionInfo Info(Constraint.getBeginLoc());602  Sema::SFINAETrap Trap(S, Info);603  Sema::InstantiatingTemplate Inst(604      S, Constraint.getBeginLoc(),605      Sema::InstantiatingTemplate::ConstraintSubstitution{},606      // FIXME: improve const-correctness of InstantiatingTemplate607      const_cast<NamedDecl *>(Template), Constraint.getSourceRange());608  if (Inst.isInvalid())609    return std::nullopt;610 611  TemplateArgumentListInfo SubstArgs;612  Sema::ArgPackSubstIndexRAII SubstIndex(613      S, Constraint.getPackSubstitutionIndex()614             ? Constraint.getPackSubstitutionIndex()615             : PackSubstitutionIndex);616 617  if (S.SubstTemplateArgumentsInParameterMapping(618          Constraint.getParameterMapping(), Constraint.getBeginLoc(), MLTAL,619          SubstArgs, /*BuildPackExpansionTypes=*/true)) {620    Satisfaction.IsSatisfied = false;621    return std::nullopt;622  }623 624  Sema::CheckTemplateArgumentInfo CTAI;625  auto *TD = const_cast<TemplateDecl *>(626      cast<TemplateDecl>(Constraint.getConstraintDecl()));627  if (S.CheckTemplateArgumentList(TD, Constraint.getUsedTemplateParamList(),628                                  TD->getLocation(), SubstArgs,629                                  /*DefaultArguments=*/{},630                                  /*PartialTemplateArgs=*/false, CTAI))631    return std::nullopt;632  const NormalizedConstraint::OccurenceList &Used =633      Constraint.mappingOccurenceList();634  // The empty MLTAL situation should only occur when evaluating non-dependent635  // constraints.636  if (MLTAL.getNumSubstitutedLevels())637    SubstitutedOutermost =638        llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());639  unsigned Offset = 0;640  for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {641    TemplateArgument Arg;642    if (Used[I])643      Arg = S.Context.getCanonicalTemplateArgument(644          CTAI.SugaredConverted[MappedIndex++]);645    if (I < SubstitutedOutermost.size()) {646      SubstitutedOutermost[I] = Arg;647      Offset = I + 1;648    } else {649      SubstitutedOutermost.push_back(Arg);650      Offset = SubstitutedOutermost.size();651    }652  }653  if (Offset < SubstitutedOutermost.size())654    SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);655 656  MultiLevelTemplateArgumentList SubstitutedTemplateArgs;657  SubstitutedTemplateArgs.addOuterTemplateArguments(TD, SubstitutedOutermost,658                                                    /*Final=*/false);659  return std::move(SubstitutedTemplateArgs);660}661 662ExprResult ConstraintSatisfactionChecker::EvaluateSlow(663    const AtomicConstraint &Constraint,664    const MultiLevelTemplateArgumentList &MLTAL) {665 666  llvm::SmallVector<TemplateArgument> SubstitutedOutermost;667  std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =668      SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);669  if (!SubstitutedArgs) {670    Satisfaction.IsSatisfied = false;671    return ExprEmpty();672  }673 674  Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);675  ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(676      Constraint.getConstraintExpr(), *SubstitutedArgs);677 678  if (SubstitutedAtomicExpr.isInvalid())679    return ExprError();680 681  if (SubstitutedAtomicExpr.isUnset())682    // Evaluator has decided satisfaction without yielding an expression.683    return ExprEmpty();684 685  // We don't have the ability to evaluate this, since it contains a686  // RecoveryExpr, so we want to fail overload resolution.  Otherwise,687  // we'd potentially pick up a different overload, and cause confusing688  // diagnostics. SO, add a failure detail that will cause us to make this689  // overload set not viable.690  if (SubstitutedAtomicExpr.get()->containsErrors()) {691    Satisfaction.IsSatisfied = false;692    Satisfaction.ContainsErrors = true;693 694    PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);695    Satisfaction.Details.emplace_back(696        new (S.Context) ConstraintSubstitutionDiagnostic{697            SubstitutedAtomicExpr.get()->getBeginLoc(),698            allocateStringFromConceptDiagnostic(S, Msg)});699    return SubstitutedAtomicExpr;700  }701 702  if (SubstitutedAtomicExpr.get()->isValueDependent()) {703    Satisfaction.IsSatisfied = true;704    Satisfaction.ContainsErrors = false;705    return SubstitutedAtomicExpr;706  }707 708  EnterExpressionEvaluationContext ConstantEvaluated(709      S, Sema::ExpressionEvaluationContext::ConstantEvaluated);710  SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;711  Expr::EvalResult EvalResult;712  EvalResult.Diag = &EvaluationDiags;713  if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,714                                                           S.Context) ||715      !EvaluationDiags.empty()) {716    // C++2a [temp.constr.atomic]p1717    //   ...E shall be a constant expression of type bool.718    S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),719           diag::err_non_constant_constraint_expression)720        << SubstitutedAtomicExpr.get()->getSourceRange();721    for (const PartialDiagnosticAt &PDiag : EvaluationDiags)722      S.Diag(PDiag.first, PDiag.second);723    return ExprError();724  }725 726  assert(EvalResult.Val.isInt() &&727         "evaluating bool expression didn't produce int");728  Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();729  if (!Satisfaction.IsSatisfied)730    Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());731 732  return SubstitutedAtomicExpr;733}734 735ExprResult ConstraintSatisfactionChecker::Evaluate(736    const AtomicConstraint &Constraint,737    const MultiLevelTemplateArgumentList &MLTAL) {738 739  unsigned Size = Satisfaction.Details.size();740  llvm::FoldingSetNodeID ID;741  UnsignedOrNone OuterPackSubstIndex =742      Constraint.getPackSubstitutionIndex()743          ? Constraint.getPackSubstitutionIndex()744          : PackSubstitutionIndex;745 746  ID.AddPointer(Constraint.getConstraintExpr());747  ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());748  HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)749      .VisitConstraint(Constraint);750 751  if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);752      Iter != S.UnsubstitutedConstraintSatisfactionCache.end()) {753    auto &Cached = Iter->second.Satisfaction;754    Satisfaction.ContainsErrors = Cached.ContainsErrors;755    Satisfaction.IsSatisfied = Cached.IsSatisfied;756    Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,757                                Cached.Details.begin(), Cached.Details.end());758    return Iter->second.SubstExpr;759  }760 761  ExprResult E = EvaluateSlow(Constraint, MLTAL);762 763  UnsubstitutedConstraintSatisfactionCacheResult Cache;764  Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;765  Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;766  Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),767                                    Satisfaction.Details.begin() + Size,768                                    Satisfaction.Details.end());769  Cache.SubstExpr = E;770  S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});771 772  return E;773}774 775UnsignedOrNone776ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(777    const FoldExpandedConstraint &FE,778    const MultiLevelTemplateArgumentList &MLTAL) {779 780  Expr *Pattern = const_cast<Expr *>(FE.getPattern());781 782  SmallVector<UnexpandedParameterPack, 2> Unexpanded;783  S.collectUnexpandedParameterPacks(Pattern, Unexpanded);784  assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");785  bool Expand = true;786  bool RetainExpansion = false;787  UnsignedOrNone NumExpansions(std::nullopt);788  if (S.CheckParameterPacksForExpansion(789          Pattern->getExprLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,790          /*FailOnPackProducingTemplates=*/false, Expand, RetainExpansion,791          NumExpansions, /*Diagnose=*/false) ||792      !Expand || RetainExpansion)793    return std::nullopt;794 795  if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions)796    return std::nullopt;797  return NumExpansions;798}799 800ExprResult ConstraintSatisfactionChecker::EvaluateSlow(801    const FoldExpandedConstraint &Constraint,802    const MultiLevelTemplateArgumentList &MLTAL) {803 804  bool Conjunction = Constraint.getFoldOperator() ==805                     FoldExpandedConstraint::FoldOperatorKind::And;806  unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();807 808  llvm::SmallVector<TemplateArgument> SubstitutedOutermost;809  // FIXME: Is PackSubstitutionIndex correct?810  llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);811  std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =812      SubstitutionInTemplateArguments(813          static_cast<const NormalizedConstraintWithParamMapping &>(Constraint),814          MLTAL, SubstitutedOutermost);815  if (!SubstitutedArgs) {816    Satisfaction.IsSatisfied = false;817    return ExprError();818  }819 820  ExprResult Out;821  UnsignedOrNone NumExpansions =822      EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);823  if (!NumExpansions)824    return ExprEmpty();825 826  if (*NumExpansions == 0) {827    Satisfaction.IsSatisfied = Conjunction;828    return ExprEmpty();829  }830 831  for (unsigned I = 0; I < *NumExpansions; I++) {832    Sema::ArgPackSubstIndexRAII SubstIndex(S, I);833    Satisfaction.IsSatisfied = false;834    Satisfaction.ContainsErrors = false;835    ExprResult Expr =836        ConstraintSatisfactionChecker(S, Template, TemplateNameLoc,837                                      UnsignedOrNone(I), Satisfaction,838                                      /*BuildExpression=*/false)839            .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs);840    if (BuildExpression && Expr.isUsable()) {841      if (Out.isUnset())842        Out = Expr;843      else844        Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(),845                                     Conjunction ? BinaryOperatorKind::BO_LAnd846                                                 : BinaryOperatorKind::BO_LOr,847                                     S.Context.BoolTy, VK_PRValue, OK_Ordinary,848                                     Constraint.getBeginLoc(),849                                     FPOptionsOverride{});850    } else {851      assert(!BuildExpression || !Satisfaction.IsSatisfied);852    }853    if (!Conjunction && Satisfaction.IsSatisfied) {854      Satisfaction.Details.erase(Satisfaction.Details.begin() +855                                     EffectiveDetailEndIndex,856                                 Satisfaction.Details.end());857      break;858    }859    if (Satisfaction.IsSatisfied != Conjunction)860      return Out;861  }862 863  return Out;864}865 866ExprResult ConstraintSatisfactionChecker::Evaluate(867    const FoldExpandedConstraint &Constraint,868    const MultiLevelTemplateArgumentList &MLTAL) {869 870  llvm::FoldingSetNodeID ID;871  ID.AddPointer(Constraint.getPattern());872  HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);873 874  if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);875      Iter != S.UnsubstitutedConstraintSatisfactionCache.end()) {876 877    auto &Cached = Iter->second.Satisfaction;878    Satisfaction.ContainsErrors = Cached.ContainsErrors;879    Satisfaction.IsSatisfied = Cached.IsSatisfied;880    Satisfaction.Details.insert(Satisfaction.Details.end(),881                                Cached.Details.begin(), Cached.Details.end());882    return Iter->second.SubstExpr;883  }884 885  unsigned Size = Satisfaction.Details.size();886 887  ExprResult E = EvaluateSlow(Constraint, MLTAL);888  UnsubstitutedConstraintSatisfactionCacheResult Cache;889  Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;890  Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;891  Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),892                                    Satisfaction.Details.begin() + Size,893                                    Satisfaction.Details.end());894  Cache.SubstExpr = E;895  S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});896  return E;897}898 899ExprResult ConstraintSatisfactionChecker::EvaluateSlow(900    const ConceptIdConstraint &Constraint,901    const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {902  const ConceptReference *ConceptId = Constraint.getConceptId();903 904  llvm::SmallVector<TemplateArgument> SubstitutedOutermost;905  std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =906      SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);907 908  if (!SubstitutedArgs) {909    Satisfaction.IsSatisfied = false;910    // FIXME: diagnostics?911    return ExprError();912  }913 914  Sema::ArgPackSubstIndexRAII SubstIndex(915      S, Constraint.getPackSubstitutionIndex()916             ? Constraint.getPackSubstitutionIndex()917             : PackSubstitutionIndex);918 919  const ASTTemplateArgumentListInfo *Ori =920      ConceptId->getTemplateArgsAsWritten();921  TemplateDeductionInfo Info(TemplateNameLoc);922  Sema::SFINAETrap Trap(S, Info);923  Sema::InstantiatingTemplate _2(924      S, TemplateNameLoc, Sema::InstantiatingTemplate::ConstraintSubstitution{},925      const_cast<NamedDecl *>(Template), Constraint.getSourceRange());926 927  TemplateArgumentListInfo OutArgs(Ori->LAngleLoc, Ori->RAngleLoc);928  if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, OutArgs) ||929      Trap.hasErrorOccurred()) {930    Satisfaction.IsSatisfied = false;931    if (!Trap.hasErrorOccurred())932      return ExprError();933 934    PartialDiagnosticAt SubstDiag{SourceLocation(),935                                  PartialDiagnostic::NullDiagnostic()};936    Info.takeSFINAEDiagnostic(SubstDiag);937    // FIXME: This is an unfortunate consequence of there938    //  being no serialization code for PartialDiagnostics and the fact939    //  that serializing them would likely take a lot more storage than940    //  just storing them as strings. We would still like, in the941    //  future, to serialize the proper PartialDiagnostic as serializing942    //  it as a string defeats the purpose of the diagnostic mechanism.943    Satisfaction.Details.insert(944        Satisfaction.Details.begin() + Size,945        new (S.Context) ConstraintSubstitutionDiagnostic{946            SubstDiag.first,947            allocateStringFromConceptDiagnostic(S, SubstDiag.second)});948    return ExprError();949  }950 951  CXXScopeSpec SS;952  SS.Adopt(ConceptId->getNestedNameSpecifierLoc());953 954  ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(955      SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(),956      ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs,957      /*DoCheckConstraintSatisfaction=*/false);958 959  if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred())960    return ExprError();961 962  if (Size != Satisfaction.Details.size()) {963    Satisfaction.Details.insert(964        Satisfaction.Details.begin() + Size,965        UnsatisfiedConstraintRecord(966            SubstitutedConceptId.getAs<ConceptSpecializationExpr>()967                ->getConceptReference()));968  }969  return SubstitutedConceptId;970}971 972ExprResult ConstraintSatisfactionChecker::Evaluate(973    const ConceptIdConstraint &Constraint,974    const MultiLevelTemplateArgumentList &MLTAL) {975 976  const ConceptReference *ConceptId = Constraint.getConceptId();977 978  UnsignedOrNone OuterPackSubstIndex =979      Constraint.getPackSubstitutionIndex()980          ? Constraint.getPackSubstitutionIndex()981          : PackSubstitutionIndex;982 983  Sema::InstantiatingTemplate InstTemplate(984      S, ConceptId->getBeginLoc(),985      Sema::InstantiatingTemplate::ConstraintsCheck{},986      ConceptId->getNamedConcept(),987      // We may have empty template arguments when checking non-dependent988      // nested constraint expressions.989      // In such cases, non-SFINAE errors would have already been diagnosed990      // during parameter mapping substitution, so the instantiating template991      // arguments are less useful here.992      MLTAL.getNumSubstitutedLevels() ? MLTAL.getInnermost()993                                      : ArrayRef<TemplateArgument>{},994      Constraint.getSourceRange());995  if (InstTemplate.isInvalid())996    return ExprError();997 998  unsigned Size = Satisfaction.Details.size();999 1000  ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL);1001 1002  if (E.isInvalid()) {1003    Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);1004    return E;1005  }1006 1007  // ConceptIdConstraint is only relevant for diagnostics,1008  // so if the normalized constraint is satisfied, we should not1009  // substitute into the constraint.1010  if (Satisfaction.IsSatisfied)1011    return E;1012 1013  llvm::FoldingSetNodeID ID;1014  ID.AddPointer(Constraint.getConceptId());1015  ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());1016  HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)1017      .VisitConstraint(Constraint);1018 1019  if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);1020      Iter != S.UnsubstitutedConstraintSatisfactionCache.end()) {1021 1022    auto &Cached = Iter->second.Satisfaction;1023    Satisfaction.ContainsErrors = Cached.ContainsErrors;1024    Satisfaction.IsSatisfied = Cached.IsSatisfied;1025    Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,1026                                Cached.Details.begin(), Cached.Details.end());1027    return Iter->second.SubstExpr;1028  }1029 1030  ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);1031  if (CE.isInvalid())1032    return E;1033  UnsubstitutedConstraintSatisfactionCacheResult Cache;1034  Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;1035  Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;1036  Cache.Satisfaction.Details.insert(Cache.Satisfaction.Details.end(),1037                                    Satisfaction.Details.begin() + Size,1038                                    Satisfaction.Details.end());1039  Cache.SubstExpr = CE;1040  S.UnsubstitutedConstraintSatisfactionCache.insert({ID, std::move(Cache)});1041  return CE;1042}1043 1044ExprResult ConstraintSatisfactionChecker::Evaluate(1045    const CompoundConstraint &Constraint,1046    const MultiLevelTemplateArgumentList &MLTAL) {1047 1048  unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();1049 1050  bool Conjunction =1051      Constraint.getCompoundKind() == NormalizedConstraint::CCK_Conjunction;1052 1053  ExprResult LHS = Evaluate(Constraint.getLHS(), MLTAL);1054 1055  if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))1056    return LHS;1057 1058  if (!Conjunction && !LHS.isInvalid() && Satisfaction.IsSatisfied &&1059      !Satisfaction.ContainsErrors)1060    return LHS;1061 1062  Satisfaction.ContainsErrors = false;1063  Satisfaction.IsSatisfied = false;1064 1065  ExprResult RHS = Evaluate(Constraint.getRHS(), MLTAL);1066 1067  if (!Conjunction && !RHS.isInvalid() && Satisfaction.IsSatisfied &&1068      !Satisfaction.ContainsErrors)1069    Satisfaction.Details.erase(Satisfaction.Details.begin() +1070                                   EffectiveDetailEndIndex,1071                               Satisfaction.Details.end());1072 1073  if (!BuildExpression)1074    return Satisfaction.ContainsErrors ? ExprError() : ExprEmpty();1075 1076  if (!LHS.isUsable())1077    return RHS;1078 1079  if (!RHS.isUsable())1080    return LHS;1081 1082  return BinaryOperator::Create(S.Context, LHS.get(), RHS.get(),1083                                Conjunction ? BinaryOperatorKind::BO_LAnd1084                                            : BinaryOperatorKind::BO_LOr,1085                                S.Context.BoolTy, VK_PRValue, OK_Ordinary,1086                                Constraint.getBeginLoc(), FPOptionsOverride{});1087}1088 1089ExprResult ConstraintSatisfactionChecker::Evaluate(1090    const NormalizedConstraint &Constraint,1091    const MultiLevelTemplateArgumentList &MLTAL) {1092  switch (Constraint.getKind()) {1093  case NormalizedConstraint::ConstraintKind::Atomic:1094    return Evaluate(static_cast<const AtomicConstraint &>(Constraint), MLTAL);1095 1096  case NormalizedConstraint::ConstraintKind::FoldExpanded:1097    return Evaluate(static_cast<const FoldExpandedConstraint &>(Constraint),1098                    MLTAL);1099 1100  case NormalizedConstraint::ConstraintKind::ConceptId:1101    return Evaluate(static_cast<const ConceptIdConstraint &>(Constraint),1102                    MLTAL);1103 1104  case NormalizedConstraint::ConstraintKind::Compound:1105    return Evaluate(static_cast<const CompoundConstraint &>(Constraint), MLTAL);1106  }1107  llvm_unreachable("Unknown ConstraintKind enum");1108}1109 1110static bool CheckConstraintSatisfaction(1111    Sema &S, const NamedDecl *Template,1112    ArrayRef<AssociatedConstraint> AssociatedConstraints,1113    const MultiLevelTemplateArgumentList &TemplateArgsLists,1114    SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,1115    Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr) {1116 1117  if (ConvertedExpr)1118    *ConvertedExpr = nullptr;1119 1120  if (AssociatedConstraints.empty()) {1121    Satisfaction.IsSatisfied = true;1122    return false;1123  }1124 1125  if (TemplateArgsLists.isAnyArgInstantiationDependent()) {1126    // No need to check satisfaction for dependent constraint expressions.1127    Satisfaction.IsSatisfied = true;1128    return false;1129  }1130 1131  llvm::ArrayRef<TemplateArgument> Args;1132  if (TemplateArgsLists.getNumLevels() != 0)1133    Args = TemplateArgsLists.getInnermost();1134 1135  struct SynthesisContextPair {1136    Sema::InstantiatingTemplate Inst;1137    Sema::NonSFINAEContext NSC;1138    SynthesisContextPair(Sema &S, NamedDecl *Template,1139                         ArrayRef<TemplateArgument> TemplateArgs,1140                         SourceRange InstantiationRange)1141        : Inst(S, InstantiationRange.getBegin(),1142               Sema::InstantiatingTemplate::ConstraintsCheck{}, Template,1143               TemplateArgs, InstantiationRange),1144          NSC(S) {}1145  };1146  std::optional<SynthesisContextPair> SynthesisContext;1147  if (!TopLevelConceptId)1148    SynthesisContext.emplace(S, const_cast<NamedDecl *>(Template), Args,1149                             TemplateIDRange);1150 1151  const NormalizedConstraint *C =1152      S.getNormalizedAssociatedConstraints(Template, AssociatedConstraints);1153  if (!C) {1154    Satisfaction.IsSatisfied = false;1155    return true;1156  }1157 1158  if (TopLevelConceptId)1159    C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,1160                                    const_cast<NormalizedConstraint *>(C),1161                                    Template, /*CSE=*/nullptr,1162                                    S.ArgPackSubstIndex);1163 1164  ExprResult Res = ConstraintSatisfactionChecker(1165                       S, Template, TemplateIDRange.getBegin(),1166                       S.ArgPackSubstIndex, Satisfaction,1167                       /*BuildExpression=*/ConvertedExpr != nullptr)1168                       .Evaluate(*C, TemplateArgsLists);1169 1170  if (Res.isInvalid())1171    return true;1172 1173  if (Res.isUsable() && ConvertedExpr)1174    *ConvertedExpr = Res.get();1175 1176  return false;1177}1178 1179bool Sema::CheckConstraintSatisfaction(1180    ConstrainedDeclOrNestedRequirement Entity,1181    ArrayRef<AssociatedConstraint> AssociatedConstraints,1182    const MultiLevelTemplateArgumentList &TemplateArgsLists,1183    SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,1184    const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr) {1185  if (AssociatedConstraints.empty()) {1186    OutSatisfaction.IsSatisfied = true;1187    return false;1188  }1189  const auto *Template = Entity.dyn_cast<const NamedDecl *>();1190  if (!Template) {1191    return ::CheckConstraintSatisfaction(1192        *this, nullptr, AssociatedConstraints, TemplateArgsLists,1193        TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);1194  }1195  // Invalid templates could make their way here. Substituting them could result1196  // in dependent expressions.1197  if (Template->isInvalidDecl()) {1198    OutSatisfaction.IsSatisfied = false;1199    return true;1200  }1201 1202  // A list of the template argument list flattened in a predictible manner for1203  // the purposes of caching. The ConstraintSatisfaction type is in AST so it1204  // has no access to the MultiLevelTemplateArgumentList, so this has to happen1205  // here.1206  llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;1207  for (auto List : TemplateArgsLists)1208    for (const TemplateArgument &Arg : List.Args)1209      FlattenedArgs.emplace_back(Context.getCanonicalTemplateArgument(Arg));1210 1211  const NamedDecl *Owner = Template;1212  if (TopLevelConceptId)1213    Owner = TopLevelConceptId->getNamedConcept();1214 1215  llvm::FoldingSetNodeID ID;1216  ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs);1217  void *InsertPos;1218  if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {1219    OutSatisfaction = *Cached;1220    return false;1221  }1222 1223  auto Satisfaction =1224      std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);1225  if (::CheckConstraintSatisfaction(1226          *this, Template, AssociatedConstraints, TemplateArgsLists,1227          TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {1228    OutSatisfaction = std::move(*Satisfaction);1229    return true;1230  }1231 1232  if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {1233    // The evaluation of this constraint resulted in us trying to re-evaluate it1234    // recursively. This isn't really possible, except we try to form a1235    // RecoveryExpr as a part of the evaluation.  If this is the case, just1236    // return the 'cached' version (which will have the same result), and save1237    // ourselves the extra-insert. If it ever becomes possible to legitimately1238    // recursively check a constraint, we should skip checking the 'inner' one1239    // above, and replace the cached version with this one, as it would be more1240    // specific.1241    OutSatisfaction = *Cached;1242    return false;1243  }1244 1245  // Else we can simply add this satisfaction to the list.1246  OutSatisfaction = *Satisfaction;1247  // We cannot use InsertPos here because CheckConstraintSatisfaction might have1248  // invalidated it.1249  // Note that entries of SatisfactionCache are deleted in Sema's destructor.1250  SatisfactionCache.InsertNode(Satisfaction.release());1251  return false;1252}1253 1254static ExprResult1255SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D,1256                                         const ConceptSpecializationExpr *CSE,1257                                         UnsignedOrNone SubstIndex) {1258 1259  // [C++2c] [temp.constr.normal]1260  // Otherwise, to form CE, any non-dependent concept template argument Ai1261  // is substituted into the constraint-expression of C.1262  // If any such substitution results in an invalid concept-id,1263  // the program is ill-formed; no diagnostic is required.1264 1265  ConceptDecl *Concept = CSE->getNamedConcept()->getCanonicalDecl();1266  Sema::ArgPackSubstIndexRAII _(S, SubstIndex);1267 1268  const ASTTemplateArgumentListInfo *ArgsAsWritten =1269      CSE->getTemplateArgsAsWritten();1270  if (llvm::none_of(1271          ArgsAsWritten->arguments(), [&](const TemplateArgumentLoc &ArgLoc) {1272            return !ArgLoc.getArgument().isDependent() &&1273                   ArgLoc.getArgument().isConceptOrConceptTemplateParameter();1274          })) {1275    return Concept->getConstraintExpr();1276  }1277 1278  MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(1279      Concept, Concept->getLexicalDeclContext(),1280      /*Final=*/false, CSE->getTemplateArguments(),1281      /*RelativeToPrimary=*/true,1282      /*Pattern=*/nullptr,1283      /*ForConstraintInstantiation=*/true);1284  return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),1285                                         MLTAL);1286}1287 1288bool Sema::CheckConstraintSatisfaction(1289    const ConceptSpecializationExpr *ConstraintExpr,1290    ConstraintSatisfaction &Satisfaction) {1291 1292  ExprResult Res = SubstituteConceptsInConstraintExpression(1293      *this, nullptr, ConstraintExpr, ArgPackSubstIndex);1294  if (!Res.isUsable())1295    return true;1296 1297  llvm::SmallVector<AssociatedConstraint, 1> Constraints;1298  Constraints.emplace_back(Res.get());1299 1300  MultiLevelTemplateArgumentList MLTAL(ConstraintExpr->getNamedConcept(),1301                                       ConstraintExpr->getTemplateArguments(),1302                                       true);1303 1304  return CheckConstraintSatisfaction(1305      ConstraintExpr->getNamedConcept(), Constraints, MLTAL,1306      ConstraintExpr->getSourceRange(), Satisfaction,1307      ConstraintExpr->getConceptReference());1308}1309 1310bool Sema::SetupConstraintScope(1311    FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,1312    const MultiLevelTemplateArgumentList &MLTAL,1313    LocalInstantiationScope &Scope) {1314  assert(!isLambdaCallOperator(FD) &&1315         "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "1316         "instantiations");1317  if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {1318    FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();1319    InstantiatingTemplate Inst(1320        *this, FD->getPointOfInstantiation(),1321        Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,1322        TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},1323        SourceRange());1324    if (Inst.isInvalid())1325      return true;1326 1327    // addInstantiatedParametersToScope creates a map of 'uninstantiated' to1328    // 'instantiated' parameters and adds it to the context. For the case where1329    // this function is a template being instantiated NOW, we also need to add1330    // the list of current template arguments to the list so that they also can1331    // be picked out of the map.1332    if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {1333      MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),1334                                                   /*Final=*/false);1335      if (addInstantiatedParametersToScope(1336              FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))1337        return true;1338    }1339 1340    // If this is a member function, make sure we get the parameters that1341    // reference the original primary template.1342    if (FunctionTemplateDecl *FromMemTempl =1343            PrimaryTemplate->getInstantiatedFromMemberTemplate()) {1344      if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),1345                                           Scope, MLTAL))1346        return true;1347    }1348 1349    return false;1350  }1351 1352  if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||1353      FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {1354    FunctionDecl *InstantiatedFrom =1355        FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization1356            ? FD->getInstantiatedFromMemberFunction()1357            : FD->getInstantiatedFromDecl();1358 1359    InstantiatingTemplate Inst(1360        *this, FD->getPointOfInstantiation(),1361        Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,1362        TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},1363        SourceRange());1364    if (Inst.isInvalid())1365      return true;1366 1367    // Case where this was not a template, but instantiated as a1368    // child-function.1369    if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))1370      return true;1371  }1372 1373  return false;1374}1375 1376// This function collects all of the template arguments for the purposes of1377// constraint-instantiation and checking.1378std::optional<MultiLevelTemplateArgumentList>1379Sema::SetupConstraintCheckingTemplateArgumentsAndScope(1380    FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,1381    LocalInstantiationScope &Scope) {1382  MultiLevelTemplateArgumentList MLTAL;1383 1384  // Collect the list of template arguments relative to the 'primary' template.1385  // We need the entire list, since the constraint is completely uninstantiated1386  // at this point.1387  MLTAL =1388      getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),1389                                   /*Final=*/false, /*Innermost=*/std::nullopt,1390                                   /*RelativeToPrimary=*/true,1391                                   /*Pattern=*/nullptr,1392                                   /*ForConstraintInstantiation=*/true);1393  // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.1394  if (isLambdaCallOperator(FD))1395    return MLTAL;1396  if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))1397    return std::nullopt;1398 1399  return MLTAL;1400}1401 1402bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,1403                                    ConstraintSatisfaction &Satisfaction,1404                                    SourceLocation UsageLoc,1405                                    bool ForOverloadResolution) {1406  // Don't check constraints if the function is dependent. Also don't check if1407  // this is a function template specialization, as the call to1408  // CheckFunctionTemplateConstraints after this will check it1409  // better.1410  if (FD->isDependentContext() ||1411      FD->getTemplatedKind() ==1412          FunctionDecl::TK_FunctionTemplateSpecialization) {1413    Satisfaction.IsSatisfied = true;1414    return false;1415  }1416 1417  // A lambda conversion operator has the same constraints as the call operator1418  // and constraints checking relies on whether we are in a lambda call operator1419  // (and may refer to its parameters), so check the call operator instead.1420  // Note that the declarations outside of the lambda should also be1421  // considered. Turning on the 'ForOverloadResolution' flag results in the1422  // LocalInstantiationScope not looking into its parents, but we can still1423  // access Decls from the parents while building a lambda RAII scope later.1424  if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);1425      MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))1426    return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),1427                                    Satisfaction, UsageLoc,1428                                    /*ShouldAddDeclsFromParentScope=*/true);1429 1430  DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);1431 1432  while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {1433    if (isLambdaCallOperator(CtxToSave))1434      CtxToSave = CtxToSave->getParent()->getParent();1435    else1436      CtxToSave = CtxToSave->getNonTransparentContext();1437  }1438 1439  ContextRAII SavedContext{*this, CtxToSave};1440  LocalInstantiationScope Scope(*this, !ForOverloadResolution);1441  std::optional<MultiLevelTemplateArgumentList> MLTAL =1442      SetupConstraintCheckingTemplateArgumentsAndScope(1443          const_cast<FunctionDecl *>(FD), {}, Scope);1444 1445  if (!MLTAL)1446    return true;1447 1448  Qualifiers ThisQuals;1449  CXXRecordDecl *Record = nullptr;1450  if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {1451    ThisQuals = Method->getMethodQualifiers();1452    Record = const_cast<CXXRecordDecl *>(Method->getParent());1453  }1454  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);1455 1456  LambdaScopeForCallOperatorInstantiationRAII LambdaScope(1457      *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,1458      ForOverloadResolution);1459 1460  return CheckConstraintSatisfaction(1461      FD, FD->getTrailingRequiresClause(), *MLTAL,1462      SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),1463      Satisfaction);1464}1465 1466static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(1467    Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,1468    const Expr *ConstrExpr) {1469  MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(1470      DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,1471      /*Innermost=*/std::nullopt,1472      /*RelativeToPrimary=*/true,1473      /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,1474      /*SkipForSpecialization*/ false);1475 1476  if (MLTAL.getNumSubstitutedLevels() == 0)1477    return ConstrExpr;1478 1479  Sema::NonSFINAEContext _(S);1480  Sema::InstantiatingTemplate Inst(1481      S, DeclInfo.getLocation(),1482      Sema::InstantiatingTemplate::ConstraintNormalization{},1483      const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});1484  if (Inst.isInvalid())1485    return nullptr;1486 1487  // Set up a dummy 'instantiation' scope in the case of reference to function1488  // parameters that the surrounding function hasn't been instantiated yet. Note1489  // this may happen while we're comparing two templates' constraint1490  // equivalence.1491  std::optional<LocalInstantiationScope> ScopeForParameters;1492  if (const NamedDecl *ND = DeclInfo.getDecl();1493      ND && ND->isFunctionOrFunctionTemplate()) {1494    ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);1495    const FunctionDecl *FD = ND->getAsFunction();1496    if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate();1497        Template && Template->getInstantiatedFromMemberTemplate())1498      FD = Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();1499    for (auto *PVD : FD->parameters()) {1500      if (ScopeForParameters->getInstantiationOfIfExists(PVD))1501        continue;1502      if (!PVD->isParameterPack()) {1503        ScopeForParameters->InstantiatedLocal(PVD, PVD);1504        continue;1505      }1506      // This is hacky: we're mapping the parameter pack to a size-of-1 argument1507      // to avoid building SubstTemplateTypeParmPackTypes for1508      // PackExpansionTypes. The SubstTemplateTypeParmPackType node would1509      // otherwise reference the AssociatedDecl of the template arguments, which1510      // is, in this case, the template declaration.1511      //1512      // However, as we are in the process of comparing potential1513      // re-declarations, the canonical declaration is the declaration itself at1514      // this point. So if we didn't expand these packs, we would end up with an1515      // incorrect profile difference because we will be profiling the1516      // canonical types!1517      //1518      // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so1519      // that we can eliminate the Scope in the cases where the declarations are1520      // not necessarily instantiated. It would also benefit the noexcept1521      // specifier comparison.1522      ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);1523      ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);1524    }1525  }1526 1527  std::optional<Sema::CXXThisScopeRAII> ThisScope;1528 1529  // See TreeTransform::RebuildTemplateSpecializationType. A context scope is1530  // essential for having an injected class as the canonical type for a template1531  // specialization type at the rebuilding stage. This guarantees that, for1532  // out-of-line definitions, injected class name types and their equivalent1533  // template specializations can be profiled to the same value, which makes it1534  // possible that e.g. constraints involving C<Class<T>> and C<Class> are1535  // perceived identical.1536  std::optional<Sema::ContextRAII> ContextScope;1537  const DeclContext *DC = [&] {1538    if (!DeclInfo.getDecl())1539      return DeclInfo.getDeclContext();1540    return DeclInfo.getDecl()->getFriendObjectKind()1541               ? DeclInfo.getLexicalDeclContext()1542               : DeclInfo.getDeclContext();1543  }();1544  if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {1545    ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());1546    ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),1547                         /*NewThisContext=*/false);1548  }1549  EnterExpressionEvaluationContext UnevaluatedContext(1550      S, Sema::ExpressionEvaluationContext::Unevaluated,1551      Sema::ReuseLambdaContextDecl);1552  ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(1553      const_cast<clang::Expr *>(ConstrExpr), MLTAL);1554  if (!SubstConstr.isUsable())1555    return nullptr;1556  return SubstConstr.get();1557}1558 1559bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,1560                                         const Expr *OldConstr,1561                                         const TemplateCompareNewDeclInfo &New,1562                                         const Expr *NewConstr) {1563  if (OldConstr == NewConstr)1564    return true;1565  // C++ [temp.constr.decl]p41566  if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&1567      Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {1568    if (const Expr *SubstConstr =1569            SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,1570                                                              OldConstr))1571      OldConstr = SubstConstr;1572    else1573      return false;1574    if (const Expr *SubstConstr =1575            SubstituteConstraintExpressionWithoutSatisfaction(*this, New,1576                                                              NewConstr))1577      NewConstr = SubstConstr;1578    else1579      return false;1580  }1581 1582  llvm::FoldingSetNodeID ID1, ID2;1583  OldConstr->Profile(ID1, Context, /*Canonical=*/true);1584  NewConstr->Profile(ID2, Context, /*Canonical=*/true);1585  return ID1 == ID2;1586}1587 1588bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {1589  assert(FD->getFriendObjectKind() && "Must be a friend!");1590 1591  // The logic for non-templates is handled in ASTContext::isSameEntity, so we1592  // don't have to bother checking 'DependsOnEnclosingTemplate' for a1593  // non-function-template.1594  assert(FD->getDescribedFunctionTemplate() &&1595         "Non-function templates don't need to be checked");1596 1597  SmallVector<AssociatedConstraint, 3> ACs;1598  FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);1599 1600  unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);1601  for (const AssociatedConstraint &AC : ACs)1602    if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,1603                                                       AC.ConstraintExpr))1604      return true;1605 1606  return false;1607}1608 1609bool Sema::EnsureTemplateArgumentListConstraints(1610    TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,1611    SourceRange TemplateIDRange) {1612  ConstraintSatisfaction Satisfaction;1613  llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;1614  TD->getAssociatedConstraints(AssociatedConstraints);1615  if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,1616                                  TemplateIDRange, Satisfaction))1617    return true;1618 1619  if (!Satisfaction.IsSatisfied) {1620    SmallString<128> TemplateArgString;1621    TemplateArgString = " ";1622    TemplateArgString += getTemplateArgumentBindingsText(1623        TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),1624        TemplateArgsLists.getInnermost().size());1625 1626    Diag(TemplateIDRange.getBegin(),1627         diag::err_template_arg_list_constraints_not_satisfied)1628        << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD1629        << TemplateArgString << TemplateIDRange;1630    DiagnoseUnsatisfiedConstraint(Satisfaction);1631    return true;1632  }1633  return false;1634}1635 1636static bool CheckFunctionConstraintsWithoutInstantiation(1637    Sema &SemaRef, SourceLocation PointOfInstantiation,1638    FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,1639    ConstraintSatisfaction &Satisfaction) {1640  SmallVector<AssociatedConstraint, 3> TemplateAC;1641  Template->getAssociatedConstraints(TemplateAC);1642  if (TemplateAC.empty()) {1643    Satisfaction.IsSatisfied = true;1644    return false;1645  }1646 1647  LocalInstantiationScope Scope(SemaRef);1648 1649  FunctionDecl *FD = Template->getTemplatedDecl();1650  // Collect the list of template arguments relative to the 'primary'1651  // template. We need the entire list, since the constraint is completely1652  // uninstantiated at this point.1653 1654  MultiLevelTemplateArgumentList MLTAL;1655  {1656    // getTemplateInstantiationArgs uses this instantiation context to find out1657    // template arguments for uninstantiated functions.1658    // We don't want this RAII object to persist, because there would be1659    // otherwise duplicate diagnostic notes.1660    Sema::InstantiatingTemplate Inst(1661        SemaRef, PointOfInstantiation,1662        Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,1663        PointOfInstantiation);1664    if (Inst.isInvalid())1665      return true;1666    MLTAL = SemaRef.getTemplateInstantiationArgs(1667        /*D=*/FD, FD,1668        /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,1669        /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);1670  }1671 1672  Sema::ContextRAII SavedContext(SemaRef, FD);1673  return SemaRef.CheckConstraintSatisfaction(1674      Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);1675}1676 1677bool Sema::CheckFunctionTemplateConstraints(1678    SourceLocation PointOfInstantiation, FunctionDecl *Decl,1679    ArrayRef<TemplateArgument> TemplateArgs,1680    ConstraintSatisfaction &Satisfaction) {1681  // In most cases we're not going to have constraints, so check for that first.1682  FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();1683 1684  if (!Template)1685    return ::CheckFunctionConstraintsWithoutInstantiation(1686        *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),1687        TemplateArgs, Satisfaction);1688 1689  // Note - code synthesis context for the constraints check is created1690  // inside CheckConstraintsSatisfaction.1691  SmallVector<AssociatedConstraint, 3> TemplateAC;1692  Template->getAssociatedConstraints(TemplateAC);1693  if (TemplateAC.empty()) {1694    Satisfaction.IsSatisfied = true;1695    return false;1696  }1697 1698  // Enter the scope of this instantiation. We don't use1699  // PushDeclContext because we don't have a scope.1700  Sema::ContextRAII savedContext(*this, Decl);1701  LocalInstantiationScope Scope(*this);1702 1703  std::optional<MultiLevelTemplateArgumentList> MLTAL =1704      SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,1705                                                       Scope);1706 1707  if (!MLTAL)1708    return true;1709 1710  Qualifiers ThisQuals;1711  CXXRecordDecl *Record = nullptr;1712  if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {1713    ThisQuals = Method->getMethodQualifiers();1714    Record = Method->getParent();1715  }1716 1717  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);1718  LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,1719                                                          Scope);1720 1721  return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,1722                                     PointOfInstantiation, Satisfaction);1723}1724 1725static void diagnoseUnsatisfiedRequirement(Sema &S,1726                                           concepts::ExprRequirement *Req,1727                                           bool First) {1728  assert(!Req->isSatisfied() &&1729         "Diagnose() can only be used on an unsatisfied requirement");1730  switch (Req->getSatisfactionStatus()) {1731  case concepts::ExprRequirement::SS_Dependent:1732    llvm_unreachable("Diagnosing a dependent requirement");1733    break;1734  case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {1735    auto *SubstDiag = Req->getExprSubstitutionDiagnostic();1736    if (!SubstDiag->DiagMessage.empty())1737      S.Diag(SubstDiag->DiagLoc,1738             diag::note_expr_requirement_expr_substitution_error)1739          << (int)First << SubstDiag->SubstitutedEntity1740          << SubstDiag->DiagMessage;1741    else1742      S.Diag(SubstDiag->DiagLoc,1743             diag::note_expr_requirement_expr_unknown_substitution_error)1744          << (int)First << SubstDiag->SubstitutedEntity;1745    break;1746  }1747  case concepts::ExprRequirement::SS_NoexceptNotMet:1748    S.Diag(Req->getNoexceptLoc(), diag::note_expr_requirement_noexcept_not_met)1749        << (int)First << Req->getExpr();1750    break;1751  case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {1752    auto *SubstDiag =1753        Req->getReturnTypeRequirement().getSubstitutionDiagnostic();1754    if (!SubstDiag->DiagMessage.empty())1755      S.Diag(SubstDiag->DiagLoc,1756             diag::note_expr_requirement_type_requirement_substitution_error)1757          << (int)First << SubstDiag->SubstitutedEntity1758          << SubstDiag->DiagMessage;1759    else1760      S.Diag(1761          SubstDiag->DiagLoc,1762          diag::1763              note_expr_requirement_type_requirement_unknown_substitution_error)1764          << (int)First << SubstDiag->SubstitutedEntity;1765    break;1766  }1767  case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {1768    ConceptSpecializationExpr *ConstraintExpr =1769        Req->getReturnTypeRequirementSubstitutedConstraintExpr();1770    S.DiagnoseUnsatisfiedConstraint(ConstraintExpr);1771    break;1772  }1773  case concepts::ExprRequirement::SS_Satisfied:1774    llvm_unreachable("We checked this above");1775  }1776}1777 1778static void diagnoseUnsatisfiedRequirement(Sema &S,1779                                           concepts::TypeRequirement *Req,1780                                           bool First) {1781  assert(!Req->isSatisfied() &&1782         "Diagnose() can only be used on an unsatisfied requirement");1783  switch (Req->getSatisfactionStatus()) {1784  case concepts::TypeRequirement::SS_Dependent:1785    llvm_unreachable("Diagnosing a dependent requirement");1786    return;1787  case concepts::TypeRequirement::SS_SubstitutionFailure: {1788    auto *SubstDiag = Req->getSubstitutionDiagnostic();1789    if (!SubstDiag->DiagMessage.empty())1790      S.Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)1791          << (int)First << SubstDiag->SubstitutedEntity1792          << SubstDiag->DiagMessage;1793    else1794      S.Diag(SubstDiag->DiagLoc,1795             diag::note_type_requirement_unknown_substitution_error)1796          << (int)First << SubstDiag->SubstitutedEntity;1797    return;1798  }1799  default:1800    llvm_unreachable("Unknown satisfaction status");1801    return;1802  }1803}1804 1805static void diagnoseUnsatisfiedConceptIdExpr(Sema &S,1806                                             const ConceptReference *Concept,1807                                             SourceLocation Loc, bool First) {1808  if (Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {1809    S.Diag(1810        Loc,1811        diag::1812            note_single_arg_concept_specialization_constraint_evaluated_to_false)1813        << (int)First1814        << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()1815        << Concept->getNamedConcept();1816  } else {1817    S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)1818        << (int)First << Concept;1819  }1820}1821 1822static void diagnoseUnsatisfiedConstraintExpr(1823    Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc,1824    bool First, concepts::NestedRequirement *Req = nullptr);1825 1826static void DiagnoseUnsatisfiedConstraint(1827    Sema &S, ArrayRef<UnsatisfiedConstraintRecord> Records, SourceLocation Loc,1828    bool First = true, concepts::NestedRequirement *Req = nullptr) {1829  for (auto &Record : Records) {1830    diagnoseUnsatisfiedConstraintExpr(S, Record, Loc, First, Req);1831    Loc = {};1832    First = isa<const ConceptReference *>(Record);1833  }1834}1835 1836static void diagnoseUnsatisfiedRequirement(Sema &S,1837                                           concepts::NestedRequirement *Req,1838                                           bool First) {1839  DiagnoseUnsatisfiedConstraint(S, Req->getConstraintSatisfaction().records(),1840                                Req->hasInvalidConstraint()1841                                    ? SourceLocation()1842                                    : Req->getConstraintExpr()->getExprLoc(),1843                                First, Req);1844}1845 1846static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,1847                                                        const Expr *SubstExpr,1848                                                        bool First) {1849  SubstExpr = SubstExpr->IgnoreParenImpCasts();1850  if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {1851    switch (BO->getOpcode()) {1852    // These two cases will in practice only be reached when using fold1853    // expressions with || and &&, since otherwise the || and && will have been1854    // broken down into atomic constraints during satisfaction checking.1855    case BO_LOr:1856      // Or evaluated to false - meaning both RHS and LHS evaluated to false.1857      diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);1858      diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),1859                                                  /*First=*/false);1860      return;1861    case BO_LAnd: {1862      bool LHSSatisfied =1863          BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();1864      if (LHSSatisfied) {1865        // LHS is true, so RHS must be false.1866        diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);1867        return;1868      }1869      // LHS is false1870      diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);1871 1872      // RHS might also be false1873      bool RHSSatisfied =1874          BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();1875      if (!RHSSatisfied)1876        diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),1877                                                    /*First=*/false);1878      return;1879    }1880    case BO_GE:1881    case BO_LE:1882    case BO_GT:1883    case BO_LT:1884    case BO_EQ:1885    case BO_NE:1886      if (BO->getLHS()->getType()->isIntegerType() &&1887          BO->getRHS()->getType()->isIntegerType()) {1888        Expr::EvalResult SimplifiedLHS;1889        Expr::EvalResult SimplifiedRHS;1890        BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,1891                                    Expr::SE_NoSideEffects,1892                                    /*InConstantContext=*/true);1893        BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,1894                                    Expr::SE_NoSideEffects,1895                                    /*InConstantContext=*/true);1896        if (!SimplifiedLHS.Diag && !SimplifiedRHS.Diag) {1897          S.Diag(SubstExpr->getBeginLoc(),1898                 diag::note_atomic_constraint_evaluated_to_false_elaborated)1899              << (int)First << SubstExpr1900              << toString(SimplifiedLHS.Val.getInt(), 10)1901              << BinaryOperator::getOpcodeStr(BO->getOpcode())1902              << toString(SimplifiedRHS.Val.getInt(), 10);1903          return;1904        }1905      }1906      break;1907 1908    default:1909      break;1910    }1911  } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {1912    // FIXME: RequiresExpr should store dependent diagnostics.1913    for (concepts::Requirement *Req : RE->getRequirements())1914      if (!Req->isDependent() && !Req->isSatisfied()) {1915        if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))1916          diagnoseUnsatisfiedRequirement(S, E, First);1917        else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))1918          diagnoseUnsatisfiedRequirement(S, T, First);1919        else1920          diagnoseUnsatisfiedRequirement(1921              S, cast<concepts::NestedRequirement>(Req), First);1922        break;1923      }1924    return;1925  } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {1926    // Drill down concept ids treated as atomic constraints1927    S.DiagnoseUnsatisfiedConstraint(CSE, First);1928    return;1929  } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);1930             TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {1931    assert(TTE->getNumArgs() == 2);1932    S.Diag(SubstExpr->getSourceRange().getBegin(),1933           diag::note_is_deducible_constraint_evaluated_to_false)1934        << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();1935    return;1936  }1937 1938  S.Diag(SubstExpr->getSourceRange().getBegin(),1939         diag::note_atomic_constraint_evaluated_to_false)1940      << (int)First << SubstExpr;1941  S.DiagnoseTypeTraitDetails(SubstExpr);1942}1943 1944static void diagnoseUnsatisfiedConstraintExpr(1945    Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc,1946    bool First, concepts::NestedRequirement *Req) {1947  if (auto *Diag =1948          Record1949              .template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {1950    if (Req)1951      S.Diag(Diag->first, diag::note_nested_requirement_substitution_error)1952          << (int)First << Req->getInvalidConstraintEntity() << Diag->second;1953    else1954      S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)1955          << Diag->second;1956    return;1957  }1958  if (const auto *Concept = dyn_cast<const ConceptReference *>(Record)) {1959    if (Loc.isInvalid())1960      Loc = Concept->getBeginLoc();1961    diagnoseUnsatisfiedConceptIdExpr(S, Concept, Loc, First);1962    return;1963  }1964  diagnoseWellFormedUnsatisfiedConstraintExpr(1965      S, cast<const class Expr *>(Record), First);1966}1967 1968void Sema::DiagnoseUnsatisfiedConstraint(1969    const ConstraintSatisfaction &Satisfaction, SourceLocation Loc,1970    bool First) {1971 1972  assert(!Satisfaction.IsSatisfied &&1973         "Attempted to diagnose a satisfied constraint");1974  ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.Details, Loc, First);1975}1976 1977void Sema::DiagnoseUnsatisfiedConstraint(1978    const ConceptSpecializationExpr *ConstraintExpr, bool First) {1979 1980  const ASTConstraintSatisfaction &Satisfaction =1981      ConstraintExpr->getSatisfaction();1982 1983  assert(!Satisfaction.IsSatisfied &&1984         "Attempted to diagnose a satisfied constraint");1985 1986  ::DiagnoseUnsatisfiedConstraint(*this, Satisfaction.records(),1987                                  ConstraintExpr->getBeginLoc(), First);1988}1989 1990namespace {1991 1992class SubstituteParameterMappings {1993  Sema &SemaRef;1994 1995  const MultiLevelTemplateArgumentList *MLTAL;1996  const ASTTemplateArgumentListInfo *ArgsAsWritten;1997 1998  bool InFoldExpr;1999 2000  SubstituteParameterMappings(Sema &SemaRef,2001                              const MultiLevelTemplateArgumentList *MLTAL,2002                              const ASTTemplateArgumentListInfo *ArgsAsWritten,2003                              bool InFoldExpr)2004      : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),2005        InFoldExpr(InFoldExpr) {}2006 2007  void buildParameterMapping(NormalizedConstraintWithParamMapping &N);2008 2009  bool substitute(NormalizedConstraintWithParamMapping &N);2010 2011  bool substitute(ConceptIdConstraint &CC);2012 2013public:2014  SubstituteParameterMappings(Sema &SemaRef, bool InFoldExpr = false)2015      : SemaRef(SemaRef), MLTAL(nullptr), ArgsAsWritten(nullptr),2016        InFoldExpr(InFoldExpr) {}2017 2018  bool substitute(NormalizedConstraint &N);2019};2020 2021void SubstituteParameterMappings::buildParameterMapping(2022    NormalizedConstraintWithParamMapping &N) {2023  TemplateParameterList *TemplateParams =2024      cast<TemplateDecl>(N.getConstraintDecl())->getTemplateParameters();2025 2026  llvm::SmallBitVector OccurringIndices(TemplateParams->size());2027  llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->size());2028 2029  if (N.getKind() == NormalizedConstraint::ConstraintKind::Atomic) {2030    SemaRef.MarkUsedTemplateParameters(2031        static_cast<AtomicConstraint &>(N).getConstraintExpr(),2032        /*OnlyDeduced=*/false,2033        /*Depth=*/0, OccurringIndices);2034 2035    SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(2036        static_cast<AtomicConstraint &>(N).getConstraintExpr(),2037        /*Depth=*/0, OccurringIndicesForSubsumption);2038 2039  } else if (N.getKind() ==2040             NormalizedConstraint::ConstraintKind::FoldExpanded) {2041    SemaRef.MarkUsedTemplateParameters(2042        static_cast<FoldExpandedConstraint &>(N).getPattern(),2043        /*OnlyDeduced=*/false,2044        /*Depth=*/0, OccurringIndices);2045  } else if (N.getKind() == NormalizedConstraint::ConstraintKind::ConceptId) {2046    auto *Args = static_cast<ConceptIdConstraint &>(N)2047                     .getConceptId()2048                     ->getTemplateArgsAsWritten();2049    if (Args)2050      SemaRef.MarkUsedTemplateParameters(Args->arguments(),2051                                         /*Depth=*/0, OccurringIndices);2052  }2053  unsigned Size = OccurringIndices.count();2054  // When the constraint is independent of any template parameters,2055  // we build an empty mapping so that we can distinguish these cases2056  // from cases where no mapping exists at all, e.g. when there are only atomic2057  // constraints.2058  TemplateArgumentLoc *TempArgs =2059      new (SemaRef.Context) TemplateArgumentLoc[Size];2060  llvm::SmallVector<NamedDecl *> UsedParams;2061  for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) {2062    SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I2063                             ? ArgsAsWritten->arguments()[I].getLocation()2064                             : SourceLocation();2065    // FIXME: Investigate why we couldn't always preserve the SourceLoc. We2066    // can't assert Loc.isValid() now.2067    if (OccurringIndices[I]) {2068      NamedDecl *Param = TemplateParams->begin()[I];2069      new (&(TempArgs)[J]) TemplateArgumentLoc(2070          SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));2071      UsedParams.push_back(Param);2072      J++;2073    }2074  }2075  auto *UsedList = TemplateParameterList::Create(2076      SemaRef.Context, TemplateParams->getTemplateLoc(),2077      TemplateParams->getLAngleLoc(), UsedParams,2078      /*RAngleLoc=*/SourceLocation(),2079      /*RequiresClause=*/nullptr);2080  N.updateParameterMapping(2081      std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),2082      MutableArrayRef<TemplateArgumentLoc>{TempArgs, Size}, UsedList);2083}2084 2085bool SubstituteParameterMappings::substitute(2086    NormalizedConstraintWithParamMapping &N) {2087  if (!N.hasParameterMapping())2088    buildParameterMapping(N);2089 2090  // If the parameter mapping is empty, there is nothing to substitute.2091  if (N.getParameterMapping().empty())2092    return false;2093 2094  SourceLocation InstLocBegin, InstLocEnd;2095  llvm::ArrayRef Arguments = ArgsAsWritten->arguments();2096  if (Arguments.empty()) {2097    InstLocBegin = ArgsAsWritten->getLAngleLoc();2098    InstLocEnd = ArgsAsWritten->getRAngleLoc();2099  } else {2100    auto SR = Arguments[0].getSourceRange();2101    InstLocBegin = SR.getBegin();2102    InstLocEnd = SR.getEnd();2103  }2104  Sema::NonSFINAEContext _(SemaRef);2105  Sema::InstantiatingTemplate Inst(2106      SemaRef, InstLocBegin,2107      Sema::InstantiatingTemplate::ParameterMappingSubstitution{},2108      const_cast<NamedDecl *>(N.getConstraintDecl()),2109      {InstLocBegin, InstLocEnd});2110  if (Inst.isInvalid())2111    return true;2112 2113  // TransformTemplateArguments is unable to preserve the source location of a2114  // pack. The SourceLocation is necessary for the instantiation location.2115  // FIXME: The BaseLoc will be used as the location of the pack expansion,2116  // which is wrong.2117  TemplateArgumentListInfo SubstArgs;2118  if (SemaRef.SubstTemplateArgumentsInParameterMapping(2119          N.getParameterMapping(), N.getBeginLoc(), *MLTAL, SubstArgs,2120          /*BuildPackExpansionTypes=*/!InFoldExpr))2121    return true;2122  Sema::CheckTemplateArgumentInfo CTAI;2123  auto *TD =2124      const_cast<TemplateDecl *>(cast<TemplateDecl>(N.getConstraintDecl()));2125  if (SemaRef.CheckTemplateArgumentList(TD, N.getUsedTemplateParamList(),2126                                        TD->getLocation(), SubstArgs,2127                                        /*DefaultArguments=*/{},2128                                        /*PartialTemplateArgs=*/false, CTAI))2129    return true;2130 2131  TemplateArgumentLoc *TempArgs =2132      new (SemaRef.Context) TemplateArgumentLoc[CTAI.SugaredConverted.size()];2133 2134  for (unsigned I = 0; I < CTAI.SugaredConverted.size(); ++I) {2135    SourceLocation Loc;2136    // If this is an empty pack, we have no corresponding SubstArgs.2137    if (I < SubstArgs.size())2138      Loc = SubstArgs.arguments()[I].getLocation();2139 2140    TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(2141        CTAI.SugaredConverted[I], QualType(), Loc);2142  }2143 2144  MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,2145                                               CTAI.SugaredConverted.size());2146  N.updateParameterMapping(N.mappingOccurenceList(),2147                           N.mappingOccurenceListForSubsumption(), Mapping,2148                           N.getUsedTemplateParamList());2149  return false;2150}2151 2152bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) {2153  assert(CC.getConstraintDecl() && MLTAL && ArgsAsWritten);2154 2155  if (substitute(static_cast<NormalizedConstraintWithParamMapping &>(CC)))2156    return true;2157 2158  auto *CSE = CC.getConceptSpecializationExpr();2159  assert(CSE);2160  assert(!CC.getBeginLoc().isInvalid());2161 2162  SourceLocation InstLocBegin, InstLocEnd;2163  if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();2164      Arguments.empty()) {2165    InstLocBegin = ArgsAsWritten->getLAngleLoc();2166    InstLocEnd = ArgsAsWritten->getRAngleLoc();2167  } else {2168    auto SR = Arguments[0].getSourceRange();2169    InstLocBegin = SR.getBegin();2170    InstLocEnd = SR.getEnd();2171  }2172  Sema::NonSFINAEContext _(SemaRef);2173  // This is useful for name lookup across modules; see Sema::getLookupModules.2174  Sema::InstantiatingTemplate Inst(2175      SemaRef, InstLocBegin,2176      Sema::InstantiatingTemplate::ParameterMappingSubstitution{},2177      const_cast<NamedDecl *>(CC.getConstraintDecl()),2178      {InstLocBegin, InstLocEnd});2179  if (Inst.isInvalid())2180    return true;2181 2182  TemplateArgumentListInfo Out;2183  // TransformTemplateArguments is unable to preserve the source location of a2184  // pack. The SourceLocation is necessary for the instantiation location.2185  // FIXME: The BaseLoc will be used as the location of the pack expansion,2186  // which is wrong.2187  const ASTTemplateArgumentListInfo *ArgsAsWritten =2188      CSE->getTemplateArgsAsWritten();2189  if (SemaRef.SubstTemplateArgumentsInParameterMapping(2190          ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out,2191          /*BuildPackExpansionTypes=*/!InFoldExpr))2192    return true;2193  Sema::CheckTemplateArgumentInfo CTAI;2194  if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(),2195                                        CSE->getConceptNameInfo().getLoc(), Out,2196                                        /*DefaultArgs=*/{},2197                                        /*PartialTemplateArgs=*/false, CTAI,2198                                        /*UpdateArgsWithConversions=*/false))2199    return true;2200  auto TemplateArgs = *MLTAL;2201  TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(),2202                                                 CTAI.SugaredConverted);2203  return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,2204                                     InFoldExpr)2205      .substitute(CC.getNormalizedConstraint());2206}2207 2208bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {2209  switch (N.getKind()) {2210  case NormalizedConstraint::ConstraintKind::Atomic: {2211    if (!MLTAL) {2212      assert(!ArgsAsWritten);2213      return false;2214    }2215    return substitute(static_cast<NormalizedConstraintWithParamMapping &>(N));2216  }2217  case NormalizedConstraint::ConstraintKind::FoldExpanded: {2218    auto &FE = static_cast<FoldExpandedConstraint &>(N);2219    if (!MLTAL) {2220      llvm::SaveAndRestore _1(InFoldExpr, true);2221      assert(!ArgsAsWritten);2222      return substitute(FE.getNormalizedPattern());2223    }2224    Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);2225    substitute(static_cast<NormalizedConstraintWithParamMapping &>(FE));2226    return SubstituteParameterMappings(SemaRef, /*InFoldExpr=*/true)2227        .substitute(FE.getNormalizedPattern());2228  }2229  case NormalizedConstraint::ConstraintKind::ConceptId: {2230    auto &CC = static_cast<ConceptIdConstraint &>(N);2231    if (MLTAL) {2232      assert(ArgsAsWritten);2233      return substitute(CC);2234    }2235    assert(!ArgsAsWritten);2236    const ConceptSpecializationExpr *CSE = CC.getConceptSpecializationExpr();2237    ConceptDecl *Concept = CSE->getNamedConcept();2238    MultiLevelTemplateArgumentList MLTAL = SemaRef.getTemplateInstantiationArgs(2239        Concept, Concept->getLexicalDeclContext(),2240        /*Final=*/true, CSE->getTemplateArguments(),2241        /*RelativeToPrimary=*/true,2242        /*Pattern=*/nullptr,2243        /*ForConstraintInstantiation=*/true);2244 2245    return SubstituteParameterMappings(2246               SemaRef, &MLTAL, CSE->getTemplateArgsAsWritten(), InFoldExpr)2247        .substitute(CC.getNormalizedConstraint());2248  }2249  case NormalizedConstraint::ConstraintKind::Compound: {2250    auto &Compound = static_cast<CompoundConstraint &>(N);2251    if (substitute(Compound.getLHS()))2252      return true;2253    return substitute(Compound.getRHS());2254  }2255  }2256  llvm_unreachable("Unknown ConstraintKind enum");2257}2258 2259} // namespace2260 2261NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(2262    Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {2263  assert(ACs.size() != 0);2264  auto *Conjunction =2265      fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);2266  if (!Conjunction)2267    return nullptr;2268  for (unsigned I = 1; I < ACs.size(); ++I) {2269    auto *Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,2270                                    ACs[I].ArgPackSubstIndex);2271    if (!Next)2272      return nullptr;2273    Conjunction = CompoundConstraint::CreateConjunction(S.getASTContext(),2274                                                        Conjunction, Next);2275  }2276  return Conjunction;2277}2278 2279NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(2280    Sema &S, const NamedDecl *D, const Expr *E, UnsignedOrNone SubstIndex) {2281  assert(E != nullptr);2282 2283  // C++ [temp.constr.normal]p1.12284  // [...]2285  // - The normal form of an expression (E) is the normal form of E.2286  // [...]2287  E = E->IgnoreParenImpCasts();2288 2289  llvm::FoldingSetNodeID ID;2290  if (D && DiagRecursiveConstraintEval(S, ID, D, E)) {2291    return nullptr;2292  }2293  SatisfactionStackRAII StackRAII(S, D, ID);2294 2295  // C++2a [temp.param]p4:2296  //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).2297  // Fold expression is considered atomic constraints per current wording.2298  // See http://cplusplus.github.io/concepts-ts/ts-active.html#282299 2300  if (LogicalBinOp BO = E) {2301    auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);2302    if (!LHS)2303      return nullptr;2304    auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);2305    if (!RHS)2306      return nullptr;2307 2308    return CompoundConstraint::Create(2309        S.Context, LHS, BO.isAnd() ? CCK_Conjunction : CCK_Disjunction, RHS);2310  } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {2311    NormalizedConstraint *SubNF;2312    {2313      Sema::NonSFINAEContext _(S);2314      Sema::InstantiatingTemplate Inst(2315          S, CSE->getExprLoc(),2316          Sema::InstantiatingTemplate::ConstraintNormalization{},2317          // FIXME: improve const-correctness of InstantiatingTemplate2318          const_cast<NamedDecl *>(D), CSE->getSourceRange());2319      if (Inst.isInvalid())2320        return nullptr;2321      // C++ [temp.constr.normal]p1.12322      // [...]2323      // The normal form of an id-expression of the form C<A1, A2, ..., AN>,2324      // where C names a concept, is the normal form of the2325      // constraint-expression of C, after substituting A1, A2, ..., AN for C’s2326      // respective template parameters in the parameter mappings in each atomic2327      // constraint. If any such substitution results in an invalid type or2328      // expression, the program is ill-formed; no diagnostic is required.2329      // [...]2330 2331      // Use canonical declarations to merge ConceptDecls across2332      // different modules.2333      ConceptDecl *CD = CSE->getNamedConcept()->getCanonicalDecl();2334 2335      ExprResult Res =2336          SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);2337      if (!Res.isUsable())2338        return nullptr;2339 2340      SubNF = NormalizedConstraint::fromAssociatedConstraints(2341          S, CD, AssociatedConstraint(Res.get(), SubstIndex));2342 2343      if (!SubNF)2344        return nullptr;2345    }2346 2347    return ConceptIdConstraint::Create(S.getASTContext(),2348                                       CSE->getConceptReference(), SubNF, D,2349                                       CSE, SubstIndex);2350 2351  } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);2352             FE && S.getLangOpts().CPlusPlus26 &&2353             (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||2354              FE->getOperator() == BinaryOperatorKind::BO_LOr)) {2355 2356    // Normalize fold expressions in C++26.2357 2358    FoldExpandedConstraint::FoldOperatorKind Kind =2359        FE->getOperator() == BinaryOperatorKind::BO_LAnd2360            ? FoldExpandedConstraint::FoldOperatorKind::And2361            : FoldExpandedConstraint::FoldOperatorKind::Or;2362 2363    if (FE->getInit()) {2364      auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);2365      auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);2366      if (!LHS || !RHS)2367        return nullptr;2368 2369      if (FE->isRightFold())2370        LHS = FoldExpandedConstraint::Create(S.getASTContext(),2371                                             FE->getPattern(), D, Kind, LHS);2372      else2373        RHS = FoldExpandedConstraint::Create(S.getASTContext(),2374                                             FE->getPattern(), D, Kind, RHS);2375 2376      return CompoundConstraint::Create(2377          S.getASTContext(), LHS,2378          (FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction2379                                                            : CCK_Disjunction),2380          RHS);2381    }2382    auto *Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);2383    if (!Sub)2384      return nullptr;2385    return FoldExpandedConstraint::Create(S.getASTContext(), FE->getPattern(),2386                                          D, Kind, Sub);2387  }2388  return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);2389}2390 2391const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(2392    ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,2393    ArrayRef<AssociatedConstraint> AssociatedConstraints) {2394  if (!ConstrainedDeclOrNestedReq) {2395    auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(2396        *this, nullptr, AssociatedConstraints);2397    if (!Normalized ||2398        SubstituteParameterMappings(*this).substitute(*Normalized))2399      return nullptr;2400 2401    return Normalized;2402  }2403 2404  // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!2405  const NamedDecl *ND =2406      ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>();2407  auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);2408  if (CacheEntry == NormalizationCache.end()) {2409    auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(2410        *this, ND, AssociatedConstraints);2411    if (!Normalized) {2412      NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, nullptr);2413      return nullptr;2414    }2415    // substitute() can invalidate iterators of NormalizationCache.2416    bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);2417    CacheEntry =2418        NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)2419            .first;2420    if (Failed)2421      return nullptr;2422  }2423  return CacheEntry->second;2424}2425 2426bool FoldExpandedConstraint::AreCompatibleForSubsumption(2427    const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {2428 2429  // [C++26] [temp.constr.fold]2430  // Two fold expanded constraints are compatible for subsumption2431  // if their respective constraints both contain an equivalent unexpanded pack.2432 2433  llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks;2434  Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.getPattern()),2435                                        APacks);2436  Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.getPattern()),2437                                        BPacks);2438 2439  for (const UnexpandedParameterPack &APack : APacks) {2440    auto ADI = getDepthAndIndex(APack);2441    if (!ADI)2442      continue;2443    auto It = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {2444      return getDepthAndIndex(BPack) == ADI;2445    });2446    if (It != BPacks.end())2447      return true;2448  }2449  return false;2450}2451 2452bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1,2453                                  MutableArrayRef<AssociatedConstraint> AC1,2454                                  const NamedDecl *D2,2455                                  MutableArrayRef<AssociatedConstraint> AC2,2456                                  bool &Result) {2457#ifndef NDEBUG2458  if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {2459    auto IsExpectedEntity = [](const FunctionDecl *FD) {2460      FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();2461      return Kind == FunctionDecl::TK_NonTemplate ||2462             Kind == FunctionDecl::TK_FunctionTemplate;2463    };2464    const auto *FD2 = dyn_cast<FunctionDecl>(D2);2465    assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&2466           "use non-instantiated function declaration for constraints partial "2467           "ordering");2468  }2469#endif2470 2471  if (AC1.empty()) {2472    Result = AC2.empty();2473    return false;2474  }2475  if (AC2.empty()) {2476    // TD1 has associated constraints and TD2 does not.2477    Result = true;2478    return false;2479  }2480 2481  std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};2482  auto CacheEntry = SubsumptionCache.find(Key);2483  if (CacheEntry != SubsumptionCache.end()) {2484    Result = CacheEntry->second;2485    return false;2486  }2487 2488  unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);2489  unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);2490 2491  for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {2492    if (Depth2 > Depth1) {2493      AC1[I].ConstraintExpr =2494          AdjustConstraintDepth(*this, Depth2 - Depth1)2495              .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))2496              .get();2497    } else if (Depth1 > Depth2) {2498      AC2[I].ConstraintExpr =2499          AdjustConstraintDepth(*this, Depth1 - Depth2)2500              .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))2501              .get();2502    }2503  }2504 2505  SubsumptionChecker SC(*this);2506  std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2);2507  if (!Subsumes) {2508    // Normalization failed2509    return true;2510  }2511  Result = *Subsumes;2512  SubsumptionCache.try_emplace(Key, *Subsumes);2513  return false;2514}2515 2516bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(2517    const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1,2518    const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2) {2519  if (isSFINAEContext())2520    // No need to work here because our notes would be discarded.2521    return false;2522 2523  if (AC1.empty() || AC2.empty())2524    return false;2525 2526  const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;2527  auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,2528                                    const AtomicConstraint &B) {2529    if (!A.hasMatchingParameterMapping(Context, B))2530      return false;2531    const Expr *EA = A.getConstraintExpr(), *EB = B.getConstraintExpr();2532    if (EA == EB)2533      return true;2534 2535    // Not the same source level expression - are the expressions2536    // identical?2537    llvm::FoldingSetNodeID IDA, IDB;2538    EA->Profile(IDA, Context, /*Canonical=*/true);2539    EB->Profile(IDB, Context, /*Canonical=*/true);2540    if (IDA != IDB)2541      return false;2542 2543    AmbiguousAtomic1 = EA;2544    AmbiguousAtomic2 = EB;2545    return true;2546  };2547 2548  {2549    auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);2550    if (!Normalized1)2551      return false;2552 2553    auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);2554    if (!Normalized2)2555      return false;2556 2557    SubsumptionChecker SC(*this);2558 2559    bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);2560    bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);2561 2562    SubsumptionChecker SC2(*this, IdenticalExprEvaluator);2563    bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);2564    bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);2565 2566    if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&2567        Is2AtLeastAs1 == Is2AtLeastAs1Normally)2568      // Same result - no ambiguity was caused by identical atomic expressions.2569      return false;2570  }2571  // A different result! Some ambiguous atomic constraint(s) caused a difference2572  assert(AmbiguousAtomic1 && AmbiguousAtomic2);2573 2574  Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)2575      << AmbiguousAtomic1->getSourceRange();2576  Diag(AmbiguousAtomic2->getBeginLoc(),2577       diag::note_ambiguous_atomic_constraints_similar_expression)2578      << AmbiguousAtomic2->getSourceRange();2579  return true;2580}2581 2582//2583//2584// ------------------------ Subsumption -----------------------------------2585//2586//2587SubsumptionChecker::SubsumptionChecker(Sema &SemaRef,2588                                       SubsumptionCallable Callable)2589    : SemaRef(SemaRef), Callable(Callable), NextID(1) {}2590 2591uint16_t SubsumptionChecker::getNewLiteralId() {2592  assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&2593         "too many constraints!");2594  return NextID++;2595}2596 2597auto SubsumptionChecker::find(const AtomicConstraint *Ori) -> Literal {2598  auto &Elems = AtomicMap[Ori->getConstraintExpr()];2599  // C++ [temp.constr.order] p22600  //   - an atomic constraint A subsumes another atomic constraint B2601  //     if and only if the A and B are identical [...]2602  //2603  // C++ [temp.constr.atomic] p22604  //   Two atomic constraints are identical if they are formed from the2605  //   same expression and the targets of the parameter mappings are2606  //   equivalent according to the rules for expressions [...]2607 2608  // Because subsumption of atomic constraints is an identity2609  // relationship that does not require further analysis2610  // We cache the results such that if an atomic constraint literal2611  // subsumes another, their literal will be the same2612 2613  llvm::FoldingSetNodeID ID;2614  ID.AddBoolean(Ori->hasParameterMapping());2615  if (Ori->hasParameterMapping()) {2616    const auto &Mapping = Ori->getParameterMapping();2617    const NormalizedConstraint::OccurenceList &Indexes =2618        Ori->mappingOccurenceListForSubsumption();2619    for (auto [Idx, TAL] : llvm::enumerate(Mapping)) {2620      if (Indexes[Idx])2621        SemaRef.getASTContext()2622            .getCanonicalTemplateArgument(TAL.getArgument())2623            .Profile(ID, SemaRef.getASTContext());2624    }2625  }2626  auto It = Elems.find(ID);2627  if (It == Elems.end()) {2628    It = Elems2629             .insert({ID,2630                      MappedAtomicConstraint{2631                          Ori, {getNewLiteralId(), Literal::Atomic}}})2632             .first;2633    ReverseMap[It->second.ID.Value] = Ori;2634  }2635  return It->getSecond().ID;2636}2637 2638auto SubsumptionChecker::find(const FoldExpandedConstraint *Ori) -> Literal {2639  auto &Elems = FoldMap[Ori->getPattern()];2640 2641  FoldExpendedConstraintKey K;2642  K.Kind = Ori->getFoldOperator();2643 2644  auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {2645    return K.Kind == Other.Kind;2646  });2647  if (It == Elems.end()) {2648    K.ID = {getNewLiteralId(), Literal::FoldExpanded};2649    It = Elems.insert(Elems.end(), std::move(K));2650    ReverseMap[It->ID.Value] = Ori;2651  }2652  return It->ID;2653}2654 2655auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {2656  return SubsumptionChecker::Normalize<CNFFormula>(C);2657}2658auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {2659  return SubsumptionChecker::Normalize<DNFFormula>(C);2660}2661 2662///2663/// \brief SubsumptionChecker::Normalize2664///2665/// Normalize a formula to Conjunctive Normal Form or2666/// Disjunctive normal form.2667///2668/// Each Atomic (and Fold Expanded) constraint gets represented by2669/// a single id to reduce space.2670///2671/// To minimize risks of exponential blow up, if two atomic2672/// constraints subsumes each other (same constraint and mapping),2673/// they are represented by the same literal.2674///2675template <typename FormulaType>2676FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {2677  FormulaType Res;2678 2679  auto Add = [&, this](Clause C) {2680    // Sort each clause and remove duplicates for faster comparisons.2681    llvm::sort(C);2682    C.erase(llvm::unique(C), C.end());2683    AddUniqueClauseToFormula(Res, std::move(C));2684  };2685 2686  switch (NC.getKind()) {2687  case NormalizedConstraint::ConstraintKind::Atomic:2688    return {{find(&static_cast<const AtomicConstraint &>(NC))}};2689 2690  case NormalizedConstraint::ConstraintKind::FoldExpanded:2691    return {{find(&static_cast<const FoldExpandedConstraint &>(NC))}};2692 2693  case NormalizedConstraint::ConstraintKind::ConceptId:2694    return Normalize<FormulaType>(2695        static_cast<const ConceptIdConstraint &>(NC).getNormalizedConstraint());2696 2697  case NormalizedConstraint::ConstraintKind::Compound: {2698    const auto &Compound = static_cast<const CompoundConstraint &>(NC);2699    FormulaType Left, Right;2700    SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {2701      Left = Normalize<FormulaType>(Compound.getLHS());2702      Right = Normalize<FormulaType>(Compound.getRHS());2703    });2704 2705    if (Compound.getCompoundKind() == FormulaType::Kind) {2706      unsigned SizeLeft = Left.size();2707      Res = std::move(Left);2708      Res.reserve(SizeLeft + Right.size());2709      std::for_each(std::make_move_iterator(Right.begin()),2710                    std::make_move_iterator(Right.end()), Add);2711      return Res;2712    }2713 2714    Res.reserve(Left.size() * Right.size());2715    for (const auto &LTransform : Left) {2716      for (const auto &RTransform : Right) {2717        Clause Combined;2718        Combined.reserve(LTransform.size() + RTransform.size());2719        llvm::copy(LTransform, std::back_inserter(Combined));2720        llvm::copy(RTransform, std::back_inserter(Combined));2721        Add(std::move(Combined));2722      }2723    }2724    return Res;2725  }2726  }2727  llvm_unreachable("Unknown ConstraintKind enum");2728}2729 2730void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {2731  for (auto &Other : F) {2732    if (llvm::equal(C, Other))2733      return;2734  }2735  F.push_back(C);2736}2737 2738std::optional<bool> SubsumptionChecker::Subsumes(2739    const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,2740    ArrayRef<AssociatedConstraint> Q) {2741  const NormalizedConstraint *PNormalized =2742      SemaRef.getNormalizedAssociatedConstraints(DP, P);2743  if (!PNormalized)2744    return std::nullopt;2745 2746  const NormalizedConstraint *QNormalized =2747      SemaRef.getNormalizedAssociatedConstraints(DQ, Q);2748  if (!QNormalized)2749    return std::nullopt;2750 2751  return Subsumes(PNormalized, QNormalized);2752}2753 2754bool SubsumptionChecker::Subsumes(const NormalizedConstraint *P,2755                                  const NormalizedConstraint *Q) {2756 2757  DNFFormula DNFP = DNF(*P);2758  CNFFormula CNFQ = CNF(*Q);2759  return Subsumes(DNFP, CNFQ);2760}2761 2762bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,2763                                  const CNFFormula &QCNF) {2764  for (const auto &Pi : PDNF) {2765    for (const auto &Qj : QCNF) {2766      // C++ [temp.constr.order] p22767      //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if2768      //     and only if there exists an atomic constraint Pia in Pi for which2769      //     there exists an atomic constraint, Qjb, in Qj such that Pia2770      //     subsumes Qjb.2771      if (!DNFSubsumes(Pi, Qj))2772        return false;2773    }2774  }2775  return true;2776}2777 2778bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {2779 2780  return llvm::any_of(P, [&](Literal LP) {2781    return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });2782  });2783}2784 2785bool SubsumptionChecker::Subsumes(const FoldExpandedConstraint *A,2786                                  const FoldExpandedConstraint *B) {2787  std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{2788      A, B};2789 2790  auto It = FoldSubsumptionCache.find(Key);2791  if (It == FoldSubsumptionCache.end()) {2792    // C++ [temp.constr.order]2793    // a fold expanded constraint A subsumes another fold expanded2794    // constraint B if they are compatible for subsumption, have the same2795    // fold-operator, and the constraint of A subsumes that of B.2796    bool DoesSubsume =2797        A->getFoldOperator() == B->getFoldOperator() &&2798        FoldExpandedConstraint::AreCompatibleForSubsumption(*A, *B) &&2799        Subsumes(&A->getNormalizedPattern(), &B->getNormalizedPattern());2800    It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;2801  }2802  return It->second;2803}2804 2805bool SubsumptionChecker::Subsumes(Literal A, Literal B) {2806  if (A.Kind != B.Kind)2807    return false;2808  switch (A.Kind) {2809  case Literal::Atomic:2810    if (!Callable)2811      return A.Value == B.Value;2812    return Callable(2813        *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),2814        *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));2815  case Literal::FoldExpanded:2816    return Subsumes(2817        static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),2818        static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));2819  }2820  llvm_unreachable("unknown literal kind");2821}2822