xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision 415efcecd8b80f68e76376ef2b854cb6f5c84b5a)
1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2a7dea167SDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric //
9a7dea167SDimitry Andric //  This file implements semantic analysis for C++ constraints and concepts.
10a7dea167SDimitry Andric //
11a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
12a7dea167SDimitry Andric 
13480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h"
1406c3fb27SDimitry Andric #include "TreeTransform.h"
15bdd1243dSDimitry Andric #include "clang/AST/ASTLambda.h"
16feb5b0c7SDimitry Andric #include "clang/AST/DeclCXX.h"
1755e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h"
18480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
19480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h"
2006c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h"
2106c3fb27SDimitry Andric #include "clang/Sema/Initialization.h"
2206c3fb27SDimitry Andric #include "clang/Sema/Overload.h"
23feb5b0c7SDimitry Andric #include "clang/Sema/ScopeInfo.h"
2406c3fb27SDimitry Andric #include "clang/Sema/Sema.h"
2506c3fb27SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
2606c3fb27SDimitry Andric #include "clang/Sema/SemaInternal.h"
2706c3fb27SDimitry Andric #include "clang/Sema/Template.h"
2806c3fb27SDimitry Andric #include "clang/Sema/TemplateDeduction.h"
29480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h"
30480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h"
31fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
32bdd1243dSDimitry Andric #include <optional>
33fe6060f1SDimitry Andric 
34a7dea167SDimitry Andric using namespace clang;
35a7dea167SDimitry Andric using namespace sema;
36a7dea167SDimitry Andric 
375ffd83dbSDimitry Andric namespace {
385ffd83dbSDimitry Andric class LogicalBinOp {
39bdd1243dSDimitry Andric   SourceLocation Loc;
405ffd83dbSDimitry Andric   OverloadedOperatorKind Op = OO_None;
415ffd83dbSDimitry Andric   const Expr *LHS = nullptr;
425ffd83dbSDimitry Andric   const Expr *RHS = nullptr;
435ffd83dbSDimitry Andric 
445ffd83dbSDimitry Andric public:
LogicalBinOp(const Expr * E)455ffd83dbSDimitry Andric   LogicalBinOp(const Expr *E) {
465ffd83dbSDimitry Andric     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
475ffd83dbSDimitry Andric       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
485ffd83dbSDimitry Andric       LHS = BO->getLHS();
495ffd83dbSDimitry Andric       RHS = BO->getRHS();
50bdd1243dSDimitry Andric       Loc = BO->getExprLoc();
515ffd83dbSDimitry Andric     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
52fe6060f1SDimitry Andric       // If OO is not || or && it might not have exactly 2 arguments.
53fe6060f1SDimitry Andric       if (OO->getNumArgs() == 2) {
545ffd83dbSDimitry Andric         Op = OO->getOperator();
555ffd83dbSDimitry Andric         LHS = OO->getArg(0);
565ffd83dbSDimitry Andric         RHS = OO->getArg(1);
57bdd1243dSDimitry Andric         Loc = OO->getOperatorLoc();
585ffd83dbSDimitry Andric       }
595ffd83dbSDimitry Andric     }
60fe6060f1SDimitry Andric   }
615ffd83dbSDimitry Andric 
isAnd() const625ffd83dbSDimitry Andric   bool isAnd() const { return Op == OO_AmpAmp; }
isOr() const635ffd83dbSDimitry Andric   bool isOr() const { return Op == OO_PipePipe; }
operator bool() const645ffd83dbSDimitry Andric   explicit operator bool() const { return isAnd() || isOr(); }
655ffd83dbSDimitry Andric 
getLHS() const665ffd83dbSDimitry Andric   const Expr *getLHS() const { return LHS; }
getRHS() const675ffd83dbSDimitry Andric   const Expr *getRHS() const { return RHS; }
getOp() const680fca6ea1SDimitry Andric   OverloadedOperatorKind getOp() const { return Op; }
69bdd1243dSDimitry Andric 
recreateBinOp(Sema & SemaRef,ExprResult LHS) const70bdd1243dSDimitry Andric   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
71bdd1243dSDimitry Andric     return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
72bdd1243dSDimitry Andric   }
73bdd1243dSDimitry Andric 
recreateBinOp(Sema & SemaRef,ExprResult LHS,ExprResult RHS) const74bdd1243dSDimitry Andric   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
75bdd1243dSDimitry Andric                            ExprResult RHS) const {
76bdd1243dSDimitry Andric     assert((isAnd() || isOr()) && "Not the right kind of op?");
77bdd1243dSDimitry Andric     assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
78bdd1243dSDimitry Andric 
79bdd1243dSDimitry Andric     if (!LHS.isUsable() || !RHS.isUsable())
80bdd1243dSDimitry Andric       return ExprEmpty();
81bdd1243dSDimitry Andric 
82bdd1243dSDimitry Andric     // We should just be able to 'normalize' these to the builtin Binary
83bdd1243dSDimitry Andric     // Operator, since that is how they are evaluated in constriant checks.
84bdd1243dSDimitry Andric     return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
85bdd1243dSDimitry Andric                                   BinaryOperator::getOverloadedOpcode(Op),
86bdd1243dSDimitry Andric                                   SemaRef.Context.BoolTy, VK_PRValue,
87bdd1243dSDimitry Andric                                   OK_Ordinary, Loc, FPOptionsOverride{});
88bdd1243dSDimitry Andric   }
895ffd83dbSDimitry Andric };
905ffd83dbSDimitry Andric }
915ffd83dbSDimitry Andric 
CheckConstraintExpression(const Expr * ConstraintExpression,Token NextToken,bool * PossibleNonPrimary,bool IsTrailingRequiresClause)925ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
935ffd83dbSDimitry Andric                                      Token NextToken, bool *PossibleNonPrimary,
94480093f4SDimitry Andric                                      bool IsTrailingRequiresClause) {
95a7dea167SDimitry Andric   // C++2a [temp.constr.atomic]p1
96a7dea167SDimitry Andric   // ..E shall be a constant expression of type bool.
97a7dea167SDimitry Andric 
98a7dea167SDimitry Andric   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
99a7dea167SDimitry Andric 
1005ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpression) {
1015ffd83dbSDimitry Andric     return CheckConstraintExpression(BO.getLHS(), NextToken,
102480093f4SDimitry Andric                                      PossibleNonPrimary) &&
1035ffd83dbSDimitry Andric            CheckConstraintExpression(BO.getRHS(), NextToken,
104480093f4SDimitry Andric                                      PossibleNonPrimary);
105a7dea167SDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
106480093f4SDimitry Andric     return CheckConstraintExpression(C->getSubExpr(), NextToken,
107480093f4SDimitry Andric                                      PossibleNonPrimary);
108a7dea167SDimitry Andric 
109a7dea167SDimitry Andric   QualType Type = ConstraintExpression->getType();
110480093f4SDimitry Andric 
111480093f4SDimitry Andric   auto CheckForNonPrimary = [&] {
11206c3fb27SDimitry Andric     if (!PossibleNonPrimary)
11306c3fb27SDimitry Andric       return;
11406c3fb27SDimitry Andric 
115480093f4SDimitry Andric     *PossibleNonPrimary =
116480093f4SDimitry Andric         // We have the following case:
117480093f4SDimitry Andric         // template<typename> requires func(0) struct S { };
118480093f4SDimitry Andric         // The user probably isn't aware of the parentheses required around
119480093f4SDimitry Andric         // the function call, and we're only going to parse 'func' as the
120480093f4SDimitry Andric         // primary-expression, and complain that it is of non-bool type.
12106c3fb27SDimitry Andric         //
12206c3fb27SDimitry Andric         // However, if we're in a lambda, this might also be:
12306c3fb27SDimitry Andric         // []<typename> requires var () {};
12406c3fb27SDimitry Andric         // Which also looks like a function call due to the lambda parentheses,
12506c3fb27SDimitry Andric         // but unlike the first case, isn't an error, so this check is skipped.
126480093f4SDimitry Andric         (NextToken.is(tok::l_paren) &&
127480093f4SDimitry Andric          (IsTrailingRequiresClause ||
128480093f4SDimitry Andric           (Type->isDependentType() &&
12906c3fb27SDimitry Andric            isa<UnresolvedLookupExpr>(ConstraintExpression) &&
13006c3fb27SDimitry Andric            !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
131480093f4SDimitry Andric           Type->isFunctionType() ||
132480093f4SDimitry Andric           Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
133480093f4SDimitry Andric         // We have the following case:
134480093f4SDimitry Andric         // template<typename T> requires size_<T> == 0 struct S { };
135480093f4SDimitry Andric         // The user probably isn't aware of the parentheses required around
136480093f4SDimitry Andric         // the binary operator, and we're only going to parse 'func' as the
137480093f4SDimitry Andric         // first operand, and complain that it is of non-bool type.
138480093f4SDimitry Andric         getBinOpPrecedence(NextToken.getKind(),
139480093f4SDimitry Andric                            /*GreaterThanIsOperator=*/true,
140480093f4SDimitry Andric                            getLangOpts().CPlusPlus11) > prec::LogicalAnd;
141480093f4SDimitry Andric   };
142480093f4SDimitry Andric 
143480093f4SDimitry Andric   // An atomic constraint!
144480093f4SDimitry Andric   if (ConstraintExpression->isTypeDependent()) {
145480093f4SDimitry Andric     CheckForNonPrimary();
146480093f4SDimitry Andric     return true;
147480093f4SDimitry Andric   }
148480093f4SDimitry Andric 
149a7dea167SDimitry Andric   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
150a7dea167SDimitry Andric     Diag(ConstraintExpression->getExprLoc(),
151a7dea167SDimitry Andric          diag::err_non_bool_atomic_constraint) << Type
152a7dea167SDimitry Andric         << ConstraintExpression->getSourceRange();
153480093f4SDimitry Andric     CheckForNonPrimary();
154a7dea167SDimitry Andric     return false;
155a7dea167SDimitry Andric   }
156480093f4SDimitry Andric 
157480093f4SDimitry Andric   if (PossibleNonPrimary)
158480093f4SDimitry Andric       *PossibleNonPrimary = false;
159a7dea167SDimitry Andric   return true;
160a7dea167SDimitry Andric }
161a7dea167SDimitry Andric 
162bdd1243dSDimitry Andric namespace {
163bdd1243dSDimitry Andric struct SatisfactionStackRAII {
164bdd1243dSDimitry Andric   Sema &SemaRef;
1651ac55f4cSDimitry Andric   bool Inserted = false;
SatisfactionStackRAII__anon0c0fec810311::SatisfactionStackRAII1661ac55f4cSDimitry Andric   SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
16706c3fb27SDimitry Andric                         const llvm::FoldingSetNodeID &FSNID)
168bdd1243dSDimitry Andric       : SemaRef(SemaRef) {
1691ac55f4cSDimitry Andric       if (ND) {
1701ac55f4cSDimitry Andric       SemaRef.PushSatisfactionStackEntry(ND, FSNID);
1711ac55f4cSDimitry Andric       Inserted = true;
172bdd1243dSDimitry Andric       }
1731ac55f4cSDimitry Andric   }
~SatisfactionStackRAII__anon0c0fec810311::SatisfactionStackRAII1741ac55f4cSDimitry Andric   ~SatisfactionStackRAII() {
1751ac55f4cSDimitry Andric         if (Inserted)
1761ac55f4cSDimitry Andric           SemaRef.PopSatisfactionStackEntry();
1771ac55f4cSDimitry Andric   }
178bdd1243dSDimitry Andric };
179bdd1243dSDimitry Andric } // namespace
180bdd1243dSDimitry Andric 
1810fca6ea1SDimitry Andric template <typename ConstraintEvaluator>
182bdd1243dSDimitry Andric static ExprResult
183480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
184480093f4SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
1850fca6ea1SDimitry Andric                                 const ConstraintEvaluator &Evaluator);
186a7dea167SDimitry Andric 
1870fca6ea1SDimitry Andric template <typename ConstraintEvaluator>
1880fca6ea1SDimitry Andric static ExprResult
calculateConstraintSatisfaction(Sema & S,const Expr * LHS,OverloadedOperatorKind Op,const Expr * RHS,ConstraintSatisfaction & Satisfaction,const ConstraintEvaluator & Evaluator)1890fca6ea1SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *LHS,
1900fca6ea1SDimitry Andric                                 OverloadedOperatorKind Op, const Expr *RHS,
1910fca6ea1SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
1920fca6ea1SDimitry Andric                                 const ConstraintEvaluator &Evaluator) {
1935f757f3fSDimitry Andric   size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
1940fca6ea1SDimitry Andric 
1950fca6ea1SDimitry Andric   ExprResult LHSRes =
1960fca6ea1SDimitry Andric       calculateConstraintSatisfaction(S, LHS, Satisfaction, Evaluator);
197bdd1243dSDimitry Andric 
198bdd1243dSDimitry Andric   if (LHSRes.isInvalid())
199bdd1243dSDimitry Andric     return ExprError();
200480093f4SDimitry Andric 
201480093f4SDimitry Andric   bool IsLHSSatisfied = Satisfaction.IsSatisfied;
202480093f4SDimitry Andric 
2030fca6ea1SDimitry Andric   if (Op == clang::OO_PipePipe && IsLHSSatisfied)
204480093f4SDimitry Andric     // [temp.constr.op] p3
205480093f4SDimitry Andric     //    A disjunction is a constraint taking two operands. To determine if
206480093f4SDimitry Andric     //    a disjunction is satisfied, the satisfaction of the first operand
207480093f4SDimitry Andric     //    is checked. If that is satisfied, the disjunction is satisfied.
208480093f4SDimitry Andric     //    Otherwise, the disjunction is satisfied if and only if the second
209480093f4SDimitry Andric     //    operand is satisfied.
210bdd1243dSDimitry Andric     // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
211bdd1243dSDimitry Andric     return LHSRes;
212480093f4SDimitry Andric 
2130fca6ea1SDimitry Andric   if (Op == clang::OO_AmpAmp && !IsLHSSatisfied)
214480093f4SDimitry Andric     // [temp.constr.op] p2
215480093f4SDimitry Andric     //    A conjunction is a constraint taking two operands. To determine if
216480093f4SDimitry Andric     //    a conjunction is satisfied, the satisfaction of the first operand
217480093f4SDimitry Andric     //    is checked. If that is not satisfied, the conjunction is not
218480093f4SDimitry Andric     //    satisfied. Otherwise, the conjunction is satisfied if and only if
219480093f4SDimitry Andric     //    the second operand is satisfied.
220bdd1243dSDimitry Andric     // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
221bdd1243dSDimitry Andric     return LHSRes;
222480093f4SDimitry Andric 
2230fca6ea1SDimitry Andric   ExprResult RHSRes =
2240fca6ea1SDimitry Andric       calculateConstraintSatisfaction(S, RHS, Satisfaction, Evaluator);
225bdd1243dSDimitry Andric   if (RHSRes.isInvalid())
226bdd1243dSDimitry Andric     return ExprError();
227bdd1243dSDimitry Andric 
2285f757f3fSDimitry Andric   bool IsRHSSatisfied = Satisfaction.IsSatisfied;
2295f757f3fSDimitry Andric   // Current implementation adds diagnostic information about the falsity
2305f757f3fSDimitry Andric   // of each false atomic constraint expression when it evaluates them.
2315f757f3fSDimitry Andric   // When the evaluation results to `false || true`, the information
2325f757f3fSDimitry Andric   // generated during the evaluation of left-hand side is meaningless
2335f757f3fSDimitry Andric   // because the whole expression evaluates to true.
2345f757f3fSDimitry Andric   // The following code removes the irrelevant diagnostic information.
2355f757f3fSDimitry Andric   // FIXME: We should probably delay the addition of diagnostic information
2365f757f3fSDimitry Andric   // until we know the entire expression is false.
2370fca6ea1SDimitry Andric   if (Op == clang::OO_PipePipe && IsRHSSatisfied) {
2380fca6ea1SDimitry Andric     auto EffectiveDetailEnd = Satisfaction.Details.begin();
2390fca6ea1SDimitry Andric     std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
2400fca6ea1SDimitry Andric     Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end());
2410fca6ea1SDimitry Andric   }
2420fca6ea1SDimitry Andric 
2430fca6ea1SDimitry Andric   if (!LHSRes.isUsable() || !RHSRes.isUsable())
2440fca6ea1SDimitry Andric     return ExprEmpty();
2450fca6ea1SDimitry Andric 
2460fca6ea1SDimitry Andric   return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(),
2470fca6ea1SDimitry Andric                                 BinaryOperator::getOverloadedOpcode(Op),
2480fca6ea1SDimitry Andric                                 S.Context.BoolTy, VK_PRValue, OK_Ordinary,
2490fca6ea1SDimitry Andric                                 LHS->getBeginLoc(), FPOptionsOverride{});
2500fca6ea1SDimitry Andric }
2510fca6ea1SDimitry Andric 
2520fca6ea1SDimitry Andric template <typename ConstraintEvaluator>
2530fca6ea1SDimitry Andric static ExprResult
calculateConstraintSatisfaction(Sema & S,const CXXFoldExpr * FE,ConstraintSatisfaction & Satisfaction,const ConstraintEvaluator & Evaluator)2540fca6ea1SDimitry Andric calculateConstraintSatisfaction(Sema &S, const CXXFoldExpr *FE,
2550fca6ea1SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
2560fca6ea1SDimitry Andric                                 const ConstraintEvaluator &Evaluator) {
2570fca6ea1SDimitry Andric   bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd;
2580fca6ea1SDimitry Andric   size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
2590fca6ea1SDimitry Andric 
2600fca6ea1SDimitry Andric   ExprResult Out;
2610fca6ea1SDimitry Andric   if (FE->isLeftFold() && FE->getInit()) {
2620fca6ea1SDimitry Andric     Out = calculateConstraintSatisfaction(S, FE->getInit(), Satisfaction,
2630fca6ea1SDimitry Andric                                           Evaluator);
2640fca6ea1SDimitry Andric     if (Out.isInvalid())
2650fca6ea1SDimitry Andric       return ExprError();
2660fca6ea1SDimitry Andric 
2670fca6ea1SDimitry Andric     // If the first clause of a conjunction is not satisfied,
2680fca6ea1SDimitry Andric     // or if the first clause of a disjection is satisfied,
2690fca6ea1SDimitry Andric     // we have established satisfaction of the whole constraint
2700fca6ea1SDimitry Andric     // and we should not continue further.
2710fca6ea1SDimitry Andric     if (Conjunction != Satisfaction.IsSatisfied)
2720fca6ea1SDimitry Andric       return Out;
2730fca6ea1SDimitry Andric   }
2740fca6ea1SDimitry Andric   std::optional<unsigned> NumExpansions =
2750fca6ea1SDimitry Andric       Evaluator.EvaluateFoldExpandedConstraintSize(FE);
2760fca6ea1SDimitry Andric   if (!NumExpansions)
2770fca6ea1SDimitry Andric     return ExprError();
2780fca6ea1SDimitry Andric   for (unsigned I = 0; I < *NumExpansions; I++) {
2790fca6ea1SDimitry Andric     Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I);
2800fca6ea1SDimitry Andric     ExprResult Res = calculateConstraintSatisfaction(S, FE->getPattern(),
2810fca6ea1SDimitry Andric                                                      Satisfaction, Evaluator);
2820fca6ea1SDimitry Andric     if (Res.isInvalid())
2830fca6ea1SDimitry Andric       return ExprError();
2840fca6ea1SDimitry Andric     bool IsRHSSatisfied = Satisfaction.IsSatisfied;
2850fca6ea1SDimitry Andric     if (!Conjunction && IsRHSSatisfied) {
2865f757f3fSDimitry Andric       auto EffectiveDetailEnd = Satisfaction.Details.begin();
2875f757f3fSDimitry Andric       std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
2885f757f3fSDimitry Andric       Satisfaction.Details.erase(EffectiveDetailEnd,
2895f757f3fSDimitry Andric                                  Satisfaction.Details.end());
2905f757f3fSDimitry Andric     }
2910fca6ea1SDimitry Andric     if (Out.isUnset())
2920fca6ea1SDimitry Andric       Out = Res;
2930fca6ea1SDimitry Andric     else if (!Res.isUnset()) {
2940fca6ea1SDimitry Andric       Out = BinaryOperator::Create(
2950fca6ea1SDimitry Andric           S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
2960fca6ea1SDimitry Andric           VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});
297bdd1243dSDimitry Andric     }
2980fca6ea1SDimitry Andric     if (Conjunction != IsRHSSatisfied)
2990fca6ea1SDimitry Andric       return Out;
3000fca6ea1SDimitry Andric   }
3010fca6ea1SDimitry Andric 
3020fca6ea1SDimitry Andric   if (FE->isRightFold() && FE->getInit()) {
3030fca6ea1SDimitry Andric     ExprResult Res = calculateConstraintSatisfaction(S, FE->getInit(),
3040fca6ea1SDimitry Andric                                                      Satisfaction, Evaluator);
3050fca6ea1SDimitry Andric     if (Out.isInvalid())
3060fca6ea1SDimitry Andric       return ExprError();
3070fca6ea1SDimitry Andric 
3080fca6ea1SDimitry Andric     if (Out.isUnset())
3090fca6ea1SDimitry Andric       Out = Res;
3100fca6ea1SDimitry Andric     else if (!Res.isUnset()) {
3110fca6ea1SDimitry Andric       Out = BinaryOperator::Create(
3120fca6ea1SDimitry Andric           S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
3130fca6ea1SDimitry Andric           VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});
3140fca6ea1SDimitry Andric     }
3150fca6ea1SDimitry Andric   }
3160fca6ea1SDimitry Andric 
3170fca6ea1SDimitry Andric   if (Out.isUnset()) {
3180fca6ea1SDimitry Andric     Satisfaction.IsSatisfied = Conjunction;
3190fca6ea1SDimitry Andric     Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator());
3200fca6ea1SDimitry Andric   }
3210fca6ea1SDimitry Andric   return Out;
3220fca6ea1SDimitry Andric }
3230fca6ea1SDimitry Andric 
3240fca6ea1SDimitry Andric template <typename ConstraintEvaluator>
3250fca6ea1SDimitry Andric static ExprResult
calculateConstraintSatisfaction(Sema & S,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction,const ConstraintEvaluator & Evaluator)3260fca6ea1SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
3270fca6ea1SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
3280fca6ea1SDimitry Andric                                 const ConstraintEvaluator &Evaluator) {
3290fca6ea1SDimitry Andric   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
3300fca6ea1SDimitry Andric 
3310fca6ea1SDimitry Andric   if (LogicalBinOp BO = ConstraintExpr)
3320fca6ea1SDimitry Andric     return calculateConstraintSatisfaction(
3330fca6ea1SDimitry Andric         S, BO.getLHS(), BO.getOp(), BO.getRHS(), Satisfaction, Evaluator);
334bdd1243dSDimitry Andric 
335bdd1243dSDimitry Andric   if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
336bdd1243dSDimitry Andric     // These aren't evaluated, so we don't care about cleanups, so we can just
337bdd1243dSDimitry Andric     // evaluate these as if the cleanups didn't exist.
3380fca6ea1SDimitry Andric     return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
3390fca6ea1SDimitry Andric                                            Evaluator);
3400fca6ea1SDimitry Andric   }
3410fca6ea1SDimitry Andric 
3420fca6ea1SDimitry Andric   if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr);
3430fca6ea1SDimitry Andric       FE && S.getLangOpts().CPlusPlus26 &&
3440fca6ea1SDimitry Andric       (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
3450fca6ea1SDimitry Andric        FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
3460fca6ea1SDimitry Andric     return calculateConstraintSatisfaction(S, FE, Satisfaction, Evaluator);
3475ffd83dbSDimitry Andric   }
348480093f4SDimitry Andric 
349480093f4SDimitry Andric   // An atomic constraint expression
3500fca6ea1SDimitry Andric   ExprResult SubstitutedAtomicExpr =
3510fca6ea1SDimitry Andric       Evaluator.EvaluateAtomicConstraint(ConstraintExpr);
352480093f4SDimitry Andric 
353480093f4SDimitry Andric   if (SubstitutedAtomicExpr.isInvalid())
354bdd1243dSDimitry Andric     return ExprError();
355480093f4SDimitry Andric 
356480093f4SDimitry Andric   if (!SubstitutedAtomicExpr.isUsable())
357480093f4SDimitry Andric     // Evaluator has decided satisfaction without yielding an expression.
358bdd1243dSDimitry Andric     return ExprEmpty();
359bdd1243dSDimitry Andric 
360bdd1243dSDimitry Andric   // We don't have the ability to evaluate this, since it contains a
361bdd1243dSDimitry Andric   // RecoveryExpr, so we want to fail overload resolution.  Otherwise,
362bdd1243dSDimitry Andric   // we'd potentially pick up a different overload, and cause confusing
363bdd1243dSDimitry Andric   // diagnostics. SO, add a failure detail that will cause us to make this
364bdd1243dSDimitry Andric   // overload set not viable.
365bdd1243dSDimitry Andric   if (SubstitutedAtomicExpr.get()->containsErrors()) {
366bdd1243dSDimitry Andric     Satisfaction.IsSatisfied = false;
367bdd1243dSDimitry Andric     Satisfaction.ContainsErrors = true;
368bdd1243dSDimitry Andric 
369bdd1243dSDimitry Andric     PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
370bdd1243dSDimitry Andric     SmallString<128> DiagString;
371bdd1243dSDimitry Andric     DiagString = ": ";
372bdd1243dSDimitry Andric     Msg.EmitToString(S.getDiagnostics(), DiagString);
373bdd1243dSDimitry Andric     unsigned MessageSize = DiagString.size();
374bdd1243dSDimitry Andric     char *Mem = new (S.Context) char[MessageSize];
375bdd1243dSDimitry Andric     memcpy(Mem, DiagString.c_str(), MessageSize);
376bdd1243dSDimitry Andric     Satisfaction.Details.emplace_back(
377bdd1243dSDimitry Andric         new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
378bdd1243dSDimitry Andric             SubstitutedAtomicExpr.get()->getBeginLoc(),
379bdd1243dSDimitry Andric             StringRef(Mem, MessageSize)});
380bdd1243dSDimitry Andric     return SubstitutedAtomicExpr;
381bdd1243dSDimitry Andric   }
382a7dea167SDimitry Andric 
383a7dea167SDimitry Andric   EnterExpressionEvaluationContext ConstantEvaluated(
384480093f4SDimitry Andric       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
385a7dea167SDimitry Andric   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
386a7dea167SDimitry Andric   Expr::EvalResult EvalResult;
387a7dea167SDimitry Andric   EvalResult.Diag = &EvaluationDiags;
388fe6060f1SDimitry Andric   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
389fe6060f1SDimitry Andric                                                            S.Context) ||
390fe6060f1SDimitry Andric       !EvaluationDiags.empty()) {
391a7dea167SDimitry Andric     // C++2a [temp.constr.atomic]p1
392a7dea167SDimitry Andric     //   ...E shall be a constant expression of type bool.
393480093f4SDimitry Andric     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
394a7dea167SDimitry Andric            diag::err_non_constant_constraint_expression)
395480093f4SDimitry Andric         << SubstitutedAtomicExpr.get()->getSourceRange();
396a7dea167SDimitry Andric     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
397480093f4SDimitry Andric       S.Diag(PDiag.first, PDiag.second);
398bdd1243dSDimitry Andric     return ExprError();
399a7dea167SDimitry Andric   }
400a7dea167SDimitry Andric 
401fe6060f1SDimitry Andric   assert(EvalResult.Val.isInt() &&
402fe6060f1SDimitry Andric          "evaluating bool expression didn't produce int");
403480093f4SDimitry Andric   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
404480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied)
4050fca6ea1SDimitry Andric     Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
406a7dea167SDimitry Andric 
407bdd1243dSDimitry Andric   return SubstitutedAtomicExpr;
408bdd1243dSDimitry Andric }
409bdd1243dSDimitry Andric 
410bdd1243dSDimitry Andric static bool
DiagRecursiveConstraintEval(Sema & S,llvm::FoldingSetNodeID & ID,const NamedDecl * Templ,const Expr * E,const MultiLevelTemplateArgumentList & MLTAL)4111ac55f4cSDimitry Andric DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
4121ac55f4cSDimitry Andric                             const NamedDecl *Templ, const Expr *E,
413bdd1243dSDimitry Andric                             const MultiLevelTemplateArgumentList &MLTAL) {
414bdd1243dSDimitry Andric   E->Profile(ID, S.Context, /*Canonical=*/true);
415bdd1243dSDimitry Andric   for (const auto &List : MLTAL)
416bdd1243dSDimitry Andric     for (const auto &TemplateArg : List.Args)
417bdd1243dSDimitry Andric       TemplateArg.Profile(ID, S.Context);
418bdd1243dSDimitry Andric 
419bdd1243dSDimitry Andric   // Note that we have to do this with our own collection, because there are
420bdd1243dSDimitry Andric   // times where a constraint-expression check can cause us to need to evaluate
421bdd1243dSDimitry Andric   // other constriants that are unrelated, such as when evaluating a recovery
422bdd1243dSDimitry Andric   // expression, or when trying to determine the constexpr-ness of special
423bdd1243dSDimitry Andric   // members. Otherwise we could just use the
424bdd1243dSDimitry Andric   // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
4251ac55f4cSDimitry Andric   if (S.SatisfactionStackContains(Templ, ID)) {
426bdd1243dSDimitry Andric     S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
427bdd1243dSDimitry Andric         << const_cast<Expr *>(E) << E->getSourceRange();
428bdd1243dSDimitry Andric     return true;
429bdd1243dSDimitry Andric   }
430bdd1243dSDimitry Andric 
431a7dea167SDimitry Andric   return false;
432a7dea167SDimitry Andric }
433480093f4SDimitry Andric 
calculateConstraintSatisfaction(Sema & S,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)434bdd1243dSDimitry Andric static ExprResult calculateConstraintSatisfaction(
435bdd1243dSDimitry Andric     Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
436bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
437bdd1243dSDimitry Andric     ConstraintSatisfaction &Satisfaction) {
4380fca6ea1SDimitry Andric 
4390fca6ea1SDimitry Andric   struct ConstraintEvaluator {
4400fca6ea1SDimitry Andric     Sema &S;
4410fca6ea1SDimitry Andric     const NamedDecl *Template;
4420fca6ea1SDimitry Andric     SourceLocation TemplateNameLoc;
4430fca6ea1SDimitry Andric     const MultiLevelTemplateArgumentList &MLTAL;
4440fca6ea1SDimitry Andric     ConstraintSatisfaction &Satisfaction;
4450fca6ea1SDimitry Andric 
4460fca6ea1SDimitry Andric     ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const {
447480093f4SDimitry Andric       EnterExpressionEvaluationContext ConstantEvaluated(
448bdd1243dSDimitry Andric           S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
449bdd1243dSDimitry Andric           Sema::ReuseLambdaContextDecl);
450480093f4SDimitry Andric 
451480093f4SDimitry Andric       // Atomic constraint - substitute arguments and check satisfaction.
452480093f4SDimitry Andric       ExprResult SubstitutedExpression;
453480093f4SDimitry Andric       {
454480093f4SDimitry Andric         TemplateDeductionInfo Info(TemplateNameLoc);
4550fca6ea1SDimitry Andric         Sema::InstantiatingTemplate Inst(
4560fca6ea1SDimitry Andric             S, AtomicExpr->getBeginLoc(),
45713138422SDimitry Andric             Sema::InstantiatingTemplate::ConstraintSubstitution{},
45813138422SDimitry Andric             const_cast<NamedDecl *>(Template), Info,
45913138422SDimitry Andric             AtomicExpr->getSourceRange());
460480093f4SDimitry Andric         if (Inst.isInvalid())
461480093f4SDimitry Andric           return ExprError();
462bdd1243dSDimitry Andric 
463bdd1243dSDimitry Andric         llvm::FoldingSetNodeID ID;
4641ac55f4cSDimitry Andric         if (Template &&
4651ac55f4cSDimitry Andric             DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
466bdd1243dSDimitry Andric           Satisfaction.IsSatisfied = false;
467bdd1243dSDimitry Andric           Satisfaction.ContainsErrors = true;
468bdd1243dSDimitry Andric           return ExprEmpty();
469bdd1243dSDimitry Andric         }
470bdd1243dSDimitry Andric 
4711ac55f4cSDimitry Andric         SatisfactionStackRAII StackRAII(S, Template, ID);
472bdd1243dSDimitry Andric 
473480093f4SDimitry Andric         // We do not want error diagnostics escaping here.
474480093f4SDimitry Andric         Sema::SFINAETrap Trap(S);
475fe6060f1SDimitry Andric         SubstitutedExpression =
476bdd1243dSDimitry Andric             S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
477bdd1243dSDimitry Andric 
478480093f4SDimitry Andric         if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
479480093f4SDimitry Andric           // C++2a [temp.constr.atomic]p1
480480093f4SDimitry Andric           //   ...If substitution results in an invalid type or expression, the
481480093f4SDimitry Andric           //   constraint is not satisfied.
482480093f4SDimitry Andric           if (!Trap.hasErrorOccurred())
483349cc55cSDimitry Andric             // A non-SFINAE error has occurred as a result of this
484480093f4SDimitry Andric             // substitution.
485480093f4SDimitry Andric             return ExprError();
486480093f4SDimitry Andric 
487480093f4SDimitry Andric           PartialDiagnosticAt SubstDiag{SourceLocation(),
488480093f4SDimitry Andric                                         PartialDiagnostic::NullDiagnostic()};
489480093f4SDimitry Andric           Info.takeSFINAEDiagnostic(SubstDiag);
490480093f4SDimitry Andric           // FIXME: Concepts: This is an unfortunate consequence of there
491480093f4SDimitry Andric           //  being no serialization code for PartialDiagnostics and the fact
492480093f4SDimitry Andric           //  that serializing them would likely take a lot more storage than
493480093f4SDimitry Andric           //  just storing them as strings. We would still like, in the
494480093f4SDimitry Andric           //  future, to serialize the proper PartialDiagnostic as serializing
495480093f4SDimitry Andric           //  it as a string defeats the purpose of the diagnostic mechanism.
496480093f4SDimitry Andric           SmallString<128> DiagString;
497480093f4SDimitry Andric           DiagString = ": ";
498480093f4SDimitry Andric           SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
499480093f4SDimitry Andric           unsigned MessageSize = DiagString.size();
500480093f4SDimitry Andric           char *Mem = new (S.Context) char[MessageSize];
501480093f4SDimitry Andric           memcpy(Mem, DiagString.c_str(), MessageSize);
502480093f4SDimitry Andric           Satisfaction.Details.emplace_back(
503480093f4SDimitry Andric               new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
504480093f4SDimitry Andric                   SubstDiag.first, StringRef(Mem, MessageSize)});
505480093f4SDimitry Andric           Satisfaction.IsSatisfied = false;
506480093f4SDimitry Andric           return ExprEmpty();
507480093f4SDimitry Andric         }
508480093f4SDimitry Andric       }
509480093f4SDimitry Andric 
510480093f4SDimitry Andric       if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
511480093f4SDimitry Andric         return ExprError();
512480093f4SDimitry Andric 
513bdd1243dSDimitry Andric       // [temp.constr.atomic]p3: To determine if an atomic constraint is
514bdd1243dSDimitry Andric       // satisfied, the parameter mapping and template arguments are first
515bdd1243dSDimitry Andric       // substituted into its expression.  If substitution results in an
516bdd1243dSDimitry Andric       // invalid type or expression, the constraint is not satisfied.
517bdd1243dSDimitry Andric       // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
518bdd1243dSDimitry Andric       // and E shall be a constant expression of type bool.
519bdd1243dSDimitry Andric       //
520bdd1243dSDimitry Andric       // Perform the L to R Value conversion if necessary. We do so for all
521bdd1243dSDimitry Andric       // non-PRValue categories, else we fail to extend the lifetime of
522bdd1243dSDimitry Andric       // temporaries, and that fails the constant expression check.
523bdd1243dSDimitry Andric       if (!SubstitutedExpression.get()->isPRValue())
524bdd1243dSDimitry Andric         SubstitutedExpression = ImplicitCastExpr::Create(
525bdd1243dSDimitry Andric             S.Context, SubstitutedExpression.get()->getType(),
526bdd1243dSDimitry Andric             CK_LValueToRValue, SubstitutedExpression.get(),
527bdd1243dSDimitry Andric             /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
528bdd1243dSDimitry Andric 
529480093f4SDimitry Andric       return SubstitutedExpression;
5300fca6ea1SDimitry Andric     }
5310fca6ea1SDimitry Andric 
5320fca6ea1SDimitry Andric     std::optional<unsigned>
5330fca6ea1SDimitry Andric     EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {
53462987288SDimitry Andric 
53562987288SDimitry Andric       // We should ignore errors in the presence of packs of different size.
53662987288SDimitry Andric       Sema::SFINAETrap Trap(S);
53762987288SDimitry Andric 
5380fca6ea1SDimitry Andric       Expr *Pattern = FE->getPattern();
5390fca6ea1SDimitry Andric 
5400fca6ea1SDimitry Andric       SmallVector<UnexpandedParameterPack, 2> Unexpanded;
5410fca6ea1SDimitry Andric       S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
5420fca6ea1SDimitry Andric       assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
5430fca6ea1SDimitry Andric       bool Expand = true;
5440fca6ea1SDimitry Andric       bool RetainExpansion = false;
5450fca6ea1SDimitry Andric       std::optional<unsigned> OrigNumExpansions = FE->getNumExpansions(),
5460fca6ea1SDimitry Andric                               NumExpansions = OrigNumExpansions;
5470fca6ea1SDimitry Andric       if (S.CheckParameterPacksForExpansion(
5480fca6ea1SDimitry Andric               FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded,
5490fca6ea1SDimitry Andric               MLTAL, Expand, RetainExpansion, NumExpansions) ||
5500fca6ea1SDimitry Andric           !Expand || RetainExpansion)
5510fca6ea1SDimitry Andric         return std::nullopt;
5520fca6ea1SDimitry Andric 
5530fca6ea1SDimitry Andric       if (NumExpansions && S.getLangOpts().BracketDepth < NumExpansions) {
5540fca6ea1SDimitry Andric         S.Diag(FE->getEllipsisLoc(),
5550fca6ea1SDimitry Andric                clang::diag::err_fold_expression_limit_exceeded)
5560fca6ea1SDimitry Andric             << *NumExpansions << S.getLangOpts().BracketDepth
5570fca6ea1SDimitry Andric             << FE->getSourceRange();
5580fca6ea1SDimitry Andric         S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth);
5590fca6ea1SDimitry Andric         return std::nullopt;
5600fca6ea1SDimitry Andric       }
5610fca6ea1SDimitry Andric       return NumExpansions;
5620fca6ea1SDimitry Andric     }
5630fca6ea1SDimitry Andric   };
5640fca6ea1SDimitry Andric 
5650fca6ea1SDimitry Andric   return calculateConstraintSatisfaction(
5660fca6ea1SDimitry Andric       S, ConstraintExpr, Satisfaction,
5670fca6ea1SDimitry Andric       ConstraintEvaluator{S, Template, TemplateNameLoc, MLTAL, Satisfaction});
568480093f4SDimitry Andric }
569480093f4SDimitry Andric 
CheckConstraintSatisfaction(Sema & S,const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,llvm::SmallVectorImpl<Expr * > & Converted,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & Satisfaction)570bdd1243dSDimitry Andric static bool CheckConstraintSatisfaction(
571bdd1243dSDimitry Andric     Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
572bdd1243dSDimitry Andric     llvm::SmallVectorImpl<Expr *> &Converted,
573bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgsLists,
574bdd1243dSDimitry Andric     SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
575480093f4SDimitry Andric   if (ConstraintExprs.empty()) {
576480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
577480093f4SDimitry Andric     return false;
578480093f4SDimitry Andric   }
579480093f4SDimitry Andric 
580bdd1243dSDimitry Andric   if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
581480093f4SDimitry Andric     // No need to check satisfaction for dependent constraint expressions.
582480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
583480093f4SDimitry Andric     return false;
584480093f4SDimitry Andric   }
585480093f4SDimitry Andric 
586bdd1243dSDimitry Andric   ArrayRef<TemplateArgument> TemplateArgs =
587bdd1243dSDimitry Andric       TemplateArgsLists.getNumSubstitutedLevels() > 0
588bdd1243dSDimitry Andric           ? TemplateArgsLists.getOutermost()
589bdd1243dSDimitry Andric           : ArrayRef<TemplateArgument> {};
590480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
59113138422SDimitry Andric       Sema::InstantiatingTemplate::ConstraintsCheck{},
59213138422SDimitry Andric       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
593480093f4SDimitry Andric   if (Inst.isInvalid())
594480093f4SDimitry Andric     return true;
595480093f4SDimitry Andric 
596480093f4SDimitry Andric   for (const Expr *ConstraintExpr : ConstraintExprs) {
597bdd1243dSDimitry Andric     ExprResult Res = calculateConstraintSatisfaction(
598bdd1243dSDimitry Andric         S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
599bdd1243dSDimitry Andric         ConstraintExpr, Satisfaction);
600bdd1243dSDimitry Andric     if (Res.isInvalid())
601480093f4SDimitry Andric       return true;
602bdd1243dSDimitry Andric 
603bdd1243dSDimitry Andric     Converted.push_back(Res.get());
604bdd1243dSDimitry Andric     if (!Satisfaction.IsSatisfied) {
605bdd1243dSDimitry Andric       // Backfill the 'converted' list with nulls so we can keep the Converted
606bdd1243dSDimitry Andric       // and unconverted lists in sync.
607bdd1243dSDimitry Andric       Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
608480093f4SDimitry Andric       // [temp.constr.op] p2
609480093f4SDimitry Andric       // [...] To determine if a conjunction is satisfied, the satisfaction
610480093f4SDimitry Andric       // of the first operand is checked. If that is not satisfied, the
611480093f4SDimitry Andric       // conjunction is not satisfied. [...]
612480093f4SDimitry Andric       return false;
613480093f4SDimitry Andric     }
614bdd1243dSDimitry Andric   }
615480093f4SDimitry Andric   return false;
616480093f4SDimitry Andric }
617480093f4SDimitry Andric 
CheckConstraintSatisfaction(const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,llvm::SmallVectorImpl<Expr * > & ConvertedConstraints,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & OutSatisfaction)61855e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction(
61913138422SDimitry Andric     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
620bdd1243dSDimitry Andric     llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
621bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgsLists,
622bdd1243dSDimitry Andric     SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
62355e4f9d5SDimitry Andric   if (ConstraintExprs.empty()) {
62455e4f9d5SDimitry Andric     OutSatisfaction.IsSatisfied = true;
62555e4f9d5SDimitry Andric     return false;
626480093f4SDimitry Andric   }
62781ad6265SDimitry Andric   if (!Template) {
628bdd1243dSDimitry Andric     return ::CheckConstraintSatisfaction(
629bdd1243dSDimitry Andric         *this, nullptr, ConstraintExprs, ConvertedConstraints,
630bdd1243dSDimitry Andric         TemplateArgsLists, TemplateIDRange, OutSatisfaction);
63181ad6265SDimitry Andric   }
6320fca6ea1SDimitry Andric   // Invalid templates could make their way here. Substituting them could result
6330fca6ea1SDimitry Andric   // in dependent expressions.
6340fca6ea1SDimitry Andric   if (Template->isInvalidDecl()) {
6350fca6ea1SDimitry Andric     OutSatisfaction.IsSatisfied = false;
6360fca6ea1SDimitry Andric     return true;
6370fca6ea1SDimitry Andric   }
638bdd1243dSDimitry Andric 
639bdd1243dSDimitry Andric   // A list of the template argument list flattened in a predictible manner for
640bdd1243dSDimitry Andric   // the purposes of caching. The ConstraintSatisfaction type is in AST so it
641bdd1243dSDimitry Andric   // has no access to the MultiLevelTemplateArgumentList, so this has to happen
642bdd1243dSDimitry Andric   // here.
643bdd1243dSDimitry Andric   llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
644bdd1243dSDimitry Andric   for (auto List : TemplateArgsLists)
645bdd1243dSDimitry Andric     FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
646bdd1243dSDimitry Andric                          List.Args.end());
647bdd1243dSDimitry Andric 
64855e4f9d5SDimitry Andric   llvm::FoldingSetNodeID ID;
649bdd1243dSDimitry Andric   ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
65081ad6265SDimitry Andric   void *InsertPos;
65181ad6265SDimitry Andric   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
65281ad6265SDimitry Andric     OutSatisfaction = *Cached;
65355e4f9d5SDimitry Andric     return false;
65455e4f9d5SDimitry Andric   }
655bdd1243dSDimitry Andric 
65681ad6265SDimitry Andric   auto Satisfaction =
657bdd1243dSDimitry Andric       std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
65813138422SDimitry Andric   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
659bdd1243dSDimitry Andric                                     ConvertedConstraints, TemplateArgsLists,
660bdd1243dSDimitry Andric                                     TemplateIDRange, *Satisfaction)) {
661bdd1243dSDimitry Andric     OutSatisfaction = *Satisfaction;
66255e4f9d5SDimitry Andric     return true;
663480093f4SDimitry Andric   }
664bdd1243dSDimitry Andric 
665bdd1243dSDimitry Andric   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
666bdd1243dSDimitry Andric     // The evaluation of this constraint resulted in us trying to re-evaluate it
667bdd1243dSDimitry Andric     // recursively. This isn't really possible, except we try to form a
668bdd1243dSDimitry Andric     // RecoveryExpr as a part of the evaluation.  If this is the case, just
669bdd1243dSDimitry Andric     // return the 'cached' version (which will have the same result), and save
670bdd1243dSDimitry Andric     // ourselves the extra-insert. If it ever becomes possible to legitimately
671bdd1243dSDimitry Andric     // recursively check a constraint, we should skip checking the 'inner' one
672bdd1243dSDimitry Andric     // above, and replace the cached version with this one, as it would be more
673bdd1243dSDimitry Andric     // specific.
674bdd1243dSDimitry Andric     OutSatisfaction = *Cached;
675bdd1243dSDimitry Andric     return false;
676bdd1243dSDimitry Andric   }
677bdd1243dSDimitry Andric 
678bdd1243dSDimitry Andric   // Else we can simply add this satisfaction to the list.
67955e4f9d5SDimitry Andric   OutSatisfaction = *Satisfaction;
68081ad6265SDimitry Andric   // We cannot use InsertPos here because CheckConstraintSatisfaction might have
68181ad6265SDimitry Andric   // invalidated it.
68281ad6265SDimitry Andric   // Note that entries of SatisfactionCache are deleted in Sema's destructor.
68381ad6265SDimitry Andric   SatisfactionCache.InsertNode(Satisfaction.release());
68455e4f9d5SDimitry Andric   return false;
685480093f4SDimitry Andric }
686480093f4SDimitry Andric 
CheckConstraintSatisfaction(const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)687480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
688480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
6890fca6ea1SDimitry Andric 
6900fca6ea1SDimitry Andric   struct ConstraintEvaluator {
6910fca6ea1SDimitry Andric     Sema &S;
6920fca6ea1SDimitry Andric     ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const {
6930fca6ea1SDimitry Andric       return S.PerformContextuallyConvertToBool(const_cast<Expr *>(AtomicExpr));
6940fca6ea1SDimitry Andric     }
6950fca6ea1SDimitry Andric 
6960fca6ea1SDimitry Andric     std::optional<unsigned>
6970fca6ea1SDimitry Andric     EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {
6980fca6ea1SDimitry Andric       return 0;
6990fca6ea1SDimitry Andric     }
7000fca6ea1SDimitry Andric   };
7010fca6ea1SDimitry Andric 
7020fca6ea1SDimitry Andric   return calculateConstraintSatisfaction(*this, ConstraintExpr, Satisfaction,
7030fca6ea1SDimitry Andric                                          ConstraintEvaluator{*this})
704bdd1243dSDimitry Andric       .isInvalid();
705bdd1243dSDimitry Andric }
706bdd1243dSDimitry Andric 
addInstantiatedCapturesToScope(FunctionDecl * Function,const FunctionDecl * PatternDecl,LocalInstantiationScope & Scope,const MultiLevelTemplateArgumentList & TemplateArgs)70706c3fb27SDimitry Andric bool Sema::addInstantiatedCapturesToScope(
70806c3fb27SDimitry Andric     FunctionDecl *Function, const FunctionDecl *PatternDecl,
70906c3fb27SDimitry Andric     LocalInstantiationScope &Scope,
71006c3fb27SDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgs) {
71106c3fb27SDimitry Andric   const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
71206c3fb27SDimitry Andric   const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
71306c3fb27SDimitry Andric 
71406c3fb27SDimitry Andric   unsigned Instantiated = 0;
71506c3fb27SDimitry Andric 
71606c3fb27SDimitry Andric   auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
71706c3fb27SDimitry Andric                               unsigned Index) {
71806c3fb27SDimitry Andric     ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
71906c3fb27SDimitry Andric     if (CapturedVar->isInitCapture())
72006c3fb27SDimitry Andric       Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
72106c3fb27SDimitry Andric   };
72206c3fb27SDimitry Andric 
72306c3fb27SDimitry Andric   for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
72406c3fb27SDimitry Andric     if (!CapturePattern.capturesVariable()) {
72506c3fb27SDimitry Andric       Instantiated++;
72606c3fb27SDimitry Andric       continue;
72706c3fb27SDimitry Andric     }
72806c3fb27SDimitry Andric     const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
72906c3fb27SDimitry Andric     if (!CapturedPattern->isParameterPack()) {
73006c3fb27SDimitry Andric       AddSingleCapture(CapturedPattern, Instantiated++);
73106c3fb27SDimitry Andric     } else {
73206c3fb27SDimitry Andric       Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
73306c3fb27SDimitry Andric       std::optional<unsigned> NumArgumentsInExpansion =
73406c3fb27SDimitry Andric           getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
73506c3fb27SDimitry Andric       if (!NumArgumentsInExpansion)
73606c3fb27SDimitry Andric         continue;
73706c3fb27SDimitry Andric       for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
73806c3fb27SDimitry Andric         AddSingleCapture(CapturedPattern, Instantiated++);
73906c3fb27SDimitry Andric     }
74006c3fb27SDimitry Andric   }
74106c3fb27SDimitry Andric   return false;
74206c3fb27SDimitry Andric }
74306c3fb27SDimitry Andric 
SetupConstraintScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,const MultiLevelTemplateArgumentList & MLTAL,LocalInstantiationScope & Scope)744bdd1243dSDimitry Andric bool Sema::SetupConstraintScope(
745bdd1243dSDimitry Andric     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
7460fca6ea1SDimitry Andric     const MultiLevelTemplateArgumentList &MLTAL,
7470fca6ea1SDimitry Andric     LocalInstantiationScope &Scope) {
748bdd1243dSDimitry Andric   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
749bdd1243dSDimitry Andric     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
750bdd1243dSDimitry Andric     InstantiatingTemplate Inst(
751bdd1243dSDimitry Andric         *this, FD->getPointOfInstantiation(),
752bdd1243dSDimitry Andric         Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
753bdd1243dSDimitry Andric         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
754bdd1243dSDimitry Andric         SourceRange());
755bdd1243dSDimitry Andric     if (Inst.isInvalid())
756bdd1243dSDimitry Andric       return true;
757bdd1243dSDimitry Andric 
758bdd1243dSDimitry Andric     // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
759bdd1243dSDimitry Andric     // 'instantiated' parameters and adds it to the context. For the case where
760bdd1243dSDimitry Andric     // this function is a template being instantiated NOW, we also need to add
761bdd1243dSDimitry Andric     // the list of current template arguments to the list so that they also can
762bdd1243dSDimitry Andric     // be picked out of the map.
763bdd1243dSDimitry Andric     if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
764bdd1243dSDimitry Andric       MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
765bdd1243dSDimitry Andric                                                    /*Final=*/false);
766bdd1243dSDimitry Andric       if (addInstantiatedParametersToScope(
767bdd1243dSDimitry Andric               FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
768bdd1243dSDimitry Andric         return true;
769bdd1243dSDimitry Andric     }
770bdd1243dSDimitry Andric 
771bdd1243dSDimitry Andric     // If this is a member function, make sure we get the parameters that
772bdd1243dSDimitry Andric     // reference the original primary template.
773b3edf446SDimitry Andric     // We walk up the instantiated template chain so that nested lambdas get
774b3edf446SDimitry Andric     // handled properly.
7750fca6ea1SDimitry Andric     // We should only collect instantiated parameters from the primary template.
7760fca6ea1SDimitry Andric     // Otherwise, we may have mismatched template parameter depth!
7770fca6ea1SDimitry Andric     if (FunctionTemplateDecl *FromMemTempl =
7780fca6ea1SDimitry Andric             PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
7790fca6ea1SDimitry Andric       while (FromMemTempl->getInstantiatedFromMemberTemplate())
7800fca6ea1SDimitry Andric         FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate();
781bdd1243dSDimitry Andric       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
782bdd1243dSDimitry Andric                                            Scope, MLTAL))
783bdd1243dSDimitry Andric         return true;
784bdd1243dSDimitry Andric     }
785bdd1243dSDimitry Andric 
786bdd1243dSDimitry Andric     return false;
787bdd1243dSDimitry Andric   }
788bdd1243dSDimitry Andric 
789bdd1243dSDimitry Andric   if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
790bdd1243dSDimitry Andric       FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
791bdd1243dSDimitry Andric     FunctionDecl *InstantiatedFrom =
792bdd1243dSDimitry Andric         FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
793bdd1243dSDimitry Andric             ? FD->getInstantiatedFromMemberFunction()
794bdd1243dSDimitry Andric             : FD->getInstantiatedFromDecl();
795bdd1243dSDimitry Andric 
796bdd1243dSDimitry Andric     InstantiatingTemplate Inst(
797bdd1243dSDimitry Andric         *this, FD->getPointOfInstantiation(),
798bdd1243dSDimitry Andric         Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
799bdd1243dSDimitry Andric         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
800bdd1243dSDimitry Andric         SourceRange());
801bdd1243dSDimitry Andric     if (Inst.isInvalid())
802bdd1243dSDimitry Andric       return true;
803bdd1243dSDimitry Andric 
804bdd1243dSDimitry Andric     // Case where this was not a template, but instantiated as a
805bdd1243dSDimitry Andric     // child-function.
806bdd1243dSDimitry Andric     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
807bdd1243dSDimitry Andric       return true;
808bdd1243dSDimitry Andric   }
809bdd1243dSDimitry Andric 
810bdd1243dSDimitry Andric   return false;
811bdd1243dSDimitry Andric }
812bdd1243dSDimitry Andric 
813bdd1243dSDimitry Andric // This function collects all of the template arguments for the purposes of
814bdd1243dSDimitry Andric // constraint-instantiation and checking.
815bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList>
SetupConstraintCheckingTemplateArgumentsAndScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,LocalInstantiationScope & Scope)816bdd1243dSDimitry Andric Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
817bdd1243dSDimitry Andric     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
818bdd1243dSDimitry Andric     LocalInstantiationScope &Scope) {
819bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
820bdd1243dSDimitry Andric 
821bdd1243dSDimitry Andric   // Collect the list of template arguments relative to the 'primary' template.
822bdd1243dSDimitry Andric   // We need the entire list, since the constraint is completely uninstantiated
823bdd1243dSDimitry Andric   // at this point.
8240fca6ea1SDimitry Andric   MLTAL =
8250fca6ea1SDimitry Andric       getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
8260fca6ea1SDimitry Andric                                    /*Final=*/false, /*Innermost=*/std::nullopt,
827bdd1243dSDimitry Andric                                    /*RelativeToPrimary=*/true,
828bdd1243dSDimitry Andric                                    /*Pattern=*/nullptr,
829bdd1243dSDimitry Andric                                    /*ForConstraintInstantiation=*/true);
830bdd1243dSDimitry Andric   if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
831bdd1243dSDimitry Andric     return std::nullopt;
832bdd1243dSDimitry Andric 
833bdd1243dSDimitry Andric   return MLTAL;
834480093f4SDimitry Andric }
835480093f4SDimitry Andric 
CheckFunctionConstraints(const FunctionDecl * FD,ConstraintSatisfaction & Satisfaction,SourceLocation UsageLoc,bool ForOverloadResolution)83613138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
83713138422SDimitry Andric                                     ConstraintSatisfaction &Satisfaction,
838bdd1243dSDimitry Andric                                     SourceLocation UsageLoc,
839bdd1243dSDimitry Andric                                     bool ForOverloadResolution) {
840bdd1243dSDimitry Andric   // Don't check constraints if the function is dependent. Also don't check if
841bdd1243dSDimitry Andric   // this is a function template specialization, as the call to
842bdd1243dSDimitry Andric   // CheckinstantiatedFunctionTemplateConstraints after this will check it
843bdd1243dSDimitry Andric   // better.
844bdd1243dSDimitry Andric   if (FD->isDependentContext() ||
845bdd1243dSDimitry Andric       FD->getTemplatedKind() ==
846bdd1243dSDimitry Andric           FunctionDecl::TK_FunctionTemplateSpecialization) {
84713138422SDimitry Andric     Satisfaction.IsSatisfied = true;
84813138422SDimitry Andric     return false;
84913138422SDimitry Andric   }
850bdd1243dSDimitry Andric 
85106c3fb27SDimitry Andric   // A lambda conversion operator has the same constraints as the call operator
85206c3fb27SDimitry Andric   // and constraints checking relies on whether we are in a lambda call operator
85306c3fb27SDimitry Andric   // (and may refer to its parameters), so check the call operator instead.
8540fca6ea1SDimitry Andric   // Note that the declarations outside of the lambda should also be
8550fca6ea1SDimitry Andric   // considered. Turning on the 'ForOverloadResolution' flag results in the
8560fca6ea1SDimitry Andric   // LocalInstantiationScope not looking into its parents, but we can still
8570fca6ea1SDimitry Andric   // access Decls from the parents while building a lambda RAII scope later.
85806c3fb27SDimitry Andric   if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
85906c3fb27SDimitry Andric       MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
86006c3fb27SDimitry Andric     return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
86106c3fb27SDimitry Andric                                     Satisfaction, UsageLoc,
8620fca6ea1SDimitry Andric                                     /*ShouldAddDeclsFromParentScope=*/true);
86306c3fb27SDimitry Andric 
864bdd1243dSDimitry Andric   DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
865bdd1243dSDimitry Andric 
866bdd1243dSDimitry Andric   while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
867bdd1243dSDimitry Andric     if (isLambdaCallOperator(CtxToSave))
868bdd1243dSDimitry Andric       CtxToSave = CtxToSave->getParent()->getParent();
869bdd1243dSDimitry Andric     else
870bdd1243dSDimitry Andric       CtxToSave = CtxToSave->getNonTransparentContext();
871bdd1243dSDimitry Andric   }
872bdd1243dSDimitry Andric 
873bdd1243dSDimitry Andric   ContextRAII SavedContext{*this, CtxToSave};
8745f757f3fSDimitry Andric   LocalInstantiationScope Scope(*this, !ForOverloadResolution);
875bdd1243dSDimitry Andric   std::optional<MultiLevelTemplateArgumentList> MLTAL =
876bdd1243dSDimitry Andric       SetupConstraintCheckingTemplateArgumentsAndScope(
877bdd1243dSDimitry Andric           const_cast<FunctionDecl *>(FD), {}, Scope);
878bdd1243dSDimitry Andric 
879bdd1243dSDimitry Andric   if (!MLTAL)
880bdd1243dSDimitry Andric     return true;
881bdd1243dSDimitry Andric 
88213138422SDimitry Andric   Qualifiers ThisQuals;
88313138422SDimitry Andric   CXXRecordDecl *Record = nullptr;
88413138422SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
88513138422SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
88613138422SDimitry Andric     Record = const_cast<CXXRecordDecl *>(Method->getParent());
88713138422SDimitry Andric   }
88813138422SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
889feb5b0c7SDimitry Andric 
890feb5b0c7SDimitry Andric   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
8915f757f3fSDimitry Andric       *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
8925f757f3fSDimitry Andric       ForOverloadResolution);
893feb5b0c7SDimitry Andric 
89406c3fb27SDimitry Andric   return CheckConstraintSatisfaction(
89506c3fb27SDimitry Andric       FD, {FD->getTrailingRequiresClause()}, *MLTAL,
89613138422SDimitry Andric       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
89706c3fb27SDimitry Andric       Satisfaction);
898bdd1243dSDimitry Andric }
899bdd1243dSDimitry Andric 
900bdd1243dSDimitry Andric 
901bdd1243dSDimitry Andric // Figure out the to-translation-unit depth for this function declaration for
902bdd1243dSDimitry Andric // the purpose of seeing if they differ by constraints. This isn't the same as
903bdd1243dSDimitry Andric // getTemplateDepth, because it includes already instantiated parents.
904bdd1243dSDimitry Andric static unsigned
CalculateTemplateDepthForConstraints(Sema & S,const NamedDecl * ND,bool SkipForSpecialization=false)905bdd1243dSDimitry Andric CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
906bdd1243dSDimitry Andric                                      bool SkipForSpecialization = false) {
907bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
9080fca6ea1SDimitry Andric       ND, ND->getLexicalDeclContext(), /*Final=*/false,
9090fca6ea1SDimitry Andric       /*Innermost=*/std::nullopt,
9105f757f3fSDimitry Andric       /*RelativeToPrimary=*/true,
911bdd1243dSDimitry Andric       /*Pattern=*/nullptr,
912bdd1243dSDimitry Andric       /*ForConstraintInstantiation=*/true, SkipForSpecialization);
91306c3fb27SDimitry Andric   return MLTAL.getNumLevels();
914bdd1243dSDimitry Andric }
915bdd1243dSDimitry Andric 
916bdd1243dSDimitry Andric namespace {
917bdd1243dSDimitry Andric   class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
918bdd1243dSDimitry Andric   unsigned TemplateDepth = 0;
919bdd1243dSDimitry Andric   public:
920bdd1243dSDimitry Andric   using inherited = TreeTransform<AdjustConstraintDepth>;
AdjustConstraintDepth(Sema & SemaRef,unsigned TemplateDepth)921bdd1243dSDimitry Andric   AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
922bdd1243dSDimitry Andric       : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
923bdd1243dSDimitry Andric 
924bdd1243dSDimitry Andric   using inherited::TransformTemplateTypeParmType;
TransformTemplateTypeParmType(TypeLocBuilder & TLB,TemplateTypeParmTypeLoc TL,bool)925bdd1243dSDimitry Andric   QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
926bdd1243dSDimitry Andric                                          TemplateTypeParmTypeLoc TL, bool) {
927bdd1243dSDimitry Andric     const TemplateTypeParmType *T = TL.getTypePtr();
928bdd1243dSDimitry Andric 
929bdd1243dSDimitry Andric     TemplateTypeParmDecl *NewTTPDecl = nullptr;
930bdd1243dSDimitry Andric     if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
931bdd1243dSDimitry Andric       NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
932bdd1243dSDimitry Andric           TransformDecl(TL.getNameLoc(), OldTTPDecl));
933bdd1243dSDimitry Andric 
934bdd1243dSDimitry Andric     QualType Result = getSema().Context.getTemplateTypeParmType(
935bdd1243dSDimitry Andric         T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
936bdd1243dSDimitry Andric         NewTTPDecl);
937bdd1243dSDimitry Andric     TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
938bdd1243dSDimitry Andric     NewTL.setNameLoc(TL.getNameLoc());
939bdd1243dSDimitry Andric     return Result;
940bdd1243dSDimitry Andric   }
941bdd1243dSDimitry Andric   };
942bdd1243dSDimitry Andric } // namespace
943bdd1243dSDimitry Andric 
SubstituteConstraintExpressionWithoutSatisfaction(Sema & S,const Sema::TemplateCompareNewDeclInfo & DeclInfo,const Expr * ConstrExpr)9441db9f3b2SDimitry Andric static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
9451db9f3b2SDimitry Andric     Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
94606c3fb27SDimitry Andric     const Expr *ConstrExpr) {
94706c3fb27SDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
9485f757f3fSDimitry Andric       DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
9490fca6ea1SDimitry Andric       /*Innermost=*/std::nullopt,
95006c3fb27SDimitry Andric       /*RelativeToPrimary=*/true,
95106c3fb27SDimitry Andric       /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
95206c3fb27SDimitry Andric       /*SkipForSpecialization*/ false);
9535f757f3fSDimitry Andric 
95406c3fb27SDimitry Andric   if (MLTAL.getNumSubstitutedLevels() == 0)
95506c3fb27SDimitry Andric     return ConstrExpr;
95606c3fb27SDimitry Andric 
95706c3fb27SDimitry Andric   Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);
95806c3fb27SDimitry Andric 
95906c3fb27SDimitry Andric   Sema::InstantiatingTemplate Inst(
9605f757f3fSDimitry Andric       S, DeclInfo.getLocation(),
96106c3fb27SDimitry Andric       Sema::InstantiatingTemplate::ConstraintNormalization{},
9625f757f3fSDimitry Andric       const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
96306c3fb27SDimitry Andric   if (Inst.isInvalid())
96406c3fb27SDimitry Andric     return nullptr;
96506c3fb27SDimitry Andric 
9660fca6ea1SDimitry Andric   // Set up a dummy 'instantiation' scope in the case of reference to function
9670fca6ea1SDimitry Andric   // parameters that the surrounding function hasn't been instantiated yet. Note
9680fca6ea1SDimitry Andric   // this may happen while we're comparing two templates' constraint
9690fca6ea1SDimitry Andric   // equivalence.
970*415efcecSDimitry Andric   LocalInstantiationScope ScopeForParameters(S, /*CombineWithOuterScope=*/true);
9710fca6ea1SDimitry Andric   if (auto *FD = DeclInfo.getDecl()->getAsFunction())
9726e516c87SDimitry Andric     for (auto *PVD : FD->parameters()) {
9736e516c87SDimitry Andric       if (!PVD->isParameterPack()) {
9740fca6ea1SDimitry Andric         ScopeForParameters.InstantiatedLocal(PVD, PVD);
9756e516c87SDimitry Andric         continue;
9766e516c87SDimitry Andric       }
9776e516c87SDimitry Andric       // This is hacky: we're mapping the parameter pack to a size-of-1 argument
9786e516c87SDimitry Andric       // to avoid building SubstTemplateTypeParmPackTypes for
9796e516c87SDimitry Andric       // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
9806e516c87SDimitry Andric       // otherwise reference the AssociatedDecl of the template arguments, which
9816e516c87SDimitry Andric       // is, in this case, the template declaration.
9826e516c87SDimitry Andric       //
9836e516c87SDimitry Andric       // However, as we are in the process of comparing potential
9846e516c87SDimitry Andric       // re-declarations, the canonical declaration is the declaration itself at
9856e516c87SDimitry Andric       // this point. So if we didn't expand these packs, we would end up with an
9866e516c87SDimitry Andric       // incorrect profile difference because we will be profiling the
9876e516c87SDimitry Andric       // canonical types!
9886e516c87SDimitry Andric       //
9896e516c87SDimitry Andric       // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
9906e516c87SDimitry Andric       // that we can eliminate the Scope in the cases where the declarations are
9916e516c87SDimitry Andric       // not necessarily instantiated. It would also benefit the noexcept
9926e516c87SDimitry Andric       // specifier comparison.
9936e516c87SDimitry Andric       ScopeForParameters.MakeInstantiatedLocalArgPack(PVD);
9946e516c87SDimitry Andric       ScopeForParameters.InstantiatedLocalPackArg(PVD, PVD);
9956e516c87SDimitry Andric     }
9960fca6ea1SDimitry Andric 
99706c3fb27SDimitry Andric   std::optional<Sema::CXXThisScopeRAII> ThisScope;
9980fca6ea1SDimitry Andric 
9990fca6ea1SDimitry Andric   // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
10000fca6ea1SDimitry Andric   // essential for having an injected class as the canonical type for a template
10010fca6ea1SDimitry Andric   // specialization type at the rebuilding stage. This guarantees that, for
10020fca6ea1SDimitry Andric   // out-of-line definitions, injected class name types and their equivalent
10030fca6ea1SDimitry Andric   // template specializations can be profiled to the same value, which makes it
10040fca6ea1SDimitry Andric   // possible that e.g. constraints involving C<Class<T>> and C<Class> are
10050fca6ea1SDimitry Andric   // perceived identical.
10060fca6ea1SDimitry Andric   std::optional<Sema::ContextRAII> ContextScope;
10070fca6ea1SDimitry Andric   if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext())) {
100806c3fb27SDimitry Andric     ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
10090fca6ea1SDimitry Andric     ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
10100fca6ea1SDimitry Andric                          /*NewThisContext=*/false);
10110fca6ea1SDimitry Andric   }
10121db9f3b2SDimitry Andric   ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
10131db9f3b2SDimitry Andric       const_cast<clang::Expr *>(ConstrExpr), MLTAL);
101406c3fb27SDimitry Andric   if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
101506c3fb27SDimitry Andric     return nullptr;
101606c3fb27SDimitry Andric   return SubstConstr.get();
101706c3fb27SDimitry Andric }
101806c3fb27SDimitry Andric 
AreConstraintExpressionsEqual(const NamedDecl * Old,const Expr * OldConstr,const TemplateCompareNewDeclInfo & New,const Expr * NewConstr)1019bdd1243dSDimitry Andric bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
1020bdd1243dSDimitry Andric                                          const Expr *OldConstr,
10215f757f3fSDimitry Andric                                          const TemplateCompareNewDeclInfo &New,
1022bdd1243dSDimitry Andric                                          const Expr *NewConstr) {
102306c3fb27SDimitry Andric   if (OldConstr == NewConstr)
102406c3fb27SDimitry Andric     return true;
102506c3fb27SDimitry Andric   // C++ [temp.constr.decl]p4
10265f757f3fSDimitry Andric   if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
10275f757f3fSDimitry Andric       Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
102806c3fb27SDimitry Andric     if (const Expr *SubstConstr =
10291db9f3b2SDimitry Andric             SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
10301db9f3b2SDimitry Andric                                                               OldConstr))
103106c3fb27SDimitry Andric       OldConstr = SubstConstr;
103206c3fb27SDimitry Andric     else
103306c3fb27SDimitry Andric       return false;
103406c3fb27SDimitry Andric     if (const Expr *SubstConstr =
10351db9f3b2SDimitry Andric             SubstituteConstraintExpressionWithoutSatisfaction(*this, New,
10361db9f3b2SDimitry Andric                                                               NewConstr))
103706c3fb27SDimitry Andric       NewConstr = SubstConstr;
103806c3fb27SDimitry Andric     else
103906c3fb27SDimitry Andric       return false;
1040bdd1243dSDimitry Andric   }
1041bdd1243dSDimitry Andric 
1042bdd1243dSDimitry Andric   llvm::FoldingSetNodeID ID1, ID2;
1043bdd1243dSDimitry Andric   OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1044bdd1243dSDimitry Andric   NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1045bdd1243dSDimitry Andric   return ID1 == ID2;
1046bdd1243dSDimitry Andric }
1047bdd1243dSDimitry Andric 
FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl * FD)1048bdd1243dSDimitry Andric bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
1049bdd1243dSDimitry Andric   assert(FD->getFriendObjectKind() && "Must be a friend!");
1050bdd1243dSDimitry Andric 
1051bdd1243dSDimitry Andric   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1052bdd1243dSDimitry Andric   // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1053bdd1243dSDimitry Andric   // non-function-template.
1054bdd1243dSDimitry Andric   assert(FD->getDescribedFunctionTemplate() &&
1055bdd1243dSDimitry Andric          "Non-function templates don't need to be checked");
1056bdd1243dSDimitry Andric 
1057bdd1243dSDimitry Andric   SmallVector<const Expr *, 3> ACs;
1058bdd1243dSDimitry Andric   FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
1059bdd1243dSDimitry Andric 
1060bdd1243dSDimitry Andric   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1061bdd1243dSDimitry Andric   for (const Expr *Constraint : ACs)
1062bdd1243dSDimitry Andric     if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1063bdd1243dSDimitry Andric                                                        Constraint))
1064bdd1243dSDimitry Andric       return true;
1065bdd1243dSDimitry Andric 
1066bdd1243dSDimitry Andric   return false;
106713138422SDimitry Andric }
106813138422SDimitry Andric 
EnsureTemplateArgumentListConstraints(TemplateDecl * TD,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange)1069480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints(
1070bdd1243dSDimitry Andric     TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1071480093f4SDimitry Andric     SourceRange TemplateIDRange) {
1072480093f4SDimitry Andric   ConstraintSatisfaction Satisfaction;
1073480093f4SDimitry Andric   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
1074480093f4SDimitry Andric   TD->getAssociatedConstraints(AssociatedConstraints);
1075bdd1243dSDimitry Andric   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1076480093f4SDimitry Andric                                   TemplateIDRange, Satisfaction))
1077480093f4SDimitry Andric     return true;
1078480093f4SDimitry Andric 
1079480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied) {
1080480093f4SDimitry Andric     SmallString<128> TemplateArgString;
1081480093f4SDimitry Andric     TemplateArgString = " ";
1082480093f4SDimitry Andric     TemplateArgString += getTemplateArgumentBindingsText(
1083bdd1243dSDimitry Andric         TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1084bdd1243dSDimitry Andric         TemplateArgsLists.getInnermost().size());
1085480093f4SDimitry Andric 
1086480093f4SDimitry Andric     Diag(TemplateIDRange.getBegin(),
1087480093f4SDimitry Andric          diag::err_template_arg_list_constraints_not_satisfied)
1088480093f4SDimitry Andric         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
1089480093f4SDimitry Andric         << TemplateArgString << TemplateIDRange;
1090480093f4SDimitry Andric     DiagnoseUnsatisfiedConstraint(Satisfaction);
1091480093f4SDimitry Andric     return true;
1092480093f4SDimitry Andric   }
1093480093f4SDimitry Andric   return false;
1094480093f4SDimitry Andric }
1095480093f4SDimitry Andric 
CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation,FunctionDecl * Decl,ArrayRef<TemplateArgument> TemplateArgs,ConstraintSatisfaction & Satisfaction)109681ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints(
109781ad6265SDimitry Andric     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
109881ad6265SDimitry Andric     ArrayRef<TemplateArgument> TemplateArgs,
109981ad6265SDimitry Andric     ConstraintSatisfaction &Satisfaction) {
110081ad6265SDimitry Andric   // In most cases we're not going to have constraints, so check for that first.
110181ad6265SDimitry Andric   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
110281ad6265SDimitry Andric   // Note - code synthesis context for the constraints check is created
110381ad6265SDimitry Andric   // inside CheckConstraintsSatisfaction.
110481ad6265SDimitry Andric   SmallVector<const Expr *, 3> TemplateAC;
110581ad6265SDimitry Andric   Template->getAssociatedConstraints(TemplateAC);
110681ad6265SDimitry Andric   if (TemplateAC.empty()) {
110781ad6265SDimitry Andric     Satisfaction.IsSatisfied = true;
110881ad6265SDimitry Andric     return false;
110981ad6265SDimitry Andric   }
111081ad6265SDimitry Andric 
111181ad6265SDimitry Andric   // Enter the scope of this instantiation. We don't use
111281ad6265SDimitry Andric   // PushDeclContext because we don't have a scope.
111381ad6265SDimitry Andric   Sema::ContextRAII savedContext(*this, Decl);
111481ad6265SDimitry Andric   LocalInstantiationScope Scope(*this);
111581ad6265SDimitry Andric 
1116bdd1243dSDimitry Andric   std::optional<MultiLevelTemplateArgumentList> MLTAL =
1117bdd1243dSDimitry Andric       SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1118bdd1243dSDimitry Andric                                                        Scope);
1119bdd1243dSDimitry Andric 
1120bdd1243dSDimitry Andric   if (!MLTAL)
112181ad6265SDimitry Andric     return true;
1122bdd1243dSDimitry Andric 
112381ad6265SDimitry Andric   Qualifiers ThisQuals;
112481ad6265SDimitry Andric   CXXRecordDecl *Record = nullptr;
112581ad6265SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
112681ad6265SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
112781ad6265SDimitry Andric     Record = Method->getParent();
112881ad6265SDimitry Andric   }
1129feb5b0c7SDimitry Andric 
113081ad6265SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1131feb5b0c7SDimitry Andric   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
1132feb5b0c7SDimitry Andric       *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
1133bdd1243dSDimitry Andric 
1134bdd1243dSDimitry Andric   llvm::SmallVector<Expr *, 1> Converted;
1135bdd1243dSDimitry Andric   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
113681ad6265SDimitry Andric                                      PointOfInstantiation, Satisfaction);
113781ad6265SDimitry Andric }
113881ad6265SDimitry Andric 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::ExprRequirement * Req,bool First)113955e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
114055e4f9d5SDimitry Andric                                            concepts::ExprRequirement *Req,
114155e4f9d5SDimitry Andric                                            bool First) {
114255e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
114355e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
114455e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
114555e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Dependent:
114655e4f9d5SDimitry Andric       llvm_unreachable("Diagnosing a dependent requirement");
114755e4f9d5SDimitry Andric       break;
114855e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
114955e4f9d5SDimitry Andric       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
115055e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
115155e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
115255e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_substitution_error)
115355e4f9d5SDimitry Andric                << (int)First << SubstDiag->SubstitutedEntity
115455e4f9d5SDimitry Andric                << SubstDiag->DiagMessage;
115555e4f9d5SDimitry Andric       else
115655e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
115755e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_unknown_substitution_error)
115855e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
115955e4f9d5SDimitry Andric       break;
116055e4f9d5SDimitry Andric     }
116155e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_NoexceptNotMet:
116255e4f9d5SDimitry Andric       S.Diag(Req->getNoexceptLoc(),
116355e4f9d5SDimitry Andric              diag::note_expr_requirement_noexcept_not_met)
116455e4f9d5SDimitry Andric           << (int)First << Req->getExpr();
116555e4f9d5SDimitry Andric       break;
116655e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
116755e4f9d5SDimitry Andric       auto *SubstDiag =
116855e4f9d5SDimitry Andric           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
116955e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
117055e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
117155e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_substitution_error)
117255e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity
117355e4f9d5SDimitry Andric             << SubstDiag->DiagMessage;
117455e4f9d5SDimitry Andric       else
117555e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
117655e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
117755e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
117855e4f9d5SDimitry Andric       break;
117955e4f9d5SDimitry Andric     }
118055e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
118155e4f9d5SDimitry Andric       ConceptSpecializationExpr *ConstraintExpr =
118255e4f9d5SDimitry Andric           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
1183fe6060f1SDimitry Andric       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
118455e4f9d5SDimitry Andric         // A simple case - expr type is the type being constrained and the concept
118555e4f9d5SDimitry Andric         // was not provided arguments.
1186fe6060f1SDimitry Andric         Expr *e = Req->getExpr();
1187fe6060f1SDimitry Andric         S.Diag(e->getBeginLoc(),
118855e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied_simple)
1189349cc55cSDimitry Andric             << (int)First << S.Context.getReferenceQualifiedType(e)
119055e4f9d5SDimitry Andric             << ConstraintExpr->getNamedConcept();
1191fe6060f1SDimitry Andric       } else {
119255e4f9d5SDimitry Andric         S.Diag(ConstraintExpr->getBeginLoc(),
119355e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied)
119455e4f9d5SDimitry Andric             << (int)First << ConstraintExpr;
1195fe6060f1SDimitry Andric       }
119655e4f9d5SDimitry Andric       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
119755e4f9d5SDimitry Andric       break;
119855e4f9d5SDimitry Andric     }
119955e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Satisfied:
120055e4f9d5SDimitry Andric       llvm_unreachable("We checked this above");
120155e4f9d5SDimitry Andric   }
120255e4f9d5SDimitry Andric }
120355e4f9d5SDimitry Andric 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::TypeRequirement * Req,bool First)120455e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
120555e4f9d5SDimitry Andric                                            concepts::TypeRequirement *Req,
120655e4f9d5SDimitry Andric                                            bool First) {
120755e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
120855e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
120955e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
121055e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_Dependent:
121155e4f9d5SDimitry Andric     llvm_unreachable("Diagnosing a dependent requirement");
121255e4f9d5SDimitry Andric     return;
121355e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_SubstitutionFailure: {
121455e4f9d5SDimitry Andric     auto *SubstDiag = Req->getSubstitutionDiagnostic();
121555e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
121655e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
121755e4f9d5SDimitry Andric              diag::note_type_requirement_substitution_error) << (int)First
121855e4f9d5SDimitry Andric           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
121955e4f9d5SDimitry Andric     else
122055e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
122155e4f9d5SDimitry Andric              diag::note_type_requirement_unknown_substitution_error)
122255e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
122355e4f9d5SDimitry Andric     return;
122455e4f9d5SDimitry Andric   }
122555e4f9d5SDimitry Andric   default:
122655e4f9d5SDimitry Andric     llvm_unreachable("Unknown satisfaction status");
122755e4f9d5SDimitry Andric     return;
122855e4f9d5SDimitry Andric   }
122955e4f9d5SDimitry Andric }
1230bdd1243dSDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1231bdd1243dSDimitry Andric                                                         Expr *SubstExpr,
1232bdd1243dSDimitry Andric                                                         bool First = true);
123355e4f9d5SDimitry Andric 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::NestedRequirement * Req,bool First)123455e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
123555e4f9d5SDimitry Andric                                            concepts::NestedRequirement *Req,
123655e4f9d5SDimitry Andric                                            bool First) {
1237bdd1243dSDimitry Andric   using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
12380fca6ea1SDimitry Andric   for (auto &Record : Req->getConstraintSatisfaction()) {
12390fca6ea1SDimitry Andric     if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>())
1240bdd1243dSDimitry Andric       S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
12410fca6ea1SDimitry Andric           << (int)First << Req->getInvalidConstraintEntity()
12420fca6ea1SDimitry Andric           << SubstDiag->second;
124355e4f9d5SDimitry Andric     else
12440fca6ea1SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, Record.dyn_cast<Expr *>(),
12450fca6ea1SDimitry Andric                                                   First);
1246bdd1243dSDimitry Andric     First = false;
124755e4f9d5SDimitry Andric   }
124855e4f9d5SDimitry Andric }
124955e4f9d5SDimitry Andric 
diagnoseWellFormedUnsatisfiedConstraintExpr(Sema & S,Expr * SubstExpr,bool First)1250480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1251480093f4SDimitry Andric                                                         Expr *SubstExpr,
1252bdd1243dSDimitry Andric                                                         bool First) {
1253480093f4SDimitry Andric   SubstExpr = SubstExpr->IgnoreParenImpCasts();
1254480093f4SDimitry Andric   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1255480093f4SDimitry Andric     switch (BO->getOpcode()) {
1256480093f4SDimitry Andric     // These two cases will in practice only be reached when using fold
1257480093f4SDimitry Andric     // expressions with || and &&, since otherwise the || and && will have been
1258480093f4SDimitry Andric     // broken down into atomic constraints during satisfaction checking.
1259480093f4SDimitry Andric     case BO_LOr:
1260480093f4SDimitry Andric       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1261480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1262480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1263480093f4SDimitry Andric                                                   /*First=*/false);
1264480093f4SDimitry Andric       return;
1265fe6060f1SDimitry Andric     case BO_LAnd: {
1266fe6060f1SDimitry Andric       bool LHSSatisfied =
1267fe6060f1SDimitry Andric           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1268480093f4SDimitry Andric       if (LHSSatisfied) {
1269480093f4SDimitry Andric         // LHS is true, so RHS must be false.
1270480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
1271480093f4SDimitry Andric         return;
1272480093f4SDimitry Andric       }
1273480093f4SDimitry Andric       // LHS is false
1274480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1275480093f4SDimitry Andric 
1276480093f4SDimitry Andric       // RHS might also be false
1277fe6060f1SDimitry Andric       bool RHSSatisfied =
1278fe6060f1SDimitry Andric           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1279480093f4SDimitry Andric       if (!RHSSatisfied)
1280480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1281480093f4SDimitry Andric                                                     /*First=*/false);
1282480093f4SDimitry Andric       return;
1283fe6060f1SDimitry Andric     }
1284480093f4SDimitry Andric     case BO_GE:
1285480093f4SDimitry Andric     case BO_LE:
1286480093f4SDimitry Andric     case BO_GT:
1287480093f4SDimitry Andric     case BO_LT:
1288480093f4SDimitry Andric     case BO_EQ:
1289480093f4SDimitry Andric     case BO_NE:
1290480093f4SDimitry Andric       if (BO->getLHS()->getType()->isIntegerType() &&
1291480093f4SDimitry Andric           BO->getRHS()->getType()->isIntegerType()) {
1292480093f4SDimitry Andric         Expr::EvalResult SimplifiedLHS;
1293480093f4SDimitry Andric         Expr::EvalResult SimplifiedRHS;
1294fe6060f1SDimitry Andric         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1295fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
1296fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
1297fe6060f1SDimitry Andric         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1298fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
1299fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
1300480093f4SDimitry Andric         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1301480093f4SDimitry Andric           S.Diag(SubstExpr->getBeginLoc(),
1302480093f4SDimitry Andric                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
1303480093f4SDimitry Andric               << (int)First << SubstExpr
1304fe6060f1SDimitry Andric               << toString(SimplifiedLHS.Val.getInt(), 10)
1305480093f4SDimitry Andric               << BinaryOperator::getOpcodeStr(BO->getOpcode())
1306fe6060f1SDimitry Andric               << toString(SimplifiedRHS.Val.getInt(), 10);
1307480093f4SDimitry Andric           return;
1308480093f4SDimitry Andric         }
1309480093f4SDimitry Andric       }
1310480093f4SDimitry Andric       break;
1311480093f4SDimitry Andric 
1312480093f4SDimitry Andric     default:
1313480093f4SDimitry Andric       break;
1314480093f4SDimitry Andric     }
1315480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1316480093f4SDimitry Andric     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1317480093f4SDimitry Andric       S.Diag(
1318480093f4SDimitry Andric           CSE->getSourceRange().getBegin(),
1319480093f4SDimitry Andric           diag::
1320480093f4SDimitry Andric           note_single_arg_concept_specialization_constraint_evaluated_to_false)
1321480093f4SDimitry Andric           << (int)First
1322480093f4SDimitry Andric           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1323480093f4SDimitry Andric           << CSE->getNamedConcept();
1324480093f4SDimitry Andric     } else {
1325480093f4SDimitry Andric       S.Diag(SubstExpr->getSourceRange().getBegin(),
1326480093f4SDimitry Andric              diag::note_concept_specialization_constraint_evaluated_to_false)
1327480093f4SDimitry Andric           << (int)First << CSE;
1328480093f4SDimitry Andric     }
1329480093f4SDimitry Andric     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1330480093f4SDimitry Andric     return;
133155e4f9d5SDimitry Andric   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1332bdd1243dSDimitry Andric     // FIXME: RequiresExpr should store dependent diagnostics.
133355e4f9d5SDimitry Andric     for (concepts::Requirement *Req : RE->getRequirements())
133455e4f9d5SDimitry Andric       if (!Req->isDependent() && !Req->isSatisfied()) {
133555e4f9d5SDimitry Andric         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
133655e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, E, First);
133755e4f9d5SDimitry Andric         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
133855e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, T, First);
133955e4f9d5SDimitry Andric         else
134055e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(
134155e4f9d5SDimitry Andric               S, cast<concepts::NestedRequirement>(Req), First);
134255e4f9d5SDimitry Andric         break;
134355e4f9d5SDimitry Andric       }
134455e4f9d5SDimitry Andric     return;
13450fca6ea1SDimitry Andric   } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
13460fca6ea1SDimitry Andric              TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
13470fca6ea1SDimitry Andric     assert(TTE->getNumArgs() == 2);
13480fca6ea1SDimitry Andric     S.Diag(SubstExpr->getSourceRange().getBegin(),
13490fca6ea1SDimitry Andric            diag::note_is_deducible_constraint_evaluated_to_false)
13500fca6ea1SDimitry Andric         << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
13510fca6ea1SDimitry Andric     return;
1352480093f4SDimitry Andric   }
1353480093f4SDimitry Andric 
1354480093f4SDimitry Andric   S.Diag(SubstExpr->getSourceRange().getBegin(),
1355480093f4SDimitry Andric          diag::note_atomic_constraint_evaluated_to_false)
1356480093f4SDimitry Andric       << (int)First << SubstExpr;
1357480093f4SDimitry Andric }
1358480093f4SDimitry Andric 
1359480093f4SDimitry Andric template <typename SubstitutionDiagnostic>
diagnoseUnsatisfiedConstraintExpr(Sema & S,const llvm::PointerUnion<Expr *,SubstitutionDiagnostic * > & Record,bool First=true)1360480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr(
13610fca6ea1SDimitry Andric     Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1362480093f4SDimitry Andric     bool First = true) {
1363480093f4SDimitry Andric   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) {
1364480093f4SDimitry Andric     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1365480093f4SDimitry Andric         << Diag->second;
1366480093f4SDimitry Andric     return;
1367480093f4SDimitry Andric   }
1368480093f4SDimitry Andric 
1369480093f4SDimitry Andric   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
1370480093f4SDimitry Andric       Record.template get<Expr *>(), First);
1371480093f4SDimitry Andric }
1372480093f4SDimitry Andric 
137355e4f9d5SDimitry Andric void
DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction & Satisfaction,bool First)137455e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
137555e4f9d5SDimitry Andric                                     bool First) {
1376480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
1377480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
13780fca6ea1SDimitry Andric   for (auto &Record : Satisfaction.Details) {
13790fca6ea1SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Record, First);
1380480093f4SDimitry Andric     First = false;
1381480093f4SDimitry Andric   }
1382480093f4SDimitry Andric }
1383480093f4SDimitry Andric 
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction & Satisfaction,bool First)1384480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
138555e4f9d5SDimitry Andric     const ASTConstraintSatisfaction &Satisfaction,
138655e4f9d5SDimitry Andric     bool First) {
1387480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
1388480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
13890fca6ea1SDimitry Andric   for (auto &Record : Satisfaction) {
13900fca6ea1SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Record, First);
1391480093f4SDimitry Andric     First = false;
1392480093f4SDimitry Andric   }
1393480093f4SDimitry Andric }
1394480093f4SDimitry Andric 
1395480093f4SDimitry Andric const NormalizedConstraint *
getNormalizedAssociatedConstraints(NamedDecl * ConstrainedDecl,ArrayRef<const Expr * > AssociatedConstraints)1396480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints(
1397480093f4SDimitry Andric     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
139806c3fb27SDimitry Andric   // In case the ConstrainedDecl comes from modules, it is necessary to use
139906c3fb27SDimitry Andric   // the canonical decl to avoid different atomic constraints with the 'same'
140006c3fb27SDimitry Andric   // declarations.
140106c3fb27SDimitry Andric   ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl());
140206c3fb27SDimitry Andric 
1403480093f4SDimitry Andric   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1404480093f4SDimitry Andric   if (CacheEntry == NormalizationCache.end()) {
1405480093f4SDimitry Andric     auto Normalized =
1406480093f4SDimitry Andric         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1407480093f4SDimitry Andric                                                   AssociatedConstraints);
1408480093f4SDimitry Andric     CacheEntry =
1409480093f4SDimitry Andric         NormalizationCache
1410480093f4SDimitry Andric             .try_emplace(ConstrainedDecl,
1411480093f4SDimitry Andric                          Normalized
1412480093f4SDimitry Andric                              ? new (Context) NormalizedConstraint(
1413480093f4SDimitry Andric                                  std::move(*Normalized))
1414480093f4SDimitry Andric                              : nullptr)
1415480093f4SDimitry Andric             .first;
1416480093f4SDimitry Andric   }
1417480093f4SDimitry Andric   return CacheEntry->second;
1418480093f4SDimitry Andric }
1419480093f4SDimitry Andric 
getNormalizedAssociatedConstraints(Sema & S,NamedDecl * ConstrainedDecl,ArrayRef<const Expr * > AssociatedConstraints)14200fca6ea1SDimitry Andric const NormalizedConstraint *clang::getNormalizedAssociatedConstraints(
14210fca6ea1SDimitry Andric     Sema &S, NamedDecl *ConstrainedDecl,
14220fca6ea1SDimitry Andric     ArrayRef<const Expr *> AssociatedConstraints) {
14230fca6ea1SDimitry Andric   return S.getNormalizedAssociatedConstraints(ConstrainedDecl,
14240fca6ea1SDimitry Andric                                               AssociatedConstraints);
14250fca6ea1SDimitry Andric }
14260fca6ea1SDimitry Andric 
1427bdd1243dSDimitry Andric static bool
substituteParameterMappings(Sema & S,NormalizedConstraint & N,ConceptDecl * Concept,const MultiLevelTemplateArgumentList & MLTAL,const ASTTemplateArgumentListInfo * ArgsAsWritten)1428bdd1243dSDimitry Andric substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1429bdd1243dSDimitry Andric                             ConceptDecl *Concept,
1430bdd1243dSDimitry Andric                             const MultiLevelTemplateArgumentList &MLTAL,
1431480093f4SDimitry Andric                             const ASTTemplateArgumentListInfo *ArgsAsWritten) {
14320fca6ea1SDimitry Andric 
14330fca6ea1SDimitry Andric   if (N.isCompound()) {
1434bdd1243dSDimitry Andric     if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1435480093f4SDimitry Andric                                     ArgsAsWritten))
1436480093f4SDimitry Andric       return true;
1437bdd1243dSDimitry Andric     return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1438480093f4SDimitry Andric                                        ArgsAsWritten);
1439480093f4SDimitry Andric   }
14400fca6ea1SDimitry Andric 
14410fca6ea1SDimitry Andric   if (N.isFoldExpanded()) {
14420fca6ea1SDimitry Andric     Sema::ArgumentPackSubstitutionIndexRAII _(S, -1);
14430fca6ea1SDimitry Andric     return substituteParameterMappings(
14440fca6ea1SDimitry Andric         S, N.getFoldExpandedConstraint()->Constraint, Concept, MLTAL,
14450fca6ea1SDimitry Andric         ArgsAsWritten);
14460fca6ea1SDimitry Andric   }
14470fca6ea1SDimitry Andric 
1448480093f4SDimitry Andric   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1449480093f4SDimitry Andric 
1450480093f4SDimitry Andric   AtomicConstraint &Atomic = *N.getAtomicConstraint();
1451480093f4SDimitry Andric   TemplateArgumentListInfo SubstArgs;
1452480093f4SDimitry Andric   if (!Atomic.ParameterMapping) {
1453480093f4SDimitry Andric     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1454480093f4SDimitry Andric     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1455480093f4SDimitry Andric                                  /*Depth=*/0, OccurringIndices);
1456bdd1243dSDimitry Andric     TemplateArgumentLoc *TempArgs =
1457bdd1243dSDimitry Andric         new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1458480093f4SDimitry Andric     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1459480093f4SDimitry Andric       if (OccurringIndices[I])
1460bdd1243dSDimitry Andric         new (&(TempArgs)[J++])
1461bdd1243dSDimitry Andric             TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(
1462bdd1243dSDimitry Andric                 TemplateParams->begin()[I],
1463480093f4SDimitry Andric                 // Here we assume we do not support things like
1464480093f4SDimitry Andric                 // template<typename A, typename B>
1465480093f4SDimitry Andric                 // concept C = ...;
1466480093f4SDimitry Andric                 //
1467480093f4SDimitry Andric                 // template<typename... Ts> requires C<Ts...>
1468480093f4SDimitry Andric                 // struct S { };
1469480093f4SDimitry Andric                 // The above currently yields a diagnostic.
1470480093f4SDimitry Andric                 // We still might have default arguments for concept parameters.
1471bdd1243dSDimitry Andric                 ArgsAsWritten->NumTemplateArgs > I
1472bdd1243dSDimitry Andric                     ? ArgsAsWritten->arguments()[I].getLocation()
1473bdd1243dSDimitry Andric                     : SourceLocation()));
1474bdd1243dSDimitry Andric     Atomic.ParameterMapping.emplace(TempArgs,  OccurringIndices.count());
1475480093f4SDimitry Andric   }
14760fca6ea1SDimitry Andric   SourceLocation InstLocBegin =
14770fca6ea1SDimitry Andric       ArgsAsWritten->arguments().empty()
14780fca6ea1SDimitry Andric           ? ArgsAsWritten->getLAngleLoc()
14790fca6ea1SDimitry Andric           : ArgsAsWritten->arguments().front().getSourceRange().getBegin();
14800fca6ea1SDimitry Andric   SourceLocation InstLocEnd =
14810fca6ea1SDimitry Andric       ArgsAsWritten->arguments().empty()
14820fca6ea1SDimitry Andric           ? ArgsAsWritten->getRAngleLoc()
14830fca6ea1SDimitry Andric           : ArgsAsWritten->arguments().front().getSourceRange().getEnd();
1484480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(
14850fca6ea1SDimitry Andric       S, InstLocBegin,
1486480093f4SDimitry Andric       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
14870fca6ea1SDimitry Andric       {InstLocBegin, InstLocEnd});
14880fca6ea1SDimitry Andric   if (Inst.isInvalid())
14890fca6ea1SDimitry Andric     return true;
1490480093f4SDimitry Andric   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1491480093f4SDimitry Andric     return true;
1492bdd1243dSDimitry Andric 
1493bdd1243dSDimitry Andric   TemplateArgumentLoc *TempArgs =
1494bdd1243dSDimitry Andric       new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1495480093f4SDimitry Andric   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1496bdd1243dSDimitry Andric             TempArgs);
1497bdd1243dSDimitry Andric   Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1498480093f4SDimitry Andric   return false;
1499480093f4SDimitry Andric }
1500480093f4SDimitry Andric 
substituteParameterMappings(Sema & S,NormalizedConstraint & N,const ConceptSpecializationExpr * CSE)1501bdd1243dSDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1502bdd1243dSDimitry Andric                                         const ConceptSpecializationExpr *CSE) {
1503bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
15045f757f3fSDimitry Andric       CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
15050fca6ea1SDimitry Andric       /*Final=*/false, CSE->getTemplateArguments(),
1506bdd1243dSDimitry Andric       /*RelativeToPrimary=*/true,
1507bdd1243dSDimitry Andric       /*Pattern=*/nullptr,
1508bdd1243dSDimitry Andric       /*ForConstraintInstantiation=*/true);
1509bdd1243dSDimitry Andric 
1510bdd1243dSDimitry Andric   return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1511bdd1243dSDimitry Andric                                      CSE->getTemplateArgsAsWritten());
1512bdd1243dSDimitry Andric }
1513bdd1243dSDimitry Andric 
NormalizedConstraint(ASTContext & C,NormalizedConstraint LHS,NormalizedConstraint RHS,CompoundConstraintKind Kind)15140fca6ea1SDimitry Andric NormalizedConstraint::NormalizedConstraint(ASTContext &C,
15150fca6ea1SDimitry Andric                                            NormalizedConstraint LHS,
15160fca6ea1SDimitry Andric                                            NormalizedConstraint RHS,
15170fca6ea1SDimitry Andric                                            CompoundConstraintKind Kind)
15180fca6ea1SDimitry Andric     : Constraint{CompoundConstraint{
15190fca6ea1SDimitry Andric           new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
15200fca6ea1SDimitry Andric           Kind}} {}
15210fca6ea1SDimitry Andric 
NormalizedConstraint(ASTContext & C,const NormalizedConstraint & Other)15220fca6ea1SDimitry Andric NormalizedConstraint::NormalizedConstraint(ASTContext &C,
15230fca6ea1SDimitry Andric                                            const NormalizedConstraint &Other) {
15240fca6ea1SDimitry Andric   if (Other.isAtomic()) {
15250fca6ea1SDimitry Andric     Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
15260fca6ea1SDimitry Andric   } else if (Other.isFoldExpanded()) {
15270fca6ea1SDimitry Andric     Constraint = new (C) FoldExpandedConstraint(
15280fca6ea1SDimitry Andric         Other.getFoldExpandedConstraint()->Kind,
15290fca6ea1SDimitry Andric         NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint),
15300fca6ea1SDimitry Andric         Other.getFoldExpandedConstraint()->Pattern);
15310fca6ea1SDimitry Andric   } else {
15320fca6ea1SDimitry Andric     Constraint = CompoundConstraint(
15330fca6ea1SDimitry Andric         new (C)
15340fca6ea1SDimitry Andric             NormalizedConstraintPair{NormalizedConstraint(C, Other.getLHS()),
15350fca6ea1SDimitry Andric                                      NormalizedConstraint(C, Other.getRHS())},
15360fca6ea1SDimitry Andric         Other.getCompoundKind());
15370fca6ea1SDimitry Andric   }
15380fca6ea1SDimitry Andric }
15390fca6ea1SDimitry Andric 
getLHS() const15400fca6ea1SDimitry Andric NormalizedConstraint &NormalizedConstraint::getLHS() const {
15410fca6ea1SDimitry Andric   assert(isCompound() && "getLHS called on a non-compound constraint.");
15420fca6ea1SDimitry Andric   return Constraint.get<CompoundConstraint>().getPointer()->LHS;
15430fca6ea1SDimitry Andric }
15440fca6ea1SDimitry Andric 
getRHS() const15450fca6ea1SDimitry Andric NormalizedConstraint &NormalizedConstraint::getRHS() const {
15460fca6ea1SDimitry Andric   assert(isCompound() && "getRHS called on a non-compound constraint.");
15470fca6ea1SDimitry Andric   return Constraint.get<CompoundConstraint>().getPointer()->RHS;
15480fca6ea1SDimitry Andric }
15490fca6ea1SDimitry Andric 
1550bdd1243dSDimitry Andric std::optional<NormalizedConstraint>
fromConstraintExprs(Sema & S,NamedDecl * D,ArrayRef<const Expr * > E)1551480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1552480093f4SDimitry Andric                                           ArrayRef<const Expr *> E) {
1553480093f4SDimitry Andric   assert(E.size() != 0);
15546e75b2fbSDimitry Andric   auto Conjunction = fromConstraintExpr(S, D, E[0]);
15556e75b2fbSDimitry Andric   if (!Conjunction)
1556bdd1243dSDimitry Andric     return std::nullopt;
15576e75b2fbSDimitry Andric   for (unsigned I = 1; I < E.size(); ++I) {
1558480093f4SDimitry Andric     auto Next = fromConstraintExpr(S, D, E[I]);
1559480093f4SDimitry Andric     if (!Next)
1560bdd1243dSDimitry Andric       return std::nullopt;
15616e75b2fbSDimitry Andric     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1562480093f4SDimitry Andric                                         std::move(*Next), CCK_Conjunction);
1563480093f4SDimitry Andric   }
1564480093f4SDimitry Andric   return Conjunction;
1565480093f4SDimitry Andric }
1566480093f4SDimitry Andric 
1567bdd1243dSDimitry Andric std::optional<NormalizedConstraint>
fromConstraintExpr(Sema & S,NamedDecl * D,const Expr * E)1568480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1569480093f4SDimitry Andric   assert(E != nullptr);
1570480093f4SDimitry Andric 
1571480093f4SDimitry Andric   // C++ [temp.constr.normal]p1.1
1572480093f4SDimitry Andric   // [...]
1573480093f4SDimitry Andric   // - The normal form of an expression (E) is the normal form of E.
1574480093f4SDimitry Andric   // [...]
1575480093f4SDimitry Andric   E = E->IgnoreParenImpCasts();
1576bdd1243dSDimitry Andric 
1577bdd1243dSDimitry Andric   // C++2a [temp.param]p4:
1578bdd1243dSDimitry Andric   //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1579bdd1243dSDimitry Andric   // Fold expression is considered atomic constraints per current wording.
1580bdd1243dSDimitry Andric   // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1581bdd1243dSDimitry Andric 
15825ffd83dbSDimitry Andric   if (LogicalBinOp BO = E) {
15835ffd83dbSDimitry Andric     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1584480093f4SDimitry Andric     if (!LHS)
1585bdd1243dSDimitry Andric       return std::nullopt;
15865ffd83dbSDimitry Andric     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1587480093f4SDimitry Andric     if (!RHS)
1588bdd1243dSDimitry Andric       return std::nullopt;
1589480093f4SDimitry Andric 
15905ffd83dbSDimitry Andric     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
15915ffd83dbSDimitry Andric                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1592480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1593480093f4SDimitry Andric     const NormalizedConstraint *SubNF;
1594480093f4SDimitry Andric     {
1595480093f4SDimitry Andric       Sema::InstantiatingTemplate Inst(
1596480093f4SDimitry Andric           S, CSE->getExprLoc(),
1597480093f4SDimitry Andric           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
1598480093f4SDimitry Andric           CSE->getSourceRange());
15990fca6ea1SDimitry Andric       if (Inst.isInvalid())
16000fca6ea1SDimitry Andric         return std::nullopt;
1601480093f4SDimitry Andric       // C++ [temp.constr.normal]p1.1
1602480093f4SDimitry Andric       // [...]
1603480093f4SDimitry Andric       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1604480093f4SDimitry Andric       // where C names a concept, is the normal form of the
1605480093f4SDimitry Andric       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1606480093f4SDimitry Andric       // respective template parameters in the parameter mappings in each atomic
1607480093f4SDimitry Andric       // constraint. If any such substitution results in an invalid type or
1608480093f4SDimitry Andric       // expression, the program is ill-formed; no diagnostic is required.
1609480093f4SDimitry Andric       // [...]
1610480093f4SDimitry Andric       ConceptDecl *CD = CSE->getNamedConcept();
1611480093f4SDimitry Andric       SubNF = S.getNormalizedAssociatedConstraints(CD,
1612480093f4SDimitry Andric                                                    {CD->getConstraintExpr()});
1613480093f4SDimitry Andric       if (!SubNF)
1614bdd1243dSDimitry Andric         return std::nullopt;
1615480093f4SDimitry Andric     }
1616480093f4SDimitry Andric 
1617bdd1243dSDimitry Andric     std::optional<NormalizedConstraint> New;
1618480093f4SDimitry Andric     New.emplace(S.Context, *SubNF);
1619480093f4SDimitry Andric 
1620bdd1243dSDimitry Andric     if (substituteParameterMappings(S, *New, CSE))
1621bdd1243dSDimitry Andric       return std::nullopt;
1622480093f4SDimitry Andric 
1623480093f4SDimitry Andric     return New;
16240fca6ea1SDimitry Andric   } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
16250fca6ea1SDimitry Andric              FE && S.getLangOpts().CPlusPlus26 &&
16260fca6ea1SDimitry Andric              (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
16270fca6ea1SDimitry Andric               FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
16280fca6ea1SDimitry Andric 
16290fca6ea1SDimitry Andric     // Normalize fold expressions in C++26.
16300fca6ea1SDimitry Andric 
16310fca6ea1SDimitry Andric     FoldExpandedConstraint::FoldOperatorKind Kind =
16320fca6ea1SDimitry Andric         FE->getOperator() == BinaryOperatorKind::BO_LAnd
16330fca6ea1SDimitry Andric             ? FoldExpandedConstraint::FoldOperatorKind::And
16340fca6ea1SDimitry Andric             : FoldExpandedConstraint::FoldOperatorKind::Or;
16350fca6ea1SDimitry Andric 
16360fca6ea1SDimitry Andric     if (FE->getInit()) {
16370fca6ea1SDimitry Andric       auto LHS = fromConstraintExpr(S, D, FE->getLHS());
16380fca6ea1SDimitry Andric       auto RHS = fromConstraintExpr(S, D, FE->getRHS());
16390fca6ea1SDimitry Andric       if (!LHS || !RHS)
16400fca6ea1SDimitry Andric         return std::nullopt;
16410fca6ea1SDimitry Andric 
16420fca6ea1SDimitry Andric       if (FE->isRightFold())
16430fca6ea1SDimitry Andric         RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
16440fca6ea1SDimitry Andric             Kind, std::move(*RHS), FE->getPattern()}};
16450fca6ea1SDimitry Andric       else
16460fca6ea1SDimitry Andric         LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
16470fca6ea1SDimitry Andric             Kind, std::move(*LHS), FE->getPattern()}};
16480fca6ea1SDimitry Andric 
16490fca6ea1SDimitry Andric       return NormalizedConstraint(
16500fca6ea1SDimitry Andric           S.Context, std::move(*LHS), std::move(*RHS),
16510fca6ea1SDimitry Andric           FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
16520fca6ea1SDimitry Andric                                                            : CCK_Disjunction);
1653480093f4SDimitry Andric     }
16540fca6ea1SDimitry Andric     auto Sub = fromConstraintExpr(S, D, FE->getPattern());
16550fca6ea1SDimitry Andric     if (!Sub)
16560fca6ea1SDimitry Andric       return std::nullopt;
16570fca6ea1SDimitry Andric     return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
16580fca6ea1SDimitry Andric         Kind, std::move(*Sub), FE->getPattern()}};
16590fca6ea1SDimitry Andric   }
16600fca6ea1SDimitry Andric 
1661480093f4SDimitry Andric   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
1662480093f4SDimitry Andric }
1663480093f4SDimitry Andric 
AreCompatibleForSubsumption(const FoldExpandedConstraint & A,const FoldExpandedConstraint & B)16640fca6ea1SDimitry Andric bool FoldExpandedConstraint::AreCompatibleForSubsumption(
16650fca6ea1SDimitry Andric     const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {
1666480093f4SDimitry Andric 
16670fca6ea1SDimitry Andric   // [C++26] [temp.constr.fold]
16680fca6ea1SDimitry Andric   // Two fold expanded constraints are compatible for subsumption
16690fca6ea1SDimitry Andric   // if their respective constraints both contain an equivalent unexpanded pack.
16700fca6ea1SDimitry Andric 
16710fca6ea1SDimitry Andric   llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks;
16720fca6ea1SDimitry Andric   Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks);
16730fca6ea1SDimitry Andric   Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks);
16740fca6ea1SDimitry Andric 
16750fca6ea1SDimitry Andric   for (const UnexpandedParameterPack &APack : APacks) {
16760fca6ea1SDimitry Andric     std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack);
16770fca6ea1SDimitry Andric     auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
16780fca6ea1SDimitry Andric       return getDepthAndIndex(BPack) == DepthAndIndex;
16790fca6ea1SDimitry Andric     });
16800fca6ea1SDimitry Andric     if (it != BPacks.end())
16810fca6ea1SDimitry Andric       return true;
16820fca6ea1SDimitry Andric   }
16830fca6ea1SDimitry Andric   return false;
16840fca6ea1SDimitry Andric }
16850fca6ea1SDimitry Andric 
makeCNF(const NormalizedConstraint & Normalized)16860fca6ea1SDimitry Andric NormalForm clang::makeCNF(const NormalizedConstraint &Normalized) {
1687480093f4SDimitry Andric   if (Normalized.isAtomic())
1688480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
1689480093f4SDimitry Andric 
16900fca6ea1SDimitry Andric   else if (Normalized.isFoldExpanded())
16910fca6ea1SDimitry Andric     return {{Normalized.getFoldExpandedConstraint()}};
16920fca6ea1SDimitry Andric 
1693480093f4SDimitry Andric   NormalForm LCNF = makeCNF(Normalized.getLHS());
1694480093f4SDimitry Andric   NormalForm RCNF = makeCNF(Normalized.getRHS());
1695480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
1696480093f4SDimitry Andric     LCNF.reserve(LCNF.size() + RCNF.size());
1697480093f4SDimitry Andric     while (!RCNF.empty())
1698480093f4SDimitry Andric       LCNF.push_back(RCNF.pop_back_val());
1699480093f4SDimitry Andric     return LCNF;
1700480093f4SDimitry Andric   }
1701480093f4SDimitry Andric 
1702480093f4SDimitry Andric   // Disjunction
1703480093f4SDimitry Andric   NormalForm Res;
1704480093f4SDimitry Andric   Res.reserve(LCNF.size() * RCNF.size());
1705480093f4SDimitry Andric   for (auto &LDisjunction : LCNF)
1706480093f4SDimitry Andric     for (auto &RDisjunction : RCNF) {
1707480093f4SDimitry Andric       NormalForm::value_type Combined;
1708480093f4SDimitry Andric       Combined.reserve(LDisjunction.size() + RDisjunction.size());
1709480093f4SDimitry Andric       std::copy(LDisjunction.begin(), LDisjunction.end(),
1710480093f4SDimitry Andric                 std::back_inserter(Combined));
1711480093f4SDimitry Andric       std::copy(RDisjunction.begin(), RDisjunction.end(),
1712480093f4SDimitry Andric                 std::back_inserter(Combined));
1713480093f4SDimitry Andric       Res.emplace_back(Combined);
1714480093f4SDimitry Andric     }
1715480093f4SDimitry Andric   return Res;
1716480093f4SDimitry Andric }
1717480093f4SDimitry Andric 
makeDNF(const NormalizedConstraint & Normalized)17180fca6ea1SDimitry Andric NormalForm clang::makeDNF(const NormalizedConstraint &Normalized) {
1719480093f4SDimitry Andric   if (Normalized.isAtomic())
1720480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
1721480093f4SDimitry Andric 
17220fca6ea1SDimitry Andric   else if (Normalized.isFoldExpanded())
17230fca6ea1SDimitry Andric     return {{Normalized.getFoldExpandedConstraint()}};
17240fca6ea1SDimitry Andric 
1725480093f4SDimitry Andric   NormalForm LDNF = makeDNF(Normalized.getLHS());
1726480093f4SDimitry Andric   NormalForm RDNF = makeDNF(Normalized.getRHS());
1727480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
1728480093f4SDimitry Andric     LDNF.reserve(LDNF.size() + RDNF.size());
1729480093f4SDimitry Andric     while (!RDNF.empty())
1730480093f4SDimitry Andric       LDNF.push_back(RDNF.pop_back_val());
1731480093f4SDimitry Andric     return LDNF;
1732480093f4SDimitry Andric   }
1733480093f4SDimitry Andric 
1734480093f4SDimitry Andric   // Conjunction
1735480093f4SDimitry Andric   NormalForm Res;
1736480093f4SDimitry Andric   Res.reserve(LDNF.size() * RDNF.size());
1737480093f4SDimitry Andric   for (auto &LConjunction : LDNF) {
1738480093f4SDimitry Andric     for (auto &RConjunction : RDNF) {
1739480093f4SDimitry Andric       NormalForm::value_type Combined;
1740480093f4SDimitry Andric       Combined.reserve(LConjunction.size() + RConjunction.size());
1741480093f4SDimitry Andric       std::copy(LConjunction.begin(), LConjunction.end(),
1742480093f4SDimitry Andric                 std::back_inserter(Combined));
1743480093f4SDimitry Andric       std::copy(RConjunction.begin(), RConjunction.end(),
1744480093f4SDimitry Andric                 std::back_inserter(Combined));
1745480093f4SDimitry Andric       Res.emplace_back(Combined);
1746480093f4SDimitry Andric     }
1747480093f4SDimitry Andric   }
1748480093f4SDimitry Andric   return Res;
1749480093f4SDimitry Andric }
1750480093f4SDimitry Andric 
IsAtLeastAsConstrained(NamedDecl * D1,MutableArrayRef<const Expr * > AC1,NamedDecl * D2,MutableArrayRef<const Expr * > AC2,bool & Result)1751bdd1243dSDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
1752bdd1243dSDimitry Andric                                   MutableArrayRef<const Expr *> AC1,
1753bdd1243dSDimitry Andric                                   NamedDecl *D2,
1754bdd1243dSDimitry Andric                                   MutableArrayRef<const Expr *> AC2,
1755480093f4SDimitry Andric                                   bool &Result) {
1756bdd1243dSDimitry Andric   if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1757bdd1243dSDimitry Andric     auto IsExpectedEntity = [](const FunctionDecl *FD) {
1758bdd1243dSDimitry Andric       FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
1759bdd1243dSDimitry Andric       return Kind == FunctionDecl::TK_NonTemplate ||
1760bdd1243dSDimitry Andric              Kind == FunctionDecl::TK_FunctionTemplate;
1761bdd1243dSDimitry Andric     };
1762bdd1243dSDimitry Andric     const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1763bdd1243dSDimitry Andric     (void)IsExpectedEntity;
1764bdd1243dSDimitry Andric     (void)FD1;
1765bdd1243dSDimitry Andric     (void)FD2;
1766bdd1243dSDimitry Andric     assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1767bdd1243dSDimitry Andric            "use non-instantiated function declaration for constraints partial "
1768bdd1243dSDimitry Andric            "ordering");
1769bdd1243dSDimitry Andric   }
1770bdd1243dSDimitry Andric 
1771480093f4SDimitry Andric   if (AC1.empty()) {
1772480093f4SDimitry Andric     Result = AC2.empty();
1773480093f4SDimitry Andric     return false;
1774480093f4SDimitry Andric   }
1775480093f4SDimitry Andric   if (AC2.empty()) {
1776480093f4SDimitry Andric     // TD1 has associated constraints and TD2 does not.
1777480093f4SDimitry Andric     Result = true;
1778480093f4SDimitry Andric     return false;
1779480093f4SDimitry Andric   }
1780480093f4SDimitry Andric 
1781480093f4SDimitry Andric   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1782480093f4SDimitry Andric   auto CacheEntry = SubsumptionCache.find(Key);
1783480093f4SDimitry Andric   if (CacheEntry != SubsumptionCache.end()) {
1784480093f4SDimitry Andric     Result = CacheEntry->second;
1785480093f4SDimitry Andric     return false;
1786480093f4SDimitry Andric   }
1787480093f4SDimitry Andric 
1788bdd1243dSDimitry Andric   unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1789bdd1243dSDimitry Andric   unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1790bdd1243dSDimitry Andric 
1791bdd1243dSDimitry Andric   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1792bdd1243dSDimitry Andric     if (Depth2 > Depth1) {
1793bdd1243dSDimitry Andric       AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1794bdd1243dSDimitry Andric                    .TransformExpr(const_cast<Expr *>(AC1[I]))
1795bdd1243dSDimitry Andric                    .get();
1796bdd1243dSDimitry Andric     } else if (Depth1 > Depth2) {
1797bdd1243dSDimitry Andric       AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1798bdd1243dSDimitry Andric                    .TransformExpr(const_cast<Expr *>(AC2[I]))
1799bdd1243dSDimitry Andric                    .get();
1800bdd1243dSDimitry Andric     }
1801bdd1243dSDimitry Andric   }
1802bdd1243dSDimitry Andric 
18030fca6ea1SDimitry Andric   if (clang::subsumes(
18040fca6ea1SDimitry Andric           *this, D1, AC1, D2, AC2, Result,
1805480093f4SDimitry Andric           [this](const AtomicConstraint &A, const AtomicConstraint &B) {
1806480093f4SDimitry Andric             return A.subsumes(Context, B);
1807480093f4SDimitry Andric           }))
1808480093f4SDimitry Andric     return true;
1809480093f4SDimitry Andric   SubsumptionCache.try_emplace(Key, Result);
1810480093f4SDimitry Andric   return false;
1811480093f4SDimitry Andric }
1812480093f4SDimitry Andric 
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl * D1,ArrayRef<const Expr * > AC1,NamedDecl * D2,ArrayRef<const Expr * > AC2)1813480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
1814480093f4SDimitry Andric     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
1815480093f4SDimitry Andric   if (isSFINAEContext())
1816480093f4SDimitry Andric     // No need to work here because our notes would be discarded.
1817480093f4SDimitry Andric     return false;
1818480093f4SDimitry Andric 
1819480093f4SDimitry Andric   if (AC1.empty() || AC2.empty())
1820480093f4SDimitry Andric     return false;
1821480093f4SDimitry Andric 
1822480093f4SDimitry Andric   auto NormalExprEvaluator =
1823480093f4SDimitry Andric       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1824480093f4SDimitry Andric         return A.subsumes(Context, B);
1825480093f4SDimitry Andric       };
1826480093f4SDimitry Andric 
1827480093f4SDimitry Andric   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1828480093f4SDimitry Andric   auto IdenticalExprEvaluator =
1829480093f4SDimitry Andric       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1830480093f4SDimitry Andric         if (!A.hasMatchingParameterMapping(Context, B))
1831480093f4SDimitry Andric           return false;
1832480093f4SDimitry Andric         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1833480093f4SDimitry Andric         if (EA == EB)
1834480093f4SDimitry Andric           return true;
1835480093f4SDimitry Andric 
1836480093f4SDimitry Andric         // Not the same source level expression - are the expressions
1837480093f4SDimitry Andric         // identical?
1838480093f4SDimitry Andric         llvm::FoldingSetNodeID IDA, IDB;
1839349cc55cSDimitry Andric         EA->Profile(IDA, Context, /*Canonical=*/true);
1840349cc55cSDimitry Andric         EB->Profile(IDB, Context, /*Canonical=*/true);
1841480093f4SDimitry Andric         if (IDA != IDB)
1842480093f4SDimitry Andric           return false;
1843480093f4SDimitry Andric 
1844480093f4SDimitry Andric         AmbiguousAtomic1 = EA;
1845480093f4SDimitry Andric         AmbiguousAtomic2 = EB;
1846480093f4SDimitry Andric         return true;
1847480093f4SDimitry Andric       };
1848480093f4SDimitry Andric 
1849480093f4SDimitry Andric   {
1850480093f4SDimitry Andric     // The subsumption checks might cause diagnostics
1851480093f4SDimitry Andric     SFINAETrap Trap(*this);
1852480093f4SDimitry Andric     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1853480093f4SDimitry Andric     if (!Normalized1)
1854480093f4SDimitry Andric       return false;
1855480093f4SDimitry Andric     const NormalForm DNF1 = makeDNF(*Normalized1);
1856480093f4SDimitry Andric     const NormalForm CNF1 = makeCNF(*Normalized1);
1857480093f4SDimitry Andric 
1858480093f4SDimitry Andric     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1859480093f4SDimitry Andric     if (!Normalized2)
1860480093f4SDimitry Andric       return false;
1861480093f4SDimitry Andric     const NormalForm DNF2 = makeDNF(*Normalized2);
1862480093f4SDimitry Andric     const NormalForm CNF2 = makeCNF(*Normalized2);
1863480093f4SDimitry Andric 
18640fca6ea1SDimitry Andric     bool Is1AtLeastAs2Normally =
18650fca6ea1SDimitry Andric         clang::subsumes(DNF1, CNF2, NormalExprEvaluator);
18660fca6ea1SDimitry Andric     bool Is2AtLeastAs1Normally =
18670fca6ea1SDimitry Andric         clang::subsumes(DNF2, CNF1, NormalExprEvaluator);
18680fca6ea1SDimitry Andric     bool Is1AtLeastAs2 = clang::subsumes(DNF1, CNF2, IdenticalExprEvaluator);
18690fca6ea1SDimitry Andric     bool Is2AtLeastAs1 = clang::subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1870480093f4SDimitry Andric     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1871480093f4SDimitry Andric         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1872480093f4SDimitry Andric       // Same result - no ambiguity was caused by identical atomic expressions.
1873480093f4SDimitry Andric       return false;
1874480093f4SDimitry Andric   }
1875480093f4SDimitry Andric 
1876480093f4SDimitry Andric   // A different result! Some ambiguous atomic constraint(s) caused a difference
1877480093f4SDimitry Andric   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1878480093f4SDimitry Andric 
1879480093f4SDimitry Andric   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1880480093f4SDimitry Andric       << AmbiguousAtomic1->getSourceRange();
1881480093f4SDimitry Andric   Diag(AmbiguousAtomic2->getBeginLoc(),
1882480093f4SDimitry Andric        diag::note_ambiguous_atomic_constraints_similar_expression)
1883480093f4SDimitry Andric       << AmbiguousAtomic2->getSourceRange();
1884480093f4SDimitry Andric   return true;
1885480093f4SDimitry Andric }
188655e4f9d5SDimitry Andric 
ExprRequirement(Expr * E,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req,SatisfactionStatus Status,ConceptSpecializationExpr * SubstitutedConstraintExpr)188755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
188855e4f9d5SDimitry Andric     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
188955e4f9d5SDimitry Andric     ReturnTypeRequirement Req, SatisfactionStatus Status,
189055e4f9d5SDimitry Andric     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
189155e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
189255e4f9d5SDimitry Andric                 Status == SS_Dependent &&
189355e4f9d5SDimitry Andric                 (E->containsUnexpandedParameterPack() ||
189455e4f9d5SDimitry Andric                  Req.containsUnexpandedParameterPack()),
189555e4f9d5SDimitry Andric                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
189655e4f9d5SDimitry Andric     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
189755e4f9d5SDimitry Andric     Status(Status) {
189855e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
189955e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
190055e4f9d5SDimitry Andric          "noexcept specification");
190155e4f9d5SDimitry Andric   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
190255e4f9d5SDimitry Andric          (SubstitutedConstraintExpr != nullptr));
190355e4f9d5SDimitry Andric }
190455e4f9d5SDimitry Andric 
ExprRequirement(SubstitutionDiagnostic * ExprSubstDiag,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req)190555e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
190655e4f9d5SDimitry Andric     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
190755e4f9d5SDimitry Andric     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
190855e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
190955e4f9d5SDimitry Andric                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
191055e4f9d5SDimitry Andric     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
191155e4f9d5SDimitry Andric     Status(SS_ExprSubstitutionFailure) {
191255e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
191355e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
191455e4f9d5SDimitry Andric          "noexcept specification");
191555e4f9d5SDimitry Andric }
191655e4f9d5SDimitry Andric 
191755e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement::
ReturnTypeRequirement(TemplateParameterList * TPL)191855e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) :
191904eeddc0SDimitry Andric     TypeConstraintInfo(TPL, false) {
192055e4f9d5SDimitry Andric   assert(TPL->size() == 1);
192155e4f9d5SDimitry Andric   const TypeConstraint *TC =
192255e4f9d5SDimitry Andric       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
192355e4f9d5SDimitry Andric   assert(TC &&
192455e4f9d5SDimitry Andric          "TPL must have a template type parameter with a type constraint");
192555e4f9d5SDimitry Andric   auto *Constraint =
1926349cc55cSDimitry Andric       cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1927e8d8bef9SDimitry Andric   bool Dependent =
1928e8d8bef9SDimitry Andric       Constraint->getTemplateArgsAsWritten() &&
1929e8d8bef9SDimitry Andric       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1930e8d8bef9SDimitry Andric           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
193104eeddc0SDimitry Andric   TypeConstraintInfo.setInt(Dependent ? true : false);
193255e4f9d5SDimitry Andric }
193355e4f9d5SDimitry Andric 
TypeRequirement(TypeSourceInfo * T)193455e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1935e8d8bef9SDimitry Andric     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
193655e4f9d5SDimitry Andric                 T->getType()->containsUnexpandedParameterPack(),
193755e4f9d5SDimitry Andric                 // We reach this ctor with either dependent types (in which
193855e4f9d5SDimitry Andric                 // IsSatisfied doesn't matter) or with non-dependent type in
193955e4f9d5SDimitry Andric                 // which the existence of the type indicates satisfaction.
1940e8d8bef9SDimitry Andric                 /*IsSatisfied=*/true),
1941e8d8bef9SDimitry Andric     Value(T),
1942e8d8bef9SDimitry Andric     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1943e8d8bef9SDimitry Andric                                                         : SS_Satisfied) {}
1944