xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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 
13*bdd1243dSDimitry Andric #include "TreeTransform.h"
14480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h"
15a7dea167SDimitry Andric #include "clang/Sema/Sema.h"
16480093f4SDimitry Andric #include "clang/Sema/SemaInternal.h"
17a7dea167SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
18a7dea167SDimitry Andric #include "clang/Sema/TemplateDeduction.h"
19a7dea167SDimitry Andric #include "clang/Sema/Template.h"
2055e4f9d5SDimitry Andric #include "clang/Sema/Overload.h"
2155e4f9d5SDimitry Andric #include "clang/Sema/Initialization.h"
22*bdd1243dSDimitry Andric #include "clang/AST/ASTLambda.h"
2355e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h"
24480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
25480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h"
26480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h"
27480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h"
28fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
29*bdd1243dSDimitry Andric #include <optional>
30fe6060f1SDimitry Andric 
31a7dea167SDimitry Andric using namespace clang;
32a7dea167SDimitry Andric using namespace sema;
33a7dea167SDimitry Andric 
345ffd83dbSDimitry Andric namespace {
355ffd83dbSDimitry Andric class LogicalBinOp {
36*bdd1243dSDimitry Andric   SourceLocation Loc;
375ffd83dbSDimitry Andric   OverloadedOperatorKind Op = OO_None;
385ffd83dbSDimitry Andric   const Expr *LHS = nullptr;
395ffd83dbSDimitry Andric   const Expr *RHS = nullptr;
405ffd83dbSDimitry Andric 
415ffd83dbSDimitry Andric public:
425ffd83dbSDimitry Andric   LogicalBinOp(const Expr *E) {
435ffd83dbSDimitry Andric     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
445ffd83dbSDimitry Andric       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
455ffd83dbSDimitry Andric       LHS = BO->getLHS();
465ffd83dbSDimitry Andric       RHS = BO->getRHS();
47*bdd1243dSDimitry Andric       Loc = BO->getExprLoc();
485ffd83dbSDimitry Andric     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
49fe6060f1SDimitry Andric       // If OO is not || or && it might not have exactly 2 arguments.
50fe6060f1SDimitry Andric       if (OO->getNumArgs() == 2) {
515ffd83dbSDimitry Andric         Op = OO->getOperator();
525ffd83dbSDimitry Andric         LHS = OO->getArg(0);
535ffd83dbSDimitry Andric         RHS = OO->getArg(1);
54*bdd1243dSDimitry Andric         Loc = OO->getOperatorLoc();
555ffd83dbSDimitry Andric       }
565ffd83dbSDimitry Andric     }
57fe6060f1SDimitry Andric   }
585ffd83dbSDimitry Andric 
595ffd83dbSDimitry Andric   bool isAnd() const { return Op == OO_AmpAmp; }
605ffd83dbSDimitry Andric   bool isOr() const { return Op == OO_PipePipe; }
615ffd83dbSDimitry Andric   explicit operator bool() const { return isAnd() || isOr(); }
625ffd83dbSDimitry Andric 
635ffd83dbSDimitry Andric   const Expr *getLHS() const { return LHS; }
645ffd83dbSDimitry Andric   const Expr *getRHS() const { return RHS; }
65*bdd1243dSDimitry Andric 
66*bdd1243dSDimitry Andric   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
67*bdd1243dSDimitry Andric     return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
68*bdd1243dSDimitry Andric   }
69*bdd1243dSDimitry Andric 
70*bdd1243dSDimitry Andric   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
71*bdd1243dSDimitry Andric                            ExprResult RHS) const {
72*bdd1243dSDimitry Andric     assert((isAnd() || isOr()) && "Not the right kind of op?");
73*bdd1243dSDimitry Andric     assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
74*bdd1243dSDimitry Andric 
75*bdd1243dSDimitry Andric     if (!LHS.isUsable() || !RHS.isUsable())
76*bdd1243dSDimitry Andric       return ExprEmpty();
77*bdd1243dSDimitry Andric 
78*bdd1243dSDimitry Andric     // We should just be able to 'normalize' these to the builtin Binary
79*bdd1243dSDimitry Andric     // Operator, since that is how they are evaluated in constriant checks.
80*bdd1243dSDimitry Andric     return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
81*bdd1243dSDimitry Andric                                   BinaryOperator::getOverloadedOpcode(Op),
82*bdd1243dSDimitry Andric                                   SemaRef.Context.BoolTy, VK_PRValue,
83*bdd1243dSDimitry Andric                                   OK_Ordinary, Loc, FPOptionsOverride{});
84*bdd1243dSDimitry Andric   }
855ffd83dbSDimitry Andric };
865ffd83dbSDimitry Andric }
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
895ffd83dbSDimitry Andric                                      Token NextToken, bool *PossibleNonPrimary,
90480093f4SDimitry Andric                                      bool IsTrailingRequiresClause) {
91a7dea167SDimitry Andric   // C++2a [temp.constr.atomic]p1
92a7dea167SDimitry Andric   // ..E shall be a constant expression of type bool.
93a7dea167SDimitry Andric 
94a7dea167SDimitry Andric   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
95a7dea167SDimitry Andric 
965ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpression) {
975ffd83dbSDimitry Andric     return CheckConstraintExpression(BO.getLHS(), NextToken,
98480093f4SDimitry Andric                                      PossibleNonPrimary) &&
995ffd83dbSDimitry Andric            CheckConstraintExpression(BO.getRHS(), NextToken,
100480093f4SDimitry Andric                                      PossibleNonPrimary);
101a7dea167SDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
102480093f4SDimitry Andric     return CheckConstraintExpression(C->getSubExpr(), NextToken,
103480093f4SDimitry Andric                                      PossibleNonPrimary);
104a7dea167SDimitry Andric 
105a7dea167SDimitry Andric   QualType Type = ConstraintExpression->getType();
106480093f4SDimitry Andric 
107480093f4SDimitry Andric   auto CheckForNonPrimary = [&] {
108480093f4SDimitry Andric     if (PossibleNonPrimary)
109480093f4SDimitry Andric       *PossibleNonPrimary =
110480093f4SDimitry Andric           // We have the following case:
111480093f4SDimitry Andric           // template<typename> requires func(0) struct S { };
112480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
113480093f4SDimitry Andric           // the function call, and we're only going to parse 'func' as the
114480093f4SDimitry Andric           // primary-expression, and complain that it is of non-bool type.
115480093f4SDimitry Andric           (NextToken.is(tok::l_paren) &&
116480093f4SDimitry Andric            (IsTrailingRequiresClause ||
117480093f4SDimitry Andric             (Type->isDependentType() &&
1185ffd83dbSDimitry Andric              isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
119480093f4SDimitry Andric             Type->isFunctionType() ||
120480093f4SDimitry Andric             Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
121480093f4SDimitry Andric           // We have the following case:
122480093f4SDimitry Andric           // template<typename T> requires size_<T> == 0 struct S { };
123480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
124480093f4SDimitry Andric           // the binary operator, and we're only going to parse 'func' as the
125480093f4SDimitry Andric           // first operand, and complain that it is of non-bool type.
126480093f4SDimitry Andric           getBinOpPrecedence(NextToken.getKind(),
127480093f4SDimitry Andric                              /*GreaterThanIsOperator=*/true,
128480093f4SDimitry Andric                              getLangOpts().CPlusPlus11) > prec::LogicalAnd;
129480093f4SDimitry Andric   };
130480093f4SDimitry Andric 
131480093f4SDimitry Andric   // An atomic constraint!
132480093f4SDimitry Andric   if (ConstraintExpression->isTypeDependent()) {
133480093f4SDimitry Andric     CheckForNonPrimary();
134480093f4SDimitry Andric     return true;
135480093f4SDimitry Andric   }
136480093f4SDimitry Andric 
137a7dea167SDimitry Andric   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
138a7dea167SDimitry Andric     Diag(ConstraintExpression->getExprLoc(),
139a7dea167SDimitry Andric          diag::err_non_bool_atomic_constraint) << Type
140a7dea167SDimitry Andric         << ConstraintExpression->getSourceRange();
141480093f4SDimitry Andric     CheckForNonPrimary();
142a7dea167SDimitry Andric     return false;
143a7dea167SDimitry Andric   }
144480093f4SDimitry Andric 
145480093f4SDimitry Andric   if (PossibleNonPrimary)
146480093f4SDimitry Andric       *PossibleNonPrimary = false;
147a7dea167SDimitry Andric   return true;
148a7dea167SDimitry Andric }
149a7dea167SDimitry Andric 
150*bdd1243dSDimitry Andric namespace {
151*bdd1243dSDimitry Andric struct SatisfactionStackRAII {
152*bdd1243dSDimitry Andric   Sema &SemaRef;
153*bdd1243dSDimitry Andric   SatisfactionStackRAII(Sema &SemaRef, llvm::FoldingSetNodeID FSNID)
154*bdd1243dSDimitry Andric       : SemaRef(SemaRef) {
155*bdd1243dSDimitry Andric       SemaRef.PushSatisfactionStackEntry(FSNID);
156*bdd1243dSDimitry Andric   }
157*bdd1243dSDimitry Andric   ~SatisfactionStackRAII() { SemaRef.PopSatisfactionStackEntry(); }
158*bdd1243dSDimitry Andric };
159*bdd1243dSDimitry Andric } // namespace
160*bdd1243dSDimitry Andric 
161480093f4SDimitry Andric template <typename AtomicEvaluator>
162*bdd1243dSDimitry Andric static ExprResult
163480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
164480093f4SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
165480093f4SDimitry Andric                                 AtomicEvaluator &&Evaluator) {
166a7dea167SDimitry Andric   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
167a7dea167SDimitry Andric 
1685ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpr) {
169*bdd1243dSDimitry Andric     ExprResult LHSRes = calculateConstraintSatisfaction(
170*bdd1243dSDimitry Andric         S, BO.getLHS(), Satisfaction, Evaluator);
171*bdd1243dSDimitry Andric 
172*bdd1243dSDimitry Andric     if (LHSRes.isInvalid())
173*bdd1243dSDimitry Andric       return ExprError();
174480093f4SDimitry Andric 
175480093f4SDimitry Andric     bool IsLHSSatisfied = Satisfaction.IsSatisfied;
176480093f4SDimitry Andric 
1775ffd83dbSDimitry Andric     if (BO.isOr() && IsLHSSatisfied)
178480093f4SDimitry Andric       // [temp.constr.op] p3
179480093f4SDimitry Andric       //    A disjunction is a constraint taking two operands. To determine if
180480093f4SDimitry Andric       //    a disjunction is satisfied, the satisfaction of the first operand
181480093f4SDimitry Andric       //    is checked. If that is satisfied, the disjunction is satisfied.
182480093f4SDimitry Andric       //    Otherwise, the disjunction is satisfied if and only if the second
183480093f4SDimitry Andric       //    operand is satisfied.
184*bdd1243dSDimitry Andric       // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
185*bdd1243dSDimitry Andric       return LHSRes;
186480093f4SDimitry Andric 
1875ffd83dbSDimitry Andric     if (BO.isAnd() && !IsLHSSatisfied)
188480093f4SDimitry Andric       // [temp.constr.op] p2
189480093f4SDimitry Andric       //    A conjunction is a constraint taking two operands. To determine if
190480093f4SDimitry Andric       //    a conjunction is satisfied, the satisfaction of the first operand
191480093f4SDimitry Andric       //    is checked. If that is not satisfied, the conjunction is not
192480093f4SDimitry Andric       //    satisfied. Otherwise, the conjunction is satisfied if and only if
193480093f4SDimitry Andric       //    the second operand is satisfied.
194*bdd1243dSDimitry Andric       // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
195*bdd1243dSDimitry Andric       return LHSRes;
196480093f4SDimitry Andric 
197*bdd1243dSDimitry Andric     ExprResult RHSRes = calculateConstraintSatisfaction(
1985ffd83dbSDimitry Andric         S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
199*bdd1243dSDimitry Andric     if (RHSRes.isInvalid())
200*bdd1243dSDimitry Andric       return ExprError();
201*bdd1243dSDimitry Andric 
202*bdd1243dSDimitry Andric     return BO.recreateBinOp(S, LHSRes, RHSRes);
203*bdd1243dSDimitry Andric   }
204*bdd1243dSDimitry Andric 
205*bdd1243dSDimitry Andric   if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
206*bdd1243dSDimitry Andric     // These aren't evaluated, so we don't care about cleanups, so we can just
207*bdd1243dSDimitry Andric     // evaluate these as if the cleanups didn't exist.
208*bdd1243dSDimitry Andric     return calculateConstraintSatisfaction(
209*bdd1243dSDimitry Andric         S, C->getSubExpr(), Satisfaction,
210480093f4SDimitry Andric         std::forward<AtomicEvaluator>(Evaluator));
2115ffd83dbSDimitry Andric   }
212480093f4SDimitry Andric 
213480093f4SDimitry Andric   // An atomic constraint expression
214480093f4SDimitry Andric   ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
215480093f4SDimitry Andric 
216480093f4SDimitry Andric   if (SubstitutedAtomicExpr.isInvalid())
217*bdd1243dSDimitry Andric     return ExprError();
218480093f4SDimitry Andric 
219480093f4SDimitry Andric   if (!SubstitutedAtomicExpr.isUsable())
220480093f4SDimitry Andric     // Evaluator has decided satisfaction without yielding an expression.
221*bdd1243dSDimitry Andric     return ExprEmpty();
222*bdd1243dSDimitry Andric 
223*bdd1243dSDimitry Andric   // We don't have the ability to evaluate this, since it contains a
224*bdd1243dSDimitry Andric   // RecoveryExpr, so we want to fail overload resolution.  Otherwise,
225*bdd1243dSDimitry Andric   // we'd potentially pick up a different overload, and cause confusing
226*bdd1243dSDimitry Andric   // diagnostics. SO, add a failure detail that will cause us to make this
227*bdd1243dSDimitry Andric   // overload set not viable.
228*bdd1243dSDimitry Andric   if (SubstitutedAtomicExpr.get()->containsErrors()) {
229*bdd1243dSDimitry Andric     Satisfaction.IsSatisfied = false;
230*bdd1243dSDimitry Andric     Satisfaction.ContainsErrors = true;
231*bdd1243dSDimitry Andric 
232*bdd1243dSDimitry Andric     PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
233*bdd1243dSDimitry Andric     SmallString<128> DiagString;
234*bdd1243dSDimitry Andric     DiagString = ": ";
235*bdd1243dSDimitry Andric     Msg.EmitToString(S.getDiagnostics(), DiagString);
236*bdd1243dSDimitry Andric     unsigned MessageSize = DiagString.size();
237*bdd1243dSDimitry Andric     char *Mem = new (S.Context) char[MessageSize];
238*bdd1243dSDimitry Andric     memcpy(Mem, DiagString.c_str(), MessageSize);
239*bdd1243dSDimitry Andric     Satisfaction.Details.emplace_back(
240*bdd1243dSDimitry Andric         ConstraintExpr,
241*bdd1243dSDimitry Andric         new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
242*bdd1243dSDimitry Andric             SubstitutedAtomicExpr.get()->getBeginLoc(),
243*bdd1243dSDimitry Andric             StringRef(Mem, MessageSize)});
244*bdd1243dSDimitry Andric     return SubstitutedAtomicExpr;
245*bdd1243dSDimitry Andric   }
246a7dea167SDimitry Andric 
247a7dea167SDimitry Andric   EnterExpressionEvaluationContext ConstantEvaluated(
248480093f4SDimitry Andric       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
249a7dea167SDimitry Andric   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
250a7dea167SDimitry Andric   Expr::EvalResult EvalResult;
251a7dea167SDimitry Andric   EvalResult.Diag = &EvaluationDiags;
252fe6060f1SDimitry Andric   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
253fe6060f1SDimitry Andric                                                            S.Context) ||
254fe6060f1SDimitry Andric       !EvaluationDiags.empty()) {
255a7dea167SDimitry Andric     // C++2a [temp.constr.atomic]p1
256a7dea167SDimitry Andric     //   ...E shall be a constant expression of type bool.
257480093f4SDimitry Andric     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
258a7dea167SDimitry Andric            diag::err_non_constant_constraint_expression)
259480093f4SDimitry Andric         << SubstitutedAtomicExpr.get()->getSourceRange();
260a7dea167SDimitry Andric     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
261480093f4SDimitry Andric       S.Diag(PDiag.first, PDiag.second);
262*bdd1243dSDimitry Andric     return ExprError();
263a7dea167SDimitry Andric   }
264a7dea167SDimitry Andric 
265fe6060f1SDimitry Andric   assert(EvalResult.Val.isInt() &&
266fe6060f1SDimitry Andric          "evaluating bool expression didn't produce int");
267480093f4SDimitry Andric   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
268480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied)
269480093f4SDimitry Andric     Satisfaction.Details.emplace_back(ConstraintExpr,
270480093f4SDimitry Andric                                       SubstitutedAtomicExpr.get());
271a7dea167SDimitry Andric 
272*bdd1243dSDimitry Andric   return SubstitutedAtomicExpr;
273*bdd1243dSDimitry Andric }
274*bdd1243dSDimitry Andric 
275*bdd1243dSDimitry Andric static bool
276*bdd1243dSDimitry Andric DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const Expr *E,
277*bdd1243dSDimitry Andric                             const MultiLevelTemplateArgumentList &MLTAL) {
278*bdd1243dSDimitry Andric   E->Profile(ID, S.Context, /*Canonical=*/true);
279*bdd1243dSDimitry Andric   for (const auto &List : MLTAL)
280*bdd1243dSDimitry Andric     for (const auto &TemplateArg : List.Args)
281*bdd1243dSDimitry Andric       TemplateArg.Profile(ID, S.Context);
282*bdd1243dSDimitry Andric 
283*bdd1243dSDimitry Andric   // Note that we have to do this with our own collection, because there are
284*bdd1243dSDimitry Andric   // times where a constraint-expression check can cause us to need to evaluate
285*bdd1243dSDimitry Andric   // other constriants that are unrelated, such as when evaluating a recovery
286*bdd1243dSDimitry Andric   // expression, or when trying to determine the constexpr-ness of special
287*bdd1243dSDimitry Andric   // members. Otherwise we could just use the
288*bdd1243dSDimitry Andric   // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
289*bdd1243dSDimitry Andric   if (S.SatisfactionStackContains(ID)) {
290*bdd1243dSDimitry Andric     S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
291*bdd1243dSDimitry Andric         << const_cast<Expr *>(E) << E->getSourceRange();
292*bdd1243dSDimitry Andric     return true;
293*bdd1243dSDimitry Andric   }
294*bdd1243dSDimitry Andric 
295a7dea167SDimitry Andric   return false;
296a7dea167SDimitry Andric }
297480093f4SDimitry Andric 
298*bdd1243dSDimitry Andric static ExprResult calculateConstraintSatisfaction(
299*bdd1243dSDimitry Andric     Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
300*bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
301*bdd1243dSDimitry Andric     ConstraintSatisfaction &Satisfaction) {
302480093f4SDimitry Andric   return calculateConstraintSatisfaction(
303480093f4SDimitry Andric       S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
304480093f4SDimitry Andric         EnterExpressionEvaluationContext ConstantEvaluated(
305*bdd1243dSDimitry Andric             S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
306*bdd1243dSDimitry Andric             Sema::ReuseLambdaContextDecl);
307480093f4SDimitry Andric 
308480093f4SDimitry Andric         // Atomic constraint - substitute arguments and check satisfaction.
309480093f4SDimitry Andric         ExprResult SubstitutedExpression;
310480093f4SDimitry Andric         {
311480093f4SDimitry Andric           TemplateDeductionInfo Info(TemplateNameLoc);
312480093f4SDimitry Andric           Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
31313138422SDimitry Andric               Sema::InstantiatingTemplate::ConstraintSubstitution{},
31413138422SDimitry Andric               const_cast<NamedDecl *>(Template), Info,
31513138422SDimitry Andric               AtomicExpr->getSourceRange());
316480093f4SDimitry Andric           if (Inst.isInvalid())
317480093f4SDimitry Andric             return ExprError();
318*bdd1243dSDimitry Andric 
319*bdd1243dSDimitry Andric           llvm::FoldingSetNodeID ID;
320*bdd1243dSDimitry Andric           if (DiagRecursiveConstraintEval(S, ID, AtomicExpr, MLTAL)) {
321*bdd1243dSDimitry Andric             Satisfaction.IsSatisfied = false;
322*bdd1243dSDimitry Andric             Satisfaction.ContainsErrors = true;
323*bdd1243dSDimitry Andric             return ExprEmpty();
324*bdd1243dSDimitry Andric           }
325*bdd1243dSDimitry Andric 
326*bdd1243dSDimitry Andric           SatisfactionStackRAII StackRAII(S, ID);
327*bdd1243dSDimitry Andric 
328480093f4SDimitry Andric           // We do not want error diagnostics escaping here.
329480093f4SDimitry Andric           Sema::SFINAETrap Trap(S);
330fe6060f1SDimitry Andric           SubstitutedExpression =
331*bdd1243dSDimitry Andric               S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
332*bdd1243dSDimitry Andric 
333480093f4SDimitry Andric           if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
334480093f4SDimitry Andric             // C++2a [temp.constr.atomic]p1
335480093f4SDimitry Andric             //   ...If substitution results in an invalid type or expression, the
336480093f4SDimitry Andric             //   constraint is not satisfied.
337480093f4SDimitry Andric             if (!Trap.hasErrorOccurred())
338349cc55cSDimitry Andric               // A non-SFINAE error has occurred as a result of this
339480093f4SDimitry Andric               // substitution.
340480093f4SDimitry Andric               return ExprError();
341480093f4SDimitry Andric 
342480093f4SDimitry Andric             PartialDiagnosticAt SubstDiag{SourceLocation(),
343480093f4SDimitry Andric                                           PartialDiagnostic::NullDiagnostic()};
344480093f4SDimitry Andric             Info.takeSFINAEDiagnostic(SubstDiag);
345480093f4SDimitry Andric             // FIXME: Concepts: This is an unfortunate consequence of there
346480093f4SDimitry Andric             //  being no serialization code for PartialDiagnostics and the fact
347480093f4SDimitry Andric             //  that serializing them would likely take a lot more storage than
348480093f4SDimitry Andric             //  just storing them as strings. We would still like, in the
349480093f4SDimitry Andric             //  future, to serialize the proper PartialDiagnostic as serializing
350480093f4SDimitry Andric             //  it as a string defeats the purpose of the diagnostic mechanism.
351480093f4SDimitry Andric             SmallString<128> DiagString;
352480093f4SDimitry Andric             DiagString = ": ";
353480093f4SDimitry Andric             SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
354480093f4SDimitry Andric             unsigned MessageSize = DiagString.size();
355480093f4SDimitry Andric             char *Mem = new (S.Context) char[MessageSize];
356480093f4SDimitry Andric             memcpy(Mem, DiagString.c_str(), MessageSize);
357480093f4SDimitry Andric             Satisfaction.Details.emplace_back(
358480093f4SDimitry Andric                 AtomicExpr,
359480093f4SDimitry Andric                 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
360480093f4SDimitry Andric                         SubstDiag.first, StringRef(Mem, MessageSize)});
361480093f4SDimitry Andric             Satisfaction.IsSatisfied = false;
362480093f4SDimitry Andric             return ExprEmpty();
363480093f4SDimitry Andric           }
364480093f4SDimitry Andric         }
365480093f4SDimitry Andric 
366480093f4SDimitry Andric         if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
367480093f4SDimitry Andric           return ExprError();
368480093f4SDimitry Andric 
369*bdd1243dSDimitry Andric         // [temp.constr.atomic]p3: To determine if an atomic constraint is
370*bdd1243dSDimitry Andric         // satisfied, the parameter mapping and template arguments are first
371*bdd1243dSDimitry Andric         // substituted into its expression.  If substitution results in an
372*bdd1243dSDimitry Andric         // invalid type or expression, the constraint is not satisfied.
373*bdd1243dSDimitry Andric         // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
374*bdd1243dSDimitry Andric         // and E shall be a constant expression of type bool.
375*bdd1243dSDimitry Andric         //
376*bdd1243dSDimitry Andric         // Perform the L to R Value conversion if necessary. We do so for all
377*bdd1243dSDimitry Andric         // non-PRValue categories, else we fail to extend the lifetime of
378*bdd1243dSDimitry Andric         // temporaries, and that fails the constant expression check.
379*bdd1243dSDimitry Andric         if (!SubstitutedExpression.get()->isPRValue())
380*bdd1243dSDimitry Andric           SubstitutedExpression = ImplicitCastExpr::Create(
381*bdd1243dSDimitry Andric               S.Context, SubstitutedExpression.get()->getType(),
382*bdd1243dSDimitry Andric               CK_LValueToRValue, SubstitutedExpression.get(),
383*bdd1243dSDimitry Andric               /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
384*bdd1243dSDimitry Andric 
385480093f4SDimitry Andric         return SubstitutedExpression;
386480093f4SDimitry Andric       });
387480093f4SDimitry Andric }
388480093f4SDimitry Andric 
389*bdd1243dSDimitry Andric static bool CheckConstraintSatisfaction(
390*bdd1243dSDimitry Andric     Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
391*bdd1243dSDimitry Andric     llvm::SmallVectorImpl<Expr *> &Converted,
392*bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgsLists,
393*bdd1243dSDimitry Andric     SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
394480093f4SDimitry Andric   if (ConstraintExprs.empty()) {
395480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
396480093f4SDimitry Andric     return false;
397480093f4SDimitry Andric   }
398480093f4SDimitry Andric 
399*bdd1243dSDimitry Andric   if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
400480093f4SDimitry Andric     // No need to check satisfaction for dependent constraint expressions.
401480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
402480093f4SDimitry Andric     return false;
403480093f4SDimitry Andric   }
404480093f4SDimitry Andric 
405*bdd1243dSDimitry Andric   ArrayRef<TemplateArgument> TemplateArgs =
406*bdd1243dSDimitry Andric       TemplateArgsLists.getNumSubstitutedLevels() > 0
407*bdd1243dSDimitry Andric           ? TemplateArgsLists.getOutermost()
408*bdd1243dSDimitry Andric           : ArrayRef<TemplateArgument> {};
409480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
41013138422SDimitry Andric       Sema::InstantiatingTemplate::ConstraintsCheck{},
41113138422SDimitry Andric       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
412480093f4SDimitry Andric   if (Inst.isInvalid())
413480093f4SDimitry Andric     return true;
414480093f4SDimitry Andric 
415480093f4SDimitry Andric   for (const Expr *ConstraintExpr : ConstraintExprs) {
416*bdd1243dSDimitry Andric     ExprResult Res = calculateConstraintSatisfaction(
417*bdd1243dSDimitry Andric         S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
418*bdd1243dSDimitry Andric         ConstraintExpr, Satisfaction);
419*bdd1243dSDimitry Andric     if (Res.isInvalid())
420480093f4SDimitry Andric       return true;
421*bdd1243dSDimitry Andric 
422*bdd1243dSDimitry Andric     Converted.push_back(Res.get());
423*bdd1243dSDimitry Andric     if (!Satisfaction.IsSatisfied) {
424*bdd1243dSDimitry Andric       // Backfill the 'converted' list with nulls so we can keep the Converted
425*bdd1243dSDimitry Andric       // and unconverted lists in sync.
426*bdd1243dSDimitry Andric       Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
427480093f4SDimitry Andric       // [temp.constr.op] p2
428480093f4SDimitry Andric       // [...] To determine if a conjunction is satisfied, the satisfaction
429480093f4SDimitry Andric       // of the first operand is checked. If that is not satisfied, the
430480093f4SDimitry Andric       // conjunction is not satisfied. [...]
431480093f4SDimitry Andric       return false;
432480093f4SDimitry Andric     }
433*bdd1243dSDimitry Andric   }
434480093f4SDimitry Andric   return false;
435480093f4SDimitry Andric }
436480093f4SDimitry Andric 
43755e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction(
43813138422SDimitry Andric     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
439*bdd1243dSDimitry Andric     llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
440*bdd1243dSDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgsLists,
441*bdd1243dSDimitry Andric     SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
44255e4f9d5SDimitry Andric   if (ConstraintExprs.empty()) {
44355e4f9d5SDimitry Andric     OutSatisfaction.IsSatisfied = true;
44455e4f9d5SDimitry Andric     return false;
445480093f4SDimitry Andric   }
44681ad6265SDimitry Andric   if (!Template) {
447*bdd1243dSDimitry Andric     return ::CheckConstraintSatisfaction(
448*bdd1243dSDimitry Andric         *this, nullptr, ConstraintExprs, ConvertedConstraints,
449*bdd1243dSDimitry Andric         TemplateArgsLists, TemplateIDRange, OutSatisfaction);
45081ad6265SDimitry Andric   }
451*bdd1243dSDimitry Andric 
452*bdd1243dSDimitry Andric   // A list of the template argument list flattened in a predictible manner for
453*bdd1243dSDimitry Andric   // the purposes of caching. The ConstraintSatisfaction type is in AST so it
454*bdd1243dSDimitry Andric   // has no access to the MultiLevelTemplateArgumentList, so this has to happen
455*bdd1243dSDimitry Andric   // here.
456*bdd1243dSDimitry Andric   llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
457*bdd1243dSDimitry Andric   for (auto List : TemplateArgsLists)
458*bdd1243dSDimitry Andric     FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
459*bdd1243dSDimitry Andric                          List.Args.end());
460*bdd1243dSDimitry Andric 
46155e4f9d5SDimitry Andric   llvm::FoldingSetNodeID ID;
462*bdd1243dSDimitry Andric   ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
46381ad6265SDimitry Andric   void *InsertPos;
46481ad6265SDimitry Andric   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
46581ad6265SDimitry Andric     OutSatisfaction = *Cached;
46655e4f9d5SDimitry Andric     return false;
46755e4f9d5SDimitry Andric   }
468*bdd1243dSDimitry Andric 
46981ad6265SDimitry Andric   auto Satisfaction =
470*bdd1243dSDimitry Andric       std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
47113138422SDimitry Andric   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
472*bdd1243dSDimitry Andric                                     ConvertedConstraints, TemplateArgsLists,
473*bdd1243dSDimitry Andric                                     TemplateIDRange, *Satisfaction)) {
474*bdd1243dSDimitry Andric     OutSatisfaction = *Satisfaction;
47555e4f9d5SDimitry Andric     return true;
476480093f4SDimitry Andric   }
477*bdd1243dSDimitry Andric 
478*bdd1243dSDimitry Andric   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
479*bdd1243dSDimitry Andric     // The evaluation of this constraint resulted in us trying to re-evaluate it
480*bdd1243dSDimitry Andric     // recursively. This isn't really possible, except we try to form a
481*bdd1243dSDimitry Andric     // RecoveryExpr as a part of the evaluation.  If this is the case, just
482*bdd1243dSDimitry Andric     // return the 'cached' version (which will have the same result), and save
483*bdd1243dSDimitry Andric     // ourselves the extra-insert. If it ever becomes possible to legitimately
484*bdd1243dSDimitry Andric     // recursively check a constraint, we should skip checking the 'inner' one
485*bdd1243dSDimitry Andric     // above, and replace the cached version with this one, as it would be more
486*bdd1243dSDimitry Andric     // specific.
487*bdd1243dSDimitry Andric     OutSatisfaction = *Cached;
488*bdd1243dSDimitry Andric     return false;
489*bdd1243dSDimitry Andric   }
490*bdd1243dSDimitry Andric 
491*bdd1243dSDimitry Andric   // Else we can simply add this satisfaction to the list.
49255e4f9d5SDimitry Andric   OutSatisfaction = *Satisfaction;
49381ad6265SDimitry Andric   // We cannot use InsertPos here because CheckConstraintSatisfaction might have
49481ad6265SDimitry Andric   // invalidated it.
49581ad6265SDimitry Andric   // Note that entries of SatisfactionCache are deleted in Sema's destructor.
49681ad6265SDimitry Andric   SatisfactionCache.InsertNode(Satisfaction.release());
49755e4f9d5SDimitry Andric   return false;
498480093f4SDimitry Andric }
499480093f4SDimitry Andric 
500480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
501480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
502480093f4SDimitry Andric   return calculateConstraintSatisfaction(
503480093f4SDimitry Andric              *this, ConstraintExpr, Satisfaction,
50481ad6265SDimitry Andric              [this](const Expr *AtomicExpr) -> ExprResult {
50581ad6265SDimitry Andric                // We only do this to immitate lvalue-to-rvalue conversion.
506*bdd1243dSDimitry Andric                return PerformContextuallyConvertToBool(
507*bdd1243dSDimitry Andric                    const_cast<Expr *>(AtomicExpr));
508*bdd1243dSDimitry Andric              })
509*bdd1243dSDimitry Andric       .isInvalid();
510*bdd1243dSDimitry Andric }
511*bdd1243dSDimitry Andric 
512*bdd1243dSDimitry Andric bool Sema::SetupConstraintScope(
513*bdd1243dSDimitry Andric     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
514*bdd1243dSDimitry Andric     MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
515*bdd1243dSDimitry Andric   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
516*bdd1243dSDimitry Andric     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
517*bdd1243dSDimitry Andric     InstantiatingTemplate Inst(
518*bdd1243dSDimitry Andric         *this, FD->getPointOfInstantiation(),
519*bdd1243dSDimitry Andric         Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
520*bdd1243dSDimitry Andric         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
521*bdd1243dSDimitry Andric         SourceRange());
522*bdd1243dSDimitry Andric     if (Inst.isInvalid())
523*bdd1243dSDimitry Andric       return true;
524*bdd1243dSDimitry Andric 
525*bdd1243dSDimitry Andric     // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
526*bdd1243dSDimitry Andric     // 'instantiated' parameters and adds it to the context. For the case where
527*bdd1243dSDimitry Andric     // this function is a template being instantiated NOW, we also need to add
528*bdd1243dSDimitry Andric     // the list of current template arguments to the list so that they also can
529*bdd1243dSDimitry Andric     // be picked out of the map.
530*bdd1243dSDimitry Andric     if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
531*bdd1243dSDimitry Andric       MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
532*bdd1243dSDimitry Andric                                                    /*Final=*/false);
533*bdd1243dSDimitry Andric       if (addInstantiatedParametersToScope(
534*bdd1243dSDimitry Andric               FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
535*bdd1243dSDimitry Andric         return true;
536*bdd1243dSDimitry Andric     }
537*bdd1243dSDimitry Andric 
538*bdd1243dSDimitry Andric     // If this is a member function, make sure we get the parameters that
539*bdd1243dSDimitry Andric     // reference the original primary template.
540*bdd1243dSDimitry Andric     if (const auto *FromMemTempl =
541*bdd1243dSDimitry Andric             PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
542*bdd1243dSDimitry Andric       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
543*bdd1243dSDimitry Andric                                            Scope, MLTAL))
544*bdd1243dSDimitry Andric         return true;
545*bdd1243dSDimitry Andric     }
546*bdd1243dSDimitry Andric 
547*bdd1243dSDimitry Andric     return false;
548*bdd1243dSDimitry Andric   }
549*bdd1243dSDimitry Andric 
550*bdd1243dSDimitry Andric   if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
551*bdd1243dSDimitry Andric       FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
552*bdd1243dSDimitry Andric     FunctionDecl *InstantiatedFrom =
553*bdd1243dSDimitry Andric         FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
554*bdd1243dSDimitry Andric             ? FD->getInstantiatedFromMemberFunction()
555*bdd1243dSDimitry Andric             : FD->getInstantiatedFromDecl();
556*bdd1243dSDimitry Andric 
557*bdd1243dSDimitry Andric     InstantiatingTemplate Inst(
558*bdd1243dSDimitry Andric         *this, FD->getPointOfInstantiation(),
559*bdd1243dSDimitry Andric         Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
560*bdd1243dSDimitry Andric         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
561*bdd1243dSDimitry Andric         SourceRange());
562*bdd1243dSDimitry Andric     if (Inst.isInvalid())
563*bdd1243dSDimitry Andric       return true;
564*bdd1243dSDimitry Andric 
565*bdd1243dSDimitry Andric     // Case where this was not a template, but instantiated as a
566*bdd1243dSDimitry Andric     // child-function.
567*bdd1243dSDimitry Andric     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
568*bdd1243dSDimitry Andric       return true;
569*bdd1243dSDimitry Andric   }
570*bdd1243dSDimitry Andric 
571*bdd1243dSDimitry Andric   return false;
572*bdd1243dSDimitry Andric }
573*bdd1243dSDimitry Andric 
574*bdd1243dSDimitry Andric // This function collects all of the template arguments for the purposes of
575*bdd1243dSDimitry Andric // constraint-instantiation and checking.
576*bdd1243dSDimitry Andric std::optional<MultiLevelTemplateArgumentList>
577*bdd1243dSDimitry Andric Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
578*bdd1243dSDimitry Andric     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
579*bdd1243dSDimitry Andric     LocalInstantiationScope &Scope) {
580*bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
581*bdd1243dSDimitry Andric 
582*bdd1243dSDimitry Andric   // Collect the list of template arguments relative to the 'primary' template.
583*bdd1243dSDimitry Andric   // We need the entire list, since the constraint is completely uninstantiated
584*bdd1243dSDimitry Andric   // at this point.
585*bdd1243dSDimitry Andric   MLTAL =
586*bdd1243dSDimitry Andric       getTemplateInstantiationArgs(FD, /*Final=*/false, /*Innermost=*/nullptr,
587*bdd1243dSDimitry Andric                                    /*RelativeToPrimary=*/true,
588*bdd1243dSDimitry Andric                                    /*Pattern=*/nullptr,
589*bdd1243dSDimitry Andric                                    /*ForConstraintInstantiation=*/true);
590*bdd1243dSDimitry Andric   if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
591*bdd1243dSDimitry Andric     return std::nullopt;
592*bdd1243dSDimitry Andric 
593*bdd1243dSDimitry Andric   return MLTAL;
594480093f4SDimitry Andric }
595480093f4SDimitry Andric 
59613138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
59713138422SDimitry Andric                                     ConstraintSatisfaction &Satisfaction,
598*bdd1243dSDimitry Andric                                     SourceLocation UsageLoc,
599*bdd1243dSDimitry Andric                                     bool ForOverloadResolution) {
600*bdd1243dSDimitry Andric   // Don't check constraints if the function is dependent. Also don't check if
601*bdd1243dSDimitry Andric   // this is a function template specialization, as the call to
602*bdd1243dSDimitry Andric   // CheckinstantiatedFunctionTemplateConstraints after this will check it
603*bdd1243dSDimitry Andric   // better.
604*bdd1243dSDimitry Andric   if (FD->isDependentContext() ||
605*bdd1243dSDimitry Andric       FD->getTemplatedKind() ==
606*bdd1243dSDimitry Andric           FunctionDecl::TK_FunctionTemplateSpecialization) {
60713138422SDimitry Andric     Satisfaction.IsSatisfied = true;
60813138422SDimitry Andric     return false;
60913138422SDimitry Andric   }
610*bdd1243dSDimitry Andric 
611*bdd1243dSDimitry Andric   DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
612*bdd1243dSDimitry Andric 
613*bdd1243dSDimitry Andric   while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
614*bdd1243dSDimitry Andric     if (isLambdaCallOperator(CtxToSave))
615*bdd1243dSDimitry Andric       CtxToSave = CtxToSave->getParent()->getParent();
616*bdd1243dSDimitry Andric     else
617*bdd1243dSDimitry Andric       CtxToSave = CtxToSave->getNonTransparentContext();
618*bdd1243dSDimitry Andric   }
619*bdd1243dSDimitry Andric 
620*bdd1243dSDimitry Andric   ContextRAII SavedContext{*this, CtxToSave};
621*bdd1243dSDimitry Andric   LocalInstantiationScope Scope(*this, !ForOverloadResolution ||
622*bdd1243dSDimitry Andric                                            isLambdaCallOperator(FD));
623*bdd1243dSDimitry Andric   std::optional<MultiLevelTemplateArgumentList> MLTAL =
624*bdd1243dSDimitry Andric       SetupConstraintCheckingTemplateArgumentsAndScope(
625*bdd1243dSDimitry Andric           const_cast<FunctionDecl *>(FD), {}, Scope);
626*bdd1243dSDimitry Andric 
627*bdd1243dSDimitry Andric   if (!MLTAL)
628*bdd1243dSDimitry Andric     return true;
629*bdd1243dSDimitry Andric 
63013138422SDimitry Andric   Qualifiers ThisQuals;
63113138422SDimitry Andric   CXXRecordDecl *Record = nullptr;
63213138422SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
63313138422SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
63413138422SDimitry Andric     Record = const_cast<CXXRecordDecl *>(Method->getParent());
63513138422SDimitry Andric   }
63613138422SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
63713138422SDimitry Andric   // We substitute with empty arguments in order to rebuild the atomic
63813138422SDimitry Andric   // constraint in a constant-evaluated context.
63913138422SDimitry Andric   // FIXME: Should this be a dedicated TreeTransform?
640*bdd1243dSDimitry Andric   const Expr *RC = FD->getTrailingRequiresClause();
641*bdd1243dSDimitry Andric   llvm::SmallVector<Expr *, 1> Converted;
642*bdd1243dSDimitry Andric 
643*bdd1243dSDimitry Andric   if (CheckConstraintSatisfaction(
644*bdd1243dSDimitry Andric           FD, {RC}, Converted, *MLTAL,
64513138422SDimitry Andric           SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
646*bdd1243dSDimitry Andric           Satisfaction))
647*bdd1243dSDimitry Andric     return true;
648*bdd1243dSDimitry Andric 
649*bdd1243dSDimitry Andric   // FIXME: we need to do this for the function constraints for
650*bdd1243dSDimitry Andric   // comparison of constraints to work, but do we also need to do it for
651*bdd1243dSDimitry Andric   // CheckInstantiatedFunctionConstraints?  That one is more difficult, but we
652*bdd1243dSDimitry Andric   // seem to always just pick up the constraints from the primary template.
653*bdd1243dSDimitry Andric   assert(Converted.size() <= 1 && "Got more expressions converted?");
654*bdd1243dSDimitry Andric   if (!Converted.empty() && Converted[0] != nullptr)
655*bdd1243dSDimitry Andric     const_cast<FunctionDecl *>(FD)->setTrailingRequiresClause(Converted[0]);
656*bdd1243dSDimitry Andric   return false;
657*bdd1243dSDimitry Andric }
658*bdd1243dSDimitry Andric 
659*bdd1243dSDimitry Andric 
660*bdd1243dSDimitry Andric // Figure out the to-translation-unit depth for this function declaration for
661*bdd1243dSDimitry Andric // the purpose of seeing if they differ by constraints. This isn't the same as
662*bdd1243dSDimitry Andric // getTemplateDepth, because it includes already instantiated parents.
663*bdd1243dSDimitry Andric static unsigned
664*bdd1243dSDimitry Andric CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
665*bdd1243dSDimitry Andric                                      bool SkipForSpecialization = false) {
666*bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
667*bdd1243dSDimitry Andric       ND, /*Final=*/false, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true,
668*bdd1243dSDimitry Andric       /*Pattern=*/nullptr,
669*bdd1243dSDimitry Andric       /*ForConstraintInstantiation=*/true, SkipForSpecialization);
670*bdd1243dSDimitry Andric   return MLTAL.getNumSubstitutedLevels();
671*bdd1243dSDimitry Andric }
672*bdd1243dSDimitry Andric 
673*bdd1243dSDimitry Andric namespace {
674*bdd1243dSDimitry Andric   class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
675*bdd1243dSDimitry Andric   unsigned TemplateDepth = 0;
676*bdd1243dSDimitry Andric   public:
677*bdd1243dSDimitry Andric   using inherited = TreeTransform<AdjustConstraintDepth>;
678*bdd1243dSDimitry Andric   AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
679*bdd1243dSDimitry Andric       : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
680*bdd1243dSDimitry Andric 
681*bdd1243dSDimitry Andric   using inherited::TransformTemplateTypeParmType;
682*bdd1243dSDimitry Andric   QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
683*bdd1243dSDimitry Andric                                          TemplateTypeParmTypeLoc TL, bool) {
684*bdd1243dSDimitry Andric     const TemplateTypeParmType *T = TL.getTypePtr();
685*bdd1243dSDimitry Andric 
686*bdd1243dSDimitry Andric     TemplateTypeParmDecl *NewTTPDecl = nullptr;
687*bdd1243dSDimitry Andric     if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
688*bdd1243dSDimitry Andric       NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
689*bdd1243dSDimitry Andric           TransformDecl(TL.getNameLoc(), OldTTPDecl));
690*bdd1243dSDimitry Andric 
691*bdd1243dSDimitry Andric     QualType Result = getSema().Context.getTemplateTypeParmType(
692*bdd1243dSDimitry Andric         T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
693*bdd1243dSDimitry Andric         NewTTPDecl);
694*bdd1243dSDimitry Andric     TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
695*bdd1243dSDimitry Andric     NewTL.setNameLoc(TL.getNameLoc());
696*bdd1243dSDimitry Andric     return Result;
697*bdd1243dSDimitry Andric   }
698*bdd1243dSDimitry Andric   };
699*bdd1243dSDimitry Andric } // namespace
700*bdd1243dSDimitry Andric 
701*bdd1243dSDimitry Andric bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
702*bdd1243dSDimitry Andric                                          const Expr *OldConstr,
703*bdd1243dSDimitry Andric                                          const NamedDecl *New,
704*bdd1243dSDimitry Andric                                          const Expr *NewConstr) {
705*bdd1243dSDimitry Andric   if (Old && New && Old != New) {
706*bdd1243dSDimitry Andric     unsigned Depth1 = CalculateTemplateDepthForConstraints(
707*bdd1243dSDimitry Andric         *this, Old);
708*bdd1243dSDimitry Andric     unsigned Depth2 = CalculateTemplateDepthForConstraints(
709*bdd1243dSDimitry Andric         *this, New);
710*bdd1243dSDimitry Andric 
711*bdd1243dSDimitry Andric     // Adjust the 'shallowest' verison of this to increase the depth to match
712*bdd1243dSDimitry Andric     // the 'other'.
713*bdd1243dSDimitry Andric     if (Depth2 > Depth1) {
714*bdd1243dSDimitry Andric       OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1)
715*bdd1243dSDimitry Andric                       .TransformExpr(const_cast<Expr *>(OldConstr))
716*bdd1243dSDimitry Andric                       .get();
717*bdd1243dSDimitry Andric     } else if (Depth1 > Depth2) {
718*bdd1243dSDimitry Andric       NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2)
719*bdd1243dSDimitry Andric                       .TransformExpr(const_cast<Expr *>(NewConstr))
720*bdd1243dSDimitry Andric                       .get();
721*bdd1243dSDimitry Andric     }
722*bdd1243dSDimitry Andric   }
723*bdd1243dSDimitry Andric 
724*bdd1243dSDimitry Andric   llvm::FoldingSetNodeID ID1, ID2;
725*bdd1243dSDimitry Andric   OldConstr->Profile(ID1, Context, /*Canonical=*/true);
726*bdd1243dSDimitry Andric   NewConstr->Profile(ID2, Context, /*Canonical=*/true);
727*bdd1243dSDimitry Andric   return ID1 == ID2;
728*bdd1243dSDimitry Andric }
729*bdd1243dSDimitry Andric 
730*bdd1243dSDimitry Andric bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
731*bdd1243dSDimitry Andric   assert(FD->getFriendObjectKind() && "Must be a friend!");
732*bdd1243dSDimitry Andric 
733*bdd1243dSDimitry Andric   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
734*bdd1243dSDimitry Andric   // don't have to bother checking 'DependsOnEnclosingTemplate' for a
735*bdd1243dSDimitry Andric   // non-function-template.
736*bdd1243dSDimitry Andric   assert(FD->getDescribedFunctionTemplate() &&
737*bdd1243dSDimitry Andric          "Non-function templates don't need to be checked");
738*bdd1243dSDimitry Andric 
739*bdd1243dSDimitry Andric   SmallVector<const Expr *, 3> ACs;
740*bdd1243dSDimitry Andric   FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
741*bdd1243dSDimitry Andric 
742*bdd1243dSDimitry Andric   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
743*bdd1243dSDimitry Andric   for (const Expr *Constraint : ACs)
744*bdd1243dSDimitry Andric     if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
745*bdd1243dSDimitry Andric                                                        Constraint))
746*bdd1243dSDimitry Andric       return true;
747*bdd1243dSDimitry Andric 
748*bdd1243dSDimitry Andric   return false;
74913138422SDimitry Andric }
75013138422SDimitry Andric 
751480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints(
752*bdd1243dSDimitry Andric     TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
753480093f4SDimitry Andric     SourceRange TemplateIDRange) {
754480093f4SDimitry Andric   ConstraintSatisfaction Satisfaction;
755480093f4SDimitry Andric   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
756480093f4SDimitry Andric   TD->getAssociatedConstraints(AssociatedConstraints);
757*bdd1243dSDimitry Andric   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
758480093f4SDimitry Andric                                   TemplateIDRange, Satisfaction))
759480093f4SDimitry Andric     return true;
760480093f4SDimitry Andric 
761480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied) {
762480093f4SDimitry Andric     SmallString<128> TemplateArgString;
763480093f4SDimitry Andric     TemplateArgString = " ";
764480093f4SDimitry Andric     TemplateArgString += getTemplateArgumentBindingsText(
765*bdd1243dSDimitry Andric         TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
766*bdd1243dSDimitry Andric         TemplateArgsLists.getInnermost().size());
767480093f4SDimitry Andric 
768480093f4SDimitry Andric     Diag(TemplateIDRange.getBegin(),
769480093f4SDimitry Andric          diag::err_template_arg_list_constraints_not_satisfied)
770480093f4SDimitry Andric         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
771480093f4SDimitry Andric         << TemplateArgString << TemplateIDRange;
772480093f4SDimitry Andric     DiagnoseUnsatisfiedConstraint(Satisfaction);
773480093f4SDimitry Andric     return true;
774480093f4SDimitry Andric   }
775480093f4SDimitry Andric   return false;
776480093f4SDimitry Andric }
777480093f4SDimitry Andric 
77881ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints(
77981ad6265SDimitry Andric     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
78081ad6265SDimitry Andric     ArrayRef<TemplateArgument> TemplateArgs,
78181ad6265SDimitry Andric     ConstraintSatisfaction &Satisfaction) {
78281ad6265SDimitry Andric   // In most cases we're not going to have constraints, so check for that first.
78381ad6265SDimitry Andric   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
78481ad6265SDimitry Andric   // Note - code synthesis context for the constraints check is created
78581ad6265SDimitry Andric   // inside CheckConstraintsSatisfaction.
78681ad6265SDimitry Andric   SmallVector<const Expr *, 3> TemplateAC;
78781ad6265SDimitry Andric   Template->getAssociatedConstraints(TemplateAC);
78881ad6265SDimitry Andric   if (TemplateAC.empty()) {
78981ad6265SDimitry Andric     Satisfaction.IsSatisfied = true;
79081ad6265SDimitry Andric     return false;
79181ad6265SDimitry Andric   }
79281ad6265SDimitry Andric 
79381ad6265SDimitry Andric   // Enter the scope of this instantiation. We don't use
79481ad6265SDimitry Andric   // PushDeclContext because we don't have a scope.
79581ad6265SDimitry Andric   Sema::ContextRAII savedContext(*this, Decl);
79681ad6265SDimitry Andric   LocalInstantiationScope Scope(*this);
79781ad6265SDimitry Andric 
798*bdd1243dSDimitry Andric   std::optional<MultiLevelTemplateArgumentList> MLTAL =
799*bdd1243dSDimitry Andric       SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
800*bdd1243dSDimitry Andric                                                        Scope);
801*bdd1243dSDimitry Andric 
802*bdd1243dSDimitry Andric   if (!MLTAL)
80381ad6265SDimitry Andric     return true;
804*bdd1243dSDimitry Andric 
80581ad6265SDimitry Andric   Qualifiers ThisQuals;
80681ad6265SDimitry Andric   CXXRecordDecl *Record = nullptr;
80781ad6265SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
80881ad6265SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
80981ad6265SDimitry Andric     Record = Method->getParent();
81081ad6265SDimitry Andric   }
81181ad6265SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
812*bdd1243dSDimitry Andric   FunctionScopeRAII FuncScope(*this);
813*bdd1243dSDimitry Andric   if (isLambdaCallOperator(Decl))
814*bdd1243dSDimitry Andric     PushLambdaScope();
815*bdd1243dSDimitry Andric   else
816*bdd1243dSDimitry Andric     FuncScope.disable();
817*bdd1243dSDimitry Andric 
818*bdd1243dSDimitry Andric   llvm::SmallVector<Expr *, 1> Converted;
819*bdd1243dSDimitry Andric   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
82081ad6265SDimitry Andric                                      PointOfInstantiation, Satisfaction);
82181ad6265SDimitry Andric }
82281ad6265SDimitry Andric 
82355e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
82455e4f9d5SDimitry Andric                                            concepts::ExprRequirement *Req,
82555e4f9d5SDimitry Andric                                            bool First) {
82655e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
82755e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
82855e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
82955e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Dependent:
83055e4f9d5SDimitry Andric       llvm_unreachable("Diagnosing a dependent requirement");
83155e4f9d5SDimitry Andric       break;
83255e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
83355e4f9d5SDimitry Andric       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
83455e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
83555e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
83655e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_substitution_error)
83755e4f9d5SDimitry Andric                << (int)First << SubstDiag->SubstitutedEntity
83855e4f9d5SDimitry Andric                << SubstDiag->DiagMessage;
83955e4f9d5SDimitry Andric       else
84055e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
84155e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_unknown_substitution_error)
84255e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
84355e4f9d5SDimitry Andric       break;
84455e4f9d5SDimitry Andric     }
84555e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_NoexceptNotMet:
84655e4f9d5SDimitry Andric       S.Diag(Req->getNoexceptLoc(),
84755e4f9d5SDimitry Andric              diag::note_expr_requirement_noexcept_not_met)
84855e4f9d5SDimitry Andric           << (int)First << Req->getExpr();
84955e4f9d5SDimitry Andric       break;
85055e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
85155e4f9d5SDimitry Andric       auto *SubstDiag =
85255e4f9d5SDimitry Andric           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
85355e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
85455e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
85555e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_substitution_error)
85655e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity
85755e4f9d5SDimitry Andric             << SubstDiag->DiagMessage;
85855e4f9d5SDimitry Andric       else
85955e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
86055e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
86155e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
86255e4f9d5SDimitry Andric       break;
86355e4f9d5SDimitry Andric     }
86455e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
86555e4f9d5SDimitry Andric       ConceptSpecializationExpr *ConstraintExpr =
86655e4f9d5SDimitry Andric           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
867fe6060f1SDimitry Andric       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
86855e4f9d5SDimitry Andric         // A simple case - expr type is the type being constrained and the concept
86955e4f9d5SDimitry Andric         // was not provided arguments.
870fe6060f1SDimitry Andric         Expr *e = Req->getExpr();
871fe6060f1SDimitry Andric         S.Diag(e->getBeginLoc(),
87255e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied_simple)
873349cc55cSDimitry Andric             << (int)First << S.Context.getReferenceQualifiedType(e)
87455e4f9d5SDimitry Andric             << ConstraintExpr->getNamedConcept();
875fe6060f1SDimitry Andric       } else {
87655e4f9d5SDimitry Andric         S.Diag(ConstraintExpr->getBeginLoc(),
87755e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied)
87855e4f9d5SDimitry Andric             << (int)First << ConstraintExpr;
879fe6060f1SDimitry Andric       }
88055e4f9d5SDimitry Andric       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
88155e4f9d5SDimitry Andric       break;
88255e4f9d5SDimitry Andric     }
88355e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Satisfied:
88455e4f9d5SDimitry Andric       llvm_unreachable("We checked this above");
88555e4f9d5SDimitry Andric   }
88655e4f9d5SDimitry Andric }
88755e4f9d5SDimitry Andric 
88855e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
88955e4f9d5SDimitry Andric                                            concepts::TypeRequirement *Req,
89055e4f9d5SDimitry Andric                                            bool First) {
89155e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
89255e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
89355e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
89455e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_Dependent:
89555e4f9d5SDimitry Andric     llvm_unreachable("Diagnosing a dependent requirement");
89655e4f9d5SDimitry Andric     return;
89755e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_SubstitutionFailure: {
89855e4f9d5SDimitry Andric     auto *SubstDiag = Req->getSubstitutionDiagnostic();
89955e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
90055e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
90155e4f9d5SDimitry Andric              diag::note_type_requirement_substitution_error) << (int)First
90255e4f9d5SDimitry Andric           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
90355e4f9d5SDimitry Andric     else
90455e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
90555e4f9d5SDimitry Andric              diag::note_type_requirement_unknown_substitution_error)
90655e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
90755e4f9d5SDimitry Andric     return;
90855e4f9d5SDimitry Andric   }
90955e4f9d5SDimitry Andric   default:
91055e4f9d5SDimitry Andric     llvm_unreachable("Unknown satisfaction status");
91155e4f9d5SDimitry Andric     return;
91255e4f9d5SDimitry Andric   }
91355e4f9d5SDimitry Andric }
914*bdd1243dSDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
915*bdd1243dSDimitry Andric                                                         Expr *SubstExpr,
916*bdd1243dSDimitry Andric                                                         bool First = true);
91755e4f9d5SDimitry Andric 
91855e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
91955e4f9d5SDimitry Andric                                            concepts::NestedRequirement *Req,
92055e4f9d5SDimitry Andric                                            bool First) {
921*bdd1243dSDimitry Andric   using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
922*bdd1243dSDimitry Andric   for (auto &Pair : Req->getConstraintSatisfaction()) {
923*bdd1243dSDimitry Andric     if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
924*bdd1243dSDimitry Andric       S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
925*bdd1243dSDimitry Andric           << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second;
92655e4f9d5SDimitry Andric     else
927*bdd1243dSDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(
928*bdd1243dSDimitry Andric           S, Pair.second.dyn_cast<Expr *>(), First);
929*bdd1243dSDimitry Andric     First = false;
93055e4f9d5SDimitry Andric   }
93155e4f9d5SDimitry Andric }
93255e4f9d5SDimitry Andric 
933480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
934480093f4SDimitry Andric                                                         Expr *SubstExpr,
935*bdd1243dSDimitry Andric                                                         bool First) {
936480093f4SDimitry Andric   SubstExpr = SubstExpr->IgnoreParenImpCasts();
937480093f4SDimitry Andric   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
938480093f4SDimitry Andric     switch (BO->getOpcode()) {
939480093f4SDimitry Andric     // These two cases will in practice only be reached when using fold
940480093f4SDimitry Andric     // expressions with || and &&, since otherwise the || and && will have been
941480093f4SDimitry Andric     // broken down into atomic constraints during satisfaction checking.
942480093f4SDimitry Andric     case BO_LOr:
943480093f4SDimitry Andric       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
944480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
945480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
946480093f4SDimitry Andric                                                   /*First=*/false);
947480093f4SDimitry Andric       return;
948fe6060f1SDimitry Andric     case BO_LAnd: {
949fe6060f1SDimitry Andric       bool LHSSatisfied =
950fe6060f1SDimitry Andric           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
951480093f4SDimitry Andric       if (LHSSatisfied) {
952480093f4SDimitry Andric         // LHS is true, so RHS must be false.
953480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
954480093f4SDimitry Andric         return;
955480093f4SDimitry Andric       }
956480093f4SDimitry Andric       // LHS is false
957480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
958480093f4SDimitry Andric 
959480093f4SDimitry Andric       // RHS might also be false
960fe6060f1SDimitry Andric       bool RHSSatisfied =
961fe6060f1SDimitry Andric           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
962480093f4SDimitry Andric       if (!RHSSatisfied)
963480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
964480093f4SDimitry Andric                                                     /*First=*/false);
965480093f4SDimitry Andric       return;
966fe6060f1SDimitry Andric     }
967480093f4SDimitry Andric     case BO_GE:
968480093f4SDimitry Andric     case BO_LE:
969480093f4SDimitry Andric     case BO_GT:
970480093f4SDimitry Andric     case BO_LT:
971480093f4SDimitry Andric     case BO_EQ:
972480093f4SDimitry Andric     case BO_NE:
973480093f4SDimitry Andric       if (BO->getLHS()->getType()->isIntegerType() &&
974480093f4SDimitry Andric           BO->getRHS()->getType()->isIntegerType()) {
975480093f4SDimitry Andric         Expr::EvalResult SimplifiedLHS;
976480093f4SDimitry Andric         Expr::EvalResult SimplifiedRHS;
977fe6060f1SDimitry Andric         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
978fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
979fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
980fe6060f1SDimitry Andric         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
981fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
982fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
983480093f4SDimitry Andric         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
984480093f4SDimitry Andric           S.Diag(SubstExpr->getBeginLoc(),
985480093f4SDimitry Andric                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
986480093f4SDimitry Andric               << (int)First << SubstExpr
987fe6060f1SDimitry Andric               << toString(SimplifiedLHS.Val.getInt(), 10)
988480093f4SDimitry Andric               << BinaryOperator::getOpcodeStr(BO->getOpcode())
989fe6060f1SDimitry Andric               << toString(SimplifiedRHS.Val.getInt(), 10);
990480093f4SDimitry Andric           return;
991480093f4SDimitry Andric         }
992480093f4SDimitry Andric       }
993480093f4SDimitry Andric       break;
994480093f4SDimitry Andric 
995480093f4SDimitry Andric     default:
996480093f4SDimitry Andric       break;
997480093f4SDimitry Andric     }
998480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
999480093f4SDimitry Andric     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1000480093f4SDimitry Andric       S.Diag(
1001480093f4SDimitry Andric           CSE->getSourceRange().getBegin(),
1002480093f4SDimitry Andric           diag::
1003480093f4SDimitry Andric           note_single_arg_concept_specialization_constraint_evaluated_to_false)
1004480093f4SDimitry Andric           << (int)First
1005480093f4SDimitry Andric           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1006480093f4SDimitry Andric           << CSE->getNamedConcept();
1007480093f4SDimitry Andric     } else {
1008480093f4SDimitry Andric       S.Diag(SubstExpr->getSourceRange().getBegin(),
1009480093f4SDimitry Andric              diag::note_concept_specialization_constraint_evaluated_to_false)
1010480093f4SDimitry Andric           << (int)First << CSE;
1011480093f4SDimitry Andric     }
1012480093f4SDimitry Andric     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1013480093f4SDimitry Andric     return;
101455e4f9d5SDimitry Andric   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1015*bdd1243dSDimitry Andric     // FIXME: RequiresExpr should store dependent diagnostics.
101655e4f9d5SDimitry Andric     for (concepts::Requirement *Req : RE->getRequirements())
101755e4f9d5SDimitry Andric       if (!Req->isDependent() && !Req->isSatisfied()) {
101855e4f9d5SDimitry Andric         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
101955e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, E, First);
102055e4f9d5SDimitry Andric         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
102155e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, T, First);
102255e4f9d5SDimitry Andric         else
102355e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(
102455e4f9d5SDimitry Andric               S, cast<concepts::NestedRequirement>(Req), First);
102555e4f9d5SDimitry Andric         break;
102655e4f9d5SDimitry Andric       }
102755e4f9d5SDimitry Andric     return;
1028480093f4SDimitry Andric   }
1029480093f4SDimitry Andric 
1030480093f4SDimitry Andric   S.Diag(SubstExpr->getSourceRange().getBegin(),
1031480093f4SDimitry Andric          diag::note_atomic_constraint_evaluated_to_false)
1032480093f4SDimitry Andric       << (int)First << SubstExpr;
1033480093f4SDimitry Andric }
1034480093f4SDimitry Andric 
1035480093f4SDimitry Andric template<typename SubstitutionDiagnostic>
1036480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr(
1037480093f4SDimitry Andric     Sema &S, const Expr *E,
1038480093f4SDimitry Andric     const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1039480093f4SDimitry Andric     bool First = true) {
1040480093f4SDimitry Andric   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
1041480093f4SDimitry Andric     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1042480093f4SDimitry Andric         << Diag->second;
1043480093f4SDimitry Andric     return;
1044480093f4SDimitry Andric   }
1045480093f4SDimitry Andric 
1046480093f4SDimitry Andric   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
1047480093f4SDimitry Andric       Record.template get<Expr *>(), First);
1048480093f4SDimitry Andric }
1049480093f4SDimitry Andric 
105055e4f9d5SDimitry Andric void
105155e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
105255e4f9d5SDimitry Andric                                     bool First) {
1053480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
1054480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
1055480093f4SDimitry Andric   for (auto &Pair : Satisfaction.Details) {
1056480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1057480093f4SDimitry Andric     First = false;
1058480093f4SDimitry Andric   }
1059480093f4SDimitry Andric }
1060480093f4SDimitry Andric 
1061480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
106255e4f9d5SDimitry Andric     const ASTConstraintSatisfaction &Satisfaction,
106355e4f9d5SDimitry Andric     bool First) {
1064480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
1065480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
1066480093f4SDimitry Andric   for (auto &Pair : Satisfaction) {
1067480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1068480093f4SDimitry Andric     First = false;
1069480093f4SDimitry Andric   }
1070480093f4SDimitry Andric }
1071480093f4SDimitry Andric 
1072480093f4SDimitry Andric const NormalizedConstraint *
1073480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints(
1074480093f4SDimitry Andric     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
1075480093f4SDimitry Andric   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1076480093f4SDimitry Andric   if (CacheEntry == NormalizationCache.end()) {
1077480093f4SDimitry Andric     auto Normalized =
1078480093f4SDimitry Andric         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1079480093f4SDimitry Andric                                                   AssociatedConstraints);
1080480093f4SDimitry Andric     CacheEntry =
1081480093f4SDimitry Andric         NormalizationCache
1082480093f4SDimitry Andric             .try_emplace(ConstrainedDecl,
1083480093f4SDimitry Andric                          Normalized
1084480093f4SDimitry Andric                              ? new (Context) NormalizedConstraint(
1085480093f4SDimitry Andric                                  std::move(*Normalized))
1086480093f4SDimitry Andric                              : nullptr)
1087480093f4SDimitry Andric             .first;
1088480093f4SDimitry Andric   }
1089480093f4SDimitry Andric   return CacheEntry->second;
1090480093f4SDimitry Andric }
1091480093f4SDimitry Andric 
1092*bdd1243dSDimitry Andric static bool
1093*bdd1243dSDimitry Andric substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1094*bdd1243dSDimitry Andric                             ConceptDecl *Concept,
1095*bdd1243dSDimitry Andric                             const MultiLevelTemplateArgumentList &MLTAL,
1096480093f4SDimitry Andric                             const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1097480093f4SDimitry Andric   if (!N.isAtomic()) {
1098*bdd1243dSDimitry Andric     if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1099480093f4SDimitry Andric                                     ArgsAsWritten))
1100480093f4SDimitry Andric       return true;
1101*bdd1243dSDimitry Andric     return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1102480093f4SDimitry Andric                                        ArgsAsWritten);
1103480093f4SDimitry Andric   }
1104480093f4SDimitry Andric   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1105480093f4SDimitry Andric 
1106480093f4SDimitry Andric   AtomicConstraint &Atomic = *N.getAtomicConstraint();
1107480093f4SDimitry Andric   TemplateArgumentListInfo SubstArgs;
1108480093f4SDimitry Andric   if (!Atomic.ParameterMapping) {
1109480093f4SDimitry Andric     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1110480093f4SDimitry Andric     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1111480093f4SDimitry Andric                                  /*Depth=*/0, OccurringIndices);
1112*bdd1243dSDimitry Andric     TemplateArgumentLoc *TempArgs =
1113*bdd1243dSDimitry Andric         new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1114480093f4SDimitry Andric     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1115480093f4SDimitry Andric       if (OccurringIndices[I])
1116*bdd1243dSDimitry Andric         new (&(TempArgs)[J++])
1117*bdd1243dSDimitry Andric             TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(
1118*bdd1243dSDimitry Andric                 TemplateParams->begin()[I],
1119480093f4SDimitry Andric                 // Here we assume we do not support things like
1120480093f4SDimitry Andric                 // template<typename A, typename B>
1121480093f4SDimitry Andric                 // concept C = ...;
1122480093f4SDimitry Andric                 //
1123480093f4SDimitry Andric                 // template<typename... Ts> requires C<Ts...>
1124480093f4SDimitry Andric                 // struct S { };
1125480093f4SDimitry Andric                 // The above currently yields a diagnostic.
1126480093f4SDimitry Andric                 // We still might have default arguments for concept parameters.
1127*bdd1243dSDimitry Andric                 ArgsAsWritten->NumTemplateArgs > I
1128*bdd1243dSDimitry Andric                     ? ArgsAsWritten->arguments()[I].getLocation()
1129*bdd1243dSDimitry Andric                     : SourceLocation()));
1130*bdd1243dSDimitry Andric     Atomic.ParameterMapping.emplace(TempArgs,  OccurringIndices.count());
1131480093f4SDimitry Andric   }
1132480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(
1133480093f4SDimitry Andric       S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
1134480093f4SDimitry Andric       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
1135480093f4SDimitry Andric       SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
1136480093f4SDimitry Andric                   ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
1137480093f4SDimitry Andric   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1138480093f4SDimitry Andric     return true;
1139*bdd1243dSDimitry Andric 
1140*bdd1243dSDimitry Andric   TemplateArgumentLoc *TempArgs =
1141*bdd1243dSDimitry Andric       new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1142480093f4SDimitry Andric   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1143*bdd1243dSDimitry Andric             TempArgs);
1144*bdd1243dSDimitry Andric   Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1145480093f4SDimitry Andric   return false;
1146480093f4SDimitry Andric }
1147480093f4SDimitry Andric 
1148*bdd1243dSDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1149*bdd1243dSDimitry Andric                                         const ConceptSpecializationExpr *CSE) {
1150*bdd1243dSDimitry Andric   TemplateArgumentList TAL{TemplateArgumentList::OnStack,
1151*bdd1243dSDimitry Andric                            CSE->getTemplateArguments()};
1152*bdd1243dSDimitry Andric   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
1153*bdd1243dSDimitry Andric       CSE->getNamedConcept(), /*Final=*/false, &TAL,
1154*bdd1243dSDimitry Andric       /*RelativeToPrimary=*/true,
1155*bdd1243dSDimitry Andric       /*Pattern=*/nullptr,
1156*bdd1243dSDimitry Andric       /*ForConstraintInstantiation=*/true);
1157*bdd1243dSDimitry Andric 
1158*bdd1243dSDimitry Andric   return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1159*bdd1243dSDimitry Andric                                      CSE->getTemplateArgsAsWritten());
1160*bdd1243dSDimitry Andric }
1161*bdd1243dSDimitry Andric 
1162*bdd1243dSDimitry Andric std::optional<NormalizedConstraint>
1163480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1164480093f4SDimitry Andric                                           ArrayRef<const Expr *> E) {
1165480093f4SDimitry Andric   assert(E.size() != 0);
11666e75b2fbSDimitry Andric   auto Conjunction = fromConstraintExpr(S, D, E[0]);
11676e75b2fbSDimitry Andric   if (!Conjunction)
1168*bdd1243dSDimitry Andric     return std::nullopt;
11696e75b2fbSDimitry Andric   for (unsigned I = 1; I < E.size(); ++I) {
1170480093f4SDimitry Andric     auto Next = fromConstraintExpr(S, D, E[I]);
1171480093f4SDimitry Andric     if (!Next)
1172*bdd1243dSDimitry Andric       return std::nullopt;
11736e75b2fbSDimitry Andric     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1174480093f4SDimitry Andric                                         std::move(*Next), CCK_Conjunction);
1175480093f4SDimitry Andric   }
1176480093f4SDimitry Andric   return Conjunction;
1177480093f4SDimitry Andric }
1178480093f4SDimitry Andric 
1179*bdd1243dSDimitry Andric std::optional<NormalizedConstraint>
1180480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1181480093f4SDimitry Andric   assert(E != nullptr);
1182480093f4SDimitry Andric 
1183480093f4SDimitry Andric   // C++ [temp.constr.normal]p1.1
1184480093f4SDimitry Andric   // [...]
1185480093f4SDimitry Andric   // - The normal form of an expression (E) is the normal form of E.
1186480093f4SDimitry Andric   // [...]
1187480093f4SDimitry Andric   E = E->IgnoreParenImpCasts();
1188*bdd1243dSDimitry Andric 
1189*bdd1243dSDimitry Andric   // C++2a [temp.param]p4:
1190*bdd1243dSDimitry Andric   //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1191*bdd1243dSDimitry Andric   // Fold expression is considered atomic constraints per current wording.
1192*bdd1243dSDimitry Andric   // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1193*bdd1243dSDimitry Andric 
11945ffd83dbSDimitry Andric   if (LogicalBinOp BO = E) {
11955ffd83dbSDimitry Andric     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1196480093f4SDimitry Andric     if (!LHS)
1197*bdd1243dSDimitry Andric       return std::nullopt;
11985ffd83dbSDimitry Andric     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1199480093f4SDimitry Andric     if (!RHS)
1200*bdd1243dSDimitry Andric       return std::nullopt;
1201480093f4SDimitry Andric 
12025ffd83dbSDimitry Andric     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
12035ffd83dbSDimitry Andric                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1204480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1205480093f4SDimitry Andric     const NormalizedConstraint *SubNF;
1206480093f4SDimitry Andric     {
1207480093f4SDimitry Andric       Sema::InstantiatingTemplate Inst(
1208480093f4SDimitry Andric           S, CSE->getExprLoc(),
1209480093f4SDimitry Andric           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
1210480093f4SDimitry Andric           CSE->getSourceRange());
1211480093f4SDimitry Andric       // C++ [temp.constr.normal]p1.1
1212480093f4SDimitry Andric       // [...]
1213480093f4SDimitry Andric       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1214480093f4SDimitry Andric       // where C names a concept, is the normal form of the
1215480093f4SDimitry Andric       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1216480093f4SDimitry Andric       // respective template parameters in the parameter mappings in each atomic
1217480093f4SDimitry Andric       // constraint. If any such substitution results in an invalid type or
1218480093f4SDimitry Andric       // expression, the program is ill-formed; no diagnostic is required.
1219480093f4SDimitry Andric       // [...]
1220480093f4SDimitry Andric       ConceptDecl *CD = CSE->getNamedConcept();
1221480093f4SDimitry Andric       SubNF = S.getNormalizedAssociatedConstraints(CD,
1222480093f4SDimitry Andric                                                    {CD->getConstraintExpr()});
1223480093f4SDimitry Andric       if (!SubNF)
1224*bdd1243dSDimitry Andric         return std::nullopt;
1225480093f4SDimitry Andric     }
1226480093f4SDimitry Andric 
1227*bdd1243dSDimitry Andric     std::optional<NormalizedConstraint> New;
1228480093f4SDimitry Andric     New.emplace(S.Context, *SubNF);
1229480093f4SDimitry Andric 
1230*bdd1243dSDimitry Andric     if (substituteParameterMappings(S, *New, CSE))
1231*bdd1243dSDimitry Andric       return std::nullopt;
1232480093f4SDimitry Andric 
1233480093f4SDimitry Andric     return New;
1234480093f4SDimitry Andric   }
1235480093f4SDimitry Andric   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
1236480093f4SDimitry Andric }
1237480093f4SDimitry Andric 
1238480093f4SDimitry Andric using NormalForm =
1239480093f4SDimitry Andric     llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
1240480093f4SDimitry Andric 
1241480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
1242480093f4SDimitry Andric   if (Normalized.isAtomic())
1243480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
1244480093f4SDimitry Andric 
1245480093f4SDimitry Andric   NormalForm LCNF = makeCNF(Normalized.getLHS());
1246480093f4SDimitry Andric   NormalForm RCNF = makeCNF(Normalized.getRHS());
1247480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
1248480093f4SDimitry Andric     LCNF.reserve(LCNF.size() + RCNF.size());
1249480093f4SDimitry Andric     while (!RCNF.empty())
1250480093f4SDimitry Andric       LCNF.push_back(RCNF.pop_back_val());
1251480093f4SDimitry Andric     return LCNF;
1252480093f4SDimitry Andric   }
1253480093f4SDimitry Andric 
1254480093f4SDimitry Andric   // Disjunction
1255480093f4SDimitry Andric   NormalForm Res;
1256480093f4SDimitry Andric   Res.reserve(LCNF.size() * RCNF.size());
1257480093f4SDimitry Andric   for (auto &LDisjunction : LCNF)
1258480093f4SDimitry Andric     for (auto &RDisjunction : RCNF) {
1259480093f4SDimitry Andric       NormalForm::value_type Combined;
1260480093f4SDimitry Andric       Combined.reserve(LDisjunction.size() + RDisjunction.size());
1261480093f4SDimitry Andric       std::copy(LDisjunction.begin(), LDisjunction.end(),
1262480093f4SDimitry Andric                 std::back_inserter(Combined));
1263480093f4SDimitry Andric       std::copy(RDisjunction.begin(), RDisjunction.end(),
1264480093f4SDimitry Andric                 std::back_inserter(Combined));
1265480093f4SDimitry Andric       Res.emplace_back(Combined);
1266480093f4SDimitry Andric     }
1267480093f4SDimitry Andric   return Res;
1268480093f4SDimitry Andric }
1269480093f4SDimitry Andric 
1270480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
1271480093f4SDimitry Andric   if (Normalized.isAtomic())
1272480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
1273480093f4SDimitry Andric 
1274480093f4SDimitry Andric   NormalForm LDNF = makeDNF(Normalized.getLHS());
1275480093f4SDimitry Andric   NormalForm RDNF = makeDNF(Normalized.getRHS());
1276480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
1277480093f4SDimitry Andric     LDNF.reserve(LDNF.size() + RDNF.size());
1278480093f4SDimitry Andric     while (!RDNF.empty())
1279480093f4SDimitry Andric       LDNF.push_back(RDNF.pop_back_val());
1280480093f4SDimitry Andric     return LDNF;
1281480093f4SDimitry Andric   }
1282480093f4SDimitry Andric 
1283480093f4SDimitry Andric   // Conjunction
1284480093f4SDimitry Andric   NormalForm Res;
1285480093f4SDimitry Andric   Res.reserve(LDNF.size() * RDNF.size());
1286480093f4SDimitry Andric   for (auto &LConjunction : LDNF) {
1287480093f4SDimitry Andric     for (auto &RConjunction : RDNF) {
1288480093f4SDimitry Andric       NormalForm::value_type Combined;
1289480093f4SDimitry Andric       Combined.reserve(LConjunction.size() + RConjunction.size());
1290480093f4SDimitry Andric       std::copy(LConjunction.begin(), LConjunction.end(),
1291480093f4SDimitry Andric                 std::back_inserter(Combined));
1292480093f4SDimitry Andric       std::copy(RConjunction.begin(), RConjunction.end(),
1293480093f4SDimitry Andric                 std::back_inserter(Combined));
1294480093f4SDimitry Andric       Res.emplace_back(Combined);
1295480093f4SDimitry Andric     }
1296480093f4SDimitry Andric   }
1297480093f4SDimitry Andric   return Res;
1298480093f4SDimitry Andric }
1299480093f4SDimitry Andric 
1300480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
1301480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF,
1302480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
1303480093f4SDimitry Andric   // C++ [temp.constr.order] p2
1304480093f4SDimitry Andric   //   Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
1305480093f4SDimitry Andric   //   disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
1306480093f4SDimitry Andric   //   the conjuctive normal form of Q, where [...]
1307480093f4SDimitry Andric   for (const auto &Pi : PDNF) {
1308480093f4SDimitry Andric     for (const auto &Qj : QCNF) {
1309480093f4SDimitry Andric       // C++ [temp.constr.order] p2
1310480093f4SDimitry Andric       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
1311480093f4SDimitry Andric       //     and only if there exists an atomic constraint Pia in Pi for which
1312480093f4SDimitry Andric       //     there exists an atomic constraint, Qjb, in Qj such that Pia
1313480093f4SDimitry Andric       //     subsumes Qjb.
1314480093f4SDimitry Andric       bool Found = false;
1315480093f4SDimitry Andric       for (const AtomicConstraint *Pia : Pi) {
1316480093f4SDimitry Andric         for (const AtomicConstraint *Qjb : Qj) {
1317480093f4SDimitry Andric           if (E(*Pia, *Qjb)) {
1318480093f4SDimitry Andric             Found = true;
1319480093f4SDimitry Andric             break;
1320480093f4SDimitry Andric           }
1321480093f4SDimitry Andric         }
1322480093f4SDimitry Andric         if (Found)
1323480093f4SDimitry Andric           break;
1324480093f4SDimitry Andric       }
1325480093f4SDimitry Andric       if (!Found)
1326480093f4SDimitry Andric         return false;
1327480093f4SDimitry Andric     }
1328480093f4SDimitry Andric   }
1329480093f4SDimitry Andric   return true;
1330480093f4SDimitry Andric }
1331480093f4SDimitry Andric 
1332480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
1333480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
1334480093f4SDimitry Andric                      NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
1335480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
1336480093f4SDimitry Andric   // C++ [temp.constr.order] p2
1337480093f4SDimitry Andric   //   In order to determine if a constraint P subsumes a constraint Q, P is
1338480093f4SDimitry Andric   //   transformed into disjunctive normal form, and Q is transformed into
1339480093f4SDimitry Andric   //   conjunctive normal form. [...]
1340480093f4SDimitry Andric   auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
1341480093f4SDimitry Andric   if (!PNormalized)
1342480093f4SDimitry Andric     return true;
1343480093f4SDimitry Andric   const NormalForm PDNF = makeDNF(*PNormalized);
1344480093f4SDimitry Andric 
1345480093f4SDimitry Andric   auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
1346480093f4SDimitry Andric   if (!QNormalized)
1347480093f4SDimitry Andric     return true;
1348480093f4SDimitry Andric   const NormalForm QCNF = makeCNF(*QNormalized);
1349480093f4SDimitry Andric 
1350480093f4SDimitry Andric   Subsumes = subsumes(PDNF, QCNF, E);
1351480093f4SDimitry Andric   return false;
1352480093f4SDimitry Andric }
1353480093f4SDimitry Andric 
1354*bdd1243dSDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
1355*bdd1243dSDimitry Andric                                   MutableArrayRef<const Expr *> AC1,
1356*bdd1243dSDimitry Andric                                   NamedDecl *D2,
1357*bdd1243dSDimitry Andric                                   MutableArrayRef<const Expr *> AC2,
1358480093f4SDimitry Andric                                   bool &Result) {
1359*bdd1243dSDimitry Andric   if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1360*bdd1243dSDimitry Andric     auto IsExpectedEntity = [](const FunctionDecl *FD) {
1361*bdd1243dSDimitry Andric       FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
1362*bdd1243dSDimitry Andric       return Kind == FunctionDecl::TK_NonTemplate ||
1363*bdd1243dSDimitry Andric              Kind == FunctionDecl::TK_FunctionTemplate;
1364*bdd1243dSDimitry Andric     };
1365*bdd1243dSDimitry Andric     const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1366*bdd1243dSDimitry Andric     (void)IsExpectedEntity;
1367*bdd1243dSDimitry Andric     (void)FD1;
1368*bdd1243dSDimitry Andric     (void)FD2;
1369*bdd1243dSDimitry Andric     assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1370*bdd1243dSDimitry Andric            "use non-instantiated function declaration for constraints partial "
1371*bdd1243dSDimitry Andric            "ordering");
1372*bdd1243dSDimitry Andric   }
1373*bdd1243dSDimitry Andric 
1374480093f4SDimitry Andric   if (AC1.empty()) {
1375480093f4SDimitry Andric     Result = AC2.empty();
1376480093f4SDimitry Andric     return false;
1377480093f4SDimitry Andric   }
1378480093f4SDimitry Andric   if (AC2.empty()) {
1379480093f4SDimitry Andric     // TD1 has associated constraints and TD2 does not.
1380480093f4SDimitry Andric     Result = true;
1381480093f4SDimitry Andric     return false;
1382480093f4SDimitry Andric   }
1383480093f4SDimitry Andric 
1384480093f4SDimitry Andric   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1385480093f4SDimitry Andric   auto CacheEntry = SubsumptionCache.find(Key);
1386480093f4SDimitry Andric   if (CacheEntry != SubsumptionCache.end()) {
1387480093f4SDimitry Andric     Result = CacheEntry->second;
1388480093f4SDimitry Andric     return false;
1389480093f4SDimitry Andric   }
1390480093f4SDimitry Andric 
1391*bdd1243dSDimitry Andric   unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1392*bdd1243dSDimitry Andric   unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1393*bdd1243dSDimitry Andric 
1394*bdd1243dSDimitry Andric   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1395*bdd1243dSDimitry Andric     if (Depth2 > Depth1) {
1396*bdd1243dSDimitry Andric       AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1397*bdd1243dSDimitry Andric                    .TransformExpr(const_cast<Expr *>(AC1[I]))
1398*bdd1243dSDimitry Andric                    .get();
1399*bdd1243dSDimitry Andric     } else if (Depth1 > Depth2) {
1400*bdd1243dSDimitry Andric       AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1401*bdd1243dSDimitry Andric                    .TransformExpr(const_cast<Expr *>(AC2[I]))
1402*bdd1243dSDimitry Andric                    .get();
1403*bdd1243dSDimitry Andric     }
1404*bdd1243dSDimitry Andric   }
1405*bdd1243dSDimitry Andric 
1406480093f4SDimitry Andric   if (subsumes(*this, D1, AC1, D2, AC2, Result,
1407480093f4SDimitry Andric         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1408480093f4SDimitry Andric           return A.subsumes(Context, B);
1409480093f4SDimitry Andric         }))
1410480093f4SDimitry Andric     return true;
1411480093f4SDimitry Andric   SubsumptionCache.try_emplace(Key, Result);
1412480093f4SDimitry Andric   return false;
1413480093f4SDimitry Andric }
1414480093f4SDimitry Andric 
1415480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
1416480093f4SDimitry Andric     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
1417480093f4SDimitry Andric   if (isSFINAEContext())
1418480093f4SDimitry Andric     // No need to work here because our notes would be discarded.
1419480093f4SDimitry Andric     return false;
1420480093f4SDimitry Andric 
1421480093f4SDimitry Andric   if (AC1.empty() || AC2.empty())
1422480093f4SDimitry Andric     return false;
1423480093f4SDimitry Andric 
1424480093f4SDimitry Andric   auto NormalExprEvaluator =
1425480093f4SDimitry Andric       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1426480093f4SDimitry Andric         return A.subsumes(Context, B);
1427480093f4SDimitry Andric       };
1428480093f4SDimitry Andric 
1429480093f4SDimitry Andric   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1430480093f4SDimitry Andric   auto IdenticalExprEvaluator =
1431480093f4SDimitry Andric       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1432480093f4SDimitry Andric         if (!A.hasMatchingParameterMapping(Context, B))
1433480093f4SDimitry Andric           return false;
1434480093f4SDimitry Andric         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1435480093f4SDimitry Andric         if (EA == EB)
1436480093f4SDimitry Andric           return true;
1437480093f4SDimitry Andric 
1438480093f4SDimitry Andric         // Not the same source level expression - are the expressions
1439480093f4SDimitry Andric         // identical?
1440480093f4SDimitry Andric         llvm::FoldingSetNodeID IDA, IDB;
1441349cc55cSDimitry Andric         EA->Profile(IDA, Context, /*Canonical=*/true);
1442349cc55cSDimitry Andric         EB->Profile(IDB, Context, /*Canonical=*/true);
1443480093f4SDimitry Andric         if (IDA != IDB)
1444480093f4SDimitry Andric           return false;
1445480093f4SDimitry Andric 
1446480093f4SDimitry Andric         AmbiguousAtomic1 = EA;
1447480093f4SDimitry Andric         AmbiguousAtomic2 = EB;
1448480093f4SDimitry Andric         return true;
1449480093f4SDimitry Andric       };
1450480093f4SDimitry Andric 
1451480093f4SDimitry Andric   {
1452480093f4SDimitry Andric     // The subsumption checks might cause diagnostics
1453480093f4SDimitry Andric     SFINAETrap Trap(*this);
1454480093f4SDimitry Andric     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1455480093f4SDimitry Andric     if (!Normalized1)
1456480093f4SDimitry Andric       return false;
1457480093f4SDimitry Andric     const NormalForm DNF1 = makeDNF(*Normalized1);
1458480093f4SDimitry Andric     const NormalForm CNF1 = makeCNF(*Normalized1);
1459480093f4SDimitry Andric 
1460480093f4SDimitry Andric     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1461480093f4SDimitry Andric     if (!Normalized2)
1462480093f4SDimitry Andric       return false;
1463480093f4SDimitry Andric     const NormalForm DNF2 = makeDNF(*Normalized2);
1464480093f4SDimitry Andric     const NormalForm CNF2 = makeCNF(*Normalized2);
1465480093f4SDimitry Andric 
1466480093f4SDimitry Andric     bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1467480093f4SDimitry Andric     bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1468480093f4SDimitry Andric     bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1469480093f4SDimitry Andric     bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1470480093f4SDimitry Andric     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1471480093f4SDimitry Andric         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1472480093f4SDimitry Andric       // Same result - no ambiguity was caused by identical atomic expressions.
1473480093f4SDimitry Andric       return false;
1474480093f4SDimitry Andric   }
1475480093f4SDimitry Andric 
1476480093f4SDimitry Andric   // A different result! Some ambiguous atomic constraint(s) caused a difference
1477480093f4SDimitry Andric   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1478480093f4SDimitry Andric 
1479480093f4SDimitry Andric   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1480480093f4SDimitry Andric       << AmbiguousAtomic1->getSourceRange();
1481480093f4SDimitry Andric   Diag(AmbiguousAtomic2->getBeginLoc(),
1482480093f4SDimitry Andric        diag::note_ambiguous_atomic_constraints_similar_expression)
1483480093f4SDimitry Andric       << AmbiguousAtomic2->getSourceRange();
1484480093f4SDimitry Andric   return true;
1485480093f4SDimitry Andric }
148655e4f9d5SDimitry Andric 
148755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
148855e4f9d5SDimitry Andric     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
148955e4f9d5SDimitry Andric     ReturnTypeRequirement Req, SatisfactionStatus Status,
149055e4f9d5SDimitry Andric     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
149155e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
149255e4f9d5SDimitry Andric                 Status == SS_Dependent &&
149355e4f9d5SDimitry Andric                 (E->containsUnexpandedParameterPack() ||
149455e4f9d5SDimitry Andric                  Req.containsUnexpandedParameterPack()),
149555e4f9d5SDimitry Andric                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
149655e4f9d5SDimitry Andric     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
149755e4f9d5SDimitry Andric     Status(Status) {
149855e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
149955e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
150055e4f9d5SDimitry Andric          "noexcept specification");
150155e4f9d5SDimitry Andric   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
150255e4f9d5SDimitry Andric          (SubstitutedConstraintExpr != nullptr));
150355e4f9d5SDimitry Andric }
150455e4f9d5SDimitry Andric 
150555e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
150655e4f9d5SDimitry Andric     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
150755e4f9d5SDimitry Andric     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
150855e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
150955e4f9d5SDimitry Andric                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
151055e4f9d5SDimitry Andric     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
151155e4f9d5SDimitry Andric     Status(SS_ExprSubstitutionFailure) {
151255e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
151355e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
151455e4f9d5SDimitry Andric          "noexcept specification");
151555e4f9d5SDimitry Andric }
151655e4f9d5SDimitry Andric 
151755e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement::
151855e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) :
151904eeddc0SDimitry Andric     TypeConstraintInfo(TPL, false) {
152055e4f9d5SDimitry Andric   assert(TPL->size() == 1);
152155e4f9d5SDimitry Andric   const TypeConstraint *TC =
152255e4f9d5SDimitry Andric       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
152355e4f9d5SDimitry Andric   assert(TC &&
152455e4f9d5SDimitry Andric          "TPL must have a template type parameter with a type constraint");
152555e4f9d5SDimitry Andric   auto *Constraint =
1526349cc55cSDimitry Andric       cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1527e8d8bef9SDimitry Andric   bool Dependent =
1528e8d8bef9SDimitry Andric       Constraint->getTemplateArgsAsWritten() &&
1529e8d8bef9SDimitry Andric       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1530e8d8bef9SDimitry Andric           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
153104eeddc0SDimitry Andric   TypeConstraintInfo.setInt(Dependent ? true : false);
153255e4f9d5SDimitry Andric }
153355e4f9d5SDimitry Andric 
153455e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1535e8d8bef9SDimitry Andric     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
153655e4f9d5SDimitry Andric                 T->getType()->containsUnexpandedParameterPack(),
153755e4f9d5SDimitry Andric                 // We reach this ctor with either dependent types (in which
153855e4f9d5SDimitry Andric                 // IsSatisfied doesn't matter) or with non-dependent type in
153955e4f9d5SDimitry Andric                 // which the existence of the type indicates satisfaction.
1540e8d8bef9SDimitry Andric                 /*IsSatisfied=*/true),
1541e8d8bef9SDimitry Andric     Value(T),
1542e8d8bef9SDimitry Andric     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1543e8d8bef9SDimitry Andric                                                         : SS_Satisfied) {}
1544