xref: /llvm-project/clang/lib/Sema/SemaConcept.cpp (revision 69d0c4c1675c90cf99126210679a9c3ae0a8637e)
15d98ba60SSaar Raz //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
25d98ba60SSaar Raz //
3c874dd53SChristopher Di Bella // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c874dd53SChristopher Di Bella // See https://llvm.org/LICENSE.txt for license information.
5c874dd53SChristopher Di Bella // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65d98ba60SSaar Raz //
75d98ba60SSaar Raz //===----------------------------------------------------------------------===//
85d98ba60SSaar Raz //
95d98ba60SSaar Raz //  This file implements semantic analysis for C++ constraints and concepts.
105d98ba60SSaar Raz //
115d98ba60SSaar Raz //===----------------------------------------------------------------------===//
125d98ba60SSaar Raz 
13b65b1f32SSaar Raz #include "clang/Sema/SemaConcept.h"
146d688055SDavid Stone #include "TreeTransform.h"
15babdef27SErich Keane #include "clang/AST/ASTLambda.h"
16158f4f30SCorentin Jabot #include "clang/AST/DeclCXX.h"
17a0f50d73SSaar Raz #include "clang/AST/ExprConcepts.h"
18b65b1f32SSaar Raz #include "clang/Basic/OperatorPrecedence.h"
196d688055SDavid Stone #include "clang/Sema/EnterExpressionEvaluationContext.h"
206d688055SDavid Stone #include "clang/Sema/Initialization.h"
216d688055SDavid Stone #include "clang/Sema/Overload.h"
22158f4f30SCorentin Jabot #include "clang/Sema/ScopeInfo.h"
236d688055SDavid Stone #include "clang/Sema/Sema.h"
246d688055SDavid Stone #include "clang/Sema/SemaInternal.h"
256d688055SDavid Stone #include "clang/Sema/Template.h"
266d688055SDavid Stone #include "clang/Sema/TemplateDeduction.h"
27fdf80e86SSaar Raz #include "llvm/ADT/DenseMap.h"
28fdf80e86SSaar Raz #include "llvm/ADT/PointerUnion.h"
2961cdaf66SSimon Pilgrim #include "llvm/ADT/StringExtras.h"
30a1580d7bSKazu Hirata #include <optional>
3161cdaf66SSimon Pilgrim 
325d98ba60SSaar Raz using namespace clang;
335d98ba60SSaar Raz using namespace sema;
345d98ba60SSaar Raz 
356c29073eSRichard Smith namespace {
366c29073eSRichard Smith class LogicalBinOp {
37babdef27SErich Keane   SourceLocation Loc;
386c29073eSRichard Smith   OverloadedOperatorKind Op = OO_None;
396c29073eSRichard Smith   const Expr *LHS = nullptr;
406c29073eSRichard Smith   const Expr *RHS = nullptr;
416c29073eSRichard Smith 
426c29073eSRichard Smith public:
436c29073eSRichard Smith   LogicalBinOp(const Expr *E) {
446c29073eSRichard Smith     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
456c29073eSRichard Smith       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
466c29073eSRichard Smith       LHS = BO->getLHS();
476c29073eSRichard Smith       RHS = BO->getRHS();
48babdef27SErich Keane       Loc = BO->getExprLoc();
496c29073eSRichard Smith     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
5022aa3680SCorentin Jabot       // If OO is not || or && it might not have exactly 2 arguments.
5122aa3680SCorentin Jabot       if (OO->getNumArgs() == 2) {
526c29073eSRichard Smith         Op = OO->getOperator();
536c29073eSRichard Smith         LHS = OO->getArg(0);
546c29073eSRichard Smith         RHS = OO->getArg(1);
55babdef27SErich Keane         Loc = OO->getOperatorLoc();
566c29073eSRichard Smith       }
576c29073eSRichard Smith     }
5822aa3680SCorentin Jabot   }
596c29073eSRichard Smith 
606c29073eSRichard Smith   bool isAnd() const { return Op == OO_AmpAmp; }
616c29073eSRichard Smith   bool isOr() const { return Op == OO_PipePipe; }
626c29073eSRichard Smith   explicit operator bool() const { return isAnd() || isOr(); }
636c29073eSRichard Smith 
646c29073eSRichard Smith   const Expr *getLHS() const { return LHS; }
656c29073eSRichard Smith   const Expr *getRHS() const { return RHS; }
66b330d800Scor3ntin   OverloadedOperatorKind getOp() const { return Op; }
67babdef27SErich Keane 
68babdef27SErich Keane   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
69babdef27SErich Keane     return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
70babdef27SErich Keane   }
71babdef27SErich Keane 
72babdef27SErich Keane   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
73babdef27SErich Keane                            ExprResult RHS) const {
74babdef27SErich Keane     assert((isAnd() || isOr()) && "Not the right kind of op?");
75babdef27SErich Keane     assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
76babdef27SErich Keane 
77babdef27SErich Keane     if (!LHS.isUsable() || !RHS.isUsable())
78babdef27SErich Keane       return ExprEmpty();
79babdef27SErich Keane 
80babdef27SErich Keane     // We should just be able to 'normalize' these to the builtin Binary
81babdef27SErich Keane     // Operator, since that is how they are evaluated in constriant checks.
82babdef27SErich Keane     return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
83babdef27SErich Keane                                   BinaryOperator::getOverloadedOpcode(Op),
84babdef27SErich Keane                                   SemaRef.Context.BoolTy, VK_PRValue,
85babdef27SErich Keane                                   OK_Ordinary, Loc, FPOptionsOverride{});
86babdef27SErich Keane   }
876c29073eSRichard Smith };
886c29073eSRichard Smith }
896c29073eSRichard Smith 
906c29073eSRichard Smith bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
916c29073eSRichard Smith                                      Token NextToken, bool *PossibleNonPrimary,
92b65b1f32SSaar Raz                                      bool IsTrailingRequiresClause) {
935d98ba60SSaar Raz   // C++2a [temp.constr.atomic]p1
945d98ba60SSaar Raz   // ..E shall be a constant expression of type bool.
955d98ba60SSaar Raz 
965d98ba60SSaar Raz   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
975d98ba60SSaar Raz 
986c29073eSRichard Smith   if (LogicalBinOp BO = ConstraintExpression) {
996c29073eSRichard Smith     return CheckConstraintExpression(BO.getLHS(), NextToken,
100b65b1f32SSaar Raz                                      PossibleNonPrimary) &&
1016c29073eSRichard Smith            CheckConstraintExpression(BO.getRHS(), NextToken,
102b65b1f32SSaar Raz                                      PossibleNonPrimary);
1035d98ba60SSaar Raz   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
104b65b1f32SSaar Raz     return CheckConstraintExpression(C->getSubExpr(), NextToken,
105b65b1f32SSaar Raz                                      PossibleNonPrimary);
1065d98ba60SSaar Raz 
1075d98ba60SSaar Raz   QualType Type = ConstraintExpression->getType();
108b65b1f32SSaar Raz 
109b65b1f32SSaar Raz   auto CheckForNonPrimary = [&] {
1106acdf589SEmilia Dreamer     if (!PossibleNonPrimary)
1116acdf589SEmilia Dreamer       return;
1126acdf589SEmilia Dreamer 
113b65b1f32SSaar Raz     *PossibleNonPrimary =
114b65b1f32SSaar Raz         // We have the following case:
115b65b1f32SSaar Raz         // template<typename> requires func(0) struct S { };
116b65b1f32SSaar Raz         // The user probably isn't aware of the parentheses required around
117b65b1f32SSaar Raz         // the function call, and we're only going to parse 'func' as the
118b65b1f32SSaar Raz         // primary-expression, and complain that it is of non-bool type.
1196acdf589SEmilia Dreamer         //
1206acdf589SEmilia Dreamer         // However, if we're in a lambda, this might also be:
1216acdf589SEmilia Dreamer         // []<typename> requires var () {};
1226acdf589SEmilia Dreamer         // Which also looks like a function call due to the lambda parentheses,
1236acdf589SEmilia Dreamer         // but unlike the first case, isn't an error, so this check is skipped.
124b65b1f32SSaar Raz         (NextToken.is(tok::l_paren) &&
125b65b1f32SSaar Raz          (IsTrailingRequiresClause ||
126b65b1f32SSaar Raz           (Type->isDependentType() &&
1276acdf589SEmilia Dreamer            isa<UnresolvedLookupExpr>(ConstraintExpression) &&
1286acdf589SEmilia Dreamer            !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
129b65b1f32SSaar Raz           Type->isFunctionType() ||
130b65b1f32SSaar Raz           Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
131b65b1f32SSaar Raz         // We have the following case:
132b65b1f32SSaar Raz         // template<typename T> requires size_<T> == 0 struct S { };
133b65b1f32SSaar Raz         // The user probably isn't aware of the parentheses required around
134b65b1f32SSaar Raz         // the binary operator, and we're only going to parse 'func' as the
135b65b1f32SSaar Raz         // first operand, and complain that it is of non-bool type.
136b65b1f32SSaar Raz         getBinOpPrecedence(NextToken.getKind(),
137b65b1f32SSaar Raz                            /*GreaterThanIsOperator=*/true,
138b65b1f32SSaar Raz                            getLangOpts().CPlusPlus11) > prec::LogicalAnd;
139b65b1f32SSaar Raz   };
140b65b1f32SSaar Raz 
141b65b1f32SSaar Raz   // An atomic constraint!
142b65b1f32SSaar Raz   if (ConstraintExpression->isTypeDependent()) {
143b65b1f32SSaar Raz     CheckForNonPrimary();
144b65b1f32SSaar Raz     return true;
145b65b1f32SSaar Raz   }
146b65b1f32SSaar Raz 
1475d98ba60SSaar Raz   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
1485d98ba60SSaar Raz     Diag(ConstraintExpression->getExprLoc(),
1495d98ba60SSaar Raz          diag::err_non_bool_atomic_constraint) << Type
1505d98ba60SSaar Raz         << ConstraintExpression->getSourceRange();
151b65b1f32SSaar Raz     CheckForNonPrimary();
1525d98ba60SSaar Raz     return false;
1535d98ba60SSaar Raz   }
154b65b1f32SSaar Raz 
155b65b1f32SSaar Raz   if (PossibleNonPrimary)
156b65b1f32SSaar Raz       *PossibleNonPrimary = false;
1575d98ba60SSaar Raz   return true;
1585d98ba60SSaar Raz }
1595d98ba60SSaar Raz 
1602cee2663SErich Keane namespace {
1612cee2663SErich Keane struct SatisfactionStackRAII {
1622cee2663SErich Keane   Sema &SemaRef;
16342667563SErich Keane   bool Inserted = false;
16442667563SErich Keane   SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
16533cf2a39SManna, Soumi                         const llvm::FoldingSetNodeID &FSNID)
1662cee2663SErich Keane       : SemaRef(SemaRef) {
16742667563SErich Keane       if (ND) {
16842667563SErich Keane       SemaRef.PushSatisfactionStackEntry(ND, FSNID);
16942667563SErich Keane       Inserted = true;
1702cee2663SErich Keane       }
17142667563SErich Keane   }
17242667563SErich Keane   ~SatisfactionStackRAII() {
17342667563SErich Keane         if (Inserted)
17442667563SErich Keane           SemaRef.PopSatisfactionStackEntry();
17542667563SErich Keane   }
1762cee2663SErich Keane };
1772cee2663SErich Keane } // namespace
1782cee2663SErich Keane 
179b330d800Scor3ntin template <typename ConstraintEvaluator>
180babdef27SErich Keane static ExprResult
181fdf80e86SSaar Raz calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
182fdf80e86SSaar Raz                                 ConstraintSatisfaction &Satisfaction,
183b330d800Scor3ntin                                 const ConstraintEvaluator &Evaluator);
1845d98ba60SSaar Raz 
185b330d800Scor3ntin template <typename ConstraintEvaluator>
186b330d800Scor3ntin static ExprResult
187b330d800Scor3ntin calculateConstraintSatisfaction(Sema &S, const Expr *LHS,
188b330d800Scor3ntin                                 OverloadedOperatorKind Op, const Expr *RHS,
189b330d800Scor3ntin                                 ConstraintSatisfaction &Satisfaction,
190b330d800Scor3ntin                                 const ConstraintEvaluator &Evaluator) {
1914af62db0STakuya Shimizu   size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
192b330d800Scor3ntin 
193b330d800Scor3ntin   ExprResult LHSRes =
194b330d800Scor3ntin       calculateConstraintSatisfaction(S, LHS, Satisfaction, Evaluator);
195babdef27SErich Keane 
196babdef27SErich Keane   if (LHSRes.isInvalid())
197babdef27SErich Keane     return ExprError();
198fdf80e86SSaar Raz 
199fdf80e86SSaar Raz   bool IsLHSSatisfied = Satisfaction.IsSatisfied;
200fdf80e86SSaar Raz 
201b330d800Scor3ntin   if (Op == clang::OO_PipePipe && IsLHSSatisfied)
202fdf80e86SSaar Raz     // [temp.constr.op] p3
203fdf80e86SSaar Raz     //    A disjunction is a constraint taking two operands. To determine if
204fdf80e86SSaar Raz     //    a disjunction is satisfied, the satisfaction of the first operand
205fdf80e86SSaar Raz     //    is checked. If that is satisfied, the disjunction is satisfied.
206fdf80e86SSaar Raz     //    Otherwise, the disjunction is satisfied if and only if the second
207fdf80e86SSaar Raz     //    operand is satisfied.
208b3ce8728SUtkarsh Saxena     // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
209b3ce8728SUtkarsh Saxena     return LHSRes;
210fdf80e86SSaar Raz 
211b330d800Scor3ntin   if (Op == clang::OO_AmpAmp && !IsLHSSatisfied)
212fdf80e86SSaar Raz     // [temp.constr.op] p2
213fdf80e86SSaar Raz     //    A conjunction is a constraint taking two operands. To determine if
214fdf80e86SSaar Raz     //    a conjunction is satisfied, the satisfaction of the first operand
215fdf80e86SSaar Raz     //    is checked. If that is not satisfied, the conjunction is not
216fdf80e86SSaar Raz     //    satisfied. Otherwise, the conjunction is satisfied if and only if
217fdf80e86SSaar Raz     //    the second operand is satisfied.
218b3ce8728SUtkarsh Saxena     // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
219b3ce8728SUtkarsh Saxena     return LHSRes;
220fdf80e86SSaar Raz 
221b330d800Scor3ntin   ExprResult RHSRes =
222b330d800Scor3ntin       calculateConstraintSatisfaction(S, RHS, Satisfaction, Evaluator);
223babdef27SErich Keane   if (RHSRes.isInvalid())
224babdef27SErich Keane     return ExprError();
225babdef27SErich Keane 
226b2cd9db5STakuya Shimizu   bool IsRHSSatisfied = Satisfaction.IsSatisfied;
227b2cd9db5STakuya Shimizu   // Current implementation adds diagnostic information about the falsity
228b2cd9db5STakuya Shimizu   // of each false atomic constraint expression when it evaluates them.
229b2cd9db5STakuya Shimizu   // When the evaluation results to `false || true`, the information
230b2cd9db5STakuya Shimizu   // generated during the evaluation of left-hand side is meaningless
231b2cd9db5STakuya Shimizu   // because the whole expression evaluates to true.
232b2cd9db5STakuya Shimizu   // The following code removes the irrelevant diagnostic information.
233b2cd9db5STakuya Shimizu   // FIXME: We should probably delay the addition of diagnostic information
234b2cd9db5STakuya Shimizu   // until we know the entire expression is false.
235b330d800Scor3ntin   if (Op == clang::OO_PipePipe && IsRHSSatisfied) {
236b330d800Scor3ntin     auto EffectiveDetailEnd = Satisfaction.Details.begin();
237b330d800Scor3ntin     std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
238b330d800Scor3ntin     Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end());
239b330d800Scor3ntin   }
240b330d800Scor3ntin 
241b330d800Scor3ntin   if (!LHSRes.isUsable() || !RHSRes.isUsable())
242b330d800Scor3ntin     return ExprEmpty();
243b330d800Scor3ntin 
244b330d800Scor3ntin   return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(),
245b330d800Scor3ntin                                 BinaryOperator::getOverloadedOpcode(Op),
246b330d800Scor3ntin                                 S.Context.BoolTy, VK_PRValue, OK_Ordinary,
247b330d800Scor3ntin                                 LHS->getBeginLoc(), FPOptionsOverride{});
248b330d800Scor3ntin }
249b330d800Scor3ntin 
250b330d800Scor3ntin template <typename ConstraintEvaluator>
251b330d800Scor3ntin static ExprResult
252b330d800Scor3ntin calculateConstraintSatisfaction(Sema &S, const CXXFoldExpr *FE,
253b330d800Scor3ntin                                 ConstraintSatisfaction &Satisfaction,
254b330d800Scor3ntin                                 const ConstraintEvaluator &Evaluator) {
255b330d800Scor3ntin   bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd;
256b330d800Scor3ntin   size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
257b330d800Scor3ntin 
258b330d800Scor3ntin   ExprResult Out;
259b330d800Scor3ntin   if (FE->isLeftFold() && FE->getInit()) {
260b330d800Scor3ntin     Out = calculateConstraintSatisfaction(S, FE->getInit(), Satisfaction,
261b330d800Scor3ntin                                           Evaluator);
262b330d800Scor3ntin     if (Out.isInvalid())
263b330d800Scor3ntin       return ExprError();
264b330d800Scor3ntin 
265b330d800Scor3ntin     // If the first clause of a conjunction is not satisfied,
266b330d800Scor3ntin     // or if the first clause of a disjection is satisfied,
267b330d800Scor3ntin     // we have established satisfaction of the whole constraint
268b330d800Scor3ntin     // and we should not continue further.
269b330d800Scor3ntin     if (Conjunction != Satisfaction.IsSatisfied)
270b330d800Scor3ntin       return Out;
271b330d800Scor3ntin   }
272b330d800Scor3ntin   std::optional<unsigned> NumExpansions =
273b330d800Scor3ntin       Evaluator.EvaluateFoldExpandedConstraintSize(FE);
274b330d800Scor3ntin   if (!NumExpansions)
275b330d800Scor3ntin     return ExprError();
276b330d800Scor3ntin   for (unsigned I = 0; I < *NumExpansions; I++) {
277b330d800Scor3ntin     Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(S, I);
278b330d800Scor3ntin     ExprResult Res = calculateConstraintSatisfaction(S, FE->getPattern(),
279b330d800Scor3ntin                                                      Satisfaction, Evaluator);
280b330d800Scor3ntin     if (Res.isInvalid())
281b330d800Scor3ntin       return ExprError();
282b330d800Scor3ntin     bool IsRHSSatisfied = Satisfaction.IsSatisfied;
283b330d800Scor3ntin     if (!Conjunction && IsRHSSatisfied) {
2844af62db0STakuya Shimizu       auto EffectiveDetailEnd = Satisfaction.Details.begin();
2854af62db0STakuya Shimizu       std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
286b2cd9db5STakuya Shimizu       Satisfaction.Details.erase(EffectiveDetailEnd,
287b2cd9db5STakuya Shimizu                                  Satisfaction.Details.end());
2884af62db0STakuya Shimizu     }
289b330d800Scor3ntin     if (Out.isUnset())
290b330d800Scor3ntin       Out = Res;
291b330d800Scor3ntin     else if (!Res.isUnset()) {
292b330d800Scor3ntin       Out = BinaryOperator::Create(
293b330d800Scor3ntin           S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
294b330d800Scor3ntin           VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});
29524489273Scor3ntin     }
296b330d800Scor3ntin     if (Conjunction != IsRHSSatisfied)
297b330d800Scor3ntin       return Out;
298b330d800Scor3ntin   }
299b330d800Scor3ntin 
300b330d800Scor3ntin   if (FE->isRightFold() && FE->getInit()) {
301b330d800Scor3ntin     ExprResult Res = calculateConstraintSatisfaction(S, FE->getInit(),
302b330d800Scor3ntin                                                      Satisfaction, Evaluator);
303b330d800Scor3ntin     if (Out.isInvalid())
304b330d800Scor3ntin       return ExprError();
305b330d800Scor3ntin 
306b330d800Scor3ntin     if (Out.isUnset())
307b330d800Scor3ntin       Out = Res;
308b330d800Scor3ntin     else if (!Res.isUnset()) {
309b330d800Scor3ntin       Out = BinaryOperator::Create(
310b330d800Scor3ntin           S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
311b330d800Scor3ntin           VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});
312b330d800Scor3ntin     }
313b330d800Scor3ntin   }
314b330d800Scor3ntin 
315b330d800Scor3ntin   if (Out.isUnset()) {
316b330d800Scor3ntin     Satisfaction.IsSatisfied = Conjunction;
317b330d800Scor3ntin     Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator());
318b330d800Scor3ntin   }
319b330d800Scor3ntin   return Out;
320b330d800Scor3ntin }
321b330d800Scor3ntin 
322b330d800Scor3ntin template <typename ConstraintEvaluator>
323b330d800Scor3ntin static ExprResult
324b330d800Scor3ntin calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
325b330d800Scor3ntin                                 ConstraintSatisfaction &Satisfaction,
326b330d800Scor3ntin                                 const ConstraintEvaluator &Evaluator) {
327b330d800Scor3ntin   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
328b330d800Scor3ntin 
329b330d800Scor3ntin   if (LogicalBinOp BO = ConstraintExpr)
330b330d800Scor3ntin     return calculateConstraintSatisfaction(
331b330d800Scor3ntin         S, BO.getLHS(), BO.getOp(), BO.getRHS(), Satisfaction, Evaluator);
332babdef27SErich Keane 
333babdef27SErich Keane   if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
334babdef27SErich Keane     // These aren't evaluated, so we don't care about cleanups, so we can just
335babdef27SErich Keane     // evaluate these as if the cleanups didn't exist.
336b330d800Scor3ntin     return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
337b330d800Scor3ntin                                            Evaluator);
338b330d800Scor3ntin   }
339b330d800Scor3ntin 
340b330d800Scor3ntin   if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr);
341b330d800Scor3ntin       FE && S.getLangOpts().CPlusPlus26 &&
342b330d800Scor3ntin       (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
343b330d800Scor3ntin        FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
344b330d800Scor3ntin     return calculateConstraintSatisfaction(S, FE, Satisfaction, Evaluator);
3456c29073eSRichard Smith   }
346fdf80e86SSaar Raz 
347fdf80e86SSaar Raz   // An atomic constraint expression
348b330d800Scor3ntin   ExprResult SubstitutedAtomicExpr =
349b330d800Scor3ntin       Evaluator.EvaluateAtomicConstraint(ConstraintExpr);
350fdf80e86SSaar Raz 
351fdf80e86SSaar Raz   if (SubstitutedAtomicExpr.isInvalid())
352babdef27SErich Keane     return ExprError();
353fdf80e86SSaar Raz 
354fdf80e86SSaar Raz   if (!SubstitutedAtomicExpr.isUsable())
355fdf80e86SSaar Raz     // Evaluator has decided satisfaction without yielding an expression.
356babdef27SErich Keane     return ExprEmpty();
3575d98ba60SSaar Raz 
358684a7896SErich Keane   // We don't have the ability to evaluate this, since it contains a
359684a7896SErich Keane   // RecoveryExpr, so we want to fail overload resolution.  Otherwise,
360684a7896SErich Keane   // we'd potentially pick up a different overload, and cause confusing
361684a7896SErich Keane   // diagnostics. SO, add a failure detail that will cause us to make this
362684a7896SErich Keane   // overload set not viable.
363684a7896SErich Keane   if (SubstitutedAtomicExpr.get()->containsErrors()) {
364684a7896SErich Keane     Satisfaction.IsSatisfied = false;
365684a7896SErich Keane     Satisfaction.ContainsErrors = true;
366684a7896SErich Keane 
367684a7896SErich Keane     PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
368684a7896SErich Keane     SmallString<128> DiagString;
369684a7896SErich Keane     DiagString = ": ";
370684a7896SErich Keane     Msg.EmitToString(S.getDiagnostics(), DiagString);
371684a7896SErich Keane     unsigned MessageSize = DiagString.size();
372684a7896SErich Keane     char *Mem = new (S.Context) char[MessageSize];
373684a7896SErich Keane     memcpy(Mem, DiagString.c_str(), MessageSize);
374684a7896SErich Keane     Satisfaction.Details.emplace_back(
375684a7896SErich Keane         new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
376684a7896SErich Keane             SubstitutedAtomicExpr.get()->getBeginLoc(),
377684a7896SErich Keane             StringRef(Mem, MessageSize)});
378684a7896SErich Keane     return SubstitutedAtomicExpr;
379684a7896SErich Keane   }
380684a7896SErich Keane 
3815d98ba60SSaar Raz   EnterExpressionEvaluationContext ConstantEvaluated(
382fdf80e86SSaar Raz       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
38338839d08SVlad Tsyrklevich   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
38438839d08SVlad Tsyrklevich   Expr::EvalResult EvalResult;
38538839d08SVlad Tsyrklevich   EvalResult.Diag = &EvaluationDiags;
3862f8ac075SRichard Smith   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
3872f8ac075SRichard Smith                                                            S.Context) ||
3882f8ac075SRichard Smith       !EvaluationDiags.empty()) {
38938839d08SVlad Tsyrklevich     // C++2a [temp.constr.atomic]p1
39038839d08SVlad Tsyrklevich     //   ...E shall be a constant expression of type bool.
391fdf80e86SSaar Raz     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
39238839d08SVlad Tsyrklevich            diag::err_non_constant_constraint_expression)
393fdf80e86SSaar Raz         << SubstitutedAtomicExpr.get()->getSourceRange();
39438839d08SVlad Tsyrklevich     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
395fdf80e86SSaar Raz       S.Diag(PDiag.first, PDiag.second);
396babdef27SErich Keane     return ExprError();
397ffa214efSSaar Raz   }
39838839d08SVlad Tsyrklevich 
3992f8ac075SRichard Smith   assert(EvalResult.Val.isInt() &&
4002f8ac075SRichard Smith          "evaluating bool expression didn't produce int");
401fdf80e86SSaar Raz   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
402fdf80e86SSaar Raz   if (!Satisfaction.IsSatisfied)
403fb196495SYounan Zhang     Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
40438839d08SVlad Tsyrklevich 
405babdef27SErich Keane   return SubstitutedAtomicExpr;
406ffa214efSSaar Raz }
407fdf80e86SSaar Raz 
4082cee2663SErich Keane static bool
40942667563SErich Keane DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
41042667563SErich Keane                             const NamedDecl *Templ, const Expr *E,
4112cee2663SErich Keane                             const MultiLevelTemplateArgumentList &MLTAL) {
4122cee2663SErich Keane   E->Profile(ID, S.Context, /*Canonical=*/true);
4132cee2663SErich Keane   for (const auto &List : MLTAL)
4142cee2663SErich Keane     for (const auto &TemplateArg : List.Args)
41500139ae1SMatheus Izvekov       TemplateArg.Profile(ID, S.Context);
4162cee2663SErich Keane 
4172cee2663SErich Keane   // Note that we have to do this with our own collection, because there are
4182cee2663SErich Keane   // times where a constraint-expression check can cause us to need to evaluate
4192cee2663SErich Keane   // other constriants that are unrelated, such as when evaluating a recovery
4202cee2663SErich Keane   // expression, or when trying to determine the constexpr-ness of special
4212cee2663SErich Keane   // members. Otherwise we could just use the
4222cee2663SErich Keane   // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
42342667563SErich Keane   if (S.SatisfactionStackContains(Templ, ID)) {
4242cee2663SErich Keane     S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
4252cee2663SErich Keane         << const_cast<Expr *>(E) << E->getSourceRange();
4262cee2663SErich Keane     return true;
4272cee2663SErich Keane   }
4282cee2663SErich Keane 
4292cee2663SErich Keane   return false;
4302cee2663SErich Keane }
4312cee2663SErich Keane 
432babdef27SErich Keane static ExprResult calculateConstraintSatisfaction(
433b2590273SErich Keane     Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
434b2590273SErich Keane     const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
435b2590273SErich Keane     ConstraintSatisfaction &Satisfaction) {
436b330d800Scor3ntin 
437b330d800Scor3ntin   struct ConstraintEvaluator {
438b330d800Scor3ntin     Sema &S;
439b330d800Scor3ntin     const NamedDecl *Template;
440b330d800Scor3ntin     SourceLocation TemplateNameLoc;
441b330d800Scor3ntin     const MultiLevelTemplateArgumentList &MLTAL;
442b330d800Scor3ntin     ConstraintSatisfaction &Satisfaction;
443b330d800Scor3ntin 
444b330d800Scor3ntin     ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const {
445fdf80e86SSaar Raz       EnterExpressionEvaluationContext ConstantEvaluated(
446975740bfSErich Keane           S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
447975740bfSErich Keane           Sema::ReuseLambdaContextDecl);
448fdf80e86SSaar Raz 
449fdf80e86SSaar Raz       // Atomic constraint - substitute arguments and check satisfaction.
450fdf80e86SSaar Raz       ExprResult SubstitutedExpression;
451fdf80e86SSaar Raz       {
452fdf80e86SSaar Raz         TemplateDeductionInfo Info(TemplateNameLoc);
453b330d800Scor3ntin         Sema::InstantiatingTemplate Inst(
454b330d800Scor3ntin             S, AtomicExpr->getBeginLoc(),
455713562f5SSaar Raz             Sema::InstantiatingTemplate::ConstraintSubstitution{},
456713562f5SSaar Raz             const_cast<NamedDecl *>(Template), Info,
457713562f5SSaar Raz             AtomicExpr->getSourceRange());
458fdf80e86SSaar Raz         if (Inst.isInvalid())
459fdf80e86SSaar Raz           return ExprError();
4602cee2663SErich Keane 
4612cee2663SErich Keane         llvm::FoldingSetNodeID ID;
46242667563SErich Keane         if (Template &&
46342667563SErich Keane             DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
4642cee2663SErich Keane           Satisfaction.IsSatisfied = false;
4652cee2663SErich Keane           Satisfaction.ContainsErrors = true;
4662cee2663SErich Keane           return ExprEmpty();
4672cee2663SErich Keane         }
4682cee2663SErich Keane 
46942667563SErich Keane         SatisfactionStackRAII StackRAII(S, Template, ID);
4702cee2663SErich Keane 
471fdf80e86SSaar Raz         // We do not want error diagnostics escaping here.
472fdf80e86SSaar Raz         Sema::SFINAETrap Trap(S);
473babdef27SErich Keane         SubstitutedExpression =
474babdef27SErich Keane             S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
475b5d9f00bSErich Keane 
476fdf80e86SSaar Raz         if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
477fdf80e86SSaar Raz           // C++2a [temp.constr.atomic]p1
478fdf80e86SSaar Raz           //   ...If substitution results in an invalid type or expression, the
479fdf80e86SSaar Raz           //   constraint is not satisfied.
480fdf80e86SSaar Raz           if (!Trap.hasErrorOccurred())
481bde305baSNico Weber             // A non-SFINAE error has occurred as a result of this
482fdf80e86SSaar Raz             // substitution.
483fdf80e86SSaar Raz             return ExprError();
484fdf80e86SSaar Raz 
485fdf80e86SSaar Raz           PartialDiagnosticAt SubstDiag{SourceLocation(),
486fdf80e86SSaar Raz                                         PartialDiagnostic::NullDiagnostic()};
487fdf80e86SSaar Raz           Info.takeSFINAEDiagnostic(SubstDiag);
488fdf80e86SSaar Raz           // FIXME: Concepts: This is an unfortunate consequence of there
489fdf80e86SSaar Raz           //  being no serialization code for PartialDiagnostics and the fact
490fdf80e86SSaar Raz           //  that serializing them would likely take a lot more storage than
491fdf80e86SSaar Raz           //  just storing them as strings. We would still like, in the
492fdf80e86SSaar Raz           //  future, to serialize the proper PartialDiagnostic as serializing
493fdf80e86SSaar Raz           //  it as a string defeats the purpose of the diagnostic mechanism.
494fdf80e86SSaar Raz           SmallString<128> DiagString;
495fdf80e86SSaar Raz           DiagString = ": ";
496fdf80e86SSaar Raz           SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
497fdf80e86SSaar Raz           unsigned MessageSize = DiagString.size();
498fdf80e86SSaar Raz           char *Mem = new (S.Context) char[MessageSize];
499fdf80e86SSaar Raz           memcpy(Mem, DiagString.c_str(), MessageSize);
500fdf80e86SSaar Raz           Satisfaction.Details.emplace_back(
501fdf80e86SSaar Raz               new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
502fdf80e86SSaar Raz                   SubstDiag.first, StringRef(Mem, MessageSize)});
503fdf80e86SSaar Raz           Satisfaction.IsSatisfied = false;
504fdf80e86SSaar Raz           return ExprEmpty();
505fdf80e86SSaar Raz         }
506fdf80e86SSaar Raz       }
507fdf80e86SSaar Raz 
508fdf80e86SSaar Raz       if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
509fdf80e86SSaar Raz         return ExprError();
510fdf80e86SSaar Raz 
511b5d9f00bSErich Keane       // [temp.constr.atomic]p3: To determine if an atomic constraint is
512b5d9f00bSErich Keane       // satisfied, the parameter mapping and template arguments are first
513b5d9f00bSErich Keane       // substituted into its expression.  If substitution results in an
514b5d9f00bSErich Keane       // invalid type or expression, the constraint is not satisfied.
515b5d9f00bSErich Keane       // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
516b5d9f00bSErich Keane       // and E shall be a constant expression of type bool.
517b5d9f00bSErich Keane       //
518b5d9f00bSErich Keane       // Perform the L to R Value conversion if necessary. We do so for all
519b5d9f00bSErich Keane       // non-PRValue categories, else we fail to extend the lifetime of
520b5d9f00bSErich Keane       // temporaries, and that fails the constant expression check.
521b5d9f00bSErich Keane       if (!SubstitutedExpression.get()->isPRValue())
522b5d9f00bSErich Keane         SubstitutedExpression = ImplicitCastExpr::Create(
523b5d9f00bSErich Keane             S.Context, SubstitutedExpression.get()->getType(),
524b5d9f00bSErich Keane             CK_LValueToRValue, SubstitutedExpression.get(),
525b5d9f00bSErich Keane             /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
526b5d9f00bSErich Keane 
527fdf80e86SSaar Raz       return SubstitutedExpression;
528b330d800Scor3ntin     }
529b330d800Scor3ntin 
530b330d800Scor3ntin     std::optional<unsigned>
531b330d800Scor3ntin     EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {
532da380b26Scor3ntin 
533da380b26Scor3ntin       // We should ignore errors in the presence of packs of different size.
534da380b26Scor3ntin       Sema::SFINAETrap Trap(S);
535da380b26Scor3ntin 
536b330d800Scor3ntin       Expr *Pattern = FE->getPattern();
537b330d800Scor3ntin 
538b330d800Scor3ntin       SmallVector<UnexpandedParameterPack, 2> Unexpanded;
539b330d800Scor3ntin       S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
540b330d800Scor3ntin       assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
541b330d800Scor3ntin       bool Expand = true;
542b330d800Scor3ntin       bool RetainExpansion = false;
543b330d800Scor3ntin       std::optional<unsigned> OrigNumExpansions = FE->getNumExpansions(),
544b330d800Scor3ntin                               NumExpansions = OrigNumExpansions;
545b330d800Scor3ntin       if (S.CheckParameterPacksForExpansion(
546b330d800Scor3ntin               FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded,
547b330d800Scor3ntin               MLTAL, Expand, RetainExpansion, NumExpansions) ||
548b330d800Scor3ntin           !Expand || RetainExpansion)
549b330d800Scor3ntin         return std::nullopt;
550b330d800Scor3ntin 
551b330d800Scor3ntin       if (NumExpansions && S.getLangOpts().BracketDepth < NumExpansions) {
552b330d800Scor3ntin         S.Diag(FE->getEllipsisLoc(),
553b330d800Scor3ntin                clang::diag::err_fold_expression_limit_exceeded)
554b330d800Scor3ntin             << *NumExpansions << S.getLangOpts().BracketDepth
555b330d800Scor3ntin             << FE->getSourceRange();
556b330d800Scor3ntin         S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth);
557b330d800Scor3ntin         return std::nullopt;
558b330d800Scor3ntin       }
559b330d800Scor3ntin       return NumExpansions;
560b330d800Scor3ntin     }
561b330d800Scor3ntin   };
562b330d800Scor3ntin 
563b330d800Scor3ntin   return calculateConstraintSatisfaction(
564b330d800Scor3ntin       S, ConstraintExpr, Satisfaction,
565b330d800Scor3ntin       ConstraintEvaluator{S, Template, TemplateNameLoc, MLTAL, Satisfaction});
566fdf80e86SSaar Raz }
567fdf80e86SSaar Raz 
568b2590273SErich Keane static bool CheckConstraintSatisfaction(
569b2590273SErich Keane     Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
570babdef27SErich Keane     llvm::SmallVectorImpl<Expr *> &Converted,
571b2590273SErich Keane     const MultiLevelTemplateArgumentList &TemplateArgsLists,
572b2590273SErich Keane     SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
573fdf80e86SSaar Raz   if (ConstraintExprs.empty()) {
574fdf80e86SSaar Raz     Satisfaction.IsSatisfied = true;
575fdf80e86SSaar Raz     return false;
576fdf80e86SSaar Raz   }
577fdf80e86SSaar Raz 
578b2590273SErich Keane   if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
579fdf80e86SSaar Raz     // No need to check satisfaction for dependent constraint expressions.
580fdf80e86SSaar Raz     Satisfaction.IsSatisfied = true;
581fdf80e86SSaar Raz     return false;
582fdf80e86SSaar Raz   }
583fdf80e86SSaar Raz 
584b2590273SErich Keane   ArrayRef<TemplateArgument> TemplateArgs =
585b2590273SErich Keane       TemplateArgsLists.getNumSubstitutedLevels() > 0
58644ab3805SKrystian Stasiowski           ? TemplateArgsLists.getOutermost()
587b2590273SErich Keane           : ArrayRef<TemplateArgument>{};
588258c3aeeSErich Keane   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
589713562f5SSaar Raz       Sema::InstantiatingTemplate::ConstraintsCheck{},
590713562f5SSaar Raz       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
591fdf80e86SSaar Raz   if (Inst.isInvalid())
592fdf80e86SSaar Raz     return true;
593fdf80e86SSaar Raz 
594258c3aeeSErich Keane   for (const Expr *ConstraintExpr : ConstraintExprs) {
595babdef27SErich Keane     ExprResult Res = calculateConstraintSatisfaction(
596babdef27SErich Keane         S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
597babdef27SErich Keane         ConstraintExpr, Satisfaction);
598babdef27SErich Keane     if (Res.isInvalid())
599258c3aeeSErich Keane       return true;
600babdef27SErich Keane 
601babdef27SErich Keane     Converted.push_back(Res.get());
602babdef27SErich Keane     if (!Satisfaction.IsSatisfied) {
603babdef27SErich Keane       // Backfill the 'converted' list with nulls so we can keep the Converted
604babdef27SErich Keane       // and unconverted lists in sync.
605babdef27SErich Keane       Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
606fdf80e86SSaar Raz       // [temp.constr.op] p2
607fdf80e86SSaar Raz       // [...] To determine if a conjunction is satisfied, the satisfaction
608fdf80e86SSaar Raz       // of the first operand is checked. If that is not satisfied, the
609fdf80e86SSaar Raz       // conjunction is not satisfied. [...]
610fdf80e86SSaar Raz       return false;
611fdf80e86SSaar Raz     }
612babdef27SErich Keane   }
613fdf80e86SSaar Raz   return false;
614fdf80e86SSaar Raz }
615fdf80e86SSaar Raz 
616b933d37cSSaar Raz bool Sema::CheckConstraintSatisfaction(
617713562f5SSaar Raz     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
618babdef27SErich Keane     llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
619b2590273SErich Keane     const MultiLevelTemplateArgumentList &TemplateArgsLists,
620b2590273SErich Keane     SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
621b933d37cSSaar Raz   if (ConstraintExprs.empty()) {
622b933d37cSSaar Raz     OutSatisfaction.IsSatisfied = true;
623b933d37cSSaar Raz     return false;
624fdf80e86SSaar Raz   }
625e13c28ecSIlya Biryukov   if (!Template) {
626babdef27SErich Keane     return ::CheckConstraintSatisfaction(
627babdef27SErich Keane         *this, nullptr, ConstraintExprs, ConvertedConstraints,
628babdef27SErich Keane         TemplateArgsLists, TemplateIDRange, OutSatisfaction);
629726d7b07SIlya Biryukov   }
630440fffadSYounan Zhang   // Invalid templates could make their way here. Substituting them could result
631440fffadSYounan Zhang   // in dependent expressions.
632440fffadSYounan Zhang   if (Template->isInvalidDecl()) {
633440fffadSYounan Zhang     OutSatisfaction.IsSatisfied = false;
634440fffadSYounan Zhang     return true;
635440fffadSYounan Zhang   }
636b2590273SErich Keane 
637b2590273SErich Keane   // A list of the template argument list flattened in a predictible manner for
638b2590273SErich Keane   // the purposes of caching. The ConstraintSatisfaction type is in AST so it
639b2590273SErich Keane   // has no access to the MultiLevelTemplateArgumentList, so this has to happen
640b2590273SErich Keane   // here.
641b2590273SErich Keane   llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
642bcd9ba2bSMatheus Izvekov   for (auto List : TemplateArgsLists)
64300139ae1SMatheus Izvekov     FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
64400139ae1SMatheus Izvekov                          List.Args.end());
645b2590273SErich Keane 
646726d7b07SIlya Biryukov   llvm::FoldingSetNodeID ID;
647b2590273SErich Keane   ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
648726d7b07SIlya Biryukov   void *InsertPos;
649726d7b07SIlya Biryukov   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
650726d7b07SIlya Biryukov     OutSatisfaction = *Cached;
651b933d37cSSaar Raz     return false;
652b933d37cSSaar Raz   }
653b9a77b56SErich Keane 
654726d7b07SIlya Biryukov   auto Satisfaction =
655b2590273SErich Keane       std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
656713562f5SSaar Raz   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
657babdef27SErich Keane                                     ConvertedConstraints, TemplateArgsLists,
658babdef27SErich Keane                                     TemplateIDRange, *Satisfaction)) {
6592cee2663SErich Keane     OutSatisfaction = *Satisfaction;
660b933d37cSSaar Raz     return true;
661fdf80e86SSaar Raz   }
662b9a77b56SErich Keane 
663b9a77b56SErich Keane   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
664b9a77b56SErich Keane     // The evaluation of this constraint resulted in us trying to re-evaluate it
665b9a77b56SErich Keane     // recursively. This isn't really possible, except we try to form a
666b9a77b56SErich Keane     // RecoveryExpr as a part of the evaluation.  If this is the case, just
667b9a77b56SErich Keane     // return the 'cached' version (which will have the same result), and save
668b9a77b56SErich Keane     // ourselves the extra-insert. If it ever becomes possible to legitimately
669b9a77b56SErich Keane     // recursively check a constraint, we should skip checking the 'inner' one
670b9a77b56SErich Keane     // above, and replace the cached version with this one, as it would be more
671b9a77b56SErich Keane     // specific.
672b9a77b56SErich Keane     OutSatisfaction = *Cached;
673b9a77b56SErich Keane     return false;
674b9a77b56SErich Keane   }
675b9a77b56SErich Keane 
676b9a77b56SErich Keane   // Else we can simply add this satisfaction to the list.
677b933d37cSSaar Raz   OutSatisfaction = *Satisfaction;
678726d7b07SIlya Biryukov   // We cannot use InsertPos here because CheckConstraintSatisfaction might have
679726d7b07SIlya Biryukov   // invalidated it.
680ad2263deSIlya Biryukov   // Note that entries of SatisfactionCache are deleted in Sema's destructor.
681726d7b07SIlya Biryukov   SatisfactionCache.InsertNode(Satisfaction.release());
682b933d37cSSaar Raz   return false;
683fdf80e86SSaar Raz }
684fdf80e86SSaar Raz 
685fdf80e86SSaar Raz bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
686fdf80e86SSaar Raz                                        ConstraintSatisfaction &Satisfaction) {
687b330d800Scor3ntin 
688b330d800Scor3ntin   struct ConstraintEvaluator {
689b330d800Scor3ntin     Sema &S;
690b330d800Scor3ntin     ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr) const {
691b330d800Scor3ntin       return S.PerformContextuallyConvertToBool(const_cast<Expr *>(AtomicExpr));
692b330d800Scor3ntin     }
693b330d800Scor3ntin 
694b330d800Scor3ntin     std::optional<unsigned>
695b330d800Scor3ntin     EvaluateFoldExpandedConstraintSize(const CXXFoldExpr *FE) const {
696b330d800Scor3ntin       return 0;
697b330d800Scor3ntin     }
698b330d800Scor3ntin   };
699b330d800Scor3ntin 
700b330d800Scor3ntin   return calculateConstraintSatisfaction(*this, ConstraintExpr, Satisfaction,
701b330d800Scor3ntin                                          ConstraintEvaluator{*this})
702babdef27SErich Keane       .isInvalid();
703babdef27SErich Keane }
704babdef27SErich Keane 
70593d7002dSCorentin Jabot bool Sema::addInstantiatedCapturesToScope(
70693d7002dSCorentin Jabot     FunctionDecl *Function, const FunctionDecl *PatternDecl,
70793d7002dSCorentin Jabot     LocalInstantiationScope &Scope,
70893d7002dSCorentin Jabot     const MultiLevelTemplateArgumentList &TemplateArgs) {
70993d7002dSCorentin Jabot   const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
71093d7002dSCorentin Jabot   const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
71193d7002dSCorentin Jabot 
71293d7002dSCorentin Jabot   unsigned Instantiated = 0;
71393d7002dSCorentin Jabot 
71493d7002dSCorentin Jabot   auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
71593d7002dSCorentin Jabot                               unsigned Index) {
71693d7002dSCorentin Jabot     ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
71752126dc7SYupei Liu     assert(CapturedVar->isInitCapture());
71893d7002dSCorentin Jabot     Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
71993d7002dSCorentin Jabot   };
72093d7002dSCorentin Jabot 
72193d7002dSCorentin Jabot   for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
72293d7002dSCorentin Jabot     if (!CapturePattern.capturesVariable()) {
72393d7002dSCorentin Jabot       Instantiated++;
72493d7002dSCorentin Jabot       continue;
72593d7002dSCorentin Jabot     }
72652126dc7SYupei Liu     ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
72752126dc7SYupei Liu 
72852126dc7SYupei Liu     if (!CapturedPattern->isInitCapture()) {
7295064c4c4SYounan Zhang       Instantiated++;
73052126dc7SYupei Liu       continue;
73152126dc7SYupei Liu     }
73252126dc7SYupei Liu 
73393d7002dSCorentin Jabot     if (!CapturedPattern->isParameterPack()) {
73493d7002dSCorentin Jabot       AddSingleCapture(CapturedPattern, Instantiated++);
73593d7002dSCorentin Jabot     } else {
73693d7002dSCorentin Jabot       Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
73752126dc7SYupei Liu       SmallVector<UnexpandedParameterPack, 2> Unexpanded;
73852126dc7SYupei Liu       SemaRef.collectUnexpandedParameterPacks(
73952126dc7SYupei Liu           dyn_cast<VarDecl>(CapturedPattern)->getInit(), Unexpanded);
74052126dc7SYupei Liu       auto NumArgumentsInExpansion =
74152126dc7SYupei Liu           getNumArgumentsInExpansionFromUnexpanded(Unexpanded, TemplateArgs);
74293d7002dSCorentin Jabot       if (!NumArgumentsInExpansion)
74393d7002dSCorentin Jabot         continue;
74493d7002dSCorentin Jabot       for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
74593d7002dSCorentin Jabot         AddSingleCapture(CapturedPattern, Instantiated++);
74693d7002dSCorentin Jabot     }
74793d7002dSCorentin Jabot   }
74893d7002dSCorentin Jabot   return false;
74993d7002dSCorentin Jabot }
75093d7002dSCorentin Jabot 
751babdef27SErich Keane bool Sema::SetupConstraintScope(
7526ad0788cSKazu Hirata     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
7535d98d882SYounan Zhang     const MultiLevelTemplateArgumentList &MLTAL,
7545d98d882SYounan Zhang     LocalInstantiationScope &Scope) {
755f07e5162SYounan Zhang   assert(!isLambdaCallOperator(FD) &&
756f07e5162SYounan Zhang          "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
757f07e5162SYounan Zhang          "instantiations");
758babdef27SErich Keane   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
759babdef27SErich Keane     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
760babdef27SErich Keane     InstantiatingTemplate Inst(
761babdef27SErich Keane         *this, FD->getPointOfInstantiation(),
762babdef27SErich Keane         Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
763babdef27SErich Keane         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
764babdef27SErich Keane         SourceRange());
765babdef27SErich Keane     if (Inst.isInvalid())
766babdef27SErich Keane       return true;
767babdef27SErich Keane 
768babdef27SErich Keane     // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
769babdef27SErich Keane     // 'instantiated' parameters and adds it to the context. For the case where
770babdef27SErich Keane     // this function is a template being instantiated NOW, we also need to add
771babdef27SErich Keane     // the list of current template arguments to the list so that they also can
772babdef27SErich Keane     // be picked out of the map.
773babdef27SErich Keane     if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
774326feaafSMatheus Izvekov       MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
775326feaafSMatheus Izvekov                                                    /*Final=*/false);
776babdef27SErich Keane       if (addInstantiatedParametersToScope(
777babdef27SErich Keane               FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
778babdef27SErich Keane         return true;
779babdef27SErich Keane     }
780babdef27SErich Keane 
781babdef27SErich Keane     // If this is a member function, make sure we get the parameters that
782babdef27SErich Keane     // reference the original primary template.
783843cc474SYounan Zhang     if (FunctionTemplateDecl *FromMemTempl =
784843cc474SYounan Zhang             PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
785babdef27SErich Keane       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
786babdef27SErich Keane                                            Scope, MLTAL))
787babdef27SErich Keane         return true;
788babdef27SErich Keane     }
789babdef27SErich Keane 
790babdef27SErich Keane     return false;
791babdef27SErich Keane   }
792babdef27SErich Keane 
793babdef27SErich Keane   if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
794babdef27SErich Keane       FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
795babdef27SErich Keane     FunctionDecl *InstantiatedFrom =
796babdef27SErich Keane         FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
797babdef27SErich Keane             ? FD->getInstantiatedFromMemberFunction()
798babdef27SErich Keane             : FD->getInstantiatedFromDecl();
799babdef27SErich Keane 
800babdef27SErich Keane     InstantiatingTemplate Inst(
801babdef27SErich Keane         *this, FD->getPointOfInstantiation(),
802babdef27SErich Keane         Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
803babdef27SErich Keane         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
804babdef27SErich Keane         SourceRange());
805babdef27SErich Keane     if (Inst.isInvalid())
806babdef27SErich Keane       return true;
807babdef27SErich Keane 
808babdef27SErich Keane     // Case where this was not a template, but instantiated as a
809babdef27SErich Keane     // child-function.
810babdef27SErich Keane     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
811babdef27SErich Keane       return true;
812babdef27SErich Keane   }
813babdef27SErich Keane 
814babdef27SErich Keane   return false;
815babdef27SErich Keane }
816babdef27SErich Keane 
817babdef27SErich Keane // This function collects all of the template arguments for the purposes of
818babdef27SErich Keane // constraint-instantiation and checking.
8196ad0788cSKazu Hirata std::optional<MultiLevelTemplateArgumentList>
820babdef27SErich Keane Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
8216ad0788cSKazu Hirata     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
822babdef27SErich Keane     LocalInstantiationScope &Scope) {
823babdef27SErich Keane   MultiLevelTemplateArgumentList MLTAL;
824babdef27SErich Keane 
825babdef27SErich Keane   // Collect the list of template arguments relative to the 'primary' template.
826babdef27SErich Keane   // We need the entire list, since the constraint is completely uninstantiated
827babdef27SErich Keane   // at this point.
8284739a97fSKrystian Stasiowski   MLTAL =
8294739a97fSKrystian Stasiowski       getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
8304739a97fSKrystian Stasiowski                                    /*Final=*/false, /*Innermost=*/std::nullopt,
831939a3d22SErich Keane                                    /*RelativeToPrimary=*/true,
83244ab3805SKrystian Stasiowski                                    /*Pattern=*/nullptr,
833939a3d22SErich Keane                                    /*ForConstraintInstantiation=*/true);
834f07e5162SYounan Zhang   // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
835f07e5162SYounan Zhang   if (isLambdaCallOperator(FD))
836f07e5162SYounan Zhang     return MLTAL;
837babdef27SErich Keane   if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
8388595f2e5SKazu Hirata     return std::nullopt;
839babdef27SErich Keane 
840babdef27SErich Keane   return MLTAL;
841fdf80e86SSaar Raz }
842fdf80e86SSaar Raz 
843713562f5SSaar Raz bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
844713562f5SSaar Raz                                     ConstraintSatisfaction &Satisfaction,
845babdef27SErich Keane                                     SourceLocation UsageLoc,
846babdef27SErich Keane                                     bool ForOverloadResolution) {
847babdef27SErich Keane   // Don't check constraints if the function is dependent. Also don't check if
848babdef27SErich Keane   // this is a function template specialization, as the call to
8493972ed57SYounan Zhang   // CheckinstantiatedFunctionTemplateConstraints after this will check it
850babdef27SErich Keane   // better.
851babdef27SErich Keane   if (FD->isDependentContext() ||
852babdef27SErich Keane       FD->getTemplatedKind() ==
853babdef27SErich Keane           FunctionDecl::TK_FunctionTemplateSpecialization) {
854a424ef99SSaar Raz     Satisfaction.IsSatisfied = true;
855a424ef99SSaar Raz     return false;
856a424ef99SSaar Raz   }
857babdef27SErich Keane 
858f9caa123SCorentin Jabot   // A lambda conversion operator has the same constraints as the call operator
859f9caa123SCorentin Jabot   // and constraints checking relies on whether we are in a lambda call operator
860f9caa123SCorentin Jabot   // (and may refer to its parameters), so check the call operator instead.
8613e69e5a1SYounan Zhang   // Note that the declarations outside of the lambda should also be
8623e69e5a1SYounan Zhang   // considered. Turning on the 'ForOverloadResolution' flag results in the
8633e69e5a1SYounan Zhang   // LocalInstantiationScope not looking into its parents, but we can still
8643e69e5a1SYounan Zhang   // access Decls from the parents while building a lambda RAII scope later.
865f9caa123SCorentin Jabot   if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
866f9caa123SCorentin Jabot       MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
867f9caa123SCorentin Jabot     return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
868f9caa123SCorentin Jabot                                     Satisfaction, UsageLoc,
8693e69e5a1SYounan Zhang                                     /*ShouldAddDeclsFromParentScope=*/true);
870f9caa123SCorentin Jabot 
8716b0b306eSErich Keane   DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
8726b0b306eSErich Keane 
8736b0b306eSErich Keane   while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
8746b0b306eSErich Keane     if (isLambdaCallOperator(CtxToSave))
8756b0b306eSErich Keane       CtxToSave = CtxToSave->getParent()->getParent();
8766b0b306eSErich Keane     else
8776b0b306eSErich Keane       CtxToSave = CtxToSave->getNonTransparentContext();
8786b0b306eSErich Keane   }
8796b0b306eSErich Keane 
8806b0b306eSErich Keane   ContextRAII SavedContext{*this, CtxToSave};
881548d67a0SSheng   LocalInstantiationScope Scope(*this, !ForOverloadResolution);
8826ad0788cSKazu Hirata   std::optional<MultiLevelTemplateArgumentList> MLTAL =
883babdef27SErich Keane       SetupConstraintCheckingTemplateArgumentsAndScope(
884babdef27SErich Keane           const_cast<FunctionDecl *>(FD), {}, Scope);
885babdef27SErich Keane 
886a726be38SErich Keane   if (!MLTAL)
887a726be38SErich Keane     return true;
888a726be38SErich Keane 
8896c232441SSaar Raz   Qualifiers ThisQuals;
8906c232441SSaar Raz   CXXRecordDecl *Record = nullptr;
8916c232441SSaar Raz   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
8926c232441SSaar Raz     ThisQuals = Method->getMethodQualifiers();
8936c232441SSaar Raz     Record = const_cast<CXXRecordDecl *>(Method->getParent());
8946c232441SSaar Raz   }
8956c232441SSaar Raz   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
896158f4f30SCorentin Jabot 
8973ed9e9e3SCorentin Jabot   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
898548d67a0SSheng       *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
899548d67a0SSheng       ForOverloadResolution);
900158f4f30SCorentin Jabot 
901aeee4ebdSRichard Smith   return CheckConstraintSatisfaction(
902aeee4ebdSRichard Smith       FD, {FD->getTrailingRequiresClause()}, *MLTAL,
903713562f5SSaar Raz       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
904aeee4ebdSRichard Smith       Satisfaction);
905babdef27SErich Keane }
906babdef27SErich Keane 
907babdef27SErich Keane 
908babdef27SErich Keane // Figure out the to-translation-unit depth for this function declaration for
909babdef27SErich Keane // the purpose of seeing if they differ by constraints. This isn't the same as
910babdef27SErich Keane // getTemplateDepth, because it includes already instantiated parents.
91144ab3805SKrystian Stasiowski static unsigned
91244ab3805SKrystian Stasiowski CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
91344ab3805SKrystian Stasiowski                                      bool SkipForSpecialization = false) {
914babdef27SErich Keane   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
9154739a97fSKrystian Stasiowski       ND, ND->getLexicalDeclContext(), /*Final=*/false,
9164739a97fSKrystian Stasiowski       /*Innermost=*/std::nullopt,
91798191d7cSErich Keane       /*RelativeToPrimary=*/true,
91844ab3805SKrystian Stasiowski       /*Pattern=*/nullptr,
91944ab3805SKrystian Stasiowski       /*ForConstraintInstantiation=*/true, SkipForSpecialization);
9206db007a0SAlexander Shaposhnikov   return MLTAL.getNumLevels();
921babdef27SErich Keane }
922babdef27SErich Keane 
923babdef27SErich Keane namespace {
924babdef27SErich Keane   class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
925babdef27SErich Keane   unsigned TemplateDepth = 0;
926babdef27SErich Keane   public:
927babdef27SErich Keane   using inherited = TreeTransform<AdjustConstraintDepth>;
928babdef27SErich Keane   AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
929babdef27SErich Keane       : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
930326feaafSMatheus Izvekov 
931326feaafSMatheus Izvekov   using inherited::TransformTemplateTypeParmType;
932babdef27SErich Keane   QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
933326feaafSMatheus Izvekov                                          TemplateTypeParmTypeLoc TL, bool) {
934babdef27SErich Keane     const TemplateTypeParmType *T = TL.getTypePtr();
935babdef27SErich Keane 
936babdef27SErich Keane     TemplateTypeParmDecl *NewTTPDecl = nullptr;
937babdef27SErich Keane     if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
938babdef27SErich Keane       NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
939babdef27SErich Keane           TransformDecl(TL.getNameLoc(), OldTTPDecl));
940babdef27SErich Keane 
941babdef27SErich Keane     QualType Result = getSema().Context.getTemplateTypeParmType(
942babdef27SErich Keane         T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
943babdef27SErich Keane         NewTTPDecl);
944babdef27SErich Keane     TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
945babdef27SErich Keane     NewTL.setNameLoc(TL.getNameLoc());
946babdef27SErich Keane     return Result;
947babdef27SErich Keane   }
948babdef27SErich Keane   };
949babdef27SErich Keane } // namespace
950babdef27SErich Keane 
951f5efa749SIlya Biryukov static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
952f5efa749SIlya Biryukov     Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
9536db007a0SAlexander Shaposhnikov     const Expr *ConstrExpr) {
9546db007a0SAlexander Shaposhnikov   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
95598191d7cSErich Keane       DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
9564739a97fSKrystian Stasiowski       /*Innermost=*/std::nullopt,
9576db007a0SAlexander Shaposhnikov       /*RelativeToPrimary=*/true,
95844ab3805SKrystian Stasiowski       /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
95944ab3805SKrystian Stasiowski       /*SkipForSpecialization*/ false);
96098191d7cSErich Keane 
9616db007a0SAlexander Shaposhnikov   if (MLTAL.getNumSubstitutedLevels() == 0)
9626db007a0SAlexander Shaposhnikov     return ConstrExpr;
9636db007a0SAlexander Shaposhnikov 
9646db007a0SAlexander Shaposhnikov   Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);
965fbd8f898SErich Keane 
966fbd8f898SErich Keane   Sema::InstantiatingTemplate Inst(
96798191d7cSErich Keane       S, DeclInfo.getLocation(),
968fbd8f898SErich Keane       Sema::InstantiatingTemplate::ConstraintNormalization{},
96998191d7cSErich Keane       const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
970fbd8f898SErich Keane   if (Inst.isInvalid())
971fbd8f898SErich Keane     return nullptr;
972fbd8f898SErich Keane 
97304d20b17SYounan Zhang   // Set up a dummy 'instantiation' scope in the case of reference to function
97404d20b17SYounan Zhang   // parameters that the surrounding function hasn't been instantiated yet. Note
97504d20b17SYounan Zhang   // this may happen while we're comparing two templates' constraint
97604d20b17SYounan Zhang   // equivalence.
977463a4f15SYounan Zhang   std::optional<LocalInstantiationScope> ScopeForParameters;
978463a4f15SYounan Zhang   if (const NamedDecl *ND = DeclInfo.getDecl();
979463a4f15SYounan Zhang       ND && ND->isFunctionOrFunctionTemplate()) {
980227afac3SYounan Zhang     ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
981463a4f15SYounan Zhang     const FunctionDecl *FD = ND->getAsFunction();
982e6974daaSYounan Zhang     for (auto *PVD : FD->parameters()) {
983e6974daaSYounan Zhang       if (!PVD->isParameterPack()) {
984463a4f15SYounan Zhang         ScopeForParameters->InstantiatedLocal(PVD, PVD);
985e6974daaSYounan Zhang         continue;
986e6974daaSYounan Zhang       }
987e6974daaSYounan Zhang       // This is hacky: we're mapping the parameter pack to a size-of-1 argument
988e6974daaSYounan Zhang       // to avoid building SubstTemplateTypeParmPackTypes for
989e6974daaSYounan Zhang       // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
990e6974daaSYounan Zhang       // otherwise reference the AssociatedDecl of the template arguments, which
991e6974daaSYounan Zhang       // is, in this case, the template declaration.
992e6974daaSYounan Zhang       //
993e6974daaSYounan Zhang       // However, as we are in the process of comparing potential
994e6974daaSYounan Zhang       // re-declarations, the canonical declaration is the declaration itself at
995e6974daaSYounan Zhang       // this point. So if we didn't expand these packs, we would end up with an
996e6974daaSYounan Zhang       // incorrect profile difference because we will be profiling the
997e6974daaSYounan Zhang       // canonical types!
998e6974daaSYounan Zhang       //
999e6974daaSYounan Zhang       // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
1000e6974daaSYounan Zhang       // that we can eliminate the Scope in the cases where the declarations are
1001e6974daaSYounan Zhang       // not necessarily instantiated. It would also benefit the noexcept
1002e6974daaSYounan Zhang       // specifier comparison.
1003463a4f15SYounan Zhang       ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1004463a4f15SYounan Zhang       ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1005463a4f15SYounan Zhang     }
1006e6974daaSYounan Zhang   }
100704d20b17SYounan Zhang 
10086db007a0SAlexander Shaposhnikov   std::optional<Sema::CXXThisScopeRAII> ThisScope;
1009ab70ac60SYounan Zhang 
1010ab70ac60SYounan Zhang   // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
1011ab70ac60SYounan Zhang   // essential for having an injected class as the canonical type for a template
1012ab70ac60SYounan Zhang   // specialization type at the rebuilding stage. This guarantees that, for
1013ab70ac60SYounan Zhang   // out-of-line definitions, injected class name types and their equivalent
1014ab70ac60SYounan Zhang   // template specializations can be profiled to the same value, which makes it
1015ab70ac60SYounan Zhang   // possible that e.g. constraints involving C<Class<T>> and C<Class> are
1016ab70ac60SYounan Zhang   // perceived identical.
1017ab70ac60SYounan Zhang   std::optional<Sema::ContextRAII> ContextScope;
1018358165deSYounan Zhang   const DeclContext *DC = [&] {
1019358165deSYounan Zhang     if (!DeclInfo.getDecl())
1020358165deSYounan Zhang       return DeclInfo.getDeclContext();
1021358165deSYounan Zhang     return DeclInfo.getDecl()->getFriendObjectKind()
1022358165deSYounan Zhang                ? DeclInfo.getLexicalDeclContext()
1023358165deSYounan Zhang                : DeclInfo.getDeclContext();
1024358165deSYounan Zhang   }();
1025358165deSYounan Zhang   if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
10266db007a0SAlexander Shaposhnikov     ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
1027ab70ac60SYounan Zhang     ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
1028ab70ac60SYounan Zhang                          /*NewThisContext=*/false);
1029ab70ac60SYounan Zhang   }
1030*69d0c4c1SYounan Zhang   EnterExpressionEvaluationContext UnevaluatedContext(
1031*69d0c4c1SYounan Zhang       S, Sema::ExpressionEvaluationContext::Unevaluated,
1032*69d0c4c1SYounan Zhang       Sema::ReuseLambdaContextDecl);
1033f5efa749SIlya Biryukov   ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
1034f5efa749SIlya Biryukov       const_cast<clang::Expr *>(ConstrExpr), MLTAL);
10356db007a0SAlexander Shaposhnikov   if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
10366db007a0SAlexander Shaposhnikov     return nullptr;
10376db007a0SAlexander Shaposhnikov   return SubstConstr.get();
10386db007a0SAlexander Shaposhnikov }
10396db007a0SAlexander Shaposhnikov 
1040babdef27SErich Keane bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
1041babdef27SErich Keane                                          const Expr *OldConstr,
104298191d7cSErich Keane                                          const TemplateCompareNewDeclInfo &New,
1043babdef27SErich Keane                                          const Expr *NewConstr) {
10446db007a0SAlexander Shaposhnikov   if (OldConstr == NewConstr)
10456db007a0SAlexander Shaposhnikov     return true;
1046122b9389SAlexander Shaposhnikov   // C++ [temp.constr.decl]p4
104798191d7cSErich Keane   if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
104898191d7cSErich Keane       Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
10496db007a0SAlexander Shaposhnikov     if (const Expr *SubstConstr =
1050f5efa749SIlya Biryukov             SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
1051f5efa749SIlya Biryukov                                                               OldConstr))
10526db007a0SAlexander Shaposhnikov       OldConstr = SubstConstr;
10536db007a0SAlexander Shaposhnikov     else
10546db007a0SAlexander Shaposhnikov       return false;
10556db007a0SAlexander Shaposhnikov     if (const Expr *SubstConstr =
1056f5efa749SIlya Biryukov             SubstituteConstraintExpressionWithoutSatisfaction(*this, New,
1057f5efa749SIlya Biryukov                                                               NewConstr))
10586db007a0SAlexander Shaposhnikov       NewConstr = SubstConstr;
10596db007a0SAlexander Shaposhnikov     else
10606db007a0SAlexander Shaposhnikov       return false;
1061babdef27SErich Keane   }
1062babdef27SErich Keane 
1063babdef27SErich Keane   llvm::FoldingSetNodeID ID1, ID2;
1064babdef27SErich Keane   OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1065babdef27SErich Keane   NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1066babdef27SErich Keane   return ID1 == ID2;
1067babdef27SErich Keane }
1068babdef27SErich Keane 
1069babdef27SErich Keane bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
1070babdef27SErich Keane   assert(FD->getFriendObjectKind() && "Must be a friend!");
1071babdef27SErich Keane 
1072babdef27SErich Keane   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1073babdef27SErich Keane   // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1074babdef27SErich Keane   // non-function-template.
107544ab3805SKrystian Stasiowski   assert(FD->getDescribedFunctionTemplate() &&
107644ab3805SKrystian Stasiowski          "Non-function templates don't need to be checked");
1077babdef27SErich Keane 
1078babdef27SErich Keane   SmallVector<const Expr *, 3> ACs;
107944ab3805SKrystian Stasiowski   FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
1080babdef27SErich Keane 
108144ab3805SKrystian Stasiowski   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1082babdef27SErich Keane   for (const Expr *Constraint : ACs)
1083853df5e1SErich Keane     if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1084babdef27SErich Keane                                                        Constraint))
1085babdef27SErich Keane       return true;
1086babdef27SErich Keane 
1087babdef27SErich Keane   return false;
1088713562f5SSaar Raz }
1089713562f5SSaar Raz 
1090fdf80e86SSaar Raz bool Sema::EnsureTemplateArgumentListConstraints(
1091b2590273SErich Keane     TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1092fdf80e86SSaar Raz     SourceRange TemplateIDRange) {
1093fdf80e86SSaar Raz   ConstraintSatisfaction Satisfaction;
1094fdf80e86SSaar Raz   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
1095fdf80e86SSaar Raz   TD->getAssociatedConstraints(AssociatedConstraints);
1096b2590273SErich Keane   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1097fdf80e86SSaar Raz                                   TemplateIDRange, Satisfaction))
1098fdf80e86SSaar Raz     return true;
1099fdf80e86SSaar Raz 
1100fdf80e86SSaar Raz   if (!Satisfaction.IsSatisfied) {
1101fdf80e86SSaar Raz     SmallString<128> TemplateArgString;
1102fdf80e86SSaar Raz     TemplateArgString = " ";
1103fdf80e86SSaar Raz     TemplateArgString += getTemplateArgumentBindingsText(
1104b2590273SErich Keane         TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1105b2590273SErich Keane         TemplateArgsLists.getInnermost().size());
1106fdf80e86SSaar Raz 
1107fdf80e86SSaar Raz     Diag(TemplateIDRange.getBegin(),
1108fdf80e86SSaar Raz          diag::err_template_arg_list_constraints_not_satisfied)
1109fdf80e86SSaar Raz         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
1110fdf80e86SSaar Raz         << TemplateArgString << TemplateIDRange;
1111fdf80e86SSaar Raz     DiagnoseUnsatisfiedConstraint(Satisfaction);
1112fdf80e86SSaar Raz     return true;
1113fdf80e86SSaar Raz   }
1114fdf80e86SSaar Raz   return false;
1115fdf80e86SSaar Raz }
1116fdf80e86SSaar Raz 
11173972ed57SYounan Zhang bool Sema::CheckInstantiatedFunctionTemplateConstraints(
111894623fb1SErich Keane     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
111994623fb1SErich Keane     ArrayRef<TemplateArgument> TemplateArgs,
112094623fb1SErich Keane     ConstraintSatisfaction &Satisfaction) {
112194623fb1SErich Keane   // In most cases we're not going to have constraints, so check for that first.
112294623fb1SErich Keane   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
112394623fb1SErich Keane   // Note - code synthesis context for the constraints check is created
112494623fb1SErich Keane   // inside CheckConstraintsSatisfaction.
112594623fb1SErich Keane   SmallVector<const Expr *, 3> TemplateAC;
112694623fb1SErich Keane   Template->getAssociatedConstraints(TemplateAC);
112794623fb1SErich Keane   if (TemplateAC.empty()) {
112894623fb1SErich Keane     Satisfaction.IsSatisfied = true;
112994623fb1SErich Keane     return false;
113094623fb1SErich Keane   }
113194623fb1SErich Keane 
113294623fb1SErich Keane   // Enter the scope of this instantiation. We don't use
113394623fb1SErich Keane   // PushDeclContext because we don't have a scope.
113494623fb1SErich Keane   Sema::ContextRAII savedContext(*this, Decl);
113594623fb1SErich Keane   LocalInstantiationScope Scope(*this);
113694623fb1SErich Keane 
11376ad0788cSKazu Hirata   std::optional<MultiLevelTemplateArgumentList> MLTAL =
1138babdef27SErich Keane       SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1139babdef27SErich Keane                                                        Scope);
1140babdef27SErich Keane 
1141babdef27SErich Keane   if (!MLTAL)
114294623fb1SErich Keane     return true;
1143babdef27SErich Keane 
114494623fb1SErich Keane   Qualifiers ThisQuals;
114594623fb1SErich Keane   CXXRecordDecl *Record = nullptr;
114694623fb1SErich Keane   if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
114794623fb1SErich Keane     ThisQuals = Method->getMethodQualifiers();
114894623fb1SErich Keane     Record = Method->getParent();
114994623fb1SErich Keane   }
115098062d8fSCorentin Jabot 
11513ed9e9e3SCorentin Jabot   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
11523ed9e9e3SCorentin Jabot   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
11533ed9e9e3SCorentin Jabot       *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
1154939a3d22SErich Keane 
1155babdef27SErich Keane   llvm::SmallVector<Expr *, 1> Converted;
1156babdef27SErich Keane   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
115794623fb1SErich Keane                                      PointOfInstantiation, Satisfaction);
115894623fb1SErich Keane }
115994623fb1SErich Keane 
1160a0f50d73SSaar Raz static void diagnoseUnsatisfiedRequirement(Sema &S,
1161a0f50d73SSaar Raz                                            concepts::ExprRequirement *Req,
1162a0f50d73SSaar Raz                                            bool First) {
1163a0f50d73SSaar Raz   assert(!Req->isSatisfied()
1164a0f50d73SSaar Raz          && "Diagnose() can only be used on an unsatisfied requirement");
1165a0f50d73SSaar Raz   switch (Req->getSatisfactionStatus()) {
1166a0f50d73SSaar Raz     case concepts::ExprRequirement::SS_Dependent:
1167a0f50d73SSaar Raz       llvm_unreachable("Diagnosing a dependent requirement");
1168a0f50d73SSaar Raz       break;
1169a0f50d73SSaar Raz     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
1170a0f50d73SSaar Raz       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1171a0f50d73SSaar Raz       if (!SubstDiag->DiagMessage.empty())
1172a0f50d73SSaar Raz         S.Diag(SubstDiag->DiagLoc,
1173a0f50d73SSaar Raz                diag::note_expr_requirement_expr_substitution_error)
1174a0f50d73SSaar Raz                << (int)First << SubstDiag->SubstitutedEntity
1175a0f50d73SSaar Raz                << SubstDiag->DiagMessage;
1176a0f50d73SSaar Raz       else
1177a0f50d73SSaar Raz         S.Diag(SubstDiag->DiagLoc,
1178a0f50d73SSaar Raz                diag::note_expr_requirement_expr_unknown_substitution_error)
1179a0f50d73SSaar Raz             << (int)First << SubstDiag->SubstitutedEntity;
1180a0f50d73SSaar Raz       break;
1181a0f50d73SSaar Raz     }
1182a0f50d73SSaar Raz     case concepts::ExprRequirement::SS_NoexceptNotMet:
1183a0f50d73SSaar Raz       S.Diag(Req->getNoexceptLoc(),
1184a0f50d73SSaar Raz              diag::note_expr_requirement_noexcept_not_met)
1185a0f50d73SSaar Raz           << (int)First << Req->getExpr();
1186a0f50d73SSaar Raz       break;
1187a0f50d73SSaar Raz     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
1188a0f50d73SSaar Raz       auto *SubstDiag =
1189a0f50d73SSaar Raz           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
1190a0f50d73SSaar Raz       if (!SubstDiag->DiagMessage.empty())
1191a0f50d73SSaar Raz         S.Diag(SubstDiag->DiagLoc,
1192a0f50d73SSaar Raz                diag::note_expr_requirement_type_requirement_substitution_error)
1193a0f50d73SSaar Raz             << (int)First << SubstDiag->SubstitutedEntity
1194a0f50d73SSaar Raz             << SubstDiag->DiagMessage;
1195a0f50d73SSaar Raz       else
1196a0f50d73SSaar Raz         S.Diag(SubstDiag->DiagLoc,
1197a0f50d73SSaar Raz                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
1198a0f50d73SSaar Raz             << (int)First << SubstDiag->SubstitutedEntity;
1199a0f50d73SSaar Raz       break;
1200a0f50d73SSaar Raz     }
1201a0f50d73SSaar Raz     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
1202a0f50d73SSaar Raz       ConceptSpecializationExpr *ConstraintExpr =
1203a0f50d73SSaar Raz           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
12043ad6dd5dSMatheus Izvekov       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1205a0f50d73SSaar Raz         // A simple case - expr type is the type being constrained and the concept
1206a0f50d73SSaar Raz         // was not provided arguments.
12073ad6dd5dSMatheus Izvekov         Expr *e = Req->getExpr();
12083ad6dd5dSMatheus Izvekov         S.Diag(e->getBeginLoc(),
1209a0f50d73SSaar Raz                diag::note_expr_requirement_constraints_not_satisfied_simple)
12100c7cd4a8SMatheus Izvekov             << (int)First << S.Context.getReferenceQualifiedType(e)
1211a0f50d73SSaar Raz             << ConstraintExpr->getNamedConcept();
12123ad6dd5dSMatheus Izvekov       } else {
1213a0f50d73SSaar Raz         S.Diag(ConstraintExpr->getBeginLoc(),
1214a0f50d73SSaar Raz                diag::note_expr_requirement_constraints_not_satisfied)
1215a0f50d73SSaar Raz             << (int)First << ConstraintExpr;
12163ad6dd5dSMatheus Izvekov       }
1217a0f50d73SSaar Raz       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
1218a0f50d73SSaar Raz       break;
1219a0f50d73SSaar Raz     }
1220a0f50d73SSaar Raz     case concepts::ExprRequirement::SS_Satisfied:
1221a0f50d73SSaar Raz       llvm_unreachable("We checked this above");
1222a0f50d73SSaar Raz   }
1223a0f50d73SSaar Raz }
1224a0f50d73SSaar Raz 
1225a0f50d73SSaar Raz static void diagnoseUnsatisfiedRequirement(Sema &S,
1226a0f50d73SSaar Raz                                            concepts::TypeRequirement *Req,
1227a0f50d73SSaar Raz                                            bool First) {
1228a0f50d73SSaar Raz   assert(!Req->isSatisfied()
1229a0f50d73SSaar Raz          && "Diagnose() can only be used on an unsatisfied requirement");
1230a0f50d73SSaar Raz   switch (Req->getSatisfactionStatus()) {
1231a0f50d73SSaar Raz   case concepts::TypeRequirement::SS_Dependent:
1232a0f50d73SSaar Raz     llvm_unreachable("Diagnosing a dependent requirement");
1233a0f50d73SSaar Raz     return;
1234a0f50d73SSaar Raz   case concepts::TypeRequirement::SS_SubstitutionFailure: {
1235a0f50d73SSaar Raz     auto *SubstDiag = Req->getSubstitutionDiagnostic();
1236a0f50d73SSaar Raz     if (!SubstDiag->DiagMessage.empty())
1237a0f50d73SSaar Raz       S.Diag(SubstDiag->DiagLoc,
1238a0f50d73SSaar Raz              diag::note_type_requirement_substitution_error) << (int)First
1239a0f50d73SSaar Raz           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
1240a0f50d73SSaar Raz     else
1241a0f50d73SSaar Raz       S.Diag(SubstDiag->DiagLoc,
1242a0f50d73SSaar Raz              diag::note_type_requirement_unknown_substitution_error)
1243a0f50d73SSaar Raz           << (int)First << SubstDiag->SubstitutedEntity;
1244a0f50d73SSaar Raz     return;
1245a0f50d73SSaar Raz   }
1246a0f50d73SSaar Raz   default:
1247a0f50d73SSaar Raz     llvm_unreachable("Unknown satisfaction status");
1248a0f50d73SSaar Raz     return;
1249a0f50d73SSaar Raz   }
1250a0f50d73SSaar Raz }
1251b3ce8728SUtkarsh Saxena static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1252b3ce8728SUtkarsh Saxena                                                         Expr *SubstExpr,
1253b3ce8728SUtkarsh Saxena                                                         bool First = true);
1254a0f50d73SSaar Raz 
1255a0f50d73SSaar Raz static void diagnoseUnsatisfiedRequirement(Sema &S,
1256a0f50d73SSaar Raz                                            concepts::NestedRequirement *Req,
1257a0f50d73SSaar Raz                                            bool First) {
1258b3ce8728SUtkarsh Saxena   using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1259fb196495SYounan Zhang   for (auto &Record : Req->getConstraintSatisfaction()) {
1260fb196495SYounan Zhang     if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>())
1261b3ce8728SUtkarsh Saxena       S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1262fb196495SYounan Zhang           << (int)First << Req->getInvalidConstraintEntity()
1263fb196495SYounan Zhang           << SubstDiag->second;
1264a0f50d73SSaar Raz     else
1265fb196495SYounan Zhang       diagnoseWellFormedUnsatisfiedConstraintExpr(S, Record.dyn_cast<Expr *>(),
1266fb196495SYounan Zhang                                                   First);
1267b3ce8728SUtkarsh Saxena     First = false;
1268a0f50d73SSaar Raz   }
1269a0f50d73SSaar Raz }
1270a0f50d73SSaar Raz 
1271fdf80e86SSaar Raz static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1272fdf80e86SSaar Raz                                                         Expr *SubstExpr,
1273b3ce8728SUtkarsh Saxena                                                         bool First) {
1274fdf80e86SSaar Raz   SubstExpr = SubstExpr->IgnoreParenImpCasts();
1275fdf80e86SSaar Raz   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1276fdf80e86SSaar Raz     switch (BO->getOpcode()) {
1277fdf80e86SSaar Raz     // These two cases will in practice only be reached when using fold
1278fdf80e86SSaar Raz     // expressions with || and &&, since otherwise the || and && will have been
1279fdf80e86SSaar Raz     // broken down into atomic constraints during satisfaction checking.
1280fdf80e86SSaar Raz     case BO_LOr:
1281fdf80e86SSaar Raz       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1282fdf80e86SSaar Raz       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1283fdf80e86SSaar Raz       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1284fdf80e86SSaar Raz                                                   /*First=*/false);
1285fdf80e86SSaar Raz       return;
12862f8ac075SRichard Smith     case BO_LAnd: {
12872f8ac075SRichard Smith       bool LHSSatisfied =
12882f8ac075SRichard Smith           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1289fdf80e86SSaar Raz       if (LHSSatisfied) {
1290fdf80e86SSaar Raz         // LHS is true, so RHS must be false.
1291fdf80e86SSaar Raz         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
1292fdf80e86SSaar Raz         return;
1293fdf80e86SSaar Raz       }
1294fdf80e86SSaar Raz       // LHS is false
1295fdf80e86SSaar Raz       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1296fdf80e86SSaar Raz 
1297fdf80e86SSaar Raz       // RHS might also be false
12982f8ac075SRichard Smith       bool RHSSatisfied =
12992f8ac075SRichard Smith           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1300fdf80e86SSaar Raz       if (!RHSSatisfied)
1301fdf80e86SSaar Raz         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1302fdf80e86SSaar Raz                                                     /*First=*/false);
1303fdf80e86SSaar Raz       return;
13042f8ac075SRichard Smith     }
1305fdf80e86SSaar Raz     case BO_GE:
1306fdf80e86SSaar Raz     case BO_LE:
1307fdf80e86SSaar Raz     case BO_GT:
1308fdf80e86SSaar Raz     case BO_LT:
1309fdf80e86SSaar Raz     case BO_EQ:
1310fdf80e86SSaar Raz     case BO_NE:
1311fdf80e86SSaar Raz       if (BO->getLHS()->getType()->isIntegerType() &&
1312fdf80e86SSaar Raz           BO->getRHS()->getType()->isIntegerType()) {
1313fdf80e86SSaar Raz         Expr::EvalResult SimplifiedLHS;
1314fdf80e86SSaar Raz         Expr::EvalResult SimplifiedRHS;
13152f8ac075SRichard Smith         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
13162f8ac075SRichard Smith                                     Expr::SE_NoSideEffects,
13172f8ac075SRichard Smith                                     /*InConstantContext=*/true);
13182f8ac075SRichard Smith         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
13192f8ac075SRichard Smith                                     Expr::SE_NoSideEffects,
13202f8ac075SRichard Smith                                     /*InConstantContext=*/true);
1321fdf80e86SSaar Raz         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1322fdf80e86SSaar Raz           S.Diag(SubstExpr->getBeginLoc(),
1323fdf80e86SSaar Raz                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
1324fdf80e86SSaar Raz               << (int)First << SubstExpr
132561cdaf66SSimon Pilgrim               << toString(SimplifiedLHS.Val.getInt(), 10)
1326fdf80e86SSaar Raz               << BinaryOperator::getOpcodeStr(BO->getOpcode())
132761cdaf66SSimon Pilgrim               << toString(SimplifiedRHS.Val.getInt(), 10);
1328fdf80e86SSaar Raz           return;
1329fdf80e86SSaar Raz         }
1330fdf80e86SSaar Raz       }
1331fdf80e86SSaar Raz       break;
1332fdf80e86SSaar Raz 
1333fdf80e86SSaar Raz     default:
1334fdf80e86SSaar Raz       break;
1335fdf80e86SSaar Raz     }
1336fdf80e86SSaar Raz   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1337fdf80e86SSaar Raz     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1338fdf80e86SSaar Raz       S.Diag(
1339fdf80e86SSaar Raz           CSE->getSourceRange().getBegin(),
1340fdf80e86SSaar Raz           diag::
1341fdf80e86SSaar Raz           note_single_arg_concept_specialization_constraint_evaluated_to_false)
1342fdf80e86SSaar Raz           << (int)First
1343fdf80e86SSaar Raz           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1344fdf80e86SSaar Raz           << CSE->getNamedConcept();
1345fdf80e86SSaar Raz     } else {
1346fdf80e86SSaar Raz       S.Diag(SubstExpr->getSourceRange().getBegin(),
1347fdf80e86SSaar Raz              diag::note_concept_specialization_constraint_evaluated_to_false)
1348fdf80e86SSaar Raz           << (int)First << CSE;
1349fdf80e86SSaar Raz     }
1350fdf80e86SSaar Raz     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1351fdf80e86SSaar Raz     return;
1352a0f50d73SSaar Raz   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
13539e0474fbSUtkarsh Saxena     // FIXME: RequiresExpr should store dependent diagnostics.
1354a0f50d73SSaar Raz     for (concepts::Requirement *Req : RE->getRequirements())
1355a0f50d73SSaar Raz       if (!Req->isDependent() && !Req->isSatisfied()) {
1356a0f50d73SSaar Raz         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1357a0f50d73SSaar Raz           diagnoseUnsatisfiedRequirement(S, E, First);
1358a0f50d73SSaar Raz         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1359a0f50d73SSaar Raz           diagnoseUnsatisfiedRequirement(S, T, First);
1360a0f50d73SSaar Raz         else
1361a0f50d73SSaar Raz           diagnoseUnsatisfiedRequirement(
1362a0f50d73SSaar Raz               S, cast<concepts::NestedRequirement>(Req), First);
1363a0f50d73SSaar Raz         break;
1364a0f50d73SSaar Raz       }
1365a0f50d73SSaar Raz     return;
1366a383b3ccSHaojian Wu   } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1367a383b3ccSHaojian Wu              TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1368a383b3ccSHaojian Wu     assert(TTE->getNumArgs() == 2);
1369a383b3ccSHaojian Wu     S.Diag(SubstExpr->getSourceRange().getBegin(),
1370a383b3ccSHaojian Wu            diag::note_is_deducible_constraint_evaluated_to_false)
1371a383b3ccSHaojian Wu         << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1372a383b3ccSHaojian Wu     return;
1373fdf80e86SSaar Raz   }
1374fdf80e86SSaar Raz 
1375fdf80e86SSaar Raz   S.Diag(SubstExpr->getSourceRange().getBegin(),
1376fdf80e86SSaar Raz          diag::note_atomic_constraint_evaluated_to_false)
1377fdf80e86SSaar Raz       << (int)First << SubstExpr;
1378fdf80e86SSaar Raz }
1379fdf80e86SSaar Raz 
1380fdf80e86SSaar Raz template <typename SubstitutionDiagnostic>
1381fdf80e86SSaar Raz static void diagnoseUnsatisfiedConstraintExpr(
1382fb196495SYounan Zhang     Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1383fdf80e86SSaar Raz     bool First = true) {
1384fdf80e86SSaar Raz   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) {
1385fdf80e86SSaar Raz     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1386fdf80e86SSaar Raz         << Diag->second;
1387fdf80e86SSaar Raz     return;
1388fdf80e86SSaar Raz   }
1389fdf80e86SSaar Raz 
13901e3e199eSKazu Hirata   diagnoseWellFormedUnsatisfiedConstraintExpr(S, cast<Expr *>(Record), First);
1391fdf80e86SSaar Raz }
1392fdf80e86SSaar Raz 
1393a0f50d73SSaar Raz void
1394a0f50d73SSaar Raz Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
1395a0f50d73SSaar Raz                                     bool First) {
1396fdf80e86SSaar Raz   assert(!Satisfaction.IsSatisfied &&
1397fdf80e86SSaar Raz          "Attempted to diagnose a satisfied constraint");
1398fb196495SYounan Zhang   for (auto &Record : Satisfaction.Details) {
1399fb196495SYounan Zhang     diagnoseUnsatisfiedConstraintExpr(*this, Record, First);
1400fdf80e86SSaar Raz     First = false;
1401fdf80e86SSaar Raz   }
1402fdf80e86SSaar Raz }
1403fdf80e86SSaar Raz 
1404fdf80e86SSaar Raz void Sema::DiagnoseUnsatisfiedConstraint(
1405a0f50d73SSaar Raz     const ASTConstraintSatisfaction &Satisfaction,
1406a0f50d73SSaar Raz     bool First) {
1407fdf80e86SSaar Raz   assert(!Satisfaction.IsSatisfied &&
1408fdf80e86SSaar Raz          "Attempted to diagnose a satisfied constraint");
1409fb196495SYounan Zhang   for (auto &Record : Satisfaction) {
1410fb196495SYounan Zhang     diagnoseUnsatisfiedConstraintExpr(*this, Record, First);
1411fdf80e86SSaar Raz     First = false;
1412fdf80e86SSaar Raz   }
1413fdf80e86SSaar Raz }
1414df061c3eSSaar Raz 
1415b65b1f32SSaar Raz const NormalizedConstraint *
1416b65b1f32SSaar Raz Sema::getNormalizedAssociatedConstraints(
1417b65b1f32SSaar Raz     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
141872ac9071SChuanqi Xu   // In case the ConstrainedDecl comes from modules, it is necessary to use
141972ac9071SChuanqi Xu   // the canonical decl to avoid different atomic constraints with the 'same'
142072ac9071SChuanqi Xu   // declarations.
142172ac9071SChuanqi Xu   ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl());
142272ac9071SChuanqi Xu 
1423b65b1f32SSaar Raz   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1424b65b1f32SSaar Raz   if (CacheEntry == NormalizationCache.end()) {
1425b65b1f32SSaar Raz     auto Normalized =
1426b65b1f32SSaar Raz         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1427b65b1f32SSaar Raz                                                   AssociatedConstraints);
1428b65b1f32SSaar Raz     CacheEntry =
1429b65b1f32SSaar Raz         NormalizationCache
1430b65b1f32SSaar Raz             .try_emplace(ConstrainedDecl,
1431b65b1f32SSaar Raz                          Normalized
1432b65b1f32SSaar Raz                              ? new (Context) NormalizedConstraint(
1433b65b1f32SSaar Raz                                  std::move(*Normalized))
1434b65b1f32SSaar Raz                              : nullptr)
1435b65b1f32SSaar Raz             .first;
1436df061c3eSSaar Raz   }
1437b65b1f32SSaar Raz   return CacheEntry->second;
1438df061c3eSSaar Raz }
1439df061c3eSSaar Raz 
1440b330d800Scor3ntin const NormalizedConstraint *clang::getNormalizedAssociatedConstraints(
1441b330d800Scor3ntin     Sema &S, NamedDecl *ConstrainedDecl,
1442b330d800Scor3ntin     ArrayRef<const Expr *> AssociatedConstraints) {
1443b330d800Scor3ntin   return S.getNormalizedAssociatedConstraints(ConstrainedDecl,
1444b330d800Scor3ntin                                               AssociatedConstraints);
1445b330d800Scor3ntin }
1446b330d800Scor3ntin 
1447babdef27SErich Keane static bool
1448babdef27SErich Keane substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1449babdef27SErich Keane                             ConceptDecl *Concept,
1450babdef27SErich Keane                             const MultiLevelTemplateArgumentList &MLTAL,
1451df061c3eSSaar Raz                             const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1452b330d800Scor3ntin 
1453b330d800Scor3ntin   if (N.isCompound()) {
1454babdef27SErich Keane     if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1455df061c3eSSaar Raz                                     ArgsAsWritten))
1456df061c3eSSaar Raz       return true;
1457babdef27SErich Keane     return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1458df061c3eSSaar Raz                                        ArgsAsWritten);
1459df061c3eSSaar Raz   }
1460b330d800Scor3ntin 
1461b330d800Scor3ntin   if (N.isFoldExpanded()) {
1462b330d800Scor3ntin     Sema::ArgumentPackSubstitutionIndexRAII _(S, -1);
1463b330d800Scor3ntin     return substituteParameterMappings(
1464b330d800Scor3ntin         S, N.getFoldExpandedConstraint()->Constraint, Concept, MLTAL,
1465b330d800Scor3ntin         ArgsAsWritten);
1466b330d800Scor3ntin   }
1467b330d800Scor3ntin 
1468df061c3eSSaar Raz   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1469df061c3eSSaar Raz 
1470df061c3eSSaar Raz   AtomicConstraint &Atomic = *N.getAtomicConstraint();
1471df061c3eSSaar Raz   TemplateArgumentListInfo SubstArgs;
1472df061c3eSSaar Raz   if (!Atomic.ParameterMapping) {
1473df061c3eSSaar Raz     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1474df061c3eSSaar Raz     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1475df061c3eSSaar Raz                                  /*Depth=*/0, OccurringIndices);
1476ec081141SYuanfang Chen     TemplateArgumentLoc *TempArgs =
1477ec081141SYuanfang Chen         new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1478b65b1f32SSaar Raz     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1479df061c3eSSaar Raz       if (OccurringIndices[I])
1480ec081141SYuanfang Chen         new (&(TempArgs)[J++])
1481ec081141SYuanfang Chen             TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(
1482ec081141SYuanfang Chen                 TemplateParams->begin()[I],
1483df061c3eSSaar Raz                 // Here we assume we do not support things like
1484df061c3eSSaar Raz                 // template<typename A, typename B>
1485df061c3eSSaar Raz                 // concept C = ...;
1486df061c3eSSaar Raz                 //
1487df061c3eSSaar Raz                 // template<typename... Ts> requires C<Ts...>
1488df061c3eSSaar Raz                 // struct S { };
1489df061c3eSSaar Raz                 // The above currently yields a diagnostic.
1490df061c3eSSaar Raz                 // We still might have default arguments for concept parameters.
1491ec081141SYuanfang Chen                 ArgsAsWritten->NumTemplateArgs > I
1492ec081141SYuanfang Chen                     ? ArgsAsWritten->arguments()[I].getLocation()
1493ec081141SYuanfang Chen                     : SourceLocation()));
1494ec081141SYuanfang Chen     Atomic.ParameterMapping.emplace(TempArgs,  OccurringIndices.count());
1495df061c3eSSaar Raz   }
149611b20d7aSHaojian Wu   SourceLocation InstLocBegin =
149711b20d7aSHaojian Wu       ArgsAsWritten->arguments().empty()
149811b20d7aSHaojian Wu           ? ArgsAsWritten->getLAngleLoc()
149911b20d7aSHaojian Wu           : ArgsAsWritten->arguments().front().getSourceRange().getBegin();
150011b20d7aSHaojian Wu   SourceLocation InstLocEnd =
150111b20d7aSHaojian Wu       ArgsAsWritten->arguments().empty()
150211b20d7aSHaojian Wu           ? ArgsAsWritten->getRAngleLoc()
150311b20d7aSHaojian Wu           : ArgsAsWritten->arguments().front().getSourceRange().getEnd();
1504df061c3eSSaar Raz   Sema::InstantiatingTemplate Inst(
150511b20d7aSHaojian Wu       S, InstLocBegin,
15069e9d98aaSMatheus Izvekov       Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
15079e9d98aaSMatheus Izvekov       Atomic.ConstraintDecl, {InstLocBegin, InstLocEnd});
1508a042fcbeSHaojian Wu   if (Inst.isInvalid())
1509a042fcbeSHaojian Wu     return true;
1510258c3aeeSErich Keane   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1511df061c3eSSaar Raz     return true;
1512ec081141SYuanfang Chen 
1513ec081141SYuanfang Chen   TemplateArgumentLoc *TempArgs =
1514ec081141SYuanfang Chen       new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1515df061c3eSSaar Raz   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1516ec081141SYuanfang Chen             TempArgs);
1517ec081141SYuanfang Chen   Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1518df061c3eSSaar Raz   return false;
1519df061c3eSSaar Raz }
1520df061c3eSSaar Raz 
1521babdef27SErich Keane static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1522babdef27SErich Keane                                         const ConceptSpecializationExpr *CSE) {
1523326feaafSMatheus Izvekov   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
152498191d7cSErich Keane       CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
152500139ae1SMatheus Izvekov       /*Final=*/false, CSE->getTemplateArguments(),
1526939a3d22SErich Keane       /*RelativeToPrimary=*/true,
152744ab3805SKrystian Stasiowski       /*Pattern=*/nullptr,
1528939a3d22SErich Keane       /*ForConstraintInstantiation=*/true);
1529babdef27SErich Keane 
1530babdef27SErich Keane   return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1531babdef27SErich Keane                                      CSE->getTemplateArgsAsWritten());
1532babdef27SErich Keane }
1533babdef27SErich Keane 
1534b330d800Scor3ntin NormalizedConstraint::NormalizedConstraint(ASTContext &C,
1535b330d800Scor3ntin                                            NormalizedConstraint LHS,
1536b330d800Scor3ntin                                            NormalizedConstraint RHS,
1537b330d800Scor3ntin                                            CompoundConstraintKind Kind)
1538b330d800Scor3ntin     : Constraint{CompoundConstraint{
1539b330d800Scor3ntin           new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
1540b330d800Scor3ntin           Kind}} {}
1541b330d800Scor3ntin 
1542b330d800Scor3ntin NormalizedConstraint::NormalizedConstraint(ASTContext &C,
1543b330d800Scor3ntin                                            const NormalizedConstraint &Other) {
1544b330d800Scor3ntin   if (Other.isAtomic()) {
1545b330d800Scor3ntin     Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
1546b330d800Scor3ntin   } else if (Other.isFoldExpanded()) {
1547b330d800Scor3ntin     Constraint = new (C) FoldExpandedConstraint(
1548b330d800Scor3ntin         Other.getFoldExpandedConstraint()->Kind,
1549b330d800Scor3ntin         NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint),
1550b330d800Scor3ntin         Other.getFoldExpandedConstraint()->Pattern);
1551b330d800Scor3ntin   } else {
1552b330d800Scor3ntin     Constraint = CompoundConstraint(
1553b330d800Scor3ntin         new (C)
1554b330d800Scor3ntin             NormalizedConstraintPair{NormalizedConstraint(C, Other.getLHS()),
1555b330d800Scor3ntin                                      NormalizedConstraint(C, Other.getRHS())},
1556b330d800Scor3ntin         Other.getCompoundKind());
1557b330d800Scor3ntin   }
1558b330d800Scor3ntin }
1559b330d800Scor3ntin 
1560b330d800Scor3ntin NormalizedConstraint &NormalizedConstraint::getLHS() const {
1561b330d800Scor3ntin   assert(isCompound() && "getLHS called on a non-compound constraint.");
15621e3e199eSKazu Hirata   return cast<CompoundConstraint>(Constraint).getPointer()->LHS;
1563b330d800Scor3ntin }
1564b330d800Scor3ntin 
1565b330d800Scor3ntin NormalizedConstraint &NormalizedConstraint::getRHS() const {
1566b330d800Scor3ntin   assert(isCompound() && "getRHS called on a non-compound constraint.");
15671e3e199eSKazu Hirata   return cast<CompoundConstraint>(Constraint).getPointer()->RHS;
1568b330d800Scor3ntin }
1569b330d800Scor3ntin 
15706ad0788cSKazu Hirata std::optional<NormalizedConstraint>
1571b65b1f32SSaar Raz NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1572b65b1f32SSaar Raz                                           ArrayRef<const Expr *> E) {
1573b65b1f32SSaar Raz   assert(E.size() != 0);
157487aa3182SMatheus Izvekov   auto Conjunction = fromConstraintExpr(S, D, E[0]);
157587aa3182SMatheus Izvekov   if (!Conjunction)
15768595f2e5SKazu Hirata     return std::nullopt;
157787aa3182SMatheus Izvekov   for (unsigned I = 1; I < E.size(); ++I) {
1578b65b1f32SSaar Raz     auto Next = fromConstraintExpr(S, D, E[I]);
1579b65b1f32SSaar Raz     if (!Next)
15808595f2e5SKazu Hirata       return std::nullopt;
158187aa3182SMatheus Izvekov     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1582b65b1f32SSaar Raz                                         std::move(*Next), CCK_Conjunction);
1583b65b1f32SSaar Raz   }
1584b65b1f32SSaar Raz   return Conjunction;
1585b65b1f32SSaar Raz }
1586b65b1f32SSaar Raz 
15876ad0788cSKazu Hirata std::optional<NormalizedConstraint>
1588df061c3eSSaar Raz NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1589df061c3eSSaar Raz   assert(E != nullptr);
1590df061c3eSSaar Raz 
1591df061c3eSSaar Raz   // C++ [temp.constr.normal]p1.1
1592df061c3eSSaar Raz   // [...]
1593df061c3eSSaar Raz   // - The normal form of an expression (E) is the normal form of E.
1594df061c3eSSaar Raz   // [...]
1595df061c3eSSaar Raz   E = E->IgnoreParenImpCasts();
1596340eac01SYuanfang Chen 
1597340eac01SYuanfang Chen   // C++2a [temp.param]p4:
1598340eac01SYuanfang Chen   //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1599c9447c62SYuanfang Chen   // Fold expression is considered atomic constraints per current wording.
1600c9447c62SYuanfang Chen   // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1601340eac01SYuanfang Chen 
16026c29073eSRichard Smith   if (LogicalBinOp BO = E) {
16036c29073eSRichard Smith     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1604df061c3eSSaar Raz     if (!LHS)
16058595f2e5SKazu Hirata       return std::nullopt;
16066c29073eSRichard Smith     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1607df061c3eSSaar Raz     if (!RHS)
16088595f2e5SKazu Hirata       return std::nullopt;
1609df061c3eSSaar Raz 
16106c29073eSRichard Smith     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
16116c29073eSRichard Smith                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1612df061c3eSSaar Raz   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1613b65b1f32SSaar Raz     const NormalizedConstraint *SubNF;
1614df061c3eSSaar Raz     {
1615df061c3eSSaar Raz       Sema::InstantiatingTemplate Inst(
1616df061c3eSSaar Raz           S, CSE->getExprLoc(),
1617df061c3eSSaar Raz           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
1618df061c3eSSaar Raz           CSE->getSourceRange());
161959902785SHaojian Wu       if (Inst.isInvalid())
162059902785SHaojian Wu         return std::nullopt;
1621df061c3eSSaar Raz       // C++ [temp.constr.normal]p1.1
1622df061c3eSSaar Raz       // [...]
1623df061c3eSSaar Raz       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1624df061c3eSSaar Raz       // where C names a concept, is the normal form of the
1625df061c3eSSaar Raz       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1626df061c3eSSaar Raz       // respective template parameters in the parameter mappings in each atomic
1627df061c3eSSaar Raz       // constraint. If any such substitution results in an invalid type or
1628df061c3eSSaar Raz       // expression, the program is ill-formed; no diagnostic is required.
1629df061c3eSSaar Raz       // [...]
1630b65b1f32SSaar Raz       ConceptDecl *CD = CSE->getNamedConcept();
1631b65b1f32SSaar Raz       SubNF = S.getNormalizedAssociatedConstraints(CD,
1632b65b1f32SSaar Raz                                                    {CD->getConstraintExpr()});
1633df061c3eSSaar Raz       if (!SubNF)
16348595f2e5SKazu Hirata         return std::nullopt;
1635df061c3eSSaar Raz     }
1636df061c3eSSaar Raz 
16376ad0788cSKazu Hirata     std::optional<NormalizedConstraint> New;
1638b65b1f32SSaar Raz     New.emplace(S.Context, *SubNF);
1639b65b1f32SSaar Raz 
1640babdef27SErich Keane     if (substituteParameterMappings(S, *New, CSE))
16418595f2e5SKazu Hirata       return std::nullopt;
1642df061c3eSSaar Raz 
1643b65b1f32SSaar Raz     return New;
1644b330d800Scor3ntin   } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
1645b330d800Scor3ntin              FE && S.getLangOpts().CPlusPlus26 &&
1646b330d800Scor3ntin              (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
1647b330d800Scor3ntin               FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
1648b330d800Scor3ntin 
1649b330d800Scor3ntin     // Normalize fold expressions in C++26.
1650b330d800Scor3ntin 
1651b330d800Scor3ntin     FoldExpandedConstraint::FoldOperatorKind Kind =
1652b330d800Scor3ntin         FE->getOperator() == BinaryOperatorKind::BO_LAnd
1653b330d800Scor3ntin             ? FoldExpandedConstraint::FoldOperatorKind::And
1654b330d800Scor3ntin             : FoldExpandedConstraint::FoldOperatorKind::Or;
1655b330d800Scor3ntin 
1656b330d800Scor3ntin     if (FE->getInit()) {
1657b330d800Scor3ntin       auto LHS = fromConstraintExpr(S, D, FE->getLHS());
1658b330d800Scor3ntin       auto RHS = fromConstraintExpr(S, D, FE->getRHS());
1659b330d800Scor3ntin       if (!LHS || !RHS)
1660b330d800Scor3ntin         return std::nullopt;
1661b330d800Scor3ntin 
1662b330d800Scor3ntin       if (FE->isRightFold())
1663b330d800Scor3ntin         RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1664b330d800Scor3ntin             Kind, std::move(*RHS), FE->getPattern()}};
1665b330d800Scor3ntin       else
1666b330d800Scor3ntin         LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1667b330d800Scor3ntin             Kind, std::move(*LHS), FE->getPattern()}};
1668b330d800Scor3ntin 
1669b330d800Scor3ntin       return NormalizedConstraint(
1670b330d800Scor3ntin           S.Context, std::move(*LHS), std::move(*RHS),
1671b330d800Scor3ntin           FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
1672b330d800Scor3ntin                                                            : CCK_Disjunction);
1673df061c3eSSaar Raz     }
1674b330d800Scor3ntin     auto Sub = fromConstraintExpr(S, D, FE->getPattern());
1675b330d800Scor3ntin     if (!Sub)
1676b330d800Scor3ntin       return std::nullopt;
1677b330d800Scor3ntin     return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1678b330d800Scor3ntin         Kind, std::move(*Sub), FE->getPattern()}};
1679b330d800Scor3ntin   }
1680b330d800Scor3ntin 
16819e9d98aaSMatheus Izvekov   return NormalizedConstraint{new (S.Context) AtomicConstraint(E, D)};
1682df061c3eSSaar Raz }
1683df061c3eSSaar Raz 
1684b330d800Scor3ntin bool FoldExpandedConstraint::AreCompatibleForSubsumption(
1685b330d800Scor3ntin     const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {
1686df061c3eSSaar Raz 
1687b330d800Scor3ntin   // [C++26] [temp.constr.fold]
1688b330d800Scor3ntin   // Two fold expanded constraints are compatible for subsumption
1689b330d800Scor3ntin   // if their respective constraints both contain an equivalent unexpanded pack.
1690b330d800Scor3ntin 
1691b330d800Scor3ntin   llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks;
1692b330d800Scor3ntin   Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks);
1693b330d800Scor3ntin   Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks);
1694b330d800Scor3ntin 
1695b330d800Scor3ntin   for (const UnexpandedParameterPack &APack : APacks) {
1696b330d800Scor3ntin     std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack);
1697b330d800Scor3ntin     auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
1698b330d800Scor3ntin       return getDepthAndIndex(BPack) == DepthAndIndex;
1699b330d800Scor3ntin     });
1700b330d800Scor3ntin     if (it != BPacks.end())
1701b330d800Scor3ntin       return true;
1702b330d800Scor3ntin   }
1703b330d800Scor3ntin   return false;
1704b330d800Scor3ntin }
1705b330d800Scor3ntin 
1706b330d800Scor3ntin NormalForm clang::makeCNF(const NormalizedConstraint &Normalized) {
1707df061c3eSSaar Raz   if (Normalized.isAtomic())
1708df061c3eSSaar Raz     return {{Normalized.getAtomicConstraint()}};
1709df061c3eSSaar Raz 
1710b330d800Scor3ntin   else if (Normalized.isFoldExpanded())
1711b330d800Scor3ntin     return {{Normalized.getFoldExpandedConstraint()}};
1712b330d800Scor3ntin 
1713df061c3eSSaar Raz   NormalForm LCNF = makeCNF(Normalized.getLHS());
1714df061c3eSSaar Raz   NormalForm RCNF = makeCNF(Normalized.getRHS());
1715df061c3eSSaar Raz   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
1716df061c3eSSaar Raz     LCNF.reserve(LCNF.size() + RCNF.size());
1717df061c3eSSaar Raz     while (!RCNF.empty())
1718df061c3eSSaar Raz       LCNF.push_back(RCNF.pop_back_val());
1719df061c3eSSaar Raz     return LCNF;
1720df061c3eSSaar Raz   }
1721df061c3eSSaar Raz 
1722df061c3eSSaar Raz   // Disjunction
1723df061c3eSSaar Raz   NormalForm Res;
1724df061c3eSSaar Raz   Res.reserve(LCNF.size() * RCNF.size());
1725df061c3eSSaar Raz   for (auto &LDisjunction : LCNF)
1726df061c3eSSaar Raz     for (auto &RDisjunction : RCNF) {
1727df061c3eSSaar Raz       NormalForm::value_type Combined;
1728df061c3eSSaar Raz       Combined.reserve(LDisjunction.size() + RDisjunction.size());
1729df061c3eSSaar Raz       std::copy(LDisjunction.begin(), LDisjunction.end(),
1730df061c3eSSaar Raz                 std::back_inserter(Combined));
1731df061c3eSSaar Raz       std::copy(RDisjunction.begin(), RDisjunction.end(),
1732df061c3eSSaar Raz                 std::back_inserter(Combined));
1733df061c3eSSaar Raz       Res.emplace_back(Combined);
1734df061c3eSSaar Raz     }
1735df061c3eSSaar Raz   return Res;
1736df061c3eSSaar Raz }
1737df061c3eSSaar Raz 
1738b330d800Scor3ntin NormalForm clang::makeDNF(const NormalizedConstraint &Normalized) {
1739df061c3eSSaar Raz   if (Normalized.isAtomic())
1740df061c3eSSaar Raz     return {{Normalized.getAtomicConstraint()}};
1741df061c3eSSaar Raz 
1742b330d800Scor3ntin   else if (Normalized.isFoldExpanded())
1743b330d800Scor3ntin     return {{Normalized.getFoldExpandedConstraint()}};
1744b330d800Scor3ntin 
1745df061c3eSSaar Raz   NormalForm LDNF = makeDNF(Normalized.getLHS());
1746df061c3eSSaar Raz   NormalForm RDNF = makeDNF(Normalized.getRHS());
1747df061c3eSSaar Raz   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
1748df061c3eSSaar Raz     LDNF.reserve(LDNF.size() + RDNF.size());
1749df061c3eSSaar Raz     while (!RDNF.empty())
1750df061c3eSSaar Raz       LDNF.push_back(RDNF.pop_back_val());
1751df061c3eSSaar Raz     return LDNF;
1752df061c3eSSaar Raz   }
1753df061c3eSSaar Raz 
1754df061c3eSSaar Raz   // Conjunction
1755df061c3eSSaar Raz   NormalForm Res;
1756df061c3eSSaar Raz   Res.reserve(LDNF.size() * RDNF.size());
1757df061c3eSSaar Raz   for (auto &LConjunction : LDNF) {
1758df061c3eSSaar Raz     for (auto &RConjunction : RDNF) {
1759df061c3eSSaar Raz       NormalForm::value_type Combined;
1760df061c3eSSaar Raz       Combined.reserve(LConjunction.size() + RConjunction.size());
1761df061c3eSSaar Raz       std::copy(LConjunction.begin(), LConjunction.end(),
1762df061c3eSSaar Raz                 std::back_inserter(Combined));
1763df061c3eSSaar Raz       std::copy(RConjunction.begin(), RConjunction.end(),
1764df061c3eSSaar Raz                 std::back_inserter(Combined));
1765df061c3eSSaar Raz       Res.emplace_back(Combined);
1766df061c3eSSaar Raz     }
1767df061c3eSSaar Raz   }
1768df061c3eSSaar Raz   return Res;
1769df061c3eSSaar Raz }
1770df061c3eSSaar Raz 
1771ae48d1c7SLiming Liu bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
1772ae48d1c7SLiming Liu                                   MutableArrayRef<const Expr *> AC1,
1773ae48d1c7SLiming Liu                                   NamedDecl *D2,
1774ae48d1c7SLiming Liu                                   MutableArrayRef<const Expr *> AC2,
1775df061c3eSSaar Raz                                   bool &Result) {
1776e18c2c55SYuanfang Chen   if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1777e18c2c55SYuanfang Chen     auto IsExpectedEntity = [](const FunctionDecl *FD) {
1778e18c2c55SYuanfang Chen       FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
1779e18c2c55SYuanfang Chen       return Kind == FunctionDecl::TK_NonTemplate ||
1780e18c2c55SYuanfang Chen              Kind == FunctionDecl::TK_FunctionTemplate;
1781e18c2c55SYuanfang Chen     };
1782e18c2c55SYuanfang Chen     const auto *FD2 = dyn_cast<FunctionDecl>(D2);
178321bac595SHaojian Wu     (void)IsExpectedEntity;
1784d0a98efbSVictor Komarov     (void)FD1;
178521bac595SHaojian Wu     (void)FD2;
1786e18c2c55SYuanfang Chen     assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1787e18c2c55SYuanfang Chen            "use non-instantiated function declaration for constraints partial "
1788e18c2c55SYuanfang Chen            "ordering");
1789e18c2c55SYuanfang Chen   }
1790e18c2c55SYuanfang Chen 
1791df061c3eSSaar Raz   if (AC1.empty()) {
1792df061c3eSSaar Raz     Result = AC2.empty();
1793df061c3eSSaar Raz     return false;
1794df061c3eSSaar Raz   }
1795df061c3eSSaar Raz   if (AC2.empty()) {
1796df061c3eSSaar Raz     // TD1 has associated constraints and TD2 does not.
1797df061c3eSSaar Raz     Result = true;
1798df061c3eSSaar Raz     return false;
1799df061c3eSSaar Raz   }
1800df061c3eSSaar Raz 
1801df061c3eSSaar Raz   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1802df061c3eSSaar Raz   auto CacheEntry = SubsumptionCache.find(Key);
1803df061c3eSSaar Raz   if (CacheEntry != SubsumptionCache.end()) {
1804df061c3eSSaar Raz     Result = CacheEntry->second;
1805df061c3eSSaar Raz     return false;
1806df061c3eSSaar Raz   }
1807b65b1f32SSaar Raz 
180844ab3805SKrystian Stasiowski   unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
180944ab3805SKrystian Stasiowski   unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1810ae48d1c7SLiming Liu 
1811ae48d1c7SLiming Liu   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1812ae48d1c7SLiming Liu     if (Depth2 > Depth1) {
1813ae48d1c7SLiming Liu       AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1814ae48d1c7SLiming Liu                    .TransformExpr(const_cast<Expr *>(AC1[I]))
1815ae48d1c7SLiming Liu                    .get();
1816ae48d1c7SLiming Liu     } else if (Depth1 > Depth2) {
1817ae48d1c7SLiming Liu       AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1818ae48d1c7SLiming Liu                    .TransformExpr(const_cast<Expr *>(AC2[I]))
1819ae48d1c7SLiming Liu                    .get();
1820ae48d1c7SLiming Liu     }
1821ae48d1c7SLiming Liu   }
1822ae48d1c7SLiming Liu 
1823b330d800Scor3ntin   if (clang::subsumes(
1824b330d800Scor3ntin           *this, D1, AC1, D2, AC2, Result,
1825b65b1f32SSaar Raz           [this](const AtomicConstraint &A, const AtomicConstraint &B) {
1826b65b1f32SSaar Raz             return A.subsumes(Context, B);
1827b65b1f32SSaar Raz           }))
1828df061c3eSSaar Raz     return true;
1829df061c3eSSaar Raz   SubsumptionCache.try_emplace(Key, Result);
1830df061c3eSSaar Raz   return false;
1831df061c3eSSaar Raz }
1832b65b1f32SSaar Raz 
1833b65b1f32SSaar Raz bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
1834b65b1f32SSaar Raz     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
1835b65b1f32SSaar Raz   if (isSFINAEContext())
1836b65b1f32SSaar Raz     // No need to work here because our notes would be discarded.
1837b65b1f32SSaar Raz     return false;
1838b65b1f32SSaar Raz 
1839b65b1f32SSaar Raz   if (AC1.empty() || AC2.empty())
1840b65b1f32SSaar Raz     return false;
1841b65b1f32SSaar Raz 
1842b65b1f32SSaar Raz   auto NormalExprEvaluator =
1843b65b1f32SSaar Raz       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1844b65b1f32SSaar Raz         return A.subsumes(Context, B);
1845b65b1f32SSaar Raz       };
1846b65b1f32SSaar Raz 
1847b65b1f32SSaar Raz   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1848b65b1f32SSaar Raz   auto IdenticalExprEvaluator =
1849b65b1f32SSaar Raz       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1850b65b1f32SSaar Raz         if (!A.hasMatchingParameterMapping(Context, B))
1851b65b1f32SSaar Raz           return false;
1852b65b1f32SSaar Raz         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1853b65b1f32SSaar Raz         if (EA == EB)
1854b65b1f32SSaar Raz           return true;
1855b65b1f32SSaar Raz 
1856b65b1f32SSaar Raz         // Not the same source level expression - are the expressions
1857b65b1f32SSaar Raz         // identical?
1858b65b1f32SSaar Raz         llvm::FoldingSetNodeID IDA, IDB;
1859bde305baSNico Weber         EA->Profile(IDA, Context, /*Canonical=*/true);
1860bde305baSNico Weber         EB->Profile(IDB, Context, /*Canonical=*/true);
1861b65b1f32SSaar Raz         if (IDA != IDB)
1862b65b1f32SSaar Raz           return false;
1863b65b1f32SSaar Raz 
1864b65b1f32SSaar Raz         AmbiguousAtomic1 = EA;
1865b65b1f32SSaar Raz         AmbiguousAtomic2 = EB;
1866b65b1f32SSaar Raz         return true;
1867b65b1f32SSaar Raz       };
1868b65b1f32SSaar Raz 
1869b65b1f32SSaar Raz   {
1870b65b1f32SSaar Raz     // The subsumption checks might cause diagnostics
1871b65b1f32SSaar Raz     SFINAETrap Trap(*this);
1872b65b1f32SSaar Raz     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1873b65b1f32SSaar Raz     if (!Normalized1)
1874b65b1f32SSaar Raz       return false;
1875b65b1f32SSaar Raz     const NormalForm DNF1 = makeDNF(*Normalized1);
1876b65b1f32SSaar Raz     const NormalForm CNF1 = makeCNF(*Normalized1);
1877b65b1f32SSaar Raz 
1878b65b1f32SSaar Raz     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1879b65b1f32SSaar Raz     if (!Normalized2)
1880b65b1f32SSaar Raz       return false;
1881b65b1f32SSaar Raz     const NormalForm DNF2 = makeDNF(*Normalized2);
1882b65b1f32SSaar Raz     const NormalForm CNF2 = makeCNF(*Normalized2);
1883b65b1f32SSaar Raz 
1884b330d800Scor3ntin     bool Is1AtLeastAs2Normally =
1885b330d800Scor3ntin         clang::subsumes(DNF1, CNF2, NormalExprEvaluator);
1886b330d800Scor3ntin     bool Is2AtLeastAs1Normally =
1887b330d800Scor3ntin         clang::subsumes(DNF2, CNF1, NormalExprEvaluator);
1888b330d800Scor3ntin     bool Is1AtLeastAs2 = clang::subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1889b330d800Scor3ntin     bool Is2AtLeastAs1 = clang::subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1890b65b1f32SSaar Raz     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1891b65b1f32SSaar Raz         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1892b65b1f32SSaar Raz       // Same result - no ambiguity was caused by identical atomic expressions.
1893b65b1f32SSaar Raz       return false;
1894b65b1f32SSaar Raz   }
1895b65b1f32SSaar Raz 
1896b65b1f32SSaar Raz   // A different result! Some ambiguous atomic constraint(s) caused a difference
1897b65b1f32SSaar Raz   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1898b65b1f32SSaar Raz 
1899b65b1f32SSaar Raz   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1900b65b1f32SSaar Raz       << AmbiguousAtomic1->getSourceRange();
1901b65b1f32SSaar Raz   Diag(AmbiguousAtomic2->getBeginLoc(),
1902b65b1f32SSaar Raz        diag::note_ambiguous_atomic_constraints_similar_expression)
1903b65b1f32SSaar Raz       << AmbiguousAtomic2->getSourceRange();
1904b65b1f32SSaar Raz   return true;
1905b65b1f32SSaar Raz }
1906a0f50d73SSaar Raz 
1907a0f50d73SSaar Raz concepts::ExprRequirement::ExprRequirement(
1908a0f50d73SSaar Raz     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1909a0f50d73SSaar Raz     ReturnTypeRequirement Req, SatisfactionStatus Status,
1910a0f50d73SSaar Raz     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1911a0f50d73SSaar Raz     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1912a0f50d73SSaar Raz                 Status == SS_Dependent &&
1913a0f50d73SSaar Raz                 (E->containsUnexpandedParameterPack() ||
1914a0f50d73SSaar Raz                  Req.containsUnexpandedParameterPack()),
1915a0f50d73SSaar Raz                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1916a0f50d73SSaar Raz     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1917a0f50d73SSaar Raz     Status(Status) {
1918a0f50d73SSaar Raz   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1919a0f50d73SSaar Raz          "Simple requirement must not have a return type requirement or a "
1920a0f50d73SSaar Raz          "noexcept specification");
1921a0f50d73SSaar Raz   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1922a0f50d73SSaar Raz          (SubstitutedConstraintExpr != nullptr));
1923a0f50d73SSaar Raz }
1924a0f50d73SSaar Raz 
1925a0f50d73SSaar Raz concepts::ExprRequirement::ExprRequirement(
1926a0f50d73SSaar Raz     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1927a0f50d73SSaar Raz     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1928a0f50d73SSaar Raz     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1929a0f50d73SSaar Raz                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1930a0f50d73SSaar Raz     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1931a0f50d73SSaar Raz     Status(SS_ExprSubstitutionFailure) {
1932a0f50d73SSaar Raz   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1933a0f50d73SSaar Raz          "Simple requirement must not have a return type requirement or a "
1934a0f50d73SSaar Raz          "noexcept specification");
1935a0f50d73SSaar Raz }
1936a0f50d73SSaar Raz 
1937a0f50d73SSaar Raz concepts::ExprRequirement::ReturnTypeRequirement::
1938a0f50d73SSaar Raz ReturnTypeRequirement(TemplateParameterList *TPL) :
193940446663SKazu Hirata     TypeConstraintInfo(TPL, false) {
1940a0f50d73SSaar Raz   assert(TPL->size() == 1);
1941a0f50d73SSaar Raz   const TypeConstraint *TC =
1942a0f50d73SSaar Raz       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
19430cf4f810SAaron Ballman   assert(TC &&
19440cf4f810SAaron Ballman          "TPL must have a template type parameter with a type constraint");
1945a0f50d73SSaar Raz   auto *Constraint =
194698339f14SSindhu Chittireddy       cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
194771886c56SRichard Smith   bool Dependent =
194871886c56SRichard Smith       Constraint->getTemplateArgsAsWritten() &&
194971886c56SRichard Smith       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
195071886c56SRichard Smith           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
195140446663SKazu Hirata   TypeConstraintInfo.setInt(Dependent ? true : false);
1952a0f50d73SSaar Raz }
1953a0f50d73SSaar Raz 
1954a0f50d73SSaar Raz concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
195571886c56SRichard Smith     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1956a0f50d73SSaar Raz                 T->getType()->containsUnexpandedParameterPack(),
1957a0f50d73SSaar Raz                 // We reach this ctor with either dependent types (in which
1958a0f50d73SSaar Raz                 // IsSatisfied doesn't matter) or with non-dependent type in
1959a0f50d73SSaar Raz                 // which the existence of the type indicates satisfaction.
196071886c56SRichard Smith                 /*IsSatisfied=*/true),
196171886c56SRichard Smith     Value(T),
196271886c56SRichard Smith     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
196371886c56SRichard Smith                                                         : SS_Satisfied) {}
19641e146dfbSKazu Hirata 
19651e146dfbSKazu Hirata NormalizedConstraint::CompoundConstraintKind
19661e146dfbSKazu Hirata NormalizedConstraint::getCompoundKind() const {
19671e146dfbSKazu Hirata   assert(isCompound() && "getCompoundKind on a non-compound constraint..");
19681e146dfbSKazu Hirata   return cast<CompoundConstraint>(Constraint).getInt();
19691e146dfbSKazu Hirata }
19701e146dfbSKazu Hirata 
19711e146dfbSKazu Hirata AtomicConstraint *NormalizedConstraint::getAtomicConstraint() const {
19721e146dfbSKazu Hirata   assert(isAtomic() && "getAtomicConstraint called on non-atomic constraint.");
19731e146dfbSKazu Hirata   return cast<AtomicConstraint *>(Constraint);
19741e146dfbSKazu Hirata }
19751e146dfbSKazu Hirata 
19761e146dfbSKazu Hirata FoldExpandedConstraint *
19771e146dfbSKazu Hirata NormalizedConstraint::getFoldExpandedConstraint() const {
19781e146dfbSKazu Hirata   assert(isFoldExpanded() &&
19791e146dfbSKazu Hirata          "getFoldExpandedConstraint called on non-fold-expanded constraint.");
19801e146dfbSKazu Hirata   return cast<FoldExpandedConstraint *>(Constraint);
19811e146dfbSKazu Hirata }
1982