xref: /openbsd-src/gnu/llvm/clang/lib/Sema/SemaConcept.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2e5dd7070Spatrick //
3*12c85518Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*12c85518Srobert // See https://llvm.org/LICENSE.txt for license information.
5*12c85518Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick //  This file implements semantic analysis for C++ constraints and concepts.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13*12c85518Srobert #include "TreeTransform.h"
14e5dd7070Spatrick #include "clang/Sema/SemaConcept.h"
15e5dd7070Spatrick #include "clang/Sema/Sema.h"
16e5dd7070Spatrick #include "clang/Sema/SemaInternal.h"
17e5dd7070Spatrick #include "clang/Sema/SemaDiagnostic.h"
18e5dd7070Spatrick #include "clang/Sema/TemplateDeduction.h"
19e5dd7070Spatrick #include "clang/Sema/Template.h"
20e5dd7070Spatrick #include "clang/Sema/Overload.h"
21e5dd7070Spatrick #include "clang/Sema/Initialization.h"
22*12c85518Srobert #include "clang/AST/ASTLambda.h"
23e5dd7070Spatrick #include "clang/AST/ExprConcepts.h"
24e5dd7070Spatrick #include "clang/AST/RecursiveASTVisitor.h"
25e5dd7070Spatrick #include "clang/Basic/OperatorPrecedence.h"
26e5dd7070Spatrick #include "llvm/ADT/DenseMap.h"
27e5dd7070Spatrick #include "llvm/ADT/PointerUnion.h"
28a9ac8606Spatrick #include "llvm/ADT/StringExtras.h"
29*12c85518Srobert #include <optional>
30a9ac8606Spatrick 
31e5dd7070Spatrick using namespace clang;
32e5dd7070Spatrick using namespace sema;
33e5dd7070Spatrick 
34ec727ea7Spatrick namespace {
35ec727ea7Spatrick class LogicalBinOp {
36*12c85518Srobert   SourceLocation Loc;
37ec727ea7Spatrick   OverloadedOperatorKind Op = OO_None;
38ec727ea7Spatrick   const Expr *LHS = nullptr;
39ec727ea7Spatrick   const Expr *RHS = nullptr;
40ec727ea7Spatrick 
41ec727ea7Spatrick public:
LogicalBinOp(const Expr * E)42ec727ea7Spatrick   LogicalBinOp(const Expr *E) {
43ec727ea7Spatrick     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
44ec727ea7Spatrick       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
45ec727ea7Spatrick       LHS = BO->getLHS();
46ec727ea7Spatrick       RHS = BO->getRHS();
47*12c85518Srobert       Loc = BO->getExprLoc();
48ec727ea7Spatrick     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
49a9ac8606Spatrick       // If OO is not || or && it might not have exactly 2 arguments.
50a9ac8606Spatrick       if (OO->getNumArgs() == 2) {
51ec727ea7Spatrick         Op = OO->getOperator();
52ec727ea7Spatrick         LHS = OO->getArg(0);
53ec727ea7Spatrick         RHS = OO->getArg(1);
54*12c85518Srobert         Loc = OO->getOperatorLoc();
55ec727ea7Spatrick       }
56ec727ea7Spatrick     }
57a9ac8606Spatrick   }
58ec727ea7Spatrick 
isAnd() const59ec727ea7Spatrick   bool isAnd() const { return Op == OO_AmpAmp; }
isOr() const60ec727ea7Spatrick   bool isOr() const { return Op == OO_PipePipe; }
operator bool() const61ec727ea7Spatrick   explicit operator bool() const { return isAnd() || isOr(); }
62ec727ea7Spatrick 
getLHS() const63ec727ea7Spatrick   const Expr *getLHS() const { return LHS; }
getRHS() const64ec727ea7Spatrick   const Expr *getRHS() const { return RHS; }
65*12c85518Srobert 
recreateBinOp(Sema & SemaRef,ExprResult LHS) const66*12c85518Srobert   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
67*12c85518Srobert     return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
68*12c85518Srobert   }
69*12c85518Srobert 
recreateBinOp(Sema & SemaRef,ExprResult LHS,ExprResult RHS) const70*12c85518Srobert   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
71*12c85518Srobert                            ExprResult RHS) const {
72*12c85518Srobert     assert((isAnd() || isOr()) && "Not the right kind of op?");
73*12c85518Srobert     assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
74*12c85518Srobert 
75*12c85518Srobert     if (!LHS.isUsable() || !RHS.isUsable())
76*12c85518Srobert       return ExprEmpty();
77*12c85518Srobert 
78*12c85518Srobert     // We should just be able to 'normalize' these to the builtin Binary
79*12c85518Srobert     // Operator, since that is how they are evaluated in constriant checks.
80*12c85518Srobert     return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
81*12c85518Srobert                                   BinaryOperator::getOverloadedOpcode(Op),
82*12c85518Srobert                                   SemaRef.Context.BoolTy, VK_PRValue,
83*12c85518Srobert                                   OK_Ordinary, Loc, FPOptionsOverride{});
84*12c85518Srobert   }
85ec727ea7Spatrick };
86ec727ea7Spatrick }
87ec727ea7Spatrick 
CheckConstraintExpression(const Expr * ConstraintExpression,Token NextToken,bool * PossibleNonPrimary,bool IsTrailingRequiresClause)88ec727ea7Spatrick bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
89ec727ea7Spatrick                                      Token NextToken, bool *PossibleNonPrimary,
90e5dd7070Spatrick                                      bool IsTrailingRequiresClause) {
91e5dd7070Spatrick   // C++2a [temp.constr.atomic]p1
92e5dd7070Spatrick   // ..E shall be a constant expression of type bool.
93e5dd7070Spatrick 
94e5dd7070Spatrick   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
95e5dd7070Spatrick 
96ec727ea7Spatrick   if (LogicalBinOp BO = ConstraintExpression) {
97ec727ea7Spatrick     return CheckConstraintExpression(BO.getLHS(), NextToken,
98e5dd7070Spatrick                                      PossibleNonPrimary) &&
99ec727ea7Spatrick            CheckConstraintExpression(BO.getRHS(), NextToken,
100e5dd7070Spatrick                                      PossibleNonPrimary);
101e5dd7070Spatrick   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
102e5dd7070Spatrick     return CheckConstraintExpression(C->getSubExpr(), NextToken,
103e5dd7070Spatrick                                      PossibleNonPrimary);
104e5dd7070Spatrick 
105e5dd7070Spatrick   QualType Type = ConstraintExpression->getType();
106e5dd7070Spatrick 
107e5dd7070Spatrick   auto CheckForNonPrimary = [&] {
108e5dd7070Spatrick     if (PossibleNonPrimary)
109e5dd7070Spatrick       *PossibleNonPrimary =
110e5dd7070Spatrick           // We have the following case:
111e5dd7070Spatrick           // template<typename> requires func(0) struct S { };
112e5dd7070Spatrick           // The user probably isn't aware of the parentheses required around
113e5dd7070Spatrick           // the function call, and we're only going to parse 'func' as the
114e5dd7070Spatrick           // primary-expression, and complain that it is of non-bool type.
115e5dd7070Spatrick           (NextToken.is(tok::l_paren) &&
116e5dd7070Spatrick            (IsTrailingRequiresClause ||
117e5dd7070Spatrick             (Type->isDependentType() &&
118ec727ea7Spatrick              isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
119e5dd7070Spatrick             Type->isFunctionType() ||
120e5dd7070Spatrick             Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
121e5dd7070Spatrick           // We have the following case:
122e5dd7070Spatrick           // template<typename T> requires size_<T> == 0 struct S { };
123e5dd7070Spatrick           // The user probably isn't aware of the parentheses required around
124e5dd7070Spatrick           // the binary operator, and we're only going to parse 'func' as the
125e5dd7070Spatrick           // first operand, and complain that it is of non-bool type.
126e5dd7070Spatrick           getBinOpPrecedence(NextToken.getKind(),
127e5dd7070Spatrick                              /*GreaterThanIsOperator=*/true,
128e5dd7070Spatrick                              getLangOpts().CPlusPlus11) > prec::LogicalAnd;
129e5dd7070Spatrick   };
130e5dd7070Spatrick 
131e5dd7070Spatrick   // An atomic constraint!
132e5dd7070Spatrick   if (ConstraintExpression->isTypeDependent()) {
133e5dd7070Spatrick     CheckForNonPrimary();
134e5dd7070Spatrick     return true;
135e5dd7070Spatrick   }
136e5dd7070Spatrick 
137e5dd7070Spatrick   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
138e5dd7070Spatrick     Diag(ConstraintExpression->getExprLoc(),
139e5dd7070Spatrick          diag::err_non_bool_atomic_constraint) << Type
140e5dd7070Spatrick         << ConstraintExpression->getSourceRange();
141e5dd7070Spatrick     CheckForNonPrimary();
142e5dd7070Spatrick     return false;
143e5dd7070Spatrick   }
144e5dd7070Spatrick 
145e5dd7070Spatrick   if (PossibleNonPrimary)
146e5dd7070Spatrick       *PossibleNonPrimary = false;
147e5dd7070Spatrick   return true;
148e5dd7070Spatrick }
149e5dd7070Spatrick 
150*12c85518Srobert namespace {
151*12c85518Srobert struct SatisfactionStackRAII {
152*12c85518Srobert   Sema &SemaRef;
153*12c85518Srobert   bool Inserted = false;
SatisfactionStackRAII__anon7c248e780311::SatisfactionStackRAII154*12c85518Srobert   SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
155*12c85518Srobert                         llvm::FoldingSetNodeID FSNID)
156*12c85518Srobert       : SemaRef(SemaRef) {
157*12c85518Srobert       if (ND) {
158*12c85518Srobert       SemaRef.PushSatisfactionStackEntry(ND, FSNID);
159*12c85518Srobert       Inserted = true;
160*12c85518Srobert       }
161*12c85518Srobert   }
~SatisfactionStackRAII__anon7c248e780311::SatisfactionStackRAII162*12c85518Srobert   ~SatisfactionStackRAII() {
163*12c85518Srobert         if (Inserted)
164*12c85518Srobert           SemaRef.PopSatisfactionStackEntry();
165*12c85518Srobert   }
166*12c85518Srobert };
167*12c85518Srobert } // namespace
168*12c85518Srobert 
169e5dd7070Spatrick template <typename AtomicEvaluator>
170*12c85518Srobert static ExprResult
calculateConstraintSatisfaction(Sema & S,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction,AtomicEvaluator && Evaluator)171e5dd7070Spatrick calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
172e5dd7070Spatrick                                 ConstraintSatisfaction &Satisfaction,
173e5dd7070Spatrick                                 AtomicEvaluator &&Evaluator) {
174e5dd7070Spatrick   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
175e5dd7070Spatrick 
176ec727ea7Spatrick   if (LogicalBinOp BO = ConstraintExpr) {
177*12c85518Srobert     ExprResult LHSRes = calculateConstraintSatisfaction(
178*12c85518Srobert         S, BO.getLHS(), Satisfaction, Evaluator);
179*12c85518Srobert 
180*12c85518Srobert     if (LHSRes.isInvalid())
181*12c85518Srobert       return ExprError();
182e5dd7070Spatrick 
183e5dd7070Spatrick     bool IsLHSSatisfied = Satisfaction.IsSatisfied;
184e5dd7070Spatrick 
185ec727ea7Spatrick     if (BO.isOr() && IsLHSSatisfied)
186e5dd7070Spatrick       // [temp.constr.op] p3
187e5dd7070Spatrick       //    A disjunction is a constraint taking two operands. To determine if
188e5dd7070Spatrick       //    a disjunction is satisfied, the satisfaction of the first operand
189e5dd7070Spatrick       //    is checked. If that is satisfied, the disjunction is satisfied.
190e5dd7070Spatrick       //    Otherwise, the disjunction is satisfied if and only if the second
191e5dd7070Spatrick       //    operand is satisfied.
192*12c85518Srobert       // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
193*12c85518Srobert       return LHSRes;
194e5dd7070Spatrick 
195ec727ea7Spatrick     if (BO.isAnd() && !IsLHSSatisfied)
196e5dd7070Spatrick       // [temp.constr.op] p2
197e5dd7070Spatrick       //    A conjunction is a constraint taking two operands. To determine if
198e5dd7070Spatrick       //    a conjunction is satisfied, the satisfaction of the first operand
199e5dd7070Spatrick       //    is checked. If that is not satisfied, the conjunction is not
200e5dd7070Spatrick       //    satisfied. Otherwise, the conjunction is satisfied if and only if
201e5dd7070Spatrick       //    the second operand is satisfied.
202*12c85518Srobert       // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
203*12c85518Srobert       return LHSRes;
204e5dd7070Spatrick 
205*12c85518Srobert     ExprResult RHSRes = calculateConstraintSatisfaction(
206ec727ea7Spatrick         S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
207*12c85518Srobert     if (RHSRes.isInvalid())
208*12c85518Srobert       return ExprError();
209*12c85518Srobert 
210*12c85518Srobert     return BO.recreateBinOp(S, LHSRes, RHSRes);
211*12c85518Srobert   }
212*12c85518Srobert 
213*12c85518Srobert   if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
214*12c85518Srobert     // These aren't evaluated, so we don't care about cleanups, so we can just
215*12c85518Srobert     // evaluate these as if the cleanups didn't exist.
216*12c85518Srobert     return calculateConstraintSatisfaction(
217*12c85518Srobert         S, C->getSubExpr(), Satisfaction,
218e5dd7070Spatrick         std::forward<AtomicEvaluator>(Evaluator));
219ec727ea7Spatrick   }
220e5dd7070Spatrick 
221e5dd7070Spatrick   // An atomic constraint expression
222e5dd7070Spatrick   ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
223e5dd7070Spatrick 
224e5dd7070Spatrick   if (SubstitutedAtomicExpr.isInvalid())
225*12c85518Srobert     return ExprError();
226e5dd7070Spatrick 
227e5dd7070Spatrick   if (!SubstitutedAtomicExpr.isUsable())
228e5dd7070Spatrick     // Evaluator has decided satisfaction without yielding an expression.
229*12c85518Srobert     return ExprEmpty();
230*12c85518Srobert 
231*12c85518Srobert   // We don't have the ability to evaluate this, since it contains a
232*12c85518Srobert   // RecoveryExpr, so we want to fail overload resolution.  Otherwise,
233*12c85518Srobert   // we'd potentially pick up a different overload, and cause confusing
234*12c85518Srobert   // diagnostics. SO, add a failure detail that will cause us to make this
235*12c85518Srobert   // overload set not viable.
236*12c85518Srobert   if (SubstitutedAtomicExpr.get()->containsErrors()) {
237*12c85518Srobert     Satisfaction.IsSatisfied = false;
238*12c85518Srobert     Satisfaction.ContainsErrors = true;
239*12c85518Srobert 
240*12c85518Srobert     PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
241*12c85518Srobert     SmallString<128> DiagString;
242*12c85518Srobert     DiagString = ": ";
243*12c85518Srobert     Msg.EmitToString(S.getDiagnostics(), DiagString);
244*12c85518Srobert     unsigned MessageSize = DiagString.size();
245*12c85518Srobert     char *Mem = new (S.Context) char[MessageSize];
246*12c85518Srobert     memcpy(Mem, DiagString.c_str(), MessageSize);
247*12c85518Srobert     Satisfaction.Details.emplace_back(
248*12c85518Srobert         ConstraintExpr,
249*12c85518Srobert         new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
250*12c85518Srobert             SubstitutedAtomicExpr.get()->getBeginLoc(),
251*12c85518Srobert             StringRef(Mem, MessageSize)});
252*12c85518Srobert     return SubstitutedAtomicExpr;
253*12c85518Srobert   }
254e5dd7070Spatrick 
255e5dd7070Spatrick   EnterExpressionEvaluationContext ConstantEvaluated(
256e5dd7070Spatrick       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
257e5dd7070Spatrick   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
258e5dd7070Spatrick   Expr::EvalResult EvalResult;
259e5dd7070Spatrick   EvalResult.Diag = &EvaluationDiags;
260a9ac8606Spatrick   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
261a9ac8606Spatrick                                                            S.Context) ||
262a9ac8606Spatrick       !EvaluationDiags.empty()) {
263e5dd7070Spatrick     // C++2a [temp.constr.atomic]p1
264e5dd7070Spatrick     //   ...E shall be a constant expression of type bool.
265e5dd7070Spatrick     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
266e5dd7070Spatrick            diag::err_non_constant_constraint_expression)
267e5dd7070Spatrick         << SubstitutedAtomicExpr.get()->getSourceRange();
268e5dd7070Spatrick     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
269e5dd7070Spatrick       S.Diag(PDiag.first, PDiag.second);
270*12c85518Srobert     return ExprError();
271e5dd7070Spatrick   }
272e5dd7070Spatrick 
273a9ac8606Spatrick   assert(EvalResult.Val.isInt() &&
274a9ac8606Spatrick          "evaluating bool expression didn't produce int");
275e5dd7070Spatrick   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
276e5dd7070Spatrick   if (!Satisfaction.IsSatisfied)
277e5dd7070Spatrick     Satisfaction.Details.emplace_back(ConstraintExpr,
278e5dd7070Spatrick                                       SubstitutedAtomicExpr.get());
279e5dd7070Spatrick 
280*12c85518Srobert   return SubstitutedAtomicExpr;
281*12c85518Srobert }
282*12c85518Srobert 
283*12c85518Srobert static bool
DiagRecursiveConstraintEval(Sema & S,llvm::FoldingSetNodeID & ID,const NamedDecl * Templ,const Expr * E,const MultiLevelTemplateArgumentList & MLTAL)284*12c85518Srobert DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
285*12c85518Srobert                             const NamedDecl *Templ, const Expr *E,
286*12c85518Srobert                             const MultiLevelTemplateArgumentList &MLTAL) {
287*12c85518Srobert   E->Profile(ID, S.Context, /*Canonical=*/true);
288*12c85518Srobert   for (const auto &List : MLTAL)
289*12c85518Srobert     for (const auto &TemplateArg : List.Args)
290*12c85518Srobert       TemplateArg.Profile(ID, S.Context);
291*12c85518Srobert 
292*12c85518Srobert   // Note that we have to do this with our own collection, because there are
293*12c85518Srobert   // times where a constraint-expression check can cause us to need to evaluate
294*12c85518Srobert   // other constriants that are unrelated, such as when evaluating a recovery
295*12c85518Srobert   // expression, or when trying to determine the constexpr-ness of special
296*12c85518Srobert   // members. Otherwise we could just use the
297*12c85518Srobert   // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
298*12c85518Srobert   if (S.SatisfactionStackContains(Templ, ID)) {
299*12c85518Srobert     S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
300*12c85518Srobert         << const_cast<Expr *>(E) << E->getSourceRange();
301*12c85518Srobert     return true;
302*12c85518Srobert   }
303*12c85518Srobert 
304e5dd7070Spatrick   return false;
305e5dd7070Spatrick }
306e5dd7070Spatrick 
calculateConstraintSatisfaction(Sema & S,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)307*12c85518Srobert static ExprResult calculateConstraintSatisfaction(
308*12c85518Srobert     Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
309*12c85518Srobert     const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
310*12c85518Srobert     ConstraintSatisfaction &Satisfaction) {
311e5dd7070Spatrick   return calculateConstraintSatisfaction(
312e5dd7070Spatrick       S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
313e5dd7070Spatrick         EnterExpressionEvaluationContext ConstantEvaluated(
314*12c85518Srobert             S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
315*12c85518Srobert             Sema::ReuseLambdaContextDecl);
316e5dd7070Spatrick 
317e5dd7070Spatrick         // Atomic constraint - substitute arguments and check satisfaction.
318e5dd7070Spatrick         ExprResult SubstitutedExpression;
319e5dd7070Spatrick         {
320e5dd7070Spatrick           TemplateDeductionInfo Info(TemplateNameLoc);
321e5dd7070Spatrick           Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
322e5dd7070Spatrick               Sema::InstantiatingTemplate::ConstraintSubstitution{},
323e5dd7070Spatrick               const_cast<NamedDecl *>(Template), Info,
324e5dd7070Spatrick               AtomicExpr->getSourceRange());
325e5dd7070Spatrick           if (Inst.isInvalid())
326e5dd7070Spatrick             return ExprError();
327*12c85518Srobert 
328*12c85518Srobert           llvm::FoldingSetNodeID ID;
329*12c85518Srobert           if (Template &&
330*12c85518Srobert               DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
331*12c85518Srobert             Satisfaction.IsSatisfied = false;
332*12c85518Srobert             Satisfaction.ContainsErrors = true;
333*12c85518Srobert             return ExprEmpty();
334*12c85518Srobert           }
335*12c85518Srobert 
336*12c85518Srobert           SatisfactionStackRAII StackRAII(S, Template, ID);
337*12c85518Srobert 
338e5dd7070Spatrick           // We do not want error diagnostics escaping here.
339e5dd7070Spatrick           Sema::SFINAETrap Trap(S);
340a9ac8606Spatrick           SubstitutedExpression =
341*12c85518Srobert               S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
342*12c85518Srobert 
343e5dd7070Spatrick           if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
344e5dd7070Spatrick             // C++2a [temp.constr.atomic]p1
345e5dd7070Spatrick             //   ...If substitution results in an invalid type or expression, the
346e5dd7070Spatrick             //   constraint is not satisfied.
347e5dd7070Spatrick             if (!Trap.hasErrorOccurred())
348*12c85518Srobert               // A non-SFINAE error has occurred as a result of this
349e5dd7070Spatrick               // substitution.
350e5dd7070Spatrick               return ExprError();
351e5dd7070Spatrick 
352e5dd7070Spatrick             PartialDiagnosticAt SubstDiag{SourceLocation(),
353e5dd7070Spatrick                                           PartialDiagnostic::NullDiagnostic()};
354e5dd7070Spatrick             Info.takeSFINAEDiagnostic(SubstDiag);
355e5dd7070Spatrick             // FIXME: Concepts: This is an unfortunate consequence of there
356e5dd7070Spatrick             //  being no serialization code for PartialDiagnostics and the fact
357e5dd7070Spatrick             //  that serializing them would likely take a lot more storage than
358e5dd7070Spatrick             //  just storing them as strings. We would still like, in the
359e5dd7070Spatrick             //  future, to serialize the proper PartialDiagnostic as serializing
360e5dd7070Spatrick             //  it as a string defeats the purpose of the diagnostic mechanism.
361e5dd7070Spatrick             SmallString<128> DiagString;
362e5dd7070Spatrick             DiagString = ": ";
363e5dd7070Spatrick             SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
364e5dd7070Spatrick             unsigned MessageSize = DiagString.size();
365e5dd7070Spatrick             char *Mem = new (S.Context) char[MessageSize];
366e5dd7070Spatrick             memcpy(Mem, DiagString.c_str(), MessageSize);
367e5dd7070Spatrick             Satisfaction.Details.emplace_back(
368e5dd7070Spatrick                 AtomicExpr,
369e5dd7070Spatrick                 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
370e5dd7070Spatrick                         SubstDiag.first, StringRef(Mem, MessageSize)});
371e5dd7070Spatrick             Satisfaction.IsSatisfied = false;
372e5dd7070Spatrick             return ExprEmpty();
373e5dd7070Spatrick           }
374e5dd7070Spatrick         }
375e5dd7070Spatrick 
376e5dd7070Spatrick         if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
377e5dd7070Spatrick           return ExprError();
378e5dd7070Spatrick 
379*12c85518Srobert         // [temp.constr.atomic]p3: To determine if an atomic constraint is
380*12c85518Srobert         // satisfied, the parameter mapping and template arguments are first
381*12c85518Srobert         // substituted into its expression.  If substitution results in an
382*12c85518Srobert         // invalid type or expression, the constraint is not satisfied.
383*12c85518Srobert         // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
384*12c85518Srobert         // and E shall be a constant expression of type bool.
385*12c85518Srobert         //
386*12c85518Srobert         // Perform the L to R Value conversion if necessary. We do so for all
387*12c85518Srobert         // non-PRValue categories, else we fail to extend the lifetime of
388*12c85518Srobert         // temporaries, and that fails the constant expression check.
389*12c85518Srobert         if (!SubstitutedExpression.get()->isPRValue())
390*12c85518Srobert           SubstitutedExpression = ImplicitCastExpr::Create(
391*12c85518Srobert               S.Context, SubstitutedExpression.get()->getType(),
392*12c85518Srobert               CK_LValueToRValue, SubstitutedExpression.get(),
393*12c85518Srobert               /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
394*12c85518Srobert 
395e5dd7070Spatrick         return SubstitutedExpression;
396e5dd7070Spatrick       });
397e5dd7070Spatrick }
398e5dd7070Spatrick 
CheckConstraintSatisfaction(Sema & S,const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,llvm::SmallVectorImpl<Expr * > & Converted,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & Satisfaction)399*12c85518Srobert static bool CheckConstraintSatisfaction(
400*12c85518Srobert     Sema &S, const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
401*12c85518Srobert     llvm::SmallVectorImpl<Expr *> &Converted,
402*12c85518Srobert     const MultiLevelTemplateArgumentList &TemplateArgsLists,
403*12c85518Srobert     SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
404e5dd7070Spatrick   if (ConstraintExprs.empty()) {
405e5dd7070Spatrick     Satisfaction.IsSatisfied = true;
406e5dd7070Spatrick     return false;
407e5dd7070Spatrick   }
408e5dd7070Spatrick 
409*12c85518Srobert   if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
410e5dd7070Spatrick     // No need to check satisfaction for dependent constraint expressions.
411e5dd7070Spatrick     Satisfaction.IsSatisfied = true;
412e5dd7070Spatrick     return false;
413e5dd7070Spatrick   }
414e5dd7070Spatrick 
415*12c85518Srobert   ArrayRef<TemplateArgument> TemplateArgs =
416*12c85518Srobert       TemplateArgsLists.getNumSubstitutedLevels() > 0
417*12c85518Srobert           ? TemplateArgsLists.getOutermost()
418*12c85518Srobert           : ArrayRef<TemplateArgument> {};
419e5dd7070Spatrick   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
420e5dd7070Spatrick       Sema::InstantiatingTemplate::ConstraintsCheck{},
421e5dd7070Spatrick       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
422e5dd7070Spatrick   if (Inst.isInvalid())
423e5dd7070Spatrick     return true;
424e5dd7070Spatrick 
425e5dd7070Spatrick   for (const Expr *ConstraintExpr : ConstraintExprs) {
426*12c85518Srobert     ExprResult Res = calculateConstraintSatisfaction(
427*12c85518Srobert         S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
428*12c85518Srobert         ConstraintExpr, Satisfaction);
429*12c85518Srobert     if (Res.isInvalid())
430e5dd7070Spatrick       return true;
431*12c85518Srobert 
432*12c85518Srobert     Converted.push_back(Res.get());
433*12c85518Srobert     if (!Satisfaction.IsSatisfied) {
434*12c85518Srobert       // Backfill the 'converted' list with nulls so we can keep the Converted
435*12c85518Srobert       // and unconverted lists in sync.
436*12c85518Srobert       Converted.append(ConstraintExprs.size() - Converted.size(), nullptr);
437e5dd7070Spatrick       // [temp.constr.op] p2
438e5dd7070Spatrick       // [...] To determine if a conjunction is satisfied, the satisfaction
439e5dd7070Spatrick       // of the first operand is checked. If that is not satisfied, the
440e5dd7070Spatrick       // conjunction is not satisfied. [...]
441e5dd7070Spatrick       return false;
442e5dd7070Spatrick     }
443*12c85518Srobert   }
444e5dd7070Spatrick   return false;
445e5dd7070Spatrick }
446e5dd7070Spatrick 
CheckConstraintSatisfaction(const NamedDecl * Template,ArrayRef<const Expr * > ConstraintExprs,llvm::SmallVectorImpl<Expr * > & ConvertedConstraints,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & OutSatisfaction)447e5dd7070Spatrick bool Sema::CheckConstraintSatisfaction(
448e5dd7070Spatrick     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
449*12c85518Srobert     llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
450*12c85518Srobert     const MultiLevelTemplateArgumentList &TemplateArgsLists,
451*12c85518Srobert     SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
452e5dd7070Spatrick   if (ConstraintExprs.empty()) {
453e5dd7070Spatrick     OutSatisfaction.IsSatisfied = true;
454e5dd7070Spatrick     return false;
455e5dd7070Spatrick   }
456*12c85518Srobert   if (!Template) {
457*12c85518Srobert     return ::CheckConstraintSatisfaction(
458*12c85518Srobert         *this, nullptr, ConstraintExprs, ConvertedConstraints,
459*12c85518Srobert         TemplateArgsLists, TemplateIDRange, OutSatisfaction);
460*12c85518Srobert   }
461*12c85518Srobert 
462*12c85518Srobert   // A list of the template argument list flattened in a predictible manner for
463*12c85518Srobert   // the purposes of caching. The ConstraintSatisfaction type is in AST so it
464*12c85518Srobert   // has no access to the MultiLevelTemplateArgumentList, so this has to happen
465*12c85518Srobert   // here.
466*12c85518Srobert   llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
467*12c85518Srobert   for (auto List : TemplateArgsLists)
468*12c85518Srobert     FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
469*12c85518Srobert                          List.Args.end());
470e5dd7070Spatrick 
471e5dd7070Spatrick   llvm::FoldingSetNodeID ID;
472*12c85518Srobert   ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
473e5dd7070Spatrick   void *InsertPos;
474*12c85518Srobert   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
475*12c85518Srobert     OutSatisfaction = *Cached;
476e5dd7070Spatrick     return false;
477e5dd7070Spatrick   }
478*12c85518Srobert 
479*12c85518Srobert   auto Satisfaction =
480*12c85518Srobert       std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
481e5dd7070Spatrick   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
482*12c85518Srobert                                     ConvertedConstraints, TemplateArgsLists,
483*12c85518Srobert                                     TemplateIDRange, *Satisfaction)) {
484*12c85518Srobert     OutSatisfaction = *Satisfaction;
485e5dd7070Spatrick     return true;
486e5dd7070Spatrick   }
487e5dd7070Spatrick 
488*12c85518Srobert   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
489*12c85518Srobert     // The evaluation of this constraint resulted in us trying to re-evaluate it
490*12c85518Srobert     // recursively. This isn't really possible, except we try to form a
491*12c85518Srobert     // RecoveryExpr as a part of the evaluation.  If this is the case, just
492*12c85518Srobert     // return the 'cached' version (which will have the same result), and save
493*12c85518Srobert     // ourselves the extra-insert. If it ever becomes possible to legitimately
494*12c85518Srobert     // recursively check a constraint, we should skip checking the 'inner' one
495*12c85518Srobert     // above, and replace the cached version with this one, as it would be more
496*12c85518Srobert     // specific.
497*12c85518Srobert     OutSatisfaction = *Cached;
498*12c85518Srobert     return false;
499e5dd7070Spatrick   }
500*12c85518Srobert 
501*12c85518Srobert   // Else we can simply add this satisfaction to the list.
502*12c85518Srobert   OutSatisfaction = *Satisfaction;
503*12c85518Srobert   // We cannot use InsertPos here because CheckConstraintSatisfaction might have
504*12c85518Srobert   // invalidated it.
505*12c85518Srobert   // Note that entries of SatisfactionCache are deleted in Sema's destructor.
506*12c85518Srobert   SatisfactionCache.InsertNode(Satisfaction.release());
507e5dd7070Spatrick   return false;
508e5dd7070Spatrick }
509e5dd7070Spatrick 
CheckConstraintSatisfaction(const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)510e5dd7070Spatrick bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
511e5dd7070Spatrick                                        ConstraintSatisfaction &Satisfaction) {
512e5dd7070Spatrick   return calculateConstraintSatisfaction(
513e5dd7070Spatrick              *this, ConstraintExpr, Satisfaction,
514*12c85518Srobert              [this](const Expr *AtomicExpr) -> ExprResult {
515*12c85518Srobert                // We only do this to immitate lvalue-to-rvalue conversion.
516*12c85518Srobert                return PerformContextuallyConvertToBool(
517*12c85518Srobert                    const_cast<Expr *>(AtomicExpr));
518*12c85518Srobert              })
519*12c85518Srobert       .isInvalid();
520*12c85518Srobert }
521*12c85518Srobert 
SetupConstraintScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,MultiLevelTemplateArgumentList MLTAL,LocalInstantiationScope & Scope)522*12c85518Srobert bool Sema::SetupConstraintScope(
523*12c85518Srobert     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
524*12c85518Srobert     MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
525*12c85518Srobert   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
526*12c85518Srobert     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
527*12c85518Srobert     InstantiatingTemplate Inst(
528*12c85518Srobert         *this, FD->getPointOfInstantiation(),
529*12c85518Srobert         Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
530*12c85518Srobert         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
531*12c85518Srobert         SourceRange());
532*12c85518Srobert     if (Inst.isInvalid())
533*12c85518Srobert       return true;
534*12c85518Srobert 
535*12c85518Srobert     // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
536*12c85518Srobert     // 'instantiated' parameters and adds it to the context. For the case where
537*12c85518Srobert     // this function is a template being instantiated NOW, we also need to add
538*12c85518Srobert     // the list of current template arguments to the list so that they also can
539*12c85518Srobert     // be picked out of the map.
540*12c85518Srobert     if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
541*12c85518Srobert       MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
542*12c85518Srobert                                                    /*Final=*/false);
543*12c85518Srobert       if (addInstantiatedParametersToScope(
544*12c85518Srobert               FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
545*12c85518Srobert         return true;
546*12c85518Srobert     }
547*12c85518Srobert 
548*12c85518Srobert     // If this is a member function, make sure we get the parameters that
549*12c85518Srobert     // reference the original primary template.
550*12c85518Srobert     if (const auto *FromMemTempl =
551*12c85518Srobert             PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
552*12c85518Srobert       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
553*12c85518Srobert                                            Scope, MLTAL))
554*12c85518Srobert         return true;
555*12c85518Srobert     }
556*12c85518Srobert 
557*12c85518Srobert     return false;
558*12c85518Srobert   }
559*12c85518Srobert 
560*12c85518Srobert   if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
561*12c85518Srobert       FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
562*12c85518Srobert     FunctionDecl *InstantiatedFrom =
563*12c85518Srobert         FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
564*12c85518Srobert             ? FD->getInstantiatedFromMemberFunction()
565*12c85518Srobert             : FD->getInstantiatedFromDecl();
566*12c85518Srobert 
567*12c85518Srobert     InstantiatingTemplate Inst(
568*12c85518Srobert         *this, FD->getPointOfInstantiation(),
569*12c85518Srobert         Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
570*12c85518Srobert         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
571*12c85518Srobert         SourceRange());
572*12c85518Srobert     if (Inst.isInvalid())
573*12c85518Srobert       return true;
574*12c85518Srobert 
575*12c85518Srobert     // Case where this was not a template, but instantiated as a
576*12c85518Srobert     // child-function.
577*12c85518Srobert     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
578*12c85518Srobert       return true;
579*12c85518Srobert   }
580*12c85518Srobert 
581*12c85518Srobert   return false;
582*12c85518Srobert }
583*12c85518Srobert 
584*12c85518Srobert // This function collects all of the template arguments for the purposes of
585*12c85518Srobert // constraint-instantiation and checking.
586*12c85518Srobert std::optional<MultiLevelTemplateArgumentList>
SetupConstraintCheckingTemplateArgumentsAndScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,LocalInstantiationScope & Scope)587*12c85518Srobert Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
588*12c85518Srobert     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
589*12c85518Srobert     LocalInstantiationScope &Scope) {
590*12c85518Srobert   MultiLevelTemplateArgumentList MLTAL;
591*12c85518Srobert 
592*12c85518Srobert   // Collect the list of template arguments relative to the 'primary' template.
593*12c85518Srobert   // We need the entire list, since the constraint is completely uninstantiated
594*12c85518Srobert   // at this point.
595*12c85518Srobert   MLTAL =
596*12c85518Srobert       getTemplateInstantiationArgs(FD, /*Final=*/false, /*Innermost=*/nullptr,
597*12c85518Srobert                                    /*RelativeToPrimary=*/true,
598*12c85518Srobert                                    /*Pattern=*/nullptr,
599*12c85518Srobert                                    /*ForConstraintInstantiation=*/true);
600*12c85518Srobert   if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
601*12c85518Srobert     return std::nullopt;
602*12c85518Srobert 
603*12c85518Srobert   return MLTAL;
604e5dd7070Spatrick }
605e5dd7070Spatrick 
CheckFunctionConstraints(const FunctionDecl * FD,ConstraintSatisfaction & Satisfaction,SourceLocation UsageLoc,bool ForOverloadResolution)606e5dd7070Spatrick bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
607e5dd7070Spatrick                                     ConstraintSatisfaction &Satisfaction,
608*12c85518Srobert                                     SourceLocation UsageLoc,
609*12c85518Srobert                                     bool ForOverloadResolution) {
610*12c85518Srobert   // Don't check constraints if the function is dependent. Also don't check if
611*12c85518Srobert   // this is a function template specialization, as the call to
612*12c85518Srobert   // CheckinstantiatedFunctionTemplateConstraints after this will check it
613*12c85518Srobert   // better.
614*12c85518Srobert   if (FD->isDependentContext() ||
615*12c85518Srobert       FD->getTemplatedKind() ==
616*12c85518Srobert           FunctionDecl::TK_FunctionTemplateSpecialization) {
617e5dd7070Spatrick     Satisfaction.IsSatisfied = true;
618e5dd7070Spatrick     return false;
619e5dd7070Spatrick   }
620*12c85518Srobert 
621*12c85518Srobert   DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
622*12c85518Srobert 
623*12c85518Srobert   while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
624*12c85518Srobert     if (isLambdaCallOperator(CtxToSave))
625*12c85518Srobert       CtxToSave = CtxToSave->getParent()->getParent();
626*12c85518Srobert     else
627*12c85518Srobert       CtxToSave = CtxToSave->getNonTransparentContext();
628*12c85518Srobert   }
629*12c85518Srobert 
630*12c85518Srobert   ContextRAII SavedContext{*this, CtxToSave};
631*12c85518Srobert   LocalInstantiationScope Scope(*this, !ForOverloadResolution ||
632*12c85518Srobert                                            isLambdaCallOperator(FD));
633*12c85518Srobert   std::optional<MultiLevelTemplateArgumentList> MLTAL =
634*12c85518Srobert       SetupConstraintCheckingTemplateArgumentsAndScope(
635*12c85518Srobert           const_cast<FunctionDecl *>(FD), {}, Scope);
636*12c85518Srobert 
637*12c85518Srobert   if (!MLTAL)
638*12c85518Srobert     return true;
639*12c85518Srobert 
640e5dd7070Spatrick   Qualifiers ThisQuals;
641e5dd7070Spatrick   CXXRecordDecl *Record = nullptr;
642e5dd7070Spatrick   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
643e5dd7070Spatrick     ThisQuals = Method->getMethodQualifiers();
644e5dd7070Spatrick     Record = const_cast<CXXRecordDecl *>(Method->getParent());
645e5dd7070Spatrick   }
646e5dd7070Spatrick   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
647e5dd7070Spatrick   // We substitute with empty arguments in order to rebuild the atomic
648e5dd7070Spatrick   // constraint in a constant-evaluated context.
649e5dd7070Spatrick   // FIXME: Should this be a dedicated TreeTransform?
650*12c85518Srobert   const Expr *RC = FD->getTrailingRequiresClause();
651*12c85518Srobert   llvm::SmallVector<Expr *, 1> Converted;
652*12c85518Srobert 
653*12c85518Srobert   if (CheckConstraintSatisfaction(
654*12c85518Srobert           FD, {RC}, Converted, *MLTAL,
655e5dd7070Spatrick           SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
656*12c85518Srobert           Satisfaction))
657*12c85518Srobert     return true;
658*12c85518Srobert 
659*12c85518Srobert   // FIXME: we need to do this for the function constraints for
660*12c85518Srobert   // comparison of constraints to work, but do we also need to do it for
661*12c85518Srobert   // CheckInstantiatedFunctionConstraints?  That one is more difficult, but we
662*12c85518Srobert   // seem to always just pick up the constraints from the primary template.
663*12c85518Srobert   assert(Converted.size() <= 1 && "Got more expressions converted?");
664*12c85518Srobert   if (!Converted.empty() && Converted[0] != nullptr)
665*12c85518Srobert     const_cast<FunctionDecl *>(FD)->setTrailingRequiresClause(Converted[0]);
666*12c85518Srobert   return false;
667*12c85518Srobert }
668*12c85518Srobert 
669*12c85518Srobert 
670*12c85518Srobert // Figure out the to-translation-unit depth for this function declaration for
671*12c85518Srobert // the purpose of seeing if they differ by constraints. This isn't the same as
672*12c85518Srobert // getTemplateDepth, because it includes already instantiated parents.
673*12c85518Srobert static unsigned
CalculateTemplateDepthForConstraints(Sema & S,const NamedDecl * ND,bool SkipForSpecialization=false)674*12c85518Srobert CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
675*12c85518Srobert                                      bool SkipForSpecialization = false) {
676*12c85518Srobert   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
677*12c85518Srobert       ND, /*Final=*/false, /*Innermost=*/nullptr, /*RelativeToPrimary=*/true,
678*12c85518Srobert       /*Pattern=*/nullptr,
679*12c85518Srobert       /*ForConstraintInstantiation=*/true, SkipForSpecialization);
680*12c85518Srobert   return MLTAL.getNumSubstitutedLevels();
681*12c85518Srobert }
682*12c85518Srobert 
683*12c85518Srobert namespace {
684*12c85518Srobert   class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
685*12c85518Srobert   unsigned TemplateDepth = 0;
686*12c85518Srobert   public:
687*12c85518Srobert   using inherited = TreeTransform<AdjustConstraintDepth>;
AdjustConstraintDepth(Sema & SemaRef,unsigned TemplateDepth)688*12c85518Srobert   AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
689*12c85518Srobert       : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
690*12c85518Srobert 
691*12c85518Srobert   using inherited::TransformTemplateTypeParmType;
TransformTemplateTypeParmType(TypeLocBuilder & TLB,TemplateTypeParmTypeLoc TL,bool)692*12c85518Srobert   QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
693*12c85518Srobert                                          TemplateTypeParmTypeLoc TL, bool) {
694*12c85518Srobert     const TemplateTypeParmType *T = TL.getTypePtr();
695*12c85518Srobert 
696*12c85518Srobert     TemplateTypeParmDecl *NewTTPDecl = nullptr;
697*12c85518Srobert     if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
698*12c85518Srobert       NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
699*12c85518Srobert           TransformDecl(TL.getNameLoc(), OldTTPDecl));
700*12c85518Srobert 
701*12c85518Srobert     QualType Result = getSema().Context.getTemplateTypeParmType(
702*12c85518Srobert         T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
703*12c85518Srobert         NewTTPDecl);
704*12c85518Srobert     TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
705*12c85518Srobert     NewTL.setNameLoc(TL.getNameLoc());
706*12c85518Srobert     return Result;
707*12c85518Srobert   }
708*12c85518Srobert   };
709*12c85518Srobert } // namespace
710*12c85518Srobert 
AreConstraintExpressionsEqual(const NamedDecl * Old,const Expr * OldConstr,const NamedDecl * New,const Expr * NewConstr)711*12c85518Srobert bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
712*12c85518Srobert                                          const Expr *OldConstr,
713*12c85518Srobert                                          const NamedDecl *New,
714*12c85518Srobert                                          const Expr *NewConstr) {
715*12c85518Srobert   if (Old && New && Old != New) {
716*12c85518Srobert     unsigned Depth1 = CalculateTemplateDepthForConstraints(
717*12c85518Srobert         *this, Old);
718*12c85518Srobert     unsigned Depth2 = CalculateTemplateDepthForConstraints(
719*12c85518Srobert         *this, New);
720*12c85518Srobert 
721*12c85518Srobert     // Adjust the 'shallowest' verison of this to increase the depth to match
722*12c85518Srobert     // the 'other'.
723*12c85518Srobert     if (Depth2 > Depth1) {
724*12c85518Srobert       OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1)
725*12c85518Srobert                       .TransformExpr(const_cast<Expr *>(OldConstr))
726*12c85518Srobert                       .get();
727*12c85518Srobert     } else if (Depth1 > Depth2) {
728*12c85518Srobert       NewConstr = AdjustConstraintDepth(*this, Depth1 - Depth2)
729*12c85518Srobert                       .TransformExpr(const_cast<Expr *>(NewConstr))
730*12c85518Srobert                       .get();
731*12c85518Srobert     }
732*12c85518Srobert   }
733*12c85518Srobert 
734*12c85518Srobert   llvm::FoldingSetNodeID ID1, ID2;
735*12c85518Srobert   OldConstr->Profile(ID1, Context, /*Canonical=*/true);
736*12c85518Srobert   NewConstr->Profile(ID2, Context, /*Canonical=*/true);
737*12c85518Srobert   return ID1 == ID2;
738*12c85518Srobert }
739*12c85518Srobert 
FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl * FD)740*12c85518Srobert bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
741*12c85518Srobert   assert(FD->getFriendObjectKind() && "Must be a friend!");
742*12c85518Srobert 
743*12c85518Srobert   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
744*12c85518Srobert   // don't have to bother checking 'DependsOnEnclosingTemplate' for a
745*12c85518Srobert   // non-function-template.
746*12c85518Srobert   assert(FD->getDescribedFunctionTemplate() &&
747*12c85518Srobert          "Non-function templates don't need to be checked");
748*12c85518Srobert 
749*12c85518Srobert   SmallVector<const Expr *, 3> ACs;
750*12c85518Srobert   FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
751*12c85518Srobert 
752*12c85518Srobert   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
753*12c85518Srobert   for (const Expr *Constraint : ACs)
754*12c85518Srobert     if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
755*12c85518Srobert                                                        Constraint))
756*12c85518Srobert       return true;
757*12c85518Srobert 
758*12c85518Srobert   return false;
759e5dd7070Spatrick }
760e5dd7070Spatrick 
EnsureTemplateArgumentListConstraints(TemplateDecl * TD,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange)761e5dd7070Spatrick bool Sema::EnsureTemplateArgumentListConstraints(
762*12c85518Srobert     TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
763e5dd7070Spatrick     SourceRange TemplateIDRange) {
764e5dd7070Spatrick   ConstraintSatisfaction Satisfaction;
765e5dd7070Spatrick   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
766e5dd7070Spatrick   TD->getAssociatedConstraints(AssociatedConstraints);
767*12c85518Srobert   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
768e5dd7070Spatrick                                   TemplateIDRange, Satisfaction))
769e5dd7070Spatrick     return true;
770e5dd7070Spatrick 
771e5dd7070Spatrick   if (!Satisfaction.IsSatisfied) {
772e5dd7070Spatrick     SmallString<128> TemplateArgString;
773e5dd7070Spatrick     TemplateArgString = " ";
774e5dd7070Spatrick     TemplateArgString += getTemplateArgumentBindingsText(
775*12c85518Srobert         TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
776*12c85518Srobert         TemplateArgsLists.getInnermost().size());
777e5dd7070Spatrick 
778e5dd7070Spatrick     Diag(TemplateIDRange.getBegin(),
779e5dd7070Spatrick          diag::err_template_arg_list_constraints_not_satisfied)
780e5dd7070Spatrick         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
781e5dd7070Spatrick         << TemplateArgString << TemplateIDRange;
782e5dd7070Spatrick     DiagnoseUnsatisfiedConstraint(Satisfaction);
783e5dd7070Spatrick     return true;
784e5dd7070Spatrick   }
785e5dd7070Spatrick   return false;
786e5dd7070Spatrick }
787e5dd7070Spatrick 
CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation,FunctionDecl * Decl,ArrayRef<TemplateArgument> TemplateArgs,ConstraintSatisfaction & Satisfaction)788*12c85518Srobert bool Sema::CheckInstantiatedFunctionTemplateConstraints(
789*12c85518Srobert     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
790*12c85518Srobert     ArrayRef<TemplateArgument> TemplateArgs,
791*12c85518Srobert     ConstraintSatisfaction &Satisfaction) {
792*12c85518Srobert   // In most cases we're not going to have constraints, so check for that first.
793*12c85518Srobert   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
794*12c85518Srobert   // Note - code synthesis context for the constraints check is created
795*12c85518Srobert   // inside CheckConstraintsSatisfaction.
796*12c85518Srobert   SmallVector<const Expr *, 3> TemplateAC;
797*12c85518Srobert   Template->getAssociatedConstraints(TemplateAC);
798*12c85518Srobert   if (TemplateAC.empty()) {
799*12c85518Srobert     Satisfaction.IsSatisfied = true;
800*12c85518Srobert     return false;
801*12c85518Srobert   }
802*12c85518Srobert 
803*12c85518Srobert   // Enter the scope of this instantiation. We don't use
804*12c85518Srobert   // PushDeclContext because we don't have a scope.
805*12c85518Srobert   Sema::ContextRAII savedContext(*this, Decl);
806*12c85518Srobert   LocalInstantiationScope Scope(*this);
807*12c85518Srobert 
808*12c85518Srobert   std::optional<MultiLevelTemplateArgumentList> MLTAL =
809*12c85518Srobert       SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
810*12c85518Srobert                                                        Scope);
811*12c85518Srobert 
812*12c85518Srobert   if (!MLTAL)
813*12c85518Srobert     return true;
814*12c85518Srobert 
815*12c85518Srobert   Qualifiers ThisQuals;
816*12c85518Srobert   CXXRecordDecl *Record = nullptr;
817*12c85518Srobert   if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
818*12c85518Srobert     ThisQuals = Method->getMethodQualifiers();
819*12c85518Srobert     Record = Method->getParent();
820*12c85518Srobert   }
821*12c85518Srobert   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
822*12c85518Srobert   FunctionScopeRAII FuncScope(*this);
823*12c85518Srobert   if (isLambdaCallOperator(Decl))
824*12c85518Srobert     PushLambdaScope();
825*12c85518Srobert   else
826*12c85518Srobert     FuncScope.disable();
827*12c85518Srobert 
828*12c85518Srobert   llvm::SmallVector<Expr *, 1> Converted;
829*12c85518Srobert   return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL,
830*12c85518Srobert                                      PointOfInstantiation, Satisfaction);
831*12c85518Srobert }
832*12c85518Srobert 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::ExprRequirement * Req,bool First)833e5dd7070Spatrick static void diagnoseUnsatisfiedRequirement(Sema &S,
834e5dd7070Spatrick                                            concepts::ExprRequirement *Req,
835e5dd7070Spatrick                                            bool First) {
836e5dd7070Spatrick   assert(!Req->isSatisfied()
837e5dd7070Spatrick          && "Diagnose() can only be used on an unsatisfied requirement");
838e5dd7070Spatrick   switch (Req->getSatisfactionStatus()) {
839e5dd7070Spatrick     case concepts::ExprRequirement::SS_Dependent:
840e5dd7070Spatrick       llvm_unreachable("Diagnosing a dependent requirement");
841e5dd7070Spatrick       break;
842e5dd7070Spatrick     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
843e5dd7070Spatrick       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
844e5dd7070Spatrick       if (!SubstDiag->DiagMessage.empty())
845e5dd7070Spatrick         S.Diag(SubstDiag->DiagLoc,
846e5dd7070Spatrick                diag::note_expr_requirement_expr_substitution_error)
847e5dd7070Spatrick                << (int)First << SubstDiag->SubstitutedEntity
848e5dd7070Spatrick                << SubstDiag->DiagMessage;
849e5dd7070Spatrick       else
850e5dd7070Spatrick         S.Diag(SubstDiag->DiagLoc,
851e5dd7070Spatrick                diag::note_expr_requirement_expr_unknown_substitution_error)
852e5dd7070Spatrick             << (int)First << SubstDiag->SubstitutedEntity;
853e5dd7070Spatrick       break;
854e5dd7070Spatrick     }
855e5dd7070Spatrick     case concepts::ExprRequirement::SS_NoexceptNotMet:
856e5dd7070Spatrick       S.Diag(Req->getNoexceptLoc(),
857e5dd7070Spatrick              diag::note_expr_requirement_noexcept_not_met)
858e5dd7070Spatrick           << (int)First << Req->getExpr();
859e5dd7070Spatrick       break;
860e5dd7070Spatrick     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
861e5dd7070Spatrick       auto *SubstDiag =
862e5dd7070Spatrick           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
863e5dd7070Spatrick       if (!SubstDiag->DiagMessage.empty())
864e5dd7070Spatrick         S.Diag(SubstDiag->DiagLoc,
865e5dd7070Spatrick                diag::note_expr_requirement_type_requirement_substitution_error)
866e5dd7070Spatrick             << (int)First << SubstDiag->SubstitutedEntity
867e5dd7070Spatrick             << SubstDiag->DiagMessage;
868e5dd7070Spatrick       else
869e5dd7070Spatrick         S.Diag(SubstDiag->DiagLoc,
870e5dd7070Spatrick                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
871e5dd7070Spatrick             << (int)First << SubstDiag->SubstitutedEntity;
872e5dd7070Spatrick       break;
873e5dd7070Spatrick     }
874e5dd7070Spatrick     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
875e5dd7070Spatrick       ConceptSpecializationExpr *ConstraintExpr =
876e5dd7070Spatrick           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
877a9ac8606Spatrick       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
878e5dd7070Spatrick         // A simple case - expr type is the type being constrained and the concept
879e5dd7070Spatrick         // was not provided arguments.
880a9ac8606Spatrick         Expr *e = Req->getExpr();
881a9ac8606Spatrick         S.Diag(e->getBeginLoc(),
882e5dd7070Spatrick                diag::note_expr_requirement_constraints_not_satisfied_simple)
883*12c85518Srobert             << (int)First << S.Context.getReferenceQualifiedType(e)
884e5dd7070Spatrick             << ConstraintExpr->getNamedConcept();
885a9ac8606Spatrick       } else {
886e5dd7070Spatrick         S.Diag(ConstraintExpr->getBeginLoc(),
887e5dd7070Spatrick                diag::note_expr_requirement_constraints_not_satisfied)
888e5dd7070Spatrick             << (int)First << ConstraintExpr;
889a9ac8606Spatrick       }
890e5dd7070Spatrick       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
891e5dd7070Spatrick       break;
892e5dd7070Spatrick     }
893e5dd7070Spatrick     case concepts::ExprRequirement::SS_Satisfied:
894e5dd7070Spatrick       llvm_unreachable("We checked this above");
895e5dd7070Spatrick   }
896e5dd7070Spatrick }
897e5dd7070Spatrick 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::TypeRequirement * Req,bool First)898e5dd7070Spatrick static void diagnoseUnsatisfiedRequirement(Sema &S,
899e5dd7070Spatrick                                            concepts::TypeRequirement *Req,
900e5dd7070Spatrick                                            bool First) {
901e5dd7070Spatrick   assert(!Req->isSatisfied()
902e5dd7070Spatrick          && "Diagnose() can only be used on an unsatisfied requirement");
903e5dd7070Spatrick   switch (Req->getSatisfactionStatus()) {
904e5dd7070Spatrick   case concepts::TypeRequirement::SS_Dependent:
905e5dd7070Spatrick     llvm_unreachable("Diagnosing a dependent requirement");
906e5dd7070Spatrick     return;
907e5dd7070Spatrick   case concepts::TypeRequirement::SS_SubstitutionFailure: {
908e5dd7070Spatrick     auto *SubstDiag = Req->getSubstitutionDiagnostic();
909e5dd7070Spatrick     if (!SubstDiag->DiagMessage.empty())
910e5dd7070Spatrick       S.Diag(SubstDiag->DiagLoc,
911e5dd7070Spatrick              diag::note_type_requirement_substitution_error) << (int)First
912e5dd7070Spatrick           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
913e5dd7070Spatrick     else
914e5dd7070Spatrick       S.Diag(SubstDiag->DiagLoc,
915e5dd7070Spatrick              diag::note_type_requirement_unknown_substitution_error)
916e5dd7070Spatrick           << (int)First << SubstDiag->SubstitutedEntity;
917e5dd7070Spatrick     return;
918e5dd7070Spatrick   }
919e5dd7070Spatrick   default:
920e5dd7070Spatrick     llvm_unreachable("Unknown satisfaction status");
921e5dd7070Spatrick     return;
922e5dd7070Spatrick   }
923e5dd7070Spatrick }
924*12c85518Srobert static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
925*12c85518Srobert                                                         Expr *SubstExpr,
926*12c85518Srobert                                                         bool First = true);
927e5dd7070Spatrick 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::NestedRequirement * Req,bool First)928e5dd7070Spatrick static void diagnoseUnsatisfiedRequirement(Sema &S,
929e5dd7070Spatrick                                            concepts::NestedRequirement *Req,
930e5dd7070Spatrick                                            bool First) {
931*12c85518Srobert   using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
932*12c85518Srobert   for (auto &Pair : Req->getConstraintSatisfaction()) {
933*12c85518Srobert     if (auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
934*12c85518Srobert       S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
935*12c85518Srobert           << (int)First << Req->getInvalidConstraintEntity() << SubstDiag->second;
936e5dd7070Spatrick     else
937*12c85518Srobert       diagnoseWellFormedUnsatisfiedConstraintExpr(
938*12c85518Srobert           S, Pair.second.dyn_cast<Expr *>(), First);
939*12c85518Srobert     First = false;
940e5dd7070Spatrick   }
941e5dd7070Spatrick }
942e5dd7070Spatrick 
diagnoseWellFormedUnsatisfiedConstraintExpr(Sema & S,Expr * SubstExpr,bool First)943e5dd7070Spatrick static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
944e5dd7070Spatrick                                                         Expr *SubstExpr,
945*12c85518Srobert                                                         bool First) {
946e5dd7070Spatrick   SubstExpr = SubstExpr->IgnoreParenImpCasts();
947e5dd7070Spatrick   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
948e5dd7070Spatrick     switch (BO->getOpcode()) {
949e5dd7070Spatrick     // These two cases will in practice only be reached when using fold
950e5dd7070Spatrick     // expressions with || and &&, since otherwise the || and && will have been
951e5dd7070Spatrick     // broken down into atomic constraints during satisfaction checking.
952e5dd7070Spatrick     case BO_LOr:
953e5dd7070Spatrick       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
954e5dd7070Spatrick       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
955e5dd7070Spatrick       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
956e5dd7070Spatrick                                                   /*First=*/false);
957e5dd7070Spatrick       return;
958a9ac8606Spatrick     case BO_LAnd: {
959a9ac8606Spatrick       bool LHSSatisfied =
960a9ac8606Spatrick           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
961e5dd7070Spatrick       if (LHSSatisfied) {
962e5dd7070Spatrick         // LHS is true, so RHS must be false.
963e5dd7070Spatrick         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
964e5dd7070Spatrick         return;
965e5dd7070Spatrick       }
966e5dd7070Spatrick       // LHS is false
967e5dd7070Spatrick       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
968e5dd7070Spatrick 
969e5dd7070Spatrick       // RHS might also be false
970a9ac8606Spatrick       bool RHSSatisfied =
971a9ac8606Spatrick           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
972e5dd7070Spatrick       if (!RHSSatisfied)
973e5dd7070Spatrick         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
974e5dd7070Spatrick                                                     /*First=*/false);
975e5dd7070Spatrick       return;
976a9ac8606Spatrick     }
977e5dd7070Spatrick     case BO_GE:
978e5dd7070Spatrick     case BO_LE:
979e5dd7070Spatrick     case BO_GT:
980e5dd7070Spatrick     case BO_LT:
981e5dd7070Spatrick     case BO_EQ:
982e5dd7070Spatrick     case BO_NE:
983e5dd7070Spatrick       if (BO->getLHS()->getType()->isIntegerType() &&
984e5dd7070Spatrick           BO->getRHS()->getType()->isIntegerType()) {
985e5dd7070Spatrick         Expr::EvalResult SimplifiedLHS;
986e5dd7070Spatrick         Expr::EvalResult SimplifiedRHS;
987a9ac8606Spatrick         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
988a9ac8606Spatrick                                     Expr::SE_NoSideEffects,
989a9ac8606Spatrick                                     /*InConstantContext=*/true);
990a9ac8606Spatrick         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
991a9ac8606Spatrick                                     Expr::SE_NoSideEffects,
992a9ac8606Spatrick                                     /*InConstantContext=*/true);
993e5dd7070Spatrick         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
994e5dd7070Spatrick           S.Diag(SubstExpr->getBeginLoc(),
995e5dd7070Spatrick                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
996e5dd7070Spatrick               << (int)First << SubstExpr
997a9ac8606Spatrick               << toString(SimplifiedLHS.Val.getInt(), 10)
998e5dd7070Spatrick               << BinaryOperator::getOpcodeStr(BO->getOpcode())
999a9ac8606Spatrick               << toString(SimplifiedRHS.Val.getInt(), 10);
1000e5dd7070Spatrick           return;
1001e5dd7070Spatrick         }
1002e5dd7070Spatrick       }
1003e5dd7070Spatrick       break;
1004e5dd7070Spatrick 
1005e5dd7070Spatrick     default:
1006e5dd7070Spatrick       break;
1007e5dd7070Spatrick     }
1008e5dd7070Spatrick   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1009e5dd7070Spatrick     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1010e5dd7070Spatrick       S.Diag(
1011e5dd7070Spatrick           CSE->getSourceRange().getBegin(),
1012e5dd7070Spatrick           diag::
1013e5dd7070Spatrick           note_single_arg_concept_specialization_constraint_evaluated_to_false)
1014e5dd7070Spatrick           << (int)First
1015e5dd7070Spatrick           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1016e5dd7070Spatrick           << CSE->getNamedConcept();
1017e5dd7070Spatrick     } else {
1018e5dd7070Spatrick       S.Diag(SubstExpr->getSourceRange().getBegin(),
1019e5dd7070Spatrick              diag::note_concept_specialization_constraint_evaluated_to_false)
1020e5dd7070Spatrick           << (int)First << CSE;
1021e5dd7070Spatrick     }
1022e5dd7070Spatrick     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1023e5dd7070Spatrick     return;
1024e5dd7070Spatrick   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1025*12c85518Srobert     // FIXME: RequiresExpr should store dependent diagnostics.
1026e5dd7070Spatrick     for (concepts::Requirement *Req : RE->getRequirements())
1027e5dd7070Spatrick       if (!Req->isDependent() && !Req->isSatisfied()) {
1028e5dd7070Spatrick         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1029e5dd7070Spatrick           diagnoseUnsatisfiedRequirement(S, E, First);
1030e5dd7070Spatrick         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1031e5dd7070Spatrick           diagnoseUnsatisfiedRequirement(S, T, First);
1032e5dd7070Spatrick         else
1033e5dd7070Spatrick           diagnoseUnsatisfiedRequirement(
1034e5dd7070Spatrick               S, cast<concepts::NestedRequirement>(Req), First);
1035e5dd7070Spatrick         break;
1036e5dd7070Spatrick       }
1037e5dd7070Spatrick     return;
1038e5dd7070Spatrick   }
1039e5dd7070Spatrick 
1040e5dd7070Spatrick   S.Diag(SubstExpr->getSourceRange().getBegin(),
1041e5dd7070Spatrick          diag::note_atomic_constraint_evaluated_to_false)
1042e5dd7070Spatrick       << (int)First << SubstExpr;
1043e5dd7070Spatrick }
1044e5dd7070Spatrick 
1045e5dd7070Spatrick template<typename SubstitutionDiagnostic>
diagnoseUnsatisfiedConstraintExpr(Sema & S,const Expr * E,const llvm::PointerUnion<Expr *,SubstitutionDiagnostic * > & Record,bool First=true)1046e5dd7070Spatrick static void diagnoseUnsatisfiedConstraintExpr(
1047e5dd7070Spatrick     Sema &S, const Expr *E,
1048e5dd7070Spatrick     const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1049e5dd7070Spatrick     bool First = true) {
1050e5dd7070Spatrick   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
1051e5dd7070Spatrick     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1052e5dd7070Spatrick         << Diag->second;
1053e5dd7070Spatrick     return;
1054e5dd7070Spatrick   }
1055e5dd7070Spatrick 
1056e5dd7070Spatrick   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
1057e5dd7070Spatrick       Record.template get<Expr *>(), First);
1058e5dd7070Spatrick }
1059e5dd7070Spatrick 
1060e5dd7070Spatrick void
DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction & Satisfaction,bool First)1061e5dd7070Spatrick Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
1062e5dd7070Spatrick                                     bool First) {
1063e5dd7070Spatrick   assert(!Satisfaction.IsSatisfied &&
1064e5dd7070Spatrick          "Attempted to diagnose a satisfied constraint");
1065e5dd7070Spatrick   for (auto &Pair : Satisfaction.Details) {
1066e5dd7070Spatrick     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1067e5dd7070Spatrick     First = false;
1068e5dd7070Spatrick   }
1069e5dd7070Spatrick }
1070e5dd7070Spatrick 
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction & Satisfaction,bool First)1071e5dd7070Spatrick void Sema::DiagnoseUnsatisfiedConstraint(
1072e5dd7070Spatrick     const ASTConstraintSatisfaction &Satisfaction,
1073e5dd7070Spatrick     bool First) {
1074e5dd7070Spatrick   assert(!Satisfaction.IsSatisfied &&
1075e5dd7070Spatrick          "Attempted to diagnose a satisfied constraint");
1076e5dd7070Spatrick   for (auto &Pair : Satisfaction) {
1077e5dd7070Spatrick     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
1078e5dd7070Spatrick     First = false;
1079e5dd7070Spatrick   }
1080e5dd7070Spatrick }
1081e5dd7070Spatrick 
1082e5dd7070Spatrick const NormalizedConstraint *
getNormalizedAssociatedConstraints(NamedDecl * ConstrainedDecl,ArrayRef<const Expr * > AssociatedConstraints)1083e5dd7070Spatrick Sema::getNormalizedAssociatedConstraints(
1084e5dd7070Spatrick     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
1085e5dd7070Spatrick   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1086e5dd7070Spatrick   if (CacheEntry == NormalizationCache.end()) {
1087e5dd7070Spatrick     auto Normalized =
1088e5dd7070Spatrick         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
1089e5dd7070Spatrick                                                   AssociatedConstraints);
1090e5dd7070Spatrick     CacheEntry =
1091e5dd7070Spatrick         NormalizationCache
1092e5dd7070Spatrick             .try_emplace(ConstrainedDecl,
1093e5dd7070Spatrick                          Normalized
1094e5dd7070Spatrick                              ? new (Context) NormalizedConstraint(
1095e5dd7070Spatrick                                  std::move(*Normalized))
1096e5dd7070Spatrick                              : nullptr)
1097e5dd7070Spatrick             .first;
1098e5dd7070Spatrick   }
1099e5dd7070Spatrick   return CacheEntry->second;
1100e5dd7070Spatrick }
1101e5dd7070Spatrick 
1102*12c85518Srobert static bool
substituteParameterMappings(Sema & S,NormalizedConstraint & N,ConceptDecl * Concept,const MultiLevelTemplateArgumentList & MLTAL,const ASTTemplateArgumentListInfo * ArgsAsWritten)1103*12c85518Srobert substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1104*12c85518Srobert                             ConceptDecl *Concept,
1105*12c85518Srobert                             const MultiLevelTemplateArgumentList &MLTAL,
1106e5dd7070Spatrick                             const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1107e5dd7070Spatrick   if (!N.isAtomic()) {
1108*12c85518Srobert     if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1109e5dd7070Spatrick                                     ArgsAsWritten))
1110e5dd7070Spatrick       return true;
1111*12c85518Srobert     return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1112e5dd7070Spatrick                                        ArgsAsWritten);
1113e5dd7070Spatrick   }
1114e5dd7070Spatrick   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1115e5dd7070Spatrick 
1116e5dd7070Spatrick   AtomicConstraint &Atomic = *N.getAtomicConstraint();
1117e5dd7070Spatrick   TemplateArgumentListInfo SubstArgs;
1118e5dd7070Spatrick   if (!Atomic.ParameterMapping) {
1119e5dd7070Spatrick     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1120e5dd7070Spatrick     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1121e5dd7070Spatrick                                  /*Depth=*/0, OccurringIndices);
1122*12c85518Srobert     TemplateArgumentLoc *TempArgs =
1123*12c85518Srobert         new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1124e5dd7070Spatrick     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1125e5dd7070Spatrick       if (OccurringIndices[I])
1126*12c85518Srobert         new (&(TempArgs)[J++])
1127*12c85518Srobert             TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(
1128*12c85518Srobert                 TemplateParams->begin()[I],
1129e5dd7070Spatrick                 // Here we assume we do not support things like
1130e5dd7070Spatrick                 // template<typename A, typename B>
1131e5dd7070Spatrick                 // concept C = ...;
1132e5dd7070Spatrick                 //
1133e5dd7070Spatrick                 // template<typename... Ts> requires C<Ts...>
1134e5dd7070Spatrick                 // struct S { };
1135e5dd7070Spatrick                 // The above currently yields a diagnostic.
1136e5dd7070Spatrick                 // We still might have default arguments for concept parameters.
1137*12c85518Srobert                 ArgsAsWritten->NumTemplateArgs > I
1138*12c85518Srobert                     ? ArgsAsWritten->arguments()[I].getLocation()
1139*12c85518Srobert                     : SourceLocation()));
1140*12c85518Srobert     Atomic.ParameterMapping.emplace(TempArgs,  OccurringIndices.count());
1141e5dd7070Spatrick   }
1142e5dd7070Spatrick   Sema::InstantiatingTemplate Inst(
1143e5dd7070Spatrick       S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
1144e5dd7070Spatrick       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
1145*12c85518Srobert       ArgsAsWritten->arguments().front().getSourceRange());
1146e5dd7070Spatrick   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1147e5dd7070Spatrick     return true;
1148*12c85518Srobert 
1149*12c85518Srobert   TemplateArgumentLoc *TempArgs =
1150*12c85518Srobert       new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1151e5dd7070Spatrick   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1152*12c85518Srobert             TempArgs);
1153*12c85518Srobert   Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1154e5dd7070Spatrick   return false;
1155e5dd7070Spatrick }
1156e5dd7070Spatrick 
substituteParameterMappings(Sema & S,NormalizedConstraint & N,const ConceptSpecializationExpr * CSE)1157*12c85518Srobert static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1158*12c85518Srobert                                         const ConceptSpecializationExpr *CSE) {
1159*12c85518Srobert   TemplateArgumentList TAL{TemplateArgumentList::OnStack,
1160*12c85518Srobert                            CSE->getTemplateArguments()};
1161*12c85518Srobert   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
1162*12c85518Srobert       CSE->getNamedConcept(), /*Final=*/false, &TAL,
1163*12c85518Srobert       /*RelativeToPrimary=*/true,
1164*12c85518Srobert       /*Pattern=*/nullptr,
1165*12c85518Srobert       /*ForConstraintInstantiation=*/true);
1166*12c85518Srobert 
1167*12c85518Srobert   return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1168*12c85518Srobert                                      CSE->getTemplateArgsAsWritten());
1169*12c85518Srobert }
1170*12c85518Srobert 
1171*12c85518Srobert std::optional<NormalizedConstraint>
fromConstraintExprs(Sema & S,NamedDecl * D,ArrayRef<const Expr * > E)1172e5dd7070Spatrick NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
1173e5dd7070Spatrick                                           ArrayRef<const Expr *> E) {
1174e5dd7070Spatrick   assert(E.size() != 0);
1175a9ac8606Spatrick   auto Conjunction = fromConstraintExpr(S, D, E[0]);
1176a9ac8606Spatrick   if (!Conjunction)
1177*12c85518Srobert     return std::nullopt;
1178a9ac8606Spatrick   for (unsigned I = 1; I < E.size(); ++I) {
1179e5dd7070Spatrick     auto Next = fromConstraintExpr(S, D, E[I]);
1180e5dd7070Spatrick     if (!Next)
1181*12c85518Srobert       return std::nullopt;
1182a9ac8606Spatrick     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1183e5dd7070Spatrick                                         std::move(*Next), CCK_Conjunction);
1184e5dd7070Spatrick   }
1185e5dd7070Spatrick   return Conjunction;
1186e5dd7070Spatrick }
1187e5dd7070Spatrick 
1188*12c85518Srobert std::optional<NormalizedConstraint>
fromConstraintExpr(Sema & S,NamedDecl * D,const Expr * E)1189e5dd7070Spatrick NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
1190e5dd7070Spatrick   assert(E != nullptr);
1191e5dd7070Spatrick 
1192e5dd7070Spatrick   // C++ [temp.constr.normal]p1.1
1193e5dd7070Spatrick   // [...]
1194e5dd7070Spatrick   // - The normal form of an expression (E) is the normal form of E.
1195e5dd7070Spatrick   // [...]
1196e5dd7070Spatrick   E = E->IgnoreParenImpCasts();
1197*12c85518Srobert 
1198*12c85518Srobert   // C++2a [temp.param]p4:
1199*12c85518Srobert   //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1200*12c85518Srobert   // Fold expression is considered atomic constraints per current wording.
1201*12c85518Srobert   // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1202*12c85518Srobert 
1203ec727ea7Spatrick   if (LogicalBinOp BO = E) {
1204ec727ea7Spatrick     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1205e5dd7070Spatrick     if (!LHS)
1206*12c85518Srobert       return std::nullopt;
1207ec727ea7Spatrick     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1208e5dd7070Spatrick     if (!RHS)
1209*12c85518Srobert       return std::nullopt;
1210e5dd7070Spatrick 
1211ec727ea7Spatrick     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
1212ec727ea7Spatrick                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1213e5dd7070Spatrick   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1214e5dd7070Spatrick     const NormalizedConstraint *SubNF;
1215e5dd7070Spatrick     {
1216e5dd7070Spatrick       Sema::InstantiatingTemplate Inst(
1217e5dd7070Spatrick           S, CSE->getExprLoc(),
1218e5dd7070Spatrick           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
1219e5dd7070Spatrick           CSE->getSourceRange());
1220e5dd7070Spatrick       // C++ [temp.constr.normal]p1.1
1221e5dd7070Spatrick       // [...]
1222e5dd7070Spatrick       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1223e5dd7070Spatrick       // where C names a concept, is the normal form of the
1224e5dd7070Spatrick       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1225e5dd7070Spatrick       // respective template parameters in the parameter mappings in each atomic
1226e5dd7070Spatrick       // constraint. If any such substitution results in an invalid type or
1227e5dd7070Spatrick       // expression, the program is ill-formed; no diagnostic is required.
1228e5dd7070Spatrick       // [...]
1229e5dd7070Spatrick       ConceptDecl *CD = CSE->getNamedConcept();
1230e5dd7070Spatrick       SubNF = S.getNormalizedAssociatedConstraints(CD,
1231e5dd7070Spatrick                                                    {CD->getConstraintExpr()});
1232e5dd7070Spatrick       if (!SubNF)
1233*12c85518Srobert         return std::nullopt;
1234e5dd7070Spatrick     }
1235e5dd7070Spatrick 
1236*12c85518Srobert     std::optional<NormalizedConstraint> New;
1237e5dd7070Spatrick     New.emplace(S.Context, *SubNF);
1238e5dd7070Spatrick 
1239*12c85518Srobert     if (substituteParameterMappings(S, *New, CSE))
1240*12c85518Srobert       return std::nullopt;
1241e5dd7070Spatrick 
1242e5dd7070Spatrick     return New;
1243e5dd7070Spatrick   }
1244e5dd7070Spatrick   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
1245e5dd7070Spatrick }
1246e5dd7070Spatrick 
1247e5dd7070Spatrick using NormalForm =
1248e5dd7070Spatrick     llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
1249e5dd7070Spatrick 
makeCNF(const NormalizedConstraint & Normalized)1250e5dd7070Spatrick static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
1251e5dd7070Spatrick   if (Normalized.isAtomic())
1252e5dd7070Spatrick     return {{Normalized.getAtomicConstraint()}};
1253e5dd7070Spatrick 
1254e5dd7070Spatrick   NormalForm LCNF = makeCNF(Normalized.getLHS());
1255e5dd7070Spatrick   NormalForm RCNF = makeCNF(Normalized.getRHS());
1256e5dd7070Spatrick   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
1257e5dd7070Spatrick     LCNF.reserve(LCNF.size() + RCNF.size());
1258e5dd7070Spatrick     while (!RCNF.empty())
1259e5dd7070Spatrick       LCNF.push_back(RCNF.pop_back_val());
1260e5dd7070Spatrick     return LCNF;
1261e5dd7070Spatrick   }
1262e5dd7070Spatrick 
1263e5dd7070Spatrick   // Disjunction
1264e5dd7070Spatrick   NormalForm Res;
1265e5dd7070Spatrick   Res.reserve(LCNF.size() * RCNF.size());
1266e5dd7070Spatrick   for (auto &LDisjunction : LCNF)
1267e5dd7070Spatrick     for (auto &RDisjunction : RCNF) {
1268e5dd7070Spatrick       NormalForm::value_type Combined;
1269e5dd7070Spatrick       Combined.reserve(LDisjunction.size() + RDisjunction.size());
1270e5dd7070Spatrick       std::copy(LDisjunction.begin(), LDisjunction.end(),
1271e5dd7070Spatrick                 std::back_inserter(Combined));
1272e5dd7070Spatrick       std::copy(RDisjunction.begin(), RDisjunction.end(),
1273e5dd7070Spatrick                 std::back_inserter(Combined));
1274e5dd7070Spatrick       Res.emplace_back(Combined);
1275e5dd7070Spatrick     }
1276e5dd7070Spatrick   return Res;
1277e5dd7070Spatrick }
1278e5dd7070Spatrick 
makeDNF(const NormalizedConstraint & Normalized)1279e5dd7070Spatrick static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
1280e5dd7070Spatrick   if (Normalized.isAtomic())
1281e5dd7070Spatrick     return {{Normalized.getAtomicConstraint()}};
1282e5dd7070Spatrick 
1283e5dd7070Spatrick   NormalForm LDNF = makeDNF(Normalized.getLHS());
1284e5dd7070Spatrick   NormalForm RDNF = makeDNF(Normalized.getRHS());
1285e5dd7070Spatrick   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
1286e5dd7070Spatrick     LDNF.reserve(LDNF.size() + RDNF.size());
1287e5dd7070Spatrick     while (!RDNF.empty())
1288e5dd7070Spatrick       LDNF.push_back(RDNF.pop_back_val());
1289e5dd7070Spatrick     return LDNF;
1290e5dd7070Spatrick   }
1291e5dd7070Spatrick 
1292e5dd7070Spatrick   // Conjunction
1293e5dd7070Spatrick   NormalForm Res;
1294e5dd7070Spatrick   Res.reserve(LDNF.size() * RDNF.size());
1295e5dd7070Spatrick   for (auto &LConjunction : LDNF) {
1296e5dd7070Spatrick     for (auto &RConjunction : RDNF) {
1297e5dd7070Spatrick       NormalForm::value_type Combined;
1298e5dd7070Spatrick       Combined.reserve(LConjunction.size() + RConjunction.size());
1299e5dd7070Spatrick       std::copy(LConjunction.begin(), LConjunction.end(),
1300e5dd7070Spatrick                 std::back_inserter(Combined));
1301e5dd7070Spatrick       std::copy(RConjunction.begin(), RConjunction.end(),
1302e5dd7070Spatrick                 std::back_inserter(Combined));
1303e5dd7070Spatrick       Res.emplace_back(Combined);
1304e5dd7070Spatrick     }
1305e5dd7070Spatrick   }
1306e5dd7070Spatrick   return Res;
1307e5dd7070Spatrick }
1308e5dd7070Spatrick 
1309e5dd7070Spatrick template<typename AtomicSubsumptionEvaluator>
subsumes(NormalForm PDNF,NormalForm QCNF,AtomicSubsumptionEvaluator E)1310e5dd7070Spatrick static bool subsumes(NormalForm PDNF, NormalForm QCNF,
1311e5dd7070Spatrick                      AtomicSubsumptionEvaluator E) {
1312e5dd7070Spatrick   // C++ [temp.constr.order] p2
1313e5dd7070Spatrick   //   Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
1314e5dd7070Spatrick   //   disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
1315e5dd7070Spatrick   //   the conjuctive normal form of Q, where [...]
1316e5dd7070Spatrick   for (const auto &Pi : PDNF) {
1317e5dd7070Spatrick     for (const auto &Qj : QCNF) {
1318e5dd7070Spatrick       // C++ [temp.constr.order] p2
1319e5dd7070Spatrick       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
1320e5dd7070Spatrick       //     and only if there exists an atomic constraint Pia in Pi for which
1321e5dd7070Spatrick       //     there exists an atomic constraint, Qjb, in Qj such that Pia
1322e5dd7070Spatrick       //     subsumes Qjb.
1323e5dd7070Spatrick       bool Found = false;
1324e5dd7070Spatrick       for (const AtomicConstraint *Pia : Pi) {
1325e5dd7070Spatrick         for (const AtomicConstraint *Qjb : Qj) {
1326e5dd7070Spatrick           if (E(*Pia, *Qjb)) {
1327e5dd7070Spatrick             Found = true;
1328e5dd7070Spatrick             break;
1329e5dd7070Spatrick           }
1330e5dd7070Spatrick         }
1331e5dd7070Spatrick         if (Found)
1332e5dd7070Spatrick           break;
1333e5dd7070Spatrick       }
1334e5dd7070Spatrick       if (!Found)
1335e5dd7070Spatrick         return false;
1336e5dd7070Spatrick     }
1337e5dd7070Spatrick   }
1338e5dd7070Spatrick   return true;
1339e5dd7070Spatrick }
1340e5dd7070Spatrick 
1341e5dd7070Spatrick template<typename AtomicSubsumptionEvaluator>
subsumes(Sema & S,NamedDecl * DP,ArrayRef<const Expr * > P,NamedDecl * DQ,ArrayRef<const Expr * > Q,bool & Subsumes,AtomicSubsumptionEvaluator E)1342e5dd7070Spatrick static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
1343e5dd7070Spatrick                      NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
1344e5dd7070Spatrick                      AtomicSubsumptionEvaluator E) {
1345e5dd7070Spatrick   // C++ [temp.constr.order] p2
1346e5dd7070Spatrick   //   In order to determine if a constraint P subsumes a constraint Q, P is
1347e5dd7070Spatrick   //   transformed into disjunctive normal form, and Q is transformed into
1348e5dd7070Spatrick   //   conjunctive normal form. [...]
1349e5dd7070Spatrick   auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
1350e5dd7070Spatrick   if (!PNormalized)
1351e5dd7070Spatrick     return true;
1352e5dd7070Spatrick   const NormalForm PDNF = makeDNF(*PNormalized);
1353e5dd7070Spatrick 
1354e5dd7070Spatrick   auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
1355e5dd7070Spatrick   if (!QNormalized)
1356e5dd7070Spatrick     return true;
1357e5dd7070Spatrick   const NormalForm QCNF = makeCNF(*QNormalized);
1358e5dd7070Spatrick 
1359e5dd7070Spatrick   Subsumes = subsumes(PDNF, QCNF, E);
1360e5dd7070Spatrick   return false;
1361e5dd7070Spatrick }
1362e5dd7070Spatrick 
IsAtLeastAsConstrained(NamedDecl * D1,MutableArrayRef<const Expr * > AC1,NamedDecl * D2,MutableArrayRef<const Expr * > AC2,bool & Result)1363*12c85518Srobert bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
1364*12c85518Srobert                                   MutableArrayRef<const Expr *> AC1,
1365*12c85518Srobert                                   NamedDecl *D2,
1366*12c85518Srobert                                   MutableArrayRef<const Expr *> AC2,
1367e5dd7070Spatrick                                   bool &Result) {
1368*12c85518Srobert   if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1369*12c85518Srobert     auto IsExpectedEntity = [](const FunctionDecl *FD) {
1370*12c85518Srobert       FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
1371*12c85518Srobert       return Kind == FunctionDecl::TK_NonTemplate ||
1372*12c85518Srobert              Kind == FunctionDecl::TK_FunctionTemplate;
1373*12c85518Srobert     };
1374*12c85518Srobert     const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1375*12c85518Srobert     (void)IsExpectedEntity;
1376*12c85518Srobert     (void)FD1;
1377*12c85518Srobert     (void)FD2;
1378*12c85518Srobert     assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1379*12c85518Srobert            "use non-instantiated function declaration for constraints partial "
1380*12c85518Srobert            "ordering");
1381*12c85518Srobert   }
1382*12c85518Srobert 
1383e5dd7070Spatrick   if (AC1.empty()) {
1384e5dd7070Spatrick     Result = AC2.empty();
1385e5dd7070Spatrick     return false;
1386e5dd7070Spatrick   }
1387e5dd7070Spatrick   if (AC2.empty()) {
1388e5dd7070Spatrick     // TD1 has associated constraints and TD2 does not.
1389e5dd7070Spatrick     Result = true;
1390e5dd7070Spatrick     return false;
1391e5dd7070Spatrick   }
1392e5dd7070Spatrick 
1393e5dd7070Spatrick   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1394e5dd7070Spatrick   auto CacheEntry = SubsumptionCache.find(Key);
1395e5dd7070Spatrick   if (CacheEntry != SubsumptionCache.end()) {
1396e5dd7070Spatrick     Result = CacheEntry->second;
1397e5dd7070Spatrick     return false;
1398e5dd7070Spatrick   }
1399e5dd7070Spatrick 
1400*12c85518Srobert   unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1401*12c85518Srobert   unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1402*12c85518Srobert 
1403*12c85518Srobert   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1404*12c85518Srobert     if (Depth2 > Depth1) {
1405*12c85518Srobert       AC1[I] = AdjustConstraintDepth(*this, Depth2 - Depth1)
1406*12c85518Srobert                    .TransformExpr(const_cast<Expr *>(AC1[I]))
1407*12c85518Srobert                    .get();
1408*12c85518Srobert     } else if (Depth1 > Depth2) {
1409*12c85518Srobert       AC2[I] = AdjustConstraintDepth(*this, Depth1 - Depth2)
1410*12c85518Srobert                    .TransformExpr(const_cast<Expr *>(AC2[I]))
1411*12c85518Srobert                    .get();
1412*12c85518Srobert     }
1413*12c85518Srobert   }
1414*12c85518Srobert 
1415e5dd7070Spatrick   if (subsumes(*this, D1, AC1, D2, AC2, Result,
1416e5dd7070Spatrick         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1417e5dd7070Spatrick           return A.subsumes(Context, B);
1418e5dd7070Spatrick         }))
1419e5dd7070Spatrick     return true;
1420e5dd7070Spatrick   SubsumptionCache.try_emplace(Key, Result);
1421e5dd7070Spatrick   return false;
1422e5dd7070Spatrick }
1423e5dd7070Spatrick 
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl * D1,ArrayRef<const Expr * > AC1,NamedDecl * D2,ArrayRef<const Expr * > AC2)1424e5dd7070Spatrick bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
1425e5dd7070Spatrick     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
1426e5dd7070Spatrick   if (isSFINAEContext())
1427e5dd7070Spatrick     // No need to work here because our notes would be discarded.
1428e5dd7070Spatrick     return false;
1429e5dd7070Spatrick 
1430e5dd7070Spatrick   if (AC1.empty() || AC2.empty())
1431e5dd7070Spatrick     return false;
1432e5dd7070Spatrick 
1433e5dd7070Spatrick   auto NormalExprEvaluator =
1434e5dd7070Spatrick       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1435e5dd7070Spatrick         return A.subsumes(Context, B);
1436e5dd7070Spatrick       };
1437e5dd7070Spatrick 
1438e5dd7070Spatrick   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1439e5dd7070Spatrick   auto IdenticalExprEvaluator =
1440e5dd7070Spatrick       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1441e5dd7070Spatrick         if (!A.hasMatchingParameterMapping(Context, B))
1442e5dd7070Spatrick           return false;
1443e5dd7070Spatrick         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1444e5dd7070Spatrick         if (EA == EB)
1445e5dd7070Spatrick           return true;
1446e5dd7070Spatrick 
1447e5dd7070Spatrick         // Not the same source level expression - are the expressions
1448e5dd7070Spatrick         // identical?
1449e5dd7070Spatrick         llvm::FoldingSetNodeID IDA, IDB;
1450*12c85518Srobert         EA->Profile(IDA, Context, /*Canonical=*/true);
1451*12c85518Srobert         EB->Profile(IDB, Context, /*Canonical=*/true);
1452e5dd7070Spatrick         if (IDA != IDB)
1453e5dd7070Spatrick           return false;
1454e5dd7070Spatrick 
1455e5dd7070Spatrick         AmbiguousAtomic1 = EA;
1456e5dd7070Spatrick         AmbiguousAtomic2 = EB;
1457e5dd7070Spatrick         return true;
1458e5dd7070Spatrick       };
1459e5dd7070Spatrick 
1460e5dd7070Spatrick   {
1461e5dd7070Spatrick     // The subsumption checks might cause diagnostics
1462e5dd7070Spatrick     SFINAETrap Trap(*this);
1463e5dd7070Spatrick     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1464e5dd7070Spatrick     if (!Normalized1)
1465e5dd7070Spatrick       return false;
1466e5dd7070Spatrick     const NormalForm DNF1 = makeDNF(*Normalized1);
1467e5dd7070Spatrick     const NormalForm CNF1 = makeCNF(*Normalized1);
1468e5dd7070Spatrick 
1469e5dd7070Spatrick     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1470e5dd7070Spatrick     if (!Normalized2)
1471e5dd7070Spatrick       return false;
1472e5dd7070Spatrick     const NormalForm DNF2 = makeDNF(*Normalized2);
1473e5dd7070Spatrick     const NormalForm CNF2 = makeCNF(*Normalized2);
1474e5dd7070Spatrick 
1475e5dd7070Spatrick     bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1476e5dd7070Spatrick     bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1477e5dd7070Spatrick     bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1478e5dd7070Spatrick     bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1479e5dd7070Spatrick     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1480e5dd7070Spatrick         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1481e5dd7070Spatrick       // Same result - no ambiguity was caused by identical atomic expressions.
1482e5dd7070Spatrick       return false;
1483e5dd7070Spatrick   }
1484e5dd7070Spatrick 
1485e5dd7070Spatrick   // A different result! Some ambiguous atomic constraint(s) caused a difference
1486e5dd7070Spatrick   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1487e5dd7070Spatrick 
1488e5dd7070Spatrick   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1489e5dd7070Spatrick       << AmbiguousAtomic1->getSourceRange();
1490e5dd7070Spatrick   Diag(AmbiguousAtomic2->getBeginLoc(),
1491e5dd7070Spatrick        diag::note_ambiguous_atomic_constraints_similar_expression)
1492e5dd7070Spatrick       << AmbiguousAtomic2->getSourceRange();
1493e5dd7070Spatrick   return true;
1494e5dd7070Spatrick }
1495e5dd7070Spatrick 
ExprRequirement(Expr * E,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req,SatisfactionStatus Status,ConceptSpecializationExpr * SubstitutedConstraintExpr)1496e5dd7070Spatrick concepts::ExprRequirement::ExprRequirement(
1497e5dd7070Spatrick     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1498e5dd7070Spatrick     ReturnTypeRequirement Req, SatisfactionStatus Status,
1499e5dd7070Spatrick     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1500e5dd7070Spatrick     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1501e5dd7070Spatrick                 Status == SS_Dependent &&
1502e5dd7070Spatrick                 (E->containsUnexpandedParameterPack() ||
1503e5dd7070Spatrick                  Req.containsUnexpandedParameterPack()),
1504e5dd7070Spatrick                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1505e5dd7070Spatrick     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1506e5dd7070Spatrick     Status(Status) {
1507e5dd7070Spatrick   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1508e5dd7070Spatrick          "Simple requirement must not have a return type requirement or a "
1509e5dd7070Spatrick          "noexcept specification");
1510e5dd7070Spatrick   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1511e5dd7070Spatrick          (SubstitutedConstraintExpr != nullptr));
1512e5dd7070Spatrick }
1513e5dd7070Spatrick 
ExprRequirement(SubstitutionDiagnostic * ExprSubstDiag,bool IsSimple,SourceLocation NoexceptLoc,ReturnTypeRequirement Req)1514e5dd7070Spatrick concepts::ExprRequirement::ExprRequirement(
1515e5dd7070Spatrick     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1516e5dd7070Spatrick     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1517e5dd7070Spatrick     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1518e5dd7070Spatrick                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1519e5dd7070Spatrick     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1520e5dd7070Spatrick     Status(SS_ExprSubstitutionFailure) {
1521e5dd7070Spatrick   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1522e5dd7070Spatrick          "Simple requirement must not have a return type requirement or a "
1523e5dd7070Spatrick          "noexcept specification");
1524e5dd7070Spatrick }
1525e5dd7070Spatrick 
1526e5dd7070Spatrick concepts::ExprRequirement::ReturnTypeRequirement::
ReturnTypeRequirement(TemplateParameterList * TPL)1527e5dd7070Spatrick ReturnTypeRequirement(TemplateParameterList *TPL) :
1528*12c85518Srobert     TypeConstraintInfo(TPL, false) {
1529e5dd7070Spatrick   assert(TPL->size() == 1);
1530e5dd7070Spatrick   const TypeConstraint *TC =
1531e5dd7070Spatrick       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1532e5dd7070Spatrick   assert(TC &&
1533e5dd7070Spatrick          "TPL must have a template type parameter with a type constraint");
1534e5dd7070Spatrick   auto *Constraint =
1535*12c85518Srobert       cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1536a9ac8606Spatrick   bool Dependent =
1537a9ac8606Spatrick       Constraint->getTemplateArgsAsWritten() &&
1538a9ac8606Spatrick       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1539a9ac8606Spatrick           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1540*12c85518Srobert   TypeConstraintInfo.setInt(Dependent ? true : false);
1541e5dd7070Spatrick }
1542e5dd7070Spatrick 
TypeRequirement(TypeSourceInfo * T)1543e5dd7070Spatrick concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1544a9ac8606Spatrick     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1545e5dd7070Spatrick                 T->getType()->containsUnexpandedParameterPack(),
1546e5dd7070Spatrick                 // We reach this ctor with either dependent types (in which
1547e5dd7070Spatrick                 // IsSatisfied doesn't matter) or with non-dependent type in
1548e5dd7070Spatrick                 // which the existence of the type indicates satisfaction.
1549a9ac8606Spatrick                 /*IsSatisfied=*/true),
1550a9ac8606Spatrick     Value(T),
1551a9ac8606Spatrick     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1552a9ac8606Spatrick                                                         : SS_Satisfied) {}
1553