xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision b3edf4467982447620505a28fc82e38a414c07dc)
1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2a7dea167SDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric //
9a7dea167SDimitry Andric //  This file implements semantic analysis for C++ constraints and concepts.
10a7dea167SDimitry Andric //
11a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
12a7dea167SDimitry Andric 
13480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h"
1406c3fb27SDimitry Andric #include "TreeTransform.h"
15bdd1243dSDimitry Andric #include "clang/AST/ASTLambda.h"
16feb5b0c7SDimitry Andric #include "clang/AST/DeclCXX.h"
1755e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h"
18480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
19480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h"
2006c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h"
2106c3fb27SDimitry Andric #include "clang/Sema/Initialization.h"
2206c3fb27SDimitry Andric #include "clang/Sema/Overload.h"
23feb5b0c7SDimitry Andric #include "clang/Sema/ScopeInfo.h"
2406c3fb27SDimitry Andric #include "clang/Sema/Sema.h"
2506c3fb27SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
2606c3fb27SDimitry Andric #include "clang/Sema/SemaInternal.h"
2706c3fb27SDimitry Andric #include "clang/Sema/Template.h"
2806c3fb27SDimitry Andric #include "clang/Sema/TemplateDeduction.h"
29480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h"
30480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h"
31fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
32bdd1243dSDimitry Andric #include <optional>
33fe6060f1SDimitry Andric 
34a7dea167SDimitry Andric using namespace clang;
35a7dea167SDimitry Andric using namespace sema;
36a7dea167SDimitry Andric 
375ffd83dbSDimitry Andric namespace {
385ffd83dbSDimitry Andric class LogicalBinOp {
39bdd1243dSDimitry Andric   SourceLocation Loc;
405ffd83dbSDimitry Andric   OverloadedOperatorKind Op = OO_None;
415ffd83dbSDimitry Andric   const Expr *LHS = nullptr;
425ffd83dbSDimitry Andric   const Expr *RHS = nullptr;
435ffd83dbSDimitry Andric 
445ffd83dbSDimitry Andric public:
455ffd83dbSDimitry Andric   LogicalBinOp(const Expr *E) {
465ffd83dbSDimitry Andric     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
475ffd83dbSDimitry Andric       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
485ffd83dbSDimitry Andric       LHS = BO->getLHS();
495ffd83dbSDimitry Andric       RHS = BO->getRHS();
50bdd1243dSDimitry Andric       Loc = BO->getExprLoc();
515ffd83dbSDimitry Andric     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
52fe6060f1SDimitry Andric       // If OO is not || or && it might not have exactly 2 arguments.
53fe6060f1SDimitry Andric       if (OO->getNumArgs() == 2) {
545ffd83dbSDimitry Andric         Op = OO->getOperator();
555ffd83dbSDimitry Andric         LHS = OO->getArg(0);
565ffd83dbSDimitry Andric         RHS = OO->getArg(1);
57bdd1243dSDimitry Andric         Loc = OO->getOperatorLoc();
585ffd83dbSDimitry Andric       }
595ffd83dbSDimitry Andric     }
60fe6060f1SDimitry Andric   }
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric   bool isAnd() const { return Op == OO_AmpAmp; }
635ffd83dbSDimitry Andric   bool isOr() const { return Op == OO_PipePipe; }
645ffd83dbSDimitry Andric   explicit operator bool() const { return isAnd() || isOr(); }
655ffd83dbSDimitry Andric 
665ffd83dbSDimitry Andric   const Expr *getLHS() const { return LHS; }
675ffd83dbSDimitry Andric   const Expr *getRHS() const { return RHS; }
68bdd1243dSDimitry Andric 
69bdd1243dSDimitry Andric   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
70bdd1243dSDimitry Andric     return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
71bdd1243dSDimitry Andric   }
72bdd1243dSDimitry Andric 
73bdd1243dSDimitry Andric   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
74bdd1243dSDimitry Andric                            ExprResult RHS) const {
75bdd1243dSDimitry Andric     assert((isAnd() || isOr()) && "Not the right kind of op?");
76bdd1243dSDimitry Andric     assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
77bdd1243dSDimitry Andric 
78bdd1243dSDimitry Andric     if (!LHS.isUsable() || !RHS.isUsable())
79bdd1243dSDimitry Andric       return ExprEmpty();
80bdd1243dSDimitry Andric 
81bdd1243dSDimitry Andric     // We should just be able to 'normalize' these to the builtin Binary
82bdd1243dSDimitry Andric     // Operator, since that is how they are evaluated in constriant checks.
83bdd1243dSDimitry Andric     return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
84bdd1243dSDimitry Andric                                   BinaryOperator::getOverloadedOpcode(Op),
85bdd1243dSDimitry Andric                                   SemaRef.Context.BoolTy, VK_PRValue,
86bdd1243dSDimitry Andric                                   OK_Ordinary, Loc, FPOptionsOverride{});
87bdd1243dSDimitry Andric   }
885ffd83dbSDimitry Andric };
895ffd83dbSDimitry Andric }
905ffd83dbSDimitry Andric 
915ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
925ffd83dbSDimitry Andric                                      Token NextToken, bool *PossibleNonPrimary,
93480093f4SDimitry Andric                                      bool IsTrailingRequiresClause) {
94a7dea167SDimitry Andric   // C++2a [temp.constr.atomic]p1
95a7dea167SDimitry Andric   // ..E shall be a constant expression of type bool.
96a7dea167SDimitry Andric 
97a7dea167SDimitry Andric   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
98a7dea167SDimitry Andric 
995ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpression) {
1005ffd83dbSDimitry Andric     return CheckConstraintExpression(BO.getLHS(), NextToken,
101480093f4SDimitry Andric                                      PossibleNonPrimary) &&
1025ffd83dbSDimitry Andric            CheckConstraintExpression(BO.getRHS(), NextToken,
103480093f4SDimitry Andric                                      PossibleNonPrimary);
104a7dea167SDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
105480093f4SDimitry Andric     return CheckConstraintExpression(C->getSubExpr(), NextToken,
106480093f4SDimitry Andric                                      PossibleNonPrimary);
107a7dea167SDimitry Andric 
108a7dea167SDimitry Andric   QualType Type = ConstraintExpression->getType();
109480093f4SDimitry Andric 
110480093f4SDimitry Andric   auto CheckForNonPrimary = [&] {
11106c3fb27SDimitry Andric     if (!PossibleNonPrimary)
11206c3fb27SDimitry Andric       return;
11306c3fb27SDimitry Andric 
114480093f4SDimitry Andric     *PossibleNonPrimary =
115480093f4SDimitry Andric         // We have the following case:
116480093f4SDimitry Andric         // template<typename> requires func(0) struct S { };
117480093f4SDimitry Andric         // The user probably isn't aware of the parentheses required around
118480093f4SDimitry Andric         // the function call, and we're only going to parse 'func' as the
119480093f4SDimitry Andric         // primary-expression, and complain that it is of non-bool type.
12006c3fb27SDimitry Andric         //
12106c3fb27SDimitry Andric         // However, if we're in a lambda, this might also be:
12206c3fb27SDimitry Andric         // []<typename> requires var () {};
12306c3fb27SDimitry Andric         // Which also looks like a function call due to the lambda parentheses,
12406c3fb27SDimitry Andric         // but unlike the first case, isn't an error, so this check is skipped.
125480093f4SDimitry Andric         (NextToken.is(tok::l_paren) &&
126480093f4SDimitry Andric          (IsTrailingRequiresClause ||
127480093f4SDimitry Andric           (Type->isDependentType() &&
12806c3fb27SDimitry Andric            isa<UnresolvedLookupExpr>(ConstraintExpression) &&
12906c3fb27SDimitry Andric            !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
130480093f4SDimitry Andric           Type->isFunctionType() ||
131480093f4SDimitry Andric           Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
132480093f4SDimitry Andric         // We have the following case:
133480093f4SDimitry Andric         // template<typename T> requires size_<T> == 0 struct S { };
134480093f4SDimitry Andric         // The user probably isn't aware of the parentheses required around
135480093f4SDimitry Andric         // the binary operator, and we're only going to parse 'func' as the
136480093f4SDimitry Andric         // first operand, and complain that it is of non-bool type.
137480093f4SDimitry Andric         getBinOpPrecedence(NextToken.getKind(),
138480093f4SDimitry Andric                            /*GreaterThanIsOperator=*/true,
139480093f4SDimitry Andric                            getLangOpts().CPlusPlus11) > prec::LogicalAnd;
140480093f4SDimitry Andric   };
141480093f4SDimitry Andric 
142480093f4SDimitry Andric   // An atomic constraint!
143480093f4SDimitry Andric   if (ConstraintExpression->isTypeDependent()) {
144480093f4SDimitry Andric     CheckForNonPrimary();
145480093f4SDimitry Andric     return true;
146480093f4SDimitry Andric   }
147480093f4SDimitry Andric 
148a7dea167SDimitry Andric   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
149a7dea167SDimitry Andric     Diag(ConstraintExpression->getExprLoc(),
150a7dea167SDimitry Andric          diag::err_non_bool_atomic_constraint) << Type
151a7dea167SDimitry Andric         << ConstraintExpression->getSourceRange();
152480093f4SDimitry Andric     CheckForNonPrimary();
153a7dea167SDimitry Andric     return false;
154a7dea167SDimitry Andric   }
155480093f4SDimitry Andric 
156480093f4SDimitry Andric   if (PossibleNonPrimary)
157480093f4SDimitry Andric       *PossibleNonPrimary = false;
158a7dea167SDimitry Andric   return true;
159a7dea167SDimitry Andric }
160a7dea167SDimitry Andric 
161bdd1243dSDimitry Andric namespace {
162bdd1243dSDimitry Andric struct SatisfactionStackRAII {
163bdd1243dSDimitry Andric   Sema &SemaRef;
1641ac55f4cSDimitry Andric   bool Inserted = false;
1651ac55f4cSDimitry Andric   SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
16606c3fb27SDimitry Andric                         const llvm::FoldingSetNodeID &FSNID)
167bdd1243dSDimitry Andric       : SemaRef(SemaRef) {
1681ac55f4cSDimitry Andric       if (ND) {
1691ac55f4cSDimitry Andric       SemaRef.PushSatisfactionStackEntry(ND, FSNID);
1701ac55f4cSDimitry Andric       Inserted = true;
171bdd1243dSDimitry Andric       }
1721ac55f4cSDimitry Andric   }
1731ac55f4cSDimitry Andric   ~SatisfactionStackRAII() {
1741ac55f4cSDimitry Andric         if (Inserted)
1751ac55f4cSDimitry Andric           SemaRef.PopSatisfactionStackEntry();
1761ac55f4cSDimitry Andric   }
177bdd1243dSDimitry Andric };
178bdd1243dSDimitry Andric } // namespace
179bdd1243dSDimitry Andric 
180480093f4SDimitry Andric template <typename AtomicEvaluator>
181bdd1243dSDimitry Andric static ExprResult
182480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
183480093f4SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
184480093f4SDimitry Andric                                 AtomicEvaluator &&Evaluator) {
185a7dea167SDimitry Andric   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
186a7dea167SDimitry Andric 
1875ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpr) {
1885f757f3fSDimitry Andric     size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
189bdd1243dSDimitry Andric     ExprResult LHSRes = calculateConstraintSatisfaction(
190bdd1243dSDimitry Andric         S, BO.getLHS(), Satisfaction, Evaluator);
191bdd1243dSDimitry Andric 
192bdd1243dSDimitry Andric     if (LHSRes.isInvalid())
193bdd1243dSDimitry Andric       return ExprError();
194480093f4SDimitry Andric 
195480093f4SDimitry Andric     bool IsLHSSatisfied = Satisfaction.IsSatisfied;
196480093f4SDimitry Andric 
1975ffd83dbSDimitry Andric     if (BO.isOr() && IsLHSSatisfied)
198480093f4SDimitry Andric       // [temp.constr.op] p3
199480093f4SDimitry Andric       //    A disjunction is a constraint taking two operands. To determine if
200480093f4SDimitry Andric       //    a disjunction is satisfied, the satisfaction of the first operand
201480093f4SDimitry Andric       //    is checked. If that is satisfied, the disjunction is satisfied.
202480093f4SDimitry Andric       //    Otherwise, the disjunction is satisfied if and only if the second
203480093f4SDimitry Andric       //    operand is satisfied.
204bdd1243dSDimitry Andric       // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
205bdd1243dSDimitry Andric       return LHSRes;
206480093f4SDimitry Andric 
2075ffd83dbSDimitry Andric     if (BO.isAnd() && !IsLHSSatisfied)
208480093f4SDimitry Andric       // [temp.constr.op] p2
209480093f4SDimitry Andric       //    A conjunction is a constraint taking two operands. To determine if
210480093f4SDimitry Andric       //    a conjunction is satisfied, the satisfaction of the first operand
211480093f4SDimitry Andric       //    is checked. If that is not satisfied, the conjunction is not
212480093f4SDimitry Andric       //    satisfied. Otherwise, the conjunction is satisfied if and only if
213480093f4SDimitry Andric       //    the second operand is satisfied.
214bdd1243dSDimitry Andric       // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
215bdd1243dSDimitry Andric       return LHSRes;
216480093f4SDimitry Andric 
217bdd1243dSDimitry Andric     ExprResult RHSRes = calculateConstraintSatisfaction(
2185ffd83dbSDimitry Andric         S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
219bdd1243dSDimitry Andric     if (RHSRes.isInvalid())
220bdd1243dSDimitry Andric       return ExprError();
221bdd1243dSDimitry Andric 
2225f757f3fSDimitry Andric     bool IsRHSSatisfied = Satisfaction.IsSatisfied;
2235f757f3fSDimitry Andric     // Current implementation adds diagnostic information about the falsity
2245f757f3fSDimitry Andric     // of each false atomic constraint expression when it evaluates them.
2255f757f3fSDimitry Andric     // When the evaluation results to `false || true`, the information
2265f757f3fSDimitry Andric     // generated during the evaluation of left-hand side is meaningless
2275f757f3fSDimitry Andric     // because the whole expression evaluates to true.
2285f757f3fSDimitry Andric     // The following code removes the irrelevant diagnostic information.
2295f757f3fSDimitry Andric     // FIXME: We should probably delay the addition of diagnostic information
2305f757f3fSDimitry Andric     // until we know the entire expression is false.
2315f757f3fSDimitry Andric     if (BO.isOr() && IsRHSSatisfied) {
2325f757f3fSDimitry Andric       auto EffectiveDetailEnd = Satisfaction.Details.begin();
2335f757f3fSDimitry Andric       std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
2345f757f3fSDimitry Andric       Satisfaction.Details.erase(EffectiveDetailEnd,
2355f757f3fSDimitry Andric                                  Satisfaction.Details.end());
2365f757f3fSDimitry Andric     }
2375f757f3fSDimitry Andric 
238bdd1243dSDimitry Andric     return BO.recreateBinOp(S, LHSRes, RHSRes);
239bdd1243dSDimitry Andric   }
240bdd1243dSDimitry Andric 
241bdd1243dSDimitry Andric   if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
242bdd1243dSDimitry Andric     // These aren't evaluated, so we don't care about cleanups, so we can just
243bdd1243dSDimitry Andric     // evaluate these as if the cleanups didn't exist.
244bdd1243dSDimitry Andric     return calculateConstraintSatisfaction(
245bdd1243dSDimitry Andric         S, C->getSubExpr(), Satisfaction,
246480093f4SDimitry Andric         std::forward<AtomicEvaluator>(Evaluator));
2475ffd83dbSDimitry Andric   }
248480093f4SDimitry Andric 
249480093f4SDimitry Andric   // An atomic constraint expression
250480093f4SDimitry Andric   ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
251480093f4SDimitry Andric 
252480093f4SDimitry Andric   if (SubstitutedAtomicExpr.isInvalid())
253bdd1243dSDimitry Andric     return ExprError();
254480093f4SDimitry Andric 
255480093f4SDimitry Andric   if (!SubstitutedAtomicExpr.isUsable())
256480093f4SDimitry Andric     // Evaluator has decided satisfaction without yielding an expression.
257bdd1243dSDimitry Andric     return ExprEmpty();
258bdd1243dSDimitry Andric 
259bdd1243dSDimitry Andric   // We don't have the ability to evaluate this, since it contains a
260bdd1243dSDimitry Andric   // RecoveryExpr, so we want to fail overload resolution.  Otherwise,
261bdd1243dSDimitry Andric   // we'd potentially pick up a different overload, and cause confusing
262bdd1243dSDimitry Andric   // diagnostics. SO, add a failure detail that will cause us to make this
263bdd1243dSDimitry Andric   // overload set not viable.
264bdd1243dSDimitry Andric   if (SubstitutedAtomicExpr.get()->containsErrors()) {
265bdd1243dSDimitry Andric     Satisfaction.IsSatisfied = false;
266bdd1243dSDimitry Andric     Satisfaction.ContainsErrors = true;
267bdd1243dSDimitry Andric 
268bdd1243dSDimitry Andric     PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
269bdd1243dSDimitry Andric     SmallString<128> DiagString;
270bdd1243dSDimitry Andric     DiagString = ": ";
271bdd1243dSDimitry Andric     Msg.EmitToString(S.getDiagnostics(), DiagString);
272bdd1243dSDimitry Andric     unsigned MessageSize = DiagString.size();
273bdd1243dSDimitry Andric     char *Mem = new (S.Context) char[MessageSize];
274bdd1243dSDimitry Andric     memcpy(Mem, DiagString.c_str(), MessageSize);
275bdd1243dSDimitry Andric     Satisfaction.Details.emplace_back(
276bdd1243dSDimitry Andric         ConstraintExpr,
277bdd1243dSDimitry Andric         new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
278bdd1243dSDimitry Andric             SubstitutedAtomicExpr.get()->getBeginLoc(),
279bdd1243dSDimitry Andric             StringRef(Mem, MessageSize)});
280bdd1243dSDimitry Andric     return SubstitutedAtomicExpr;
281bdd1243dSDimitry Andric   }
282a7dea167SDimitry Andric 
283a7dea167SDimitry Andric   EnterExpressionEvaluationContext ConstantEvaluated(
284480093f4SDimitry Andric       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
285a7dea167SDimitry Andric   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
286a7dea167SDimitry Andric   Expr::EvalResult EvalResult;
287a7dea167SDimitry Andric   EvalResult.Diag = &EvaluationDiags;
288fe6060f1SDimitry Andric   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
289fe6060f1SDimitry Andric                                                            S.Context) ||
290fe6060f1SDimitry Andric       !EvaluationDiags.empty()) {
291a7dea167SDimitry Andric     // C++2a [temp.constr.atomic]p1
292a7dea167SDimitry Andric     //   ...E shall be a constant expression of type bool.
293480093f4SDimitry Andric     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
294a7dea167SDimitry Andric            diag::err_non_constant_constraint_expression)
295480093f4SDimitry Andric         << SubstitutedAtomicExpr.get()->getSourceRange();
296a7dea167SDimitry Andric     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
297480093f4SDimitry Andric       S.Diag(PDiag.first, PDiag.second);
298bdd1243dSDimitry Andric     return ExprError();
299a7dea167SDimitry Andric   }
300a7dea167SDimitry Andric 
301fe6060f1SDimitry Andric   assert(EvalResult.Val.isInt() &&
302fe6060f1SDimitry Andric          "evaluating bool expression didn't produce int");
303480093f4SDimitry Andric   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
304480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied)
305480093f4SDimitry Andric     Satisfaction.Details.emplace_back(ConstraintExpr,
306480093f4SDimitry Andric                                       SubstitutedAtomicExpr.get());
307a7dea167SDimitry Andric 
308bdd1243dSDimitry Andric   return SubstitutedAtomicExpr;
309bdd1243dSDimitry Andric }
310bdd1243dSDimitry Andric 
311bdd1243dSDimitry Andric static bool
3121ac55f4cSDimitry Andric DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
3131ac55f4cSDimitry Andric                             const NamedDecl *Templ, const Expr *E,
314bdd1243dSDimitry Andric                             const MultiLevelTemplateArgumentList &MLTAL) {
315bdd1243dSDimitry Andric   E->Profile(ID, S.Context, /*Canonical=*/true);
316bdd1243dSDimitry Andric   for (const auto &List : MLTAL)
317bdd1243dSDimitry Andric     for (const auto &TemplateArg : List.Args)
318bdd1243dSDimitry Andric       TemplateArg.Profile(ID, S.Context);
319bdd1243dSDimitry Andric 
320bdd1243dSDimitry Andric   // Note that we have to do this with our own collection, because there are
321bdd1243dSDimitry Andric   // times where a constraint-expression check can cause us to need to evaluate
322bdd1243dSDimitry Andric   // other constriants that are unrelated, such as when evaluating a recovery
323bdd1243dSDimitry Andric   // expression, or when trying to determine the constexpr-ness of special
324bdd1243dSDimitry Andric   // members. Otherwise we could just use the
325bdd1243dSDimitry Andric   // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
3261ac55f4cSDimitry Andric   if (S.SatisfactionStackContains(Templ, ID)) {
327bdd1243dSDimitry Andric     S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
328bdd1243dSDimitry Andric         << const_cast<Expr *>(E) << E->getSourceRange();
329bdd1243dSDimitry Andric     return true;
330bdd1243dSDimitry Andric   }
331bdd1243dSDimitry Andric 
332a7dea167SDimitry Andric   return false;
333a7dea167SDimitry Andric }
334480093f4SDimitry Andric 
335bdd1243dSDimitry Andric static ExprResult calculateConstraintSatisfaction(
336bdd1243dSDimitry Andric     Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
337bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
338bdd1243dSDimitry Andric     ConstraintSatisfaction &Satisfaction) {
339480093f4SDimitry Andric   return calculateConstraintSatisfaction(
340480093f4SDimitry Andric       S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
341480093f4SDimitry Andric         EnterExpressionEvaluationContext ConstantEvaluated(
342bdd1243dSDimitry Andric             S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
343bdd1243dSDimitry Andric             Sema::ReuseLambdaContextDecl);
344480093f4SDimitry Andric 
345480093f4SDimitry Andric         // Atomic constraint - substitute arguments and check satisfaction.
346480093f4SDimitry Andric         ExprResult SubstitutedExpression;
347480093f4SDimitry Andric         {
348480093f4SDimitry Andric           TemplateDeductionInfo Info(TemplateNameLoc);
349480093f4SDimitry Andric           Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
35013138422SDimitry Andric               Sema::InstantiatingTemplate::ConstraintSubstitution{},
35113138422SDimitry Andric               const_cast<NamedDecl *>(Template), Info,
35213138422SDimitry Andric               AtomicExpr->getSourceRange());
353480093f4SDimitry Andric           if (Inst.isInvalid())
354480093f4SDimitry Andric             return ExprError();
355bdd1243dSDimitry Andric 
356bdd1243dSDimitry Andric           llvm::FoldingSetNodeID ID;
3571ac55f4cSDimitry Andric           if (Template &&
3581ac55f4cSDimitry Andric               DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
359bdd1243dSDimitry Andric             Satisfaction.IsSatisfied = false;
360bdd1243dSDimitry Andric             Satisfaction.ContainsErrors = true;
361bdd1243dSDimitry Andric             return ExprEmpty();
362bdd1243dSDimitry Andric           }
363bdd1243dSDimitry Andric 
3641ac55f4cSDimitry Andric           SatisfactionStackRAII StackRAII(S, Template, ID);
365bdd1243dSDimitry Andric 
366480093f4SDimitry Andric           // We do not want error diagnostics escaping here.
367480093f4SDimitry Andric           Sema::SFINAETrap Trap(S);
368fe6060f1SDimitry Andric           SubstitutedExpression =
369bdd1243dSDimitry Andric               S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
370bdd1243dSDimitry Andric 
371480093f4SDimitry Andric           if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
372480093f4SDimitry Andric             // C++2a [temp.constr.atomic]p1
373480093f4SDimitry Andric             //   ...If substitution results in an invalid type or expression, the
374480093f4SDimitry Andric             //   constraint is not satisfied.
375480093f4SDimitry Andric             if (!Trap.hasErrorOccurred())
376349cc55cSDimitry Andric               // A non-SFINAE error has occurred as a result of this
377480093f4SDimitry Andric               // substitution.
378480093f4SDimitry Andric               return ExprError();
379480093f4SDimitry Andric 
380480093f4SDimitry Andric             PartialDiagnosticAt SubstDiag{SourceLocation(),
381480093f4SDimitry Andric                                           PartialDiagnostic::NullDiagnostic()};
382480093f4SDimitry Andric             Info.takeSFINAEDiagnostic(SubstDiag);
383480093f4SDimitry Andric             // FIXME: Concepts: This is an unfortunate consequence of there
384480093f4SDimitry Andric             //  being no serialization code for PartialDiagnostics and the fact
385480093f4SDimitry Andric             //  that serializing them would likely take a lot more storage than
386480093f4SDimitry Andric             //  just storing them as strings. We would still like, in the
387480093f4SDimitry Andric             //  future, to serialize the proper PartialDiagnostic as serializing
388480093f4SDimitry Andric             //  it as a string defeats the purpose of the diagnostic mechanism.
389480093f4SDimitry Andric             SmallString<128> DiagString;
390480093f4SDimitry Andric             DiagString = ": ";
391480093f4SDimitry Andric             SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
392480093f4SDimitry Andric             unsigned MessageSize = DiagString.size();
393480093f4SDimitry Andric             char *Mem = new (S.Context) char[MessageSize];
394480093f4SDimitry Andric             memcpy(Mem, DiagString.c_str(), MessageSize);
395480093f4SDimitry Andric             Satisfaction.Details.emplace_back(
396480093f4SDimitry Andric                 AtomicExpr,
397480093f4SDimitry Andric                 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
398480093f4SDimitry Andric                         SubstDiag.first, StringRef(Mem, MessageSize)});
399480093f4SDimitry Andric             Satisfaction.IsSatisfied = false;
400480093f4SDimitry Andric             return ExprEmpty();
401480093f4SDimitry Andric           }
402480093f4SDimitry Andric         }
403480093f4SDimitry Andric 
404480093f4SDimitry Andric         if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
405480093f4SDimitry Andric           return ExprError();
406480093f4SDimitry Andric 
407bdd1243dSDimitry Andric         // [temp.constr.atomic]p3: To determine if an atomic constraint is
408bdd1243dSDimitry Andric         // satisfied, the parameter mapping and template arguments are first
409bdd1243dSDimitry Andric         // substituted into its expression.  If substitution results in an
410bdd1243dSDimitry Andric         // invalid type or expression, the constraint is not satisfied.
411bdd1243dSDimitry Andric         // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
412bdd1243dSDimitry Andric         // and E shall be a constant expression of type bool.
413bdd1243dSDimitry Andric         //
414bdd1243dSDimitry Andric         // Perform the L to R Value conversion if necessary. We do so for all
415bdd1243dSDimitry Andric         // non-PRValue categories, else we fail to extend the lifetime of
416bdd1243dSDimitry Andric         // temporaries, and that fails the constant expression check.
417bdd1243dSDimitry Andric         if (!SubstitutedExpression.get()->isPRValue())
418bdd1243dSDimitry Andric           SubstitutedExpression = ImplicitCastExpr::Create(
419bdd1243dSDimitry Andric               S.Context, SubstitutedExpression.get()->getType(),
420bdd1243dSDimitry Andric               CK_LValueToRValue, SubstitutedExpression.get(),
421bdd1243dSDimitry Andric               /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
422bdd1243dSDimitry Andric 
423480093f4SDimitry Andric         return SubstitutedExpression;
424480093f4SDimitry Andric       });
425480093f4SDimitry Andric }
426480093f4SDimitry Andric 
427bdd1243dSDimitry Andric static bool CheckConstraintSatisfaction(
428bdd1243dSDimitry Andric     Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
429bdd1243dSDimitry Andric     llvm::SmallVectorImpl<Expr *> &Converted,
430bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgsLists,
431bdd1243dSDimitry Andric     SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
432480093f4SDimitry Andric   if (ConstraintExprs.empty()) {
433480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
434480093f4SDimitry Andric     return false;
435480093f4SDimitry Andric   }
436480093f4SDimitry Andric 
437bdd1243dSDimitry Andric   if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
438480093f4SDimitry Andric     // No need to check satisfaction for dependent constraint expressions.
439480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
440480093f4SDimitry Andric     return false;
441480093f4SDimitry Andric   }
442480093f4SDimitry Andric 
443bdd1243dSDimitry Andric   ArrayRef<TemplateArgument> TemplateArgs =
444bdd1243dSDimitry Andric       TemplateArgsLists.getNumSubstitutedLevels() > 0
445bdd1243dSDimitry Andric           ? TemplateArgsLists.getOutermost()
446bdd1243dSDimitry Andric           : ArrayRef<TemplateArgument> {};
447480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
44813138422SDimitry Andric       Sema::InstantiatingTemplate::ConstraintsCheck{},
44913138422SDimitry Andric       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
450480093f4SDimitry Andric   if (Inst.isInvalid())
451480093f4SDimitry Andric     return true;
452480093f4SDimitry Andric 
453480093f4SDimitry Andric   for (const Expr *ConstraintExpr : ConstraintExprs) {
454bdd1243dSDimitry Andric     ExprResult Res = calculateConstraintSatisfaction(
455bdd1243dSDimitry Andric         S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
456bdd1243dSDimitry Andric         ConstraintExpr, Satisfaction);
457bdd1243dSDimitry Andric     if (Res.isInvalid())
458480093f4SDimitry Andric       return true;
459bdd1243dSDimitry Andric 
460bdd1243dSDimitry Andric     Converted.push_back(Res.get());
461bdd1243dSDimitry Andric     if (!Satisfaction.IsSatisfied) {
462bdd1243dSDimitry Andric       // Backfill the 'converted' list with nulls so we can keep the Converted
463bdd1243dSDimitry Andric       // and unconverted lists in sync.
464bdd1243dSDimitry Andric       Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
465480093f4SDimitry Andric       // [temp.constr.op] p2
466480093f4SDimitry Andric       // [...] To determine if a conjunction is satisfied, the satisfaction
467480093f4SDimitry Andric       // of the first operand is checked. If that is not satisfied, the
468480093f4SDimitry Andric       // conjunction is not satisfied. [...]
469480093f4SDimitry Andric       return false;
470480093f4SDimitry Andric     }
471bdd1243dSDimitry Andric   }
472480093f4SDimitry Andric   return false;
473480093f4SDimitry Andric }
474480093f4SDimitry Andric 
47555e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction(
47613138422SDimitry Andric     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
477bdd1243dSDimitry Andric     llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
478bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgsLists,
479bdd1243dSDimitry Andric     SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
48055e4f9d5SDimitry Andric   if (ConstraintExprs.empty()) {
48155e4f9d5SDimitry Andric     OutSatisfaction.IsSatisfied = true;
48255e4f9d5SDimitry Andric     return false;
483480093f4SDimitry Andric   }
48481ad6265SDimitry Andric   if (!Template) {
485bdd1243dSDimitry Andric     return ::CheckConstraintSatisfaction(
486bdd1243dSDimitry Andric         *this, nullptr, ConstraintExprs, ConvertedConstraints,
487bdd1243dSDimitry Andric         TemplateArgsLists, TemplateIDRange, OutSatisfaction);
48881ad6265SDimitry Andric   }
489bdd1243dSDimitry Andric 
490bdd1243dSDimitry Andric   // A list of the template argument list flattened in a predictible manner for
491bdd1243dSDimitry Andric   // the purposes of caching. The ConstraintSatisfaction type is in AST so it
492bdd1243dSDimitry Andric   // has no access to the MultiLevelTemplateArgumentList, so this has to happen
493bdd1243dSDimitry Andric   // here.
494bdd1243dSDimitry Andric   llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
495bdd1243dSDimitry Andric   for (auto List : TemplateArgsLists)
496bdd1243dSDimitry Andric     FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
497bdd1243dSDimitry Andric                          List.Args.end());
498bdd1243dSDimitry Andric 
49955e4f9d5SDimitry Andric   llvm::FoldingSetNodeID ID;
500bdd1243dSDimitry Andric   ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
50181ad6265SDimitry Andric   void *InsertPos;
50281ad6265SDimitry Andric   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
50381ad6265SDimitry Andric     OutSatisfaction = *Cached;
50455e4f9d5SDimitry Andric     return false;
50555e4f9d5SDimitry Andric   }
506bdd1243dSDimitry Andric 
50781ad6265SDimitry Andric   auto Satisfaction =
508bdd1243dSDimitry Andric       std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
50913138422SDimitry Andric   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
510bdd1243dSDimitry Andric                                     ConvertedConstraints, TemplateArgsLists,
511bdd1243dSDimitry Andric                                     TemplateIDRange, *Satisfaction)) {
512bdd1243dSDimitry Andric     OutSatisfaction = *Satisfaction;
51355e4f9d5SDimitry Andric     return true;
514480093f4SDimitry Andric   }
515bdd1243dSDimitry Andric 
516bdd1243dSDimitry Andric   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
517bdd1243dSDimitry Andric     // The evaluation of this constraint resulted in us trying to re-evaluate it
518bdd1243dSDimitry Andric     // recursively. This isn't really possible, except we try to form a
519bdd1243dSDimitry Andric     // RecoveryExpr as a part of the evaluation.  If this is the case, just
520bdd1243dSDimitry Andric     // return the 'cached' version (which will have the same result), and save
521bdd1243dSDimitry Andric     // ourselves the extra-insert. If it ever becomes possible to legitimately
522bdd1243dSDimitry Andric     // recursively check a constraint, we should skip checking the 'inner' one
523bdd1243dSDimitry Andric     // above, and replace the cached version with this one, as it would be more
524bdd1243dSDimitry Andric     // specific.
525bdd1243dSDimitry Andric     OutSatisfaction = *Cached;
526bdd1243dSDimitry Andric     return false;
527bdd1243dSDimitry Andric   }
528bdd1243dSDimitry Andric 
529bdd1243dSDimitry Andric   // Else we can simply add this satisfaction to the list.
53055e4f9d5SDimitry Andric   OutSatisfaction = *Satisfaction;
53181ad6265SDimitry Andric   // We cannot use InsertPos here because CheckConstraintSatisfaction might have
53281ad6265SDimitry Andric   // invalidated it.
53381ad6265SDimitry Andric   // Note that entries of SatisfactionCache are deleted in Sema's destructor.
53481ad6265SDimitry Andric   SatisfactionCache.InsertNode(Satisfaction.release());
53555e4f9d5SDimitry Andric   return false;
536480093f4SDimitry Andric }
537480093f4SDimitry Andric 
538480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
539480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
540480093f4SDimitry Andric   return calculateConstraintSatisfaction(
541480093f4SDimitry Andric              *this, ConstraintExpr, Satisfaction,
54281ad6265SDimitry Andric              [this](const Expr *AtomicExpr) -> ExprResult {
54381ad6265SDimitry Andric                // We only do this to immitate lvalue-to-rvalue conversion.
544bdd1243dSDimitry Andric                return PerformContextuallyConvertToBool(
545bdd1243dSDimitry Andric                    const_cast<Expr *>(AtomicExpr));
546bdd1243dSDimitry Andric              })
547bdd1243dSDimitry Andric       .isInvalid();
548bdd1243dSDimitry Andric }
549bdd1243dSDimitry Andric 
55006c3fb27SDimitry Andric bool Sema::addInstantiatedCapturesToScope(
55106c3fb27SDimitry Andric     FunctionDecl *Function, const FunctionDecl *PatternDecl,
55206c3fb27SDimitry Andric     LocalInstantiationScope &Scope,
55306c3fb27SDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgs) {
55406c3fb27SDimitry Andric   const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
55506c3fb27SDimitry Andric   const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
55606c3fb27SDimitry Andric 
55706c3fb27SDimitry Andric   unsigned Instantiated = 0;
55806c3fb27SDimitry Andric 
55906c3fb27SDimitry Andric   auto AddSingleCapture = [&](const ValueDecl *CapturedPattern,
56006c3fb27SDimitry Andric                               unsigned Index) {
56106c3fb27SDimitry Andric     ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
56206c3fb27SDimitry Andric     if (CapturedVar->isInitCapture())
56306c3fb27SDimitry Andric       Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
56406c3fb27SDimitry Andric   };
56506c3fb27SDimitry Andric 
56606c3fb27SDimitry Andric   for (const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
56706c3fb27SDimitry Andric     if (!CapturePattern.capturesVariable()) {
56806c3fb27SDimitry Andric       Instantiated++;
56906c3fb27SDimitry Andric       continue;
57006c3fb27SDimitry Andric     }
57106c3fb27SDimitry Andric     const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
57206c3fb27SDimitry Andric     if (!CapturedPattern->isParameterPack()) {
57306c3fb27SDimitry Andric       AddSingleCapture(CapturedPattern, Instantiated++);
57406c3fb27SDimitry Andric     } else {
57506c3fb27SDimitry Andric       Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
57606c3fb27SDimitry Andric       std::optional<unsigned> NumArgumentsInExpansion =
57706c3fb27SDimitry Andric           getNumArgumentsInExpansion(CapturedPattern->getType(), TemplateArgs);
57806c3fb27SDimitry Andric       if (!NumArgumentsInExpansion)
57906c3fb27SDimitry Andric         continue;
58006c3fb27SDimitry Andric       for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
58106c3fb27SDimitry Andric         AddSingleCapture(CapturedPattern, Instantiated++);
58206c3fb27SDimitry Andric     }
58306c3fb27SDimitry Andric   }
58406c3fb27SDimitry Andric   return false;
58506c3fb27SDimitry Andric }
58606c3fb27SDimitry Andric 
587bdd1243dSDimitry Andric bool Sema::SetupConstraintScope(
588bdd1243dSDimitry Andric     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
589bdd1243dSDimitry Andric     MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
590bdd1243dSDimitry Andric   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
591bdd1243dSDimitry Andric     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
592bdd1243dSDimitry Andric     InstantiatingTemplate Inst(
593bdd1243dSDimitry Andric         *this, FD->getPointOfInstantiation(),
594bdd1243dSDimitry Andric         Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
595bdd1243dSDimitry Andric         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
596bdd1243dSDimitry Andric         SourceRange());
597bdd1243dSDimitry Andric     if (Inst.isInvalid())
598bdd1243dSDimitry Andric       return true;
599bdd1243dSDimitry Andric 
600bdd1243dSDimitry Andric     // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
601bdd1243dSDimitry Andric     // 'instantiated' parameters and adds it to the context. For the case where
602bdd1243dSDimitry Andric     // this function is a template being instantiated NOW, we also need to add
603bdd1243dSDimitry Andric     // the list of current template arguments to the list so that they also can
604bdd1243dSDimitry Andric     // be picked out of the map.
605bdd1243dSDimitry Andric     if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
606bdd1243dSDimitry Andric       MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
607bdd1243dSDimitry Andric                                                    /*Final=*/false);
608bdd1243dSDimitry Andric       if (addInstantiatedParametersToScope(
609bdd1243dSDimitry Andric               FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
610bdd1243dSDimitry Andric         return true;
611bdd1243dSDimitry Andric     }
612bdd1243dSDimitry Andric 
613bdd1243dSDimitry Andric     // If this is a member function, make sure we get the parameters that
614bdd1243dSDimitry Andric     // reference the original primary template.
615*b3edf446SDimitry Andric     // We walk up the instantiated template chain so that nested lambdas get
616*b3edf446SDimitry Andric     // handled properly.
617*b3edf446SDimitry Andric     for (FunctionTemplateDecl *FromMemTempl =
618*b3edf446SDimitry Andric              PrimaryTemplate->getInstantiatedFromMemberTemplate();
619*b3edf446SDimitry Andric          FromMemTempl;
620*b3edf446SDimitry Andric          FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate()) {
621bdd1243dSDimitry Andric       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
622bdd1243dSDimitry Andric                                            Scope, MLTAL))
623bdd1243dSDimitry Andric         return true;
624bdd1243dSDimitry Andric     }
625bdd1243dSDimitry Andric 
626bdd1243dSDimitry Andric     return false;
627bdd1243dSDimitry Andric   }
628bdd1243dSDimitry Andric 
629bdd1243dSDimitry Andric   if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
630bdd1243dSDimitry Andric       FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
631bdd1243dSDimitry Andric     FunctionDecl *InstantiatedFrom =
632bdd1243dSDimitry Andric         FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
633bdd1243dSDimitry Andric             ? FD->getInstantiatedFromMemberFunction()
634bdd1243dSDimitry Andric             : FD->getInstantiatedFromDecl();
635bdd1243dSDimitry Andric 
636bdd1243dSDimitry Andric     InstantiatingTemplate Inst(
637bdd1243dSDimitry Andric         *this, FD->getPointOfInstantiation(),
638bdd1243dSDimitry Andric         Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
639bdd1243dSDimitry Andric         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
640bdd1243dSDimitry Andric         SourceRange());
641bdd1243dSDimitry Andric     if (Inst.isInvalid())
642bdd1243dSDimitry Andric       return true;
643bdd1243dSDimitry Andric 
644bdd1243dSDimitry Andric     // Case where this was not a template, but instantiated as a
645bdd1243dSDimitry Andric     // child-function.
646bdd1243dSDimitry Andric     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
647bdd1243dSDimitry Andric       return true;
648bdd1243dSDimitry Andric   }
649bdd1243dSDimitry Andric 
650bdd1243dSDimitry Andric   return false;
651bdd1243dSDimitry Andric }
652bdd1243dSDimitry Andric 
653bdd1243dSDimitry Andric // This function collects all of the template arguments for the purposes of
654bdd1243dSDimitry Andric // constraint-instantiation and checking.
655bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList>
656bdd1243dSDimitry Andric Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
657bdd1243dSDimitry Andric     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
658bdd1243dSDimitry Andric     LocalInstantiationScope &Scope) {
659bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
660bdd1243dSDimitry Andric 
661bdd1243dSDimitry Andric   // Collect the list of template arguments relative to the 'primary' template.
662bdd1243dSDimitry Andric   // We need the entire list, since the constraint is completely uninstantiated
663bdd1243dSDimitry Andric   // at this point.
6645f757f3fSDimitry Andric   MLTAL = getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
6655f757f3fSDimitry Andric                                        /*Final=*/false, /*Innermost=*/nullptr,
666bdd1243dSDimitry Andric                                        /*RelativeToPrimary=*/true,
667bdd1243dSDimitry Andric                                        /*Pattern=*/nullptr,
668bdd1243dSDimitry Andric                                        /*ForConstraintInstantiation=*/true);
669bdd1243dSDimitry Andric   if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
670bdd1243dSDimitry Andric     return std::nullopt;
671bdd1243dSDimitry Andric 
672bdd1243dSDimitry Andric   return MLTAL;
673480093f4SDimitry Andric }
674480093f4SDimitry Andric 
67513138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
67613138422SDimitry Andric                                     ConstraintSatisfaction &Satisfaction,
677bdd1243dSDimitry Andric                                     SourceLocation UsageLoc,
678bdd1243dSDimitry Andric                                     bool ForOverloadResolution) {
679bdd1243dSDimitry Andric   // Don't check constraints if the function is dependent. Also don't check if
680bdd1243dSDimitry Andric   // this is a function template specialization, as the call to
681bdd1243dSDimitry Andric   // CheckinstantiatedFunctionTemplateConstraints after this will check it
682bdd1243dSDimitry Andric   // better.
683bdd1243dSDimitry Andric   if (FD->isDependentContext() ||
684bdd1243dSDimitry Andric       FD->getTemplatedKind() ==
685bdd1243dSDimitry Andric           FunctionDecl::TK_FunctionTemplateSpecialization) {
68613138422SDimitry Andric     Satisfaction.IsSatisfied = true;
68713138422SDimitry Andric     return false;
68813138422SDimitry Andric   }
689bdd1243dSDimitry Andric 
69006c3fb27SDimitry Andric   // A lambda conversion operator has the same constraints as the call operator
69106c3fb27SDimitry Andric   // and constraints checking relies on whether we are in a lambda call operator
69206c3fb27SDimitry Andric   // (and may refer to its parameters), so check the call operator instead.
69306c3fb27SDimitry Andric   if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
69406c3fb27SDimitry Andric       MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
69506c3fb27SDimitry Andric     return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
69606c3fb27SDimitry Andric                                     Satisfaction, UsageLoc,
69706c3fb27SDimitry Andric                                     ForOverloadResolution);
69806c3fb27SDimitry Andric 
699bdd1243dSDimitry Andric   DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
700bdd1243dSDimitry Andric 
701bdd1243dSDimitry Andric   while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
702bdd1243dSDimitry Andric     if (isLambdaCallOperator(CtxToSave))
703bdd1243dSDimitry Andric       CtxToSave = CtxToSave->getParent()->getParent();
704bdd1243dSDimitry Andric     else
705bdd1243dSDimitry Andric       CtxToSave = CtxToSave->getNonTransparentContext();
706bdd1243dSDimitry Andric   }
707bdd1243dSDimitry Andric 
708bdd1243dSDimitry Andric   ContextRAII SavedContext{*this, CtxToSave};
7095f757f3fSDimitry Andric   LocalInstantiationScope Scope(*this, !ForOverloadResolution);
710bdd1243dSDimitry Andric   std::optional<MultiLevelTemplateArgumentList> MLTAL =
711bdd1243dSDimitry Andric       SetupConstraintCheckingTemplateArgumentsAndScope(
712bdd1243dSDimitry Andric           const_cast<FunctionDecl *>(FD), {}, Scope);
713bdd1243dSDimitry Andric 
714bdd1243dSDimitry Andric   if (!MLTAL)
715bdd1243dSDimitry Andric     return true;
716bdd1243dSDimitry Andric 
71713138422SDimitry Andric   Qualifiers ThisQuals;
71813138422SDimitry Andric   CXXRecordDecl *Record = nullptr;
71913138422SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
72013138422SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
72113138422SDimitry Andric     Record = const_cast<CXXRecordDecl *>(Method->getParent());
72213138422SDimitry Andric   }
72313138422SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
724feb5b0c7SDimitry Andric 
725feb5b0c7SDimitry Andric   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
7265f757f3fSDimitry Andric       *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
7275f757f3fSDimitry Andric       ForOverloadResolution);
728feb5b0c7SDimitry Andric 
72906c3fb27SDimitry Andric   return CheckConstraintSatisfaction(
73006c3fb27SDimitry Andric       FD, {FD->getTrailingRequiresClause()}, *MLTAL,
73113138422SDimitry Andric       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
73206c3fb27SDimitry Andric       Satisfaction);
733bdd1243dSDimitry Andric }
734bdd1243dSDimitry Andric 
735bdd1243dSDimitry Andric 
736bdd1243dSDimitry Andric // Figure out the to-translation-unit depth for this function declaration for
737bdd1243dSDimitry Andric // the purpose of seeing if they differ by constraints. This isn't the same as
738bdd1243dSDimitry Andric // getTemplateDepth, because it includes already instantiated parents.
739bdd1243dSDimitry Andric static unsigned
740bdd1243dSDimitry Andric CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
741bdd1243dSDimitry Andric                                      bool SkipForSpecialization = false) {
742bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
7435f757f3fSDimitry Andric       ND, ND->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/nullptr,
7445f757f3fSDimitry Andric       /*RelativeToPrimary=*/true,
745bdd1243dSDimitry Andric       /*Pattern=*/nullptr,
746bdd1243dSDimitry Andric       /*ForConstraintInstantiation=*/true, SkipForSpecialization);
74706c3fb27SDimitry Andric   return MLTAL.getNumLevels();
748bdd1243dSDimitry Andric }
749bdd1243dSDimitry Andric 
750bdd1243dSDimitry Andric namespace {
751bdd1243dSDimitry Andric   class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
752bdd1243dSDimitry Andric   unsigned TemplateDepth = 0;
753bdd1243dSDimitry Andric   public:
754bdd1243dSDimitry Andric   using inherited = TreeTransform<AdjustConstraintDepth>;
755bdd1243dSDimitry Andric   AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
756bdd1243dSDimitry Andric       : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
757bdd1243dSDimitry Andric 
758bdd1243dSDimitry Andric   using inherited::TransformTemplateTypeParmType;
759bdd1243dSDimitry Andric   QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
760bdd1243dSDimitry Andric                                          TemplateTypeParmTypeLoc TL, bool) {
761bdd1243dSDimitry Andric     const TemplateTypeParmType *T = TL.getTypePtr();
762bdd1243dSDimitry Andric 
763bdd1243dSDimitry Andric     TemplateTypeParmDecl *NewTTPDecl = nullptr;
764bdd1243dSDimitry Andric     if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
765bdd1243dSDimitry Andric       NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
766bdd1243dSDimitry Andric           TransformDecl(TL.getNameLoc(), OldTTPDecl));
767bdd1243dSDimitry Andric 
768bdd1243dSDimitry Andric     QualType Result = getSema().Context.getTemplateTypeParmType(
769bdd1243dSDimitry Andric         T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
770bdd1243dSDimitry Andric         NewTTPDecl);
771bdd1243dSDimitry Andric     TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
772bdd1243dSDimitry Andric     NewTL.setNameLoc(TL.getNameLoc());
773bdd1243dSDimitry Andric     return Result;
774bdd1243dSDimitry Andric   }
775bdd1243dSDimitry Andric   };
776bdd1243dSDimitry Andric } // namespace
777bdd1243dSDimitry Andric 
7781db9f3b2SDimitry Andric static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
7791db9f3b2SDimitry Andric     Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
78006c3fb27SDimitry Andric     const Expr *ConstrExpr) {
78106c3fb27SDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
7825f757f3fSDimitry Andric       DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
7835f757f3fSDimitry Andric       /*Innermost=*/nullptr,
78406c3fb27SDimitry Andric       /*RelativeToPrimary=*/true,
78506c3fb27SDimitry Andric       /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
78606c3fb27SDimitry Andric       /*SkipForSpecialization*/ false);
7875f757f3fSDimitry Andric 
78806c3fb27SDimitry Andric   if (MLTAL.getNumSubstitutedLevels() == 0)
78906c3fb27SDimitry Andric     return ConstrExpr;
79006c3fb27SDimitry Andric 
79106c3fb27SDimitry Andric   Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);
79206c3fb27SDimitry Andric 
79306c3fb27SDimitry Andric   Sema::InstantiatingTemplate Inst(
7945f757f3fSDimitry Andric       S, DeclInfo.getLocation(),
79506c3fb27SDimitry Andric       Sema::InstantiatingTemplate::ConstraintNormalization{},
7965f757f3fSDimitry Andric       const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
79706c3fb27SDimitry Andric   if (Inst.isInvalid())
79806c3fb27SDimitry Andric     return nullptr;
79906c3fb27SDimitry Andric 
80006c3fb27SDimitry Andric   std::optional<Sema::CXXThisScopeRAII> ThisScope;
8015f757f3fSDimitry Andric   if (auto *RD = dyn_cast<CXXRecordDecl>(DeclInfo.getDeclContext()))
80206c3fb27SDimitry Andric     ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
8031db9f3b2SDimitry Andric   ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
8041db9f3b2SDimitry Andric       const_cast<clang::Expr *>(ConstrExpr), MLTAL);
80506c3fb27SDimitry Andric   if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
80606c3fb27SDimitry Andric     return nullptr;
80706c3fb27SDimitry Andric   return SubstConstr.get();
80806c3fb27SDimitry Andric }
80906c3fb27SDimitry Andric 
810bdd1243dSDimitry Andric bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
811bdd1243dSDimitry Andric                                          const Expr *OldConstr,
8125f757f3fSDimitry Andric                                          const TemplateCompareNewDeclInfo &New,
813bdd1243dSDimitry Andric                                          const Expr *NewConstr) {
81406c3fb27SDimitry Andric   if (OldConstr == NewConstr)
81506c3fb27SDimitry Andric     return true;
81606c3fb27SDimitry Andric   // C++ [temp.constr.decl]p4
8175f757f3fSDimitry Andric   if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
8185f757f3fSDimitry Andric       Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
81906c3fb27SDimitry Andric     if (const Expr *SubstConstr =
8201db9f3b2SDimitry Andric             SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
8211db9f3b2SDimitry Andric                                                               OldConstr))
82206c3fb27SDimitry Andric       OldConstr = SubstConstr;
82306c3fb27SDimitry Andric     else
82406c3fb27SDimitry Andric       return false;
82506c3fb27SDimitry Andric     if (const Expr *SubstConstr =
8261db9f3b2SDimitry Andric             SubstituteConstraintExpressionWithoutSatisfaction(*this, New,
8271db9f3b2SDimitry Andric                                                               NewConstr))
82806c3fb27SDimitry Andric       NewConstr = SubstConstr;
82906c3fb27SDimitry Andric     else
83006c3fb27SDimitry Andric       return false;
831bdd1243dSDimitry Andric   }
832bdd1243dSDimitry Andric 
833bdd1243dSDimitry Andric   llvm::FoldingSetNodeID ID1, ID2;
834bdd1243dSDimitry Andric   OldConstr->Profile(ID1, Context, /*Canonical=*/true);
835bdd1243dSDimitry Andric   NewConstr->Profile(ID2, Context, /*Canonical=*/true);
836bdd1243dSDimitry Andric   return ID1 == ID2;
837bdd1243dSDimitry Andric }
838bdd1243dSDimitry Andric 
839bdd1243dSDimitry Andric bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
840bdd1243dSDimitry Andric   assert(FD->getFriendObjectKind() && "Must be a friend!");
841bdd1243dSDimitry Andric 
842bdd1243dSDimitry Andric   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
843bdd1243dSDimitry Andric   // don't have to bother checking 'DependsOnEnclosingTemplate' for a
844bdd1243dSDimitry Andric   // non-function-template.
845bdd1243dSDimitry Andric   assert(FD->getDescribedFunctionTemplate() &&
846bdd1243dSDimitry Andric          "Non-function templates don't need to be checked");
847bdd1243dSDimitry Andric 
848bdd1243dSDimitry Andric   SmallVector<const Expr *, 3> ACs;
849bdd1243dSDimitry Andric   FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
850bdd1243dSDimitry Andric 
851bdd1243dSDimitry Andric   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
852bdd1243dSDimitry Andric   for (const Expr *Constraint : ACs)
853bdd1243dSDimitry Andric     if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
854bdd1243dSDimitry Andric                                                        Constraint))
855bdd1243dSDimitry Andric       return true;
856bdd1243dSDimitry Andric 
857bdd1243dSDimitry Andric   return false;
85813138422SDimitry Andric }
85913138422SDimitry Andric 
860480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints(
861bdd1243dSDimitry Andric     TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
862480093f4SDimitry Andric     SourceRange TemplateIDRange) {
863480093f4SDimitry Andric   ConstraintSatisfaction Satisfaction;
864480093f4SDimitry Andric   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
865480093f4SDimitry Andric   TD->getAssociatedConstraints(AssociatedConstraints);
866bdd1243dSDimitry Andric   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
867480093f4SDimitry Andric                                   TemplateIDRange, Satisfaction))
868480093f4SDimitry Andric     return true;
869480093f4SDimitry Andric 
870480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied) {
871480093f4SDimitry Andric     SmallString<128> TemplateArgString;
872480093f4SDimitry Andric     TemplateArgString = " ";
873480093f4SDimitry Andric     TemplateArgString += getTemplateArgumentBindingsText(
874bdd1243dSDimitry Andric         TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
875bdd1243dSDimitry Andric         TemplateArgsLists.getInnermost().size());
876480093f4SDimitry Andric 
877480093f4SDimitry Andric     Diag(TemplateIDRange.getBegin(),
878480093f4SDimitry Andric          diag::err_template_arg_list_constraints_not_satisfied)
879480093f4SDimitry Andric         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
880480093f4SDimitry Andric         << TemplateArgString << TemplateIDRange;
881480093f4SDimitry Andric     DiagnoseUnsatisfiedConstraint(Satisfaction);
882480093f4SDimitry Andric     return true;
883480093f4SDimitry Andric   }
884480093f4SDimitry Andric   return false;
885480093f4SDimitry Andric }
886480093f4SDimitry Andric 
88781ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints(
88881ad6265SDimitry Andric     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
88981ad6265SDimitry Andric     ArrayRef<TemplateArgument> TemplateArgs,
89081ad6265SDimitry Andric     ConstraintSatisfaction &Satisfaction) {
89181ad6265SDimitry Andric   // In most cases we're not going to have constraints, so check for that first.
89281ad6265SDimitry Andric   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
89381ad6265SDimitry Andric   // Note - code synthesis context for the constraints check is created
89481ad6265SDimitry Andric   // inside CheckConstraintsSatisfaction.
89581ad6265SDimitry Andric   SmallVector<const Expr *, 3> TemplateAC;
89681ad6265SDimitry Andric   Template->getAssociatedConstraints(TemplateAC);
89781ad6265SDimitry Andric   if (TemplateAC.empty()) {
89881ad6265SDimitry Andric     Satisfaction.IsSatisfied = true;
89981ad6265SDimitry Andric     return false;
90081ad6265SDimitry Andric   }
90181ad6265SDimitry Andric 
90281ad6265SDimitry Andric   // Enter the scope of this instantiation. We don't use
90381ad6265SDimitry Andric   // PushDeclContext because we don't have a scope.
90481ad6265SDimitry Andric   Sema::ContextRAII savedContext(*this, Decl);
90581ad6265SDimitry Andric   LocalInstantiationScope Scope(*this);
90681ad6265SDimitry Andric 
907bdd1243dSDimitry Andric   std::optional<MultiLevelTemplateArgumentList> MLTAL =
908bdd1243dSDimitry Andric       SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
909bdd1243dSDimitry Andric                                                        Scope);
910bdd1243dSDimitry Andric 
911bdd1243dSDimitry Andric   if (!MLTAL)
91281ad6265SDimitry Andric     return true;
913bdd1243dSDimitry Andric 
91481ad6265SDimitry Andric   Qualifiers ThisQuals;
91581ad6265SDimitry Andric   CXXRecordDecl *Record = nullptr;
91681ad6265SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
91781ad6265SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
91881ad6265SDimitry Andric     Record = Method->getParent();
91981ad6265SDimitry Andric   }
920feb5b0c7SDimitry Andric 
92181ad6265SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
922feb5b0c7SDimitry Andric   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
923feb5b0c7SDimitry Andric       *this, const_cast<FunctionDecl *>(Decl), *MLTAL, Scope);
924bdd1243dSDimitry Andric 
925bdd1243dSDimitry Andric   llvm::SmallVector<Expr *, 1> Converted;
926bdd1243dSDimitry Andric   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
92781ad6265SDimitry Andric                                      PointOfInstantiation, Satisfaction);
92881ad6265SDimitry Andric }
92981ad6265SDimitry Andric 
93055e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
93155e4f9d5SDimitry Andric                                            concepts::ExprRequirement *Req,
93255e4f9d5SDimitry Andric                                            bool First) {
93355e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
93455e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
93555e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
93655e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Dependent:
93755e4f9d5SDimitry Andric       llvm_unreachable("Diagnosing a dependent requirement");
93855e4f9d5SDimitry Andric       break;
93955e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
94055e4f9d5SDimitry Andric       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
94155e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
94255e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
94355e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_substitution_error)
94455e4f9d5SDimitry Andric                << (int)First << SubstDiag->SubstitutedEntity
94555e4f9d5SDimitry Andric                << SubstDiag->DiagMessage;
94655e4f9d5SDimitry Andric       else
94755e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
94855e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_unknown_substitution_error)
94955e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
95055e4f9d5SDimitry Andric       break;
95155e4f9d5SDimitry Andric     }
95255e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_NoexceptNotMet:
95355e4f9d5SDimitry Andric       S.Diag(Req->getNoexceptLoc(),
95455e4f9d5SDimitry Andric              diag::note_expr_requirement_noexcept_not_met)
95555e4f9d5SDimitry Andric           << (int)First << Req->getExpr();
95655e4f9d5SDimitry Andric       break;
95755e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
95855e4f9d5SDimitry Andric       auto *SubstDiag =
95955e4f9d5SDimitry Andric           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
96055e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
96155e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
96255e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_substitution_error)
96355e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity
96455e4f9d5SDimitry Andric             << SubstDiag->DiagMessage;
96555e4f9d5SDimitry Andric       else
96655e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
96755e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
96855e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
96955e4f9d5SDimitry Andric       break;
97055e4f9d5SDimitry Andric     }
97155e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
97255e4f9d5SDimitry Andric       ConceptSpecializationExpr *ConstraintExpr =
97355e4f9d5SDimitry Andric           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
974fe6060f1SDimitry Andric       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
97555e4f9d5SDimitry Andric         // A simple case - expr type is the type being constrained and the concept
97655e4f9d5SDimitry Andric         // was not provided arguments.
977fe6060f1SDimitry Andric         Expr *e = Req->getExpr();
978fe6060f1SDimitry Andric         S.Diag(e->getBeginLoc(),
97955e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied_simple)
980349cc55cSDimitry Andric             << (int)First << S.Context.getReferenceQualifiedType(e)
98155e4f9d5SDimitry Andric             << ConstraintExpr->getNamedConcept();
982fe6060f1SDimitry Andric       } else {
98355e4f9d5SDimitry Andric         S.Diag(ConstraintExpr->getBeginLoc(),
98455e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied)
98555e4f9d5SDimitry Andric             << (int)First << ConstraintExpr;
986fe6060f1SDimitry Andric       }
98755e4f9d5SDimitry Andric       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
98855e4f9d5SDimitry Andric       break;
98955e4f9d5SDimitry Andric     }
99055e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Satisfied:
99155e4f9d5SDimitry Andric       llvm_unreachable("We checked this above");
99255e4f9d5SDimitry Andric   }
99355e4f9d5SDimitry Andric }
99455e4f9d5SDimitry Andric 
99555e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
99655e4f9d5SDimitry Andric                                            concepts::TypeRequirement *Req,
99755e4f9d5SDimitry Andric                                            bool First) {
99855e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
99955e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
100055e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
100155e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_Dependent:
100255e4f9d5SDimitry Andric     llvm_unreachable("Diagnosing a dependent requirement");
100355e4f9d5SDimitry Andric     return;
100455e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_SubstitutionFailure: {
100555e4f9d5SDimitry Andric     auto *SubstDiag = Req->getSubstitutionDiagnostic();
100655e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
100755e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
100855e4f9d5SDimitry Andric              diag::note_type_requirement_substitution_error) << (int)First
100955e4f9d5SDimitry Andric           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
101055e4f9d5SDimitry Andric     else
101155e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
101255e4f9d5SDimitry Andric              diag::note_type_requirement_unknown_substitution_error)
101355e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
101455e4f9d5SDimitry Andric     return;
101555e4f9d5SDimitry Andric   }
101655e4f9d5SDimitry Andric   default:
101755e4f9d5SDimitry Andric     llvm_unreachable("Unknown satisfaction status");
101855e4f9d5SDimitry Andric     return;
101955e4f9d5SDimitry Andric   }
102055e4f9d5SDimitry Andric }
1021bdd1243dSDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1022bdd1243dSDimitry Andric                                                         Expr *SubstExpr,
1023bdd1243dSDimitry Andric                                                         bool First = true);
102455e4f9d5SDimitry Andric 
102555e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
102655e4f9d5SDimitry Andric                                            concepts::NestedRequirement *Req,
102755e4f9d5SDimitry Andric                                            bool First) {
1028bdd1243dSDimitry Andric   using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1029bdd1243dSDimitry Andric   for (auto &Pair : Req->getConstraintSatisfaction()) {
1030bdd1243dSDimitry Andric     if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
1031bdd1243dSDimitry Andric       S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1032bdd1243dSDimitry Andric           << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second;
103355e4f9d5SDimitry Andric     else
1034bdd1243dSDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(
1035bdd1243dSDimitry Andric           S, Pair.second.dyn_cast<Expr *>(), First);
1036bdd1243dSDimitry Andric     First = false;
103755e4f9d5SDimitry Andric   }
103855e4f9d5SDimitry Andric }
103955e4f9d5SDimitry Andric 
1040480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1041480093f4SDimitry Andric                                                         Expr *SubstExpr,
1042bdd1243dSDimitry Andric                                                         bool First) {
1043480093f4SDimitry Andric   SubstExpr = SubstExpr->IgnoreParenImpCasts();
1044480093f4SDimitry Andric   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1045480093f4SDimitry Andric     switch (BO->getOpcode()) {
1046480093f4SDimitry Andric     // These two cases will in practice only be reached when using fold
1047480093f4SDimitry Andric     // expressions with || and &&, since otherwise the || and && will have been
1048480093f4SDimitry Andric     // broken down into atomic constraints during satisfaction checking.
1049480093f4SDimitry Andric     case BO_LOr:
1050480093f4SDimitry Andric       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1051480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1052480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1053480093f4SDimitry Andric                                                   /*First=*/false);
1054480093f4SDimitry Andric       return;
1055fe6060f1SDimitry Andric     case BO_LAnd: {
1056fe6060f1SDimitry Andric       bool LHSSatisfied =
1057fe6060f1SDimitry Andric           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1058480093f4SDimitry Andric       if (LHSSatisfied) {
1059480093f4SDimitry Andric         // LHS is true, so RHS must be false.
1060480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
1061480093f4SDimitry Andric         return;
1062480093f4SDimitry Andric       }
1063480093f4SDimitry Andric       // LHS is false
1064480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1065480093f4SDimitry Andric 
1066480093f4SDimitry Andric       // RHS might also be false
1067fe6060f1SDimitry Andric       bool RHSSatisfied =
1068fe6060f1SDimitry Andric           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1069480093f4SDimitry Andric       if (!RHSSatisfied)
1070480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1071480093f4SDimitry Andric                                                     /*First=*/false);
1072480093f4SDimitry Andric       return;
1073fe6060f1SDimitry Andric     }
1074480093f4SDimitry Andric     case BO_GE:
1075480093f4SDimitry Andric     case BO_LE:
1076480093f4SDimitry Andric     case BO_GT:
1077480093f4SDimitry Andric     case BO_LT:
1078480093f4SDimitry Andric     case BO_EQ:
1079480093f4SDimitry Andric     case BO_NE:
1080480093f4SDimitry Andric       if (BO->getLHS()->getType()->isIntegerType() &&
1081480093f4SDimitry Andric           BO->getRHS()->getType()->isIntegerType()) {
1082480093f4SDimitry Andric         Expr::EvalResult SimplifiedLHS;
1083480093f4SDimitry Andric         Expr::EvalResult SimplifiedRHS;
1084fe6060f1SDimitry Andric         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1085fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
1086fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
1087fe6060f1SDimitry Andric         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1088fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
1089fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
1090480093f4SDimitry Andric         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1091480093f4SDimitry Andric           S.Diag(SubstExpr->getBeginLoc(),
1092480093f4SDimitry Andric                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
1093480093f4SDimitry Andric               << (int)First << SubstExpr
1094fe6060f1SDimitry Andric               << toString(SimplifiedLHS.Val.getInt(), 10)
1095480093f4SDimitry Andric               << BinaryOperator::getOpcodeStr(BO->getOpcode())
1096fe6060f1SDimitry Andric               << toString(SimplifiedRHS.Val.getInt(), 10);
1097480093f4SDimitry Andric           return;
1098480093f4SDimitry Andric         }
1099480093f4SDimitry Andric       }
1100480093f4SDimitry Andric       break;
1101480093f4SDimitry Andric 
1102480093f4SDimitry Andric     default:
1103480093f4SDimitry Andric       break;
1104480093f4SDimitry Andric     }
1105480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1106480093f4SDimitry Andric     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1107480093f4SDimitry Andric       S.Diag(
1108480093f4SDimitry Andric           CSE->getSourceRange().getBegin(),
1109480093f4SDimitry Andric           diag::
1110480093f4SDimitry Andric           note_single_arg_concept_specialization_constraint_evaluated_to_false)
1111480093f4SDimitry Andric           << (int)First
1112480093f4SDimitry Andric           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1113480093f4SDimitry Andric           << CSE->getNamedConcept();
1114480093f4SDimitry Andric     } else {
1115480093f4SDimitry Andric       S.Diag(SubstExpr->getSourceRange().getBegin(),
1116480093f4SDimitry Andric              diag::note_concept_specialization_constraint_evaluated_to_false)
1117480093f4SDimitry Andric           << (int)First << CSE;
1118480093f4SDimitry Andric     }
1119480093f4SDimitry Andric     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1120480093f4SDimitry Andric     return;
112155e4f9d5SDimitry Andric   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1122bdd1243dSDimitry Andric     // FIXME: RequiresExpr should store dependent diagnostics.
112355e4f9d5SDimitry Andric     for (concepts::Requirement *Req : RE->getRequirements())
112455e4f9d5SDimitry Andric       if (!Req->isDependent() && !Req->isSatisfied()) {
112555e4f9d5SDimitry Andric         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
112655e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, E, First);
112755e4f9d5SDimitry Andric         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
112855e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, T, First);
112955e4f9d5SDimitry Andric         else
113055e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(
113155e4f9d5SDimitry Andric               S, cast<concepts::NestedRequirement>(Req), First);
113255e4f9d5SDimitry Andric         break;
113355e4f9d5SDimitry Andric       }
113455e4f9d5SDimitry Andric     return;
1135480093f4SDimitry Andric   }
1136480093f4SDimitry Andric 
1137480093f4SDimitry Andric   S.Diag(SubstExpr->getSourceRange().getBegin(),
1138480093f4SDimitry Andric          diag::note_atomic_constraint_evaluated_to_false)
1139480093f4SDimitry Andric       << (int)First << SubstExpr;
1140480093f4SDimitry Andric }
1141480093f4SDimitry Andric 
1142480093f4SDimitry Andric template<typename SubstitutionDiagnostic>
1143480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr(
1144480093f4SDimitry Andric     Sema &S, const Expr *E,
1145480093f4SDimitry Andric     const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1146480093f4SDimitry Andric     bool First = true) {
1147480093f4SDimitry Andric   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
1148480093f4SDimitry Andric     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1149480093f4SDimitry Andric         << Diag->second;
1150480093f4SDimitry Andric     return;
1151480093f4SDimitry Andric   }
1152480093f4SDimitry Andric 
1153480093f4SDimitry Andric   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
1154480093f4SDimitry Andric       Record.template get<Expr *>(), First);
1155480093f4SDimitry Andric }
1156480093f4SDimitry Andric 
115755e4f9d5SDimitry Andric void
115855e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
115955e4f9d5SDimitry Andric                                     bool First) {
1160480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
1161480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
1162480093f4SDimitry Andric   for (auto &Pair : Satisfaction.Details) {
1163480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1164480093f4SDimitry Andric     First = false;
1165480093f4SDimitry Andric   }
1166480093f4SDimitry Andric }
1167480093f4SDimitry Andric 
1168480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
116955e4f9d5SDimitry Andric     const ASTConstraintSatisfaction &Satisfaction,
117055e4f9d5SDimitry Andric     bool First) {
1171480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
1172480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
1173480093f4SDimitry Andric   for (auto &Pair : Satisfaction) {
1174480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1175480093f4SDimitry Andric     First = false;
1176480093f4SDimitry Andric   }
1177480093f4SDimitry Andric }
1178480093f4SDimitry Andric 
1179480093f4SDimitry Andric const NormalizedConstraint *
1180480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints(
1181480093f4SDimitry Andric     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
118206c3fb27SDimitry Andric   // In case the ConstrainedDecl comes from modules, it is necessary to use
118306c3fb27SDimitry Andric   // the canonical decl to avoid different atomic constraints with the 'same'
118406c3fb27SDimitry Andric   // declarations.
118506c3fb27SDimitry Andric   ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl());
118606c3fb27SDimitry Andric 
1187480093f4SDimitry Andric   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1188480093f4SDimitry Andric   if (CacheEntry == NormalizationCache.end()) {
1189480093f4SDimitry Andric     auto Normalized =
1190480093f4SDimitry Andric         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1191480093f4SDimitry Andric                                                   AssociatedConstraints);
1192480093f4SDimitry Andric     CacheEntry =
1193480093f4SDimitry Andric         NormalizationCache
1194480093f4SDimitry Andric             .try_emplace(ConstrainedDecl,
1195480093f4SDimitry Andric                          Normalized
1196480093f4SDimitry Andric                              ? new (Context) NormalizedConstraint(
1197480093f4SDimitry Andric                                  std::move(*Normalized))
1198480093f4SDimitry Andric                              : nullptr)
1199480093f4SDimitry Andric             .first;
1200480093f4SDimitry Andric   }
1201480093f4SDimitry Andric   return CacheEntry->second;
1202480093f4SDimitry Andric }
1203480093f4SDimitry Andric 
1204bdd1243dSDimitry Andric static bool
1205bdd1243dSDimitry Andric substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1206bdd1243dSDimitry Andric                             ConceptDecl *Concept,
1207bdd1243dSDimitry Andric                             const MultiLevelTemplateArgumentList &MLTAL,
1208480093f4SDimitry Andric                             const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1209480093f4SDimitry Andric   if (!N.isAtomic()) {
1210bdd1243dSDimitry Andric     if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1211480093f4SDimitry Andric                                     ArgsAsWritten))
1212480093f4SDimitry Andric       return true;
1213bdd1243dSDimitry Andric     return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1214480093f4SDimitry Andric                                        ArgsAsWritten);
1215480093f4SDimitry Andric   }
1216480093f4SDimitry Andric   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1217480093f4SDimitry Andric 
1218480093f4SDimitry Andric   AtomicConstraint &Atomic = *N.getAtomicConstraint();
1219480093f4SDimitry Andric   TemplateArgumentListInfo SubstArgs;
1220480093f4SDimitry Andric   if (!Atomic.ParameterMapping) {
1221480093f4SDimitry Andric     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1222480093f4SDimitry Andric     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1223480093f4SDimitry Andric                                  /*Depth=*/0, OccurringIndices);
1224bdd1243dSDimitry Andric     TemplateArgumentLoc *TempArgs =
1225bdd1243dSDimitry Andric         new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1226480093f4SDimitry Andric     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1227480093f4SDimitry Andric       if (OccurringIndices[I])
1228bdd1243dSDimitry Andric         new (&(TempArgs)[J++])
1229bdd1243dSDimitry Andric             TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(
1230bdd1243dSDimitry Andric                 TemplateParams->begin()[I],
1231480093f4SDimitry Andric                 // Here we assume we do not support things like
1232480093f4SDimitry Andric                 // template<typename A, typename B>
1233480093f4SDimitry Andric                 // concept C = ...;
1234480093f4SDimitry Andric                 //
1235480093f4SDimitry Andric                 // template<typename... Ts> requires C<Ts...>
1236480093f4SDimitry Andric                 // struct S { };
1237480093f4SDimitry Andric                 // The above currently yields a diagnostic.
1238480093f4SDimitry Andric                 // We still might have default arguments for concept parameters.
1239bdd1243dSDimitry Andric                 ArgsAsWritten->NumTemplateArgs > I
1240bdd1243dSDimitry Andric                     ? ArgsAsWritten->arguments()[I].getLocation()
1241bdd1243dSDimitry Andric                     : SourceLocation()));
1242bdd1243dSDimitry Andric     Atomic.ParameterMapping.emplace(TempArgs,  OccurringIndices.count());
1243480093f4SDimitry Andric   }
1244480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(
1245480093f4SDimitry Andric       S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
1246480093f4SDimitry Andric       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
12471ac55f4cSDimitry Andric       ArgsAsWritten->arguments().front().getSourceRange());
1248480093f4SDimitry Andric   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1249480093f4SDimitry Andric     return true;
1250bdd1243dSDimitry Andric 
1251bdd1243dSDimitry Andric   TemplateArgumentLoc *TempArgs =
1252bdd1243dSDimitry Andric       new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1253480093f4SDimitry Andric   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1254bdd1243dSDimitry Andric             TempArgs);
1255bdd1243dSDimitry Andric   Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1256480093f4SDimitry Andric   return false;
1257480093f4SDimitry Andric }
1258480093f4SDimitry Andric 
1259bdd1243dSDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1260bdd1243dSDimitry Andric                                         const ConceptSpecializationExpr *CSE) {
1261bdd1243dSDimitry Andric   TemplateArgumentList TAL{TemplateArgumentList::OnStack,
1262bdd1243dSDimitry Andric                            CSE->getTemplateArguments()};
1263bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
12645f757f3fSDimitry Andric       CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
12655f757f3fSDimitry Andric       /*Final=*/false, &TAL,
1266bdd1243dSDimitry Andric       /*RelativeToPrimary=*/true,
1267bdd1243dSDimitry Andric       /*Pattern=*/nullptr,
1268bdd1243dSDimitry Andric       /*ForConstraintInstantiation=*/true);
1269bdd1243dSDimitry Andric 
1270bdd1243dSDimitry Andric   return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1271bdd1243dSDimitry Andric                                      CSE->getTemplateArgsAsWritten());
1272bdd1243dSDimitry Andric }
1273bdd1243dSDimitry Andric 
1274bdd1243dSDimitry Andric std::optional<NormalizedConstraint>
1275480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1276480093f4SDimitry Andric                                           ArrayRef<const Expr *> E) {
1277480093f4SDimitry Andric   assert(E.size() != 0);
12786e75b2fbSDimitry Andric   auto Conjunction = fromConstraintExpr(S, D, E[0]);
12796e75b2fbSDimitry Andric   if (!Conjunction)
1280bdd1243dSDimitry Andric     return std::nullopt;
12816e75b2fbSDimitry Andric   for (unsigned I = 1; I < E.size(); ++I) {
1282480093f4SDimitry Andric     auto Next = fromConstraintExpr(S, D, E[I]);
1283480093f4SDimitry Andric     if (!Next)
1284bdd1243dSDimitry Andric       return std::nullopt;
12856e75b2fbSDimitry Andric     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1286480093f4SDimitry Andric                                         std::move(*Next), CCK_Conjunction);
1287480093f4SDimitry Andric   }
1288480093f4SDimitry Andric   return Conjunction;
1289480093f4SDimitry Andric }
1290480093f4SDimitry Andric 
1291bdd1243dSDimitry Andric std::optional<NormalizedConstraint>
1292480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1293480093f4SDimitry Andric   assert(E != nullptr);
1294480093f4SDimitry Andric 
1295480093f4SDimitry Andric   // C++ [temp.constr.normal]p1.1
1296480093f4SDimitry Andric   // [...]
1297480093f4SDimitry Andric   // - The normal form of an expression (E) is the normal form of E.
1298480093f4SDimitry Andric   // [...]
1299480093f4SDimitry Andric   E = E->IgnoreParenImpCasts();
1300bdd1243dSDimitry Andric 
1301bdd1243dSDimitry Andric   // C++2a [temp.param]p4:
1302bdd1243dSDimitry Andric   //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1303bdd1243dSDimitry Andric   // Fold expression is considered atomic constraints per current wording.
1304bdd1243dSDimitry Andric   // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1305bdd1243dSDimitry Andric 
13065ffd83dbSDimitry Andric   if (LogicalBinOp BO = E) {
13075ffd83dbSDimitry Andric     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1308480093f4SDimitry Andric     if (!LHS)
1309bdd1243dSDimitry Andric       return std::nullopt;
13105ffd83dbSDimitry Andric     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1311480093f4SDimitry Andric     if (!RHS)
1312bdd1243dSDimitry Andric       return std::nullopt;
1313480093f4SDimitry Andric 
13145ffd83dbSDimitry Andric     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
13155ffd83dbSDimitry Andric                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1316480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1317480093f4SDimitry Andric     const NormalizedConstraint *SubNF;
1318480093f4SDimitry Andric     {
1319480093f4SDimitry Andric       Sema::InstantiatingTemplate Inst(
1320480093f4SDimitry Andric           S, CSE->getExprLoc(),
1321480093f4SDimitry Andric           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
1322480093f4SDimitry Andric           CSE->getSourceRange());
1323480093f4SDimitry Andric       // C++ [temp.constr.normal]p1.1
1324480093f4SDimitry Andric       // [...]
1325480093f4SDimitry Andric       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1326480093f4SDimitry Andric       // where C names a concept, is the normal form of the
1327480093f4SDimitry Andric       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1328480093f4SDimitry Andric       // respective template parameters in the parameter mappings in each atomic
1329480093f4SDimitry Andric       // constraint. If any such substitution results in an invalid type or
1330480093f4SDimitry Andric       // expression, the program is ill-formed; no diagnostic is required.
1331480093f4SDimitry Andric       // [...]
1332480093f4SDimitry Andric       ConceptDecl *CD = CSE->getNamedConcept();
1333480093f4SDimitry Andric       SubNF = S.getNormalizedAssociatedConstraints(CD,
1334480093f4SDimitry Andric                                                    {CD->getConstraintExpr()});
1335480093f4SDimitry Andric       if (!SubNF)
1336bdd1243dSDimitry Andric         return std::nullopt;
1337480093f4SDimitry Andric     }
1338480093f4SDimitry Andric 
1339bdd1243dSDimitry Andric     std::optional<NormalizedConstraint> New;
1340480093f4SDimitry Andric     New.emplace(S.Context, *SubNF);
1341480093f4SDimitry Andric 
1342bdd1243dSDimitry Andric     if (substituteParameterMappings(S, *New, CSE))
1343bdd1243dSDimitry Andric       return std::nullopt;
1344480093f4SDimitry Andric 
1345480093f4SDimitry Andric     return New;
1346480093f4SDimitry Andric   }
1347480093f4SDimitry Andric   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
1348480093f4SDimitry Andric }
1349480093f4SDimitry Andric 
1350480093f4SDimitry Andric using NormalForm =
1351480093f4SDimitry Andric     llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
1352480093f4SDimitry Andric 
1353480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
1354480093f4SDimitry Andric   if (Normalized.isAtomic())
1355480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
1356480093f4SDimitry Andric 
1357480093f4SDimitry Andric   NormalForm LCNF = makeCNF(Normalized.getLHS());
1358480093f4SDimitry Andric   NormalForm RCNF = makeCNF(Normalized.getRHS());
1359480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
1360480093f4SDimitry Andric     LCNF.reserve(LCNF.size() + RCNF.size());
1361480093f4SDimitry Andric     while (!RCNF.empty())
1362480093f4SDimitry Andric       LCNF.push_back(RCNF.pop_back_val());
1363480093f4SDimitry Andric     return LCNF;
1364480093f4SDimitry Andric   }
1365480093f4SDimitry Andric 
1366480093f4SDimitry Andric   // Disjunction
1367480093f4SDimitry Andric   NormalForm Res;
1368480093f4SDimitry Andric   Res.reserve(LCNF.size() * RCNF.size());
1369480093f4SDimitry Andric   for (auto &LDisjunction : LCNF)
1370480093f4SDimitry Andric     for (auto &RDisjunction : RCNF) {
1371480093f4SDimitry Andric       NormalForm::value_type Combined;
1372480093f4SDimitry Andric       Combined.reserve(LDisjunction.size() + RDisjunction.size());
1373480093f4SDimitry Andric       std::copy(LDisjunction.begin(), LDisjunction.end(),
1374480093f4SDimitry Andric                 std::back_inserter(Combined));
1375480093f4SDimitry Andric       std::copy(RDisjunction.begin(), RDisjunction.end(),
1376480093f4SDimitry Andric                 std::back_inserter(Combined));
1377480093f4SDimitry Andric       Res.emplace_back(Combined);
1378480093f4SDimitry Andric     }
1379480093f4SDimitry Andric   return Res;
1380480093f4SDimitry Andric }
1381480093f4SDimitry Andric 
1382480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
1383480093f4SDimitry Andric   if (Normalized.isAtomic())
1384480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
1385480093f4SDimitry Andric 
1386480093f4SDimitry Andric   NormalForm LDNF = makeDNF(Normalized.getLHS());
1387480093f4SDimitry Andric   NormalForm RDNF = makeDNF(Normalized.getRHS());
1388480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
1389480093f4SDimitry Andric     LDNF.reserve(LDNF.size() + RDNF.size());
1390480093f4SDimitry Andric     while (!RDNF.empty())
1391480093f4SDimitry Andric       LDNF.push_back(RDNF.pop_back_val());
1392480093f4SDimitry Andric     return LDNF;
1393480093f4SDimitry Andric   }
1394480093f4SDimitry Andric 
1395480093f4SDimitry Andric   // Conjunction
1396480093f4SDimitry Andric   NormalForm Res;
1397480093f4SDimitry Andric   Res.reserve(LDNF.size() * RDNF.size());
1398480093f4SDimitry Andric   for (auto &LConjunction : LDNF) {
1399480093f4SDimitry Andric     for (auto &RConjunction : RDNF) {
1400480093f4SDimitry Andric       NormalForm::value_type Combined;
1401480093f4SDimitry Andric       Combined.reserve(LConjunction.size() + RConjunction.size());
1402480093f4SDimitry Andric       std::copy(LConjunction.begin(), LConjunction.end(),
1403480093f4SDimitry Andric                 std::back_inserter(Combined));
1404480093f4SDimitry Andric       std::copy(RConjunction.begin(), RConjunction.end(),
1405480093f4SDimitry Andric                 std::back_inserter(Combined));
1406480093f4SDimitry Andric       Res.emplace_back(Combined);
1407480093f4SDimitry Andric     }
1408480093f4SDimitry Andric   }
1409480093f4SDimitry Andric   return Res;
1410480093f4SDimitry Andric }
1411480093f4SDimitry Andric 
1412480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
141306c3fb27SDimitry Andric static bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF,
1414480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
1415480093f4SDimitry Andric   // C++ [temp.constr.order] p2
1416480093f4SDimitry Andric   //   Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
1417480093f4SDimitry Andric   //   disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
1418480093f4SDimitry Andric   //   the conjuctive normal form of Q, where [...]
1419480093f4SDimitry Andric   for (const auto &Pi : PDNF) {
1420480093f4SDimitry Andric     for (const auto &Qj : QCNF) {
1421480093f4SDimitry Andric       // C++ [temp.constr.order] p2
1422480093f4SDimitry Andric       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
1423480093f4SDimitry Andric       //     and only if there exists an atomic constraint Pia in Pi for which
1424480093f4SDimitry Andric       //     there exists an atomic constraint, Qjb, in Qj such that Pia
1425480093f4SDimitry Andric       //     subsumes Qjb.
1426480093f4SDimitry Andric       bool Found = false;
1427480093f4SDimitry Andric       for (const AtomicConstraint *Pia : Pi) {
1428480093f4SDimitry Andric         for (const AtomicConstraint *Qjb : Qj) {
1429480093f4SDimitry Andric           if (E(*Pia, *Qjb)) {
1430480093f4SDimitry Andric             Found = true;
1431480093f4SDimitry Andric             break;
1432480093f4SDimitry Andric           }
1433480093f4SDimitry Andric         }
1434480093f4SDimitry Andric         if (Found)
1435480093f4SDimitry Andric           break;
1436480093f4SDimitry Andric       }
1437480093f4SDimitry Andric       if (!Found)
1438480093f4SDimitry Andric         return false;
1439480093f4SDimitry Andric     }
1440480093f4SDimitry Andric   }
1441480093f4SDimitry Andric   return true;
1442480093f4SDimitry Andric }
1443480093f4SDimitry Andric 
1444480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
1445480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
1446480093f4SDimitry Andric                      NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
1447480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
1448480093f4SDimitry Andric   // C++ [temp.constr.order] p2
1449480093f4SDimitry Andric   //   In order to determine if a constraint P subsumes a constraint Q, P is
1450480093f4SDimitry Andric   //   transformed into disjunctive normal form, and Q is transformed into
1451480093f4SDimitry Andric   //   conjunctive normal form. [...]
1452480093f4SDimitry Andric   auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
1453480093f4SDimitry Andric   if (!PNormalized)
1454480093f4SDimitry Andric     return true;
1455480093f4SDimitry Andric   const NormalForm PDNF = makeDNF(*PNormalized);
1456480093f4SDimitry Andric 
1457480093f4SDimitry Andric   auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
1458480093f4SDimitry Andric   if (!QNormalized)
1459480093f4SDimitry Andric     return true;
1460480093f4SDimitry Andric   const NormalForm QCNF = makeCNF(*QNormalized);
1461480093f4SDimitry Andric 
1462480093f4SDimitry Andric   Subsumes = subsumes(PDNF, QCNF, E);
1463480093f4SDimitry Andric   return false;
1464480093f4SDimitry Andric }
1465480093f4SDimitry Andric 
1466bdd1243dSDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
1467bdd1243dSDimitry Andric                                   MutableArrayRef<const Expr *> AC1,
1468bdd1243dSDimitry Andric                                   NamedDecl *D2,
1469bdd1243dSDimitry Andric                                   MutableArrayRef<const Expr *> AC2,
1470480093f4SDimitry Andric                                   bool &Result) {
1471bdd1243dSDimitry Andric   if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1472bdd1243dSDimitry Andric     auto IsExpectedEntity = [](const FunctionDecl *FD) {
1473bdd1243dSDimitry Andric       FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
1474bdd1243dSDimitry Andric       return Kind == FunctionDecl::TK_NonTemplate ||
1475bdd1243dSDimitry Andric              Kind == FunctionDecl::TK_FunctionTemplate;
1476bdd1243dSDimitry Andric     };
1477bdd1243dSDimitry Andric     const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1478bdd1243dSDimitry Andric     (void)IsExpectedEntity;
1479bdd1243dSDimitry Andric     (void)FD1;
1480bdd1243dSDimitry Andric     (void)FD2;
1481bdd1243dSDimitry Andric     assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1482bdd1243dSDimitry Andric            "use non-instantiated function declaration for constraints partial "
1483bdd1243dSDimitry Andric            "ordering");
1484bdd1243dSDimitry Andric   }
1485bdd1243dSDimitry Andric 
1486480093f4SDimitry Andric   if (AC1.empty()) {
1487480093f4SDimitry Andric     Result = AC2.empty();
1488480093f4SDimitry Andric     return false;
1489480093f4SDimitry Andric   }
1490480093f4SDimitry Andric   if (AC2.empty()) {
1491480093f4SDimitry Andric     // TD1 has associated constraints and TD2 does not.
1492480093f4SDimitry Andric     Result = true;
1493480093f4SDimitry Andric     return false;
1494480093f4SDimitry Andric   }
1495480093f4SDimitry Andric 
1496480093f4SDimitry Andric   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1497480093f4SDimitry Andric   auto CacheEntry = SubsumptionCache.find(Key);
1498480093f4SDimitry Andric   if (CacheEntry != SubsumptionCache.end()) {
1499480093f4SDimitry Andric     Result = CacheEntry->second;
1500480093f4SDimitry Andric     return false;
1501480093f4SDimitry Andric   }
1502480093f4SDimitry Andric 
1503bdd1243dSDimitry Andric   unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1504bdd1243dSDimitry Andric   unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1505bdd1243dSDimitry Andric 
1506bdd1243dSDimitry Andric   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1507bdd1243dSDimitry Andric     if (Depth2 > Depth1) {
1508bdd1243dSDimitry Andric       AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1509bdd1243dSDimitry Andric                    .TransformExpr(const_cast<Expr *>(AC1[I]))
1510bdd1243dSDimitry Andric                    .get();
1511bdd1243dSDimitry Andric     } else if (Depth1 > Depth2) {
1512bdd1243dSDimitry Andric       AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1513bdd1243dSDimitry Andric                    .TransformExpr(const_cast<Expr *>(AC2[I]))
1514bdd1243dSDimitry Andric                    .get();
1515bdd1243dSDimitry Andric     }
1516bdd1243dSDimitry Andric   }
1517bdd1243dSDimitry Andric 
1518480093f4SDimitry Andric   if (subsumes(*this, D1, AC1, D2, AC2, Result,
1519480093f4SDimitry Andric         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1520480093f4SDimitry Andric           return A.subsumes(Context, B);
1521480093f4SDimitry Andric         }))
1522480093f4SDimitry Andric     return true;
1523480093f4SDimitry Andric   SubsumptionCache.try_emplace(Key, Result);
1524480093f4SDimitry Andric   return false;
1525480093f4SDimitry Andric }
1526480093f4SDimitry Andric 
1527480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
1528480093f4SDimitry Andric     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
1529480093f4SDimitry Andric   if (isSFINAEContext())
1530480093f4SDimitry Andric     // No need to work here because our notes would be discarded.
1531480093f4SDimitry Andric     return false;
1532480093f4SDimitry Andric 
1533480093f4SDimitry Andric   if (AC1.empty() || AC2.empty())
1534480093f4SDimitry Andric     return false;
1535480093f4SDimitry Andric 
1536480093f4SDimitry Andric   auto NormalExprEvaluator =
1537480093f4SDimitry Andric       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1538480093f4SDimitry Andric         return A.subsumes(Context, B);
1539480093f4SDimitry Andric       };
1540480093f4SDimitry Andric 
1541480093f4SDimitry Andric   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1542480093f4SDimitry Andric   auto IdenticalExprEvaluator =
1543480093f4SDimitry Andric       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1544480093f4SDimitry Andric         if (!A.hasMatchingParameterMapping(Context, B))
1545480093f4SDimitry Andric           return false;
1546480093f4SDimitry Andric         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1547480093f4SDimitry Andric         if (EA == EB)
1548480093f4SDimitry Andric           return true;
1549480093f4SDimitry Andric 
1550480093f4SDimitry Andric         // Not the same source level expression - are the expressions
1551480093f4SDimitry Andric         // identical?
1552480093f4SDimitry Andric         llvm::FoldingSetNodeID IDA, IDB;
1553349cc55cSDimitry Andric         EA->Profile(IDA, Context, /*Canonical=*/true);
1554349cc55cSDimitry Andric         EB->Profile(IDB, Context, /*Canonical=*/true);
1555480093f4SDimitry Andric         if (IDA != IDB)
1556480093f4SDimitry Andric           return false;
1557480093f4SDimitry Andric 
1558480093f4SDimitry Andric         AmbiguousAtomic1 = EA;
1559480093f4SDimitry Andric         AmbiguousAtomic2 = EB;
1560480093f4SDimitry Andric         return true;
1561480093f4SDimitry Andric       };
1562480093f4SDimitry Andric 
1563480093f4SDimitry Andric   {
1564480093f4SDimitry Andric     // The subsumption checks might cause diagnostics
1565480093f4SDimitry Andric     SFINAETrap Trap(*this);
1566480093f4SDimitry Andric     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1567480093f4SDimitry Andric     if (!Normalized1)
1568480093f4SDimitry Andric       return false;
1569480093f4SDimitry Andric     const NormalForm DNF1 = makeDNF(*Normalized1);
1570480093f4SDimitry Andric     const NormalForm CNF1 = makeCNF(*Normalized1);
1571480093f4SDimitry Andric 
1572480093f4SDimitry Andric     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1573480093f4SDimitry Andric     if (!Normalized2)
1574480093f4SDimitry Andric       return false;
1575480093f4SDimitry Andric     const NormalForm DNF2 = makeDNF(*Normalized2);
1576480093f4SDimitry Andric     const NormalForm CNF2 = makeCNF(*Normalized2);
1577480093f4SDimitry Andric 
1578480093f4SDimitry Andric     bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1579480093f4SDimitry Andric     bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1580480093f4SDimitry Andric     bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1581480093f4SDimitry Andric     bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1582480093f4SDimitry Andric     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1583480093f4SDimitry Andric         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1584480093f4SDimitry Andric       // Same result - no ambiguity was caused by identical atomic expressions.
1585480093f4SDimitry Andric       return false;
1586480093f4SDimitry Andric   }
1587480093f4SDimitry Andric 
1588480093f4SDimitry Andric   // A different result! Some ambiguous atomic constraint(s) caused a difference
1589480093f4SDimitry Andric   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1590480093f4SDimitry Andric 
1591480093f4SDimitry Andric   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1592480093f4SDimitry Andric       << AmbiguousAtomic1->getSourceRange();
1593480093f4SDimitry Andric   Diag(AmbiguousAtomic2->getBeginLoc(),
1594480093f4SDimitry Andric        diag::note_ambiguous_atomic_constraints_similar_expression)
1595480093f4SDimitry Andric       << AmbiguousAtomic2->getSourceRange();
1596480093f4SDimitry Andric   return true;
1597480093f4SDimitry Andric }
159855e4f9d5SDimitry Andric 
159955e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
160055e4f9d5SDimitry Andric     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
160155e4f9d5SDimitry Andric     ReturnTypeRequirement Req, SatisfactionStatus Status,
160255e4f9d5SDimitry Andric     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
160355e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
160455e4f9d5SDimitry Andric                 Status == SS_Dependent &&
160555e4f9d5SDimitry Andric                 (E->containsUnexpandedParameterPack() ||
160655e4f9d5SDimitry Andric                  Req.containsUnexpandedParameterPack()),
160755e4f9d5SDimitry Andric                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
160855e4f9d5SDimitry Andric     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
160955e4f9d5SDimitry Andric     Status(Status) {
161055e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
161155e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
161255e4f9d5SDimitry Andric          "noexcept specification");
161355e4f9d5SDimitry Andric   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
161455e4f9d5SDimitry Andric          (SubstitutedConstraintExpr != nullptr));
161555e4f9d5SDimitry Andric }
161655e4f9d5SDimitry Andric 
161755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
161855e4f9d5SDimitry Andric     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
161955e4f9d5SDimitry Andric     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
162055e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
162155e4f9d5SDimitry Andric                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
162255e4f9d5SDimitry Andric     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
162355e4f9d5SDimitry Andric     Status(SS_ExprSubstitutionFailure) {
162455e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
162555e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
162655e4f9d5SDimitry Andric          "noexcept specification");
162755e4f9d5SDimitry Andric }
162855e4f9d5SDimitry Andric 
162955e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement::
163055e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) :
163104eeddc0SDimitry Andric     TypeConstraintInfo(TPL, false) {
163255e4f9d5SDimitry Andric   assert(TPL->size() == 1);
163355e4f9d5SDimitry Andric   const TypeConstraint *TC =
163455e4f9d5SDimitry Andric       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
163555e4f9d5SDimitry Andric   assert(TC &&
163655e4f9d5SDimitry Andric          "TPL must have a template type parameter with a type constraint");
163755e4f9d5SDimitry Andric   auto *Constraint =
1638349cc55cSDimitry Andric       cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1639e8d8bef9SDimitry Andric   bool Dependent =
1640e8d8bef9SDimitry Andric       Constraint->getTemplateArgsAsWritten() &&
1641e8d8bef9SDimitry Andric       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1642e8d8bef9SDimitry Andric           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
164304eeddc0SDimitry Andric   TypeConstraintInfo.setInt(Dependent ? true : false);
164455e4f9d5SDimitry Andric }
164555e4f9d5SDimitry Andric 
164655e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1647e8d8bef9SDimitry Andric     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
164855e4f9d5SDimitry Andric                 T->getType()->containsUnexpandedParameterPack(),
164955e4f9d5SDimitry Andric                 // We reach this ctor with either dependent types (in which
165055e4f9d5SDimitry Andric                 // IsSatisfied doesn't matter) or with non-dependent type in
165155e4f9d5SDimitry Andric                 // which the existence of the type indicates satisfaction.
1652e8d8bef9SDimitry Andric                 /*IsSatisfied=*/true),
1653e8d8bef9SDimitry Andric     Value(T),
1654e8d8bef9SDimitry Andric     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1655e8d8bef9SDimitry Andric                                                         : SS_Satisfied) {}
1656