xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2a7dea167SDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric //
9a7dea167SDimitry Andric //  This file implements semantic analysis for C++ constraints and concepts.
10a7dea167SDimitry Andric //
11a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
12a7dea167SDimitry Andric 
13480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h"
14a7dea167SDimitry Andric #include "clang/Sema/Sema.h"
15480093f4SDimitry Andric #include "clang/Sema/SemaInternal.h"
16a7dea167SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
17a7dea167SDimitry Andric #include "clang/Sema/TemplateDeduction.h"
18a7dea167SDimitry Andric #include "clang/Sema/Template.h"
1955e4f9d5SDimitry Andric #include "clang/Sema/Overload.h"
2055e4f9d5SDimitry Andric #include "clang/Sema/Initialization.h"
2155e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h"
22480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
23480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h"
24480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h"
25480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h"
26fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
27fe6060f1SDimitry Andric 
28a7dea167SDimitry Andric using namespace clang;
29a7dea167SDimitry Andric using namespace sema;
30a7dea167SDimitry Andric 
315ffd83dbSDimitry Andric namespace {
325ffd83dbSDimitry Andric class LogicalBinOp {
335ffd83dbSDimitry Andric   OverloadedOperatorKind Op = OO_None;
345ffd83dbSDimitry Andric   const Expr *LHS = nullptr;
355ffd83dbSDimitry Andric   const Expr *RHS = nullptr;
365ffd83dbSDimitry Andric 
375ffd83dbSDimitry Andric public:
385ffd83dbSDimitry Andric   LogicalBinOp(const Expr *E) {
395ffd83dbSDimitry Andric     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
405ffd83dbSDimitry Andric       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
415ffd83dbSDimitry Andric       LHS = BO->getLHS();
425ffd83dbSDimitry Andric       RHS = BO->getRHS();
435ffd83dbSDimitry Andric     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
44fe6060f1SDimitry Andric       // If OO is not || or && it might not have exactly 2 arguments.
45fe6060f1SDimitry Andric       if (OO->getNumArgs() == 2) {
465ffd83dbSDimitry Andric         Op = OO->getOperator();
475ffd83dbSDimitry Andric         LHS = OO->getArg(0);
485ffd83dbSDimitry Andric         RHS = OO->getArg(1);
495ffd83dbSDimitry Andric       }
505ffd83dbSDimitry Andric     }
51fe6060f1SDimitry Andric   }
525ffd83dbSDimitry Andric 
535ffd83dbSDimitry Andric   bool isAnd() const { return Op == OO_AmpAmp; }
545ffd83dbSDimitry Andric   bool isOr() const { return Op == OO_PipePipe; }
555ffd83dbSDimitry Andric   explicit operator bool() const { return isAnd() || isOr(); }
565ffd83dbSDimitry Andric 
575ffd83dbSDimitry Andric   const Expr *getLHS() const { return LHS; }
585ffd83dbSDimitry Andric   const Expr *getRHS() const { return RHS; }
595ffd83dbSDimitry Andric };
605ffd83dbSDimitry Andric }
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
635ffd83dbSDimitry Andric                                      Token NextToken, bool *PossibleNonPrimary,
64480093f4SDimitry Andric                                      bool IsTrailingRequiresClause) {
65a7dea167SDimitry Andric   // C++2a [temp.constr.atomic]p1
66a7dea167SDimitry Andric   // ..E shall be a constant expression of type bool.
67a7dea167SDimitry Andric 
68a7dea167SDimitry Andric   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
69a7dea167SDimitry Andric 
705ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpression) {
715ffd83dbSDimitry Andric     return CheckConstraintExpression(BO.getLHS(), NextToken,
72480093f4SDimitry Andric                                      PossibleNonPrimary) &&
735ffd83dbSDimitry Andric            CheckConstraintExpression(BO.getRHS(), NextToken,
74480093f4SDimitry Andric                                      PossibleNonPrimary);
75a7dea167SDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
76480093f4SDimitry Andric     return CheckConstraintExpression(C->getSubExpr(), NextToken,
77480093f4SDimitry Andric                                      PossibleNonPrimary);
78a7dea167SDimitry Andric 
79a7dea167SDimitry Andric   QualType Type = ConstraintExpression->getType();
80480093f4SDimitry Andric 
81480093f4SDimitry Andric   auto CheckForNonPrimary = [&] {
82480093f4SDimitry Andric     if (PossibleNonPrimary)
83480093f4SDimitry Andric       *PossibleNonPrimary =
84480093f4SDimitry Andric           // We have the following case:
85480093f4SDimitry Andric           // template<typename> requires func(0) struct S { };
86480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
87480093f4SDimitry Andric           // the function call, and we're only going to parse 'func' as the
88480093f4SDimitry Andric           // primary-expression, and complain that it is of non-bool type.
89480093f4SDimitry Andric           (NextToken.is(tok::l_paren) &&
90480093f4SDimitry Andric            (IsTrailingRequiresClause ||
91480093f4SDimitry Andric             (Type->isDependentType() &&
925ffd83dbSDimitry Andric              isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
93480093f4SDimitry Andric             Type->isFunctionType() ||
94480093f4SDimitry Andric             Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
95480093f4SDimitry Andric           // We have the following case:
96480093f4SDimitry Andric           // template<typename T> requires size_<T> == 0 struct S { };
97480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
98480093f4SDimitry Andric           // the binary operator, and we're only going to parse 'func' as the
99480093f4SDimitry Andric           // first operand, and complain that it is of non-bool type.
100480093f4SDimitry Andric           getBinOpPrecedence(NextToken.getKind(),
101480093f4SDimitry Andric                              /*GreaterThanIsOperator=*/true,
102480093f4SDimitry Andric                              getLangOpts().CPlusPlus11) > prec::LogicalAnd;
103480093f4SDimitry Andric   };
104480093f4SDimitry Andric 
105480093f4SDimitry Andric   // An atomic constraint!
106480093f4SDimitry Andric   if (ConstraintExpression->isTypeDependent()) {
107480093f4SDimitry Andric     CheckForNonPrimary();
108480093f4SDimitry Andric     return true;
109480093f4SDimitry Andric   }
110480093f4SDimitry Andric 
111a7dea167SDimitry Andric   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
112a7dea167SDimitry Andric     Diag(ConstraintExpression->getExprLoc(),
113a7dea167SDimitry Andric          diag::err_non_bool_atomic_constraint) << Type
114a7dea167SDimitry Andric         << ConstraintExpression->getSourceRange();
115480093f4SDimitry Andric     CheckForNonPrimary();
116a7dea167SDimitry Andric     return false;
117a7dea167SDimitry Andric   }
118480093f4SDimitry Andric 
119480093f4SDimitry Andric   if (PossibleNonPrimary)
120480093f4SDimitry Andric       *PossibleNonPrimary = false;
121a7dea167SDimitry Andric   return true;
122a7dea167SDimitry Andric }
123a7dea167SDimitry Andric 
124480093f4SDimitry Andric template <typename AtomicEvaluator>
125480093f4SDimitry Andric static bool
126480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
127480093f4SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
128480093f4SDimitry Andric                                 AtomicEvaluator &&Evaluator) {
129a7dea167SDimitry Andric   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
130a7dea167SDimitry Andric 
1315ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpr) {
1325ffd83dbSDimitry Andric     if (calculateConstraintSatisfaction(S, BO.getLHS(), Satisfaction,
133480093f4SDimitry Andric                                         Evaluator))
134a7dea167SDimitry Andric       return true;
135480093f4SDimitry Andric 
136480093f4SDimitry Andric     bool IsLHSSatisfied = Satisfaction.IsSatisfied;
137480093f4SDimitry Andric 
1385ffd83dbSDimitry Andric     if (BO.isOr() && IsLHSSatisfied)
139480093f4SDimitry Andric       // [temp.constr.op] p3
140480093f4SDimitry Andric       //    A disjunction is a constraint taking two operands. To determine if
141480093f4SDimitry Andric       //    a disjunction is satisfied, the satisfaction of the first operand
142480093f4SDimitry Andric       //    is checked. If that is satisfied, the disjunction is satisfied.
143480093f4SDimitry Andric       //    Otherwise, the disjunction is satisfied if and only if the second
144480093f4SDimitry Andric       //    operand is satisfied.
145a7dea167SDimitry Andric       return false;
146480093f4SDimitry Andric 
1475ffd83dbSDimitry Andric     if (BO.isAnd() && !IsLHSSatisfied)
148480093f4SDimitry Andric       // [temp.constr.op] p2
149480093f4SDimitry Andric       //    A conjunction is a constraint taking two operands. To determine if
150480093f4SDimitry Andric       //    a conjunction is satisfied, the satisfaction of the first operand
151480093f4SDimitry Andric       //    is checked. If that is not satisfied, the conjunction is not
152480093f4SDimitry Andric       //    satisfied. Otherwise, the conjunction is satisfied if and only if
153480093f4SDimitry Andric       //    the second operand is satisfied.
154a7dea167SDimitry Andric       return false;
155480093f4SDimitry Andric 
1565ffd83dbSDimitry Andric     return calculateConstraintSatisfaction(
1575ffd83dbSDimitry Andric         S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
1585ffd83dbSDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
159480093f4SDimitry Andric     return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
160480093f4SDimitry Andric         std::forward<AtomicEvaluator>(Evaluator));
1615ffd83dbSDimitry Andric   }
162480093f4SDimitry Andric 
163480093f4SDimitry Andric   // An atomic constraint expression
164480093f4SDimitry Andric   ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
165480093f4SDimitry Andric 
166480093f4SDimitry Andric   if (SubstitutedAtomicExpr.isInvalid())
167480093f4SDimitry Andric     return true;
168480093f4SDimitry Andric 
169480093f4SDimitry Andric   if (!SubstitutedAtomicExpr.isUsable())
170480093f4SDimitry Andric     // Evaluator has decided satisfaction without yielding an expression.
171480093f4SDimitry Andric     return false;
172a7dea167SDimitry Andric 
173a7dea167SDimitry Andric   EnterExpressionEvaluationContext ConstantEvaluated(
174480093f4SDimitry Andric       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
175a7dea167SDimitry Andric   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
176a7dea167SDimitry Andric   Expr::EvalResult EvalResult;
177a7dea167SDimitry Andric   EvalResult.Diag = &EvaluationDiags;
178fe6060f1SDimitry Andric   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
179fe6060f1SDimitry Andric                                                            S.Context) ||
180fe6060f1SDimitry Andric       !EvaluationDiags.empty()) {
181a7dea167SDimitry Andric     // C++2a [temp.constr.atomic]p1
182a7dea167SDimitry Andric     //   ...E shall be a constant expression of type bool.
183480093f4SDimitry Andric     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
184a7dea167SDimitry Andric            diag::err_non_constant_constraint_expression)
185480093f4SDimitry Andric         << SubstitutedAtomicExpr.get()->getSourceRange();
186a7dea167SDimitry Andric     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
187480093f4SDimitry Andric       S.Diag(PDiag.first, PDiag.second);
188a7dea167SDimitry Andric     return true;
189a7dea167SDimitry Andric   }
190a7dea167SDimitry Andric 
191fe6060f1SDimitry Andric   assert(EvalResult.Val.isInt() &&
192fe6060f1SDimitry Andric          "evaluating bool expression didn't produce int");
193480093f4SDimitry Andric   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
194480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied)
195480093f4SDimitry Andric     Satisfaction.Details.emplace_back(ConstraintExpr,
196480093f4SDimitry Andric                                       SubstitutedAtomicExpr.get());
197a7dea167SDimitry Andric 
198a7dea167SDimitry Andric   return false;
199a7dea167SDimitry Andric }
200480093f4SDimitry Andric 
201480093f4SDimitry Andric static bool calculateConstraintSatisfaction(
20213138422SDimitry Andric     Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
203480093f4SDimitry Andric     SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
204480093f4SDimitry Andric     const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
205480093f4SDimitry Andric   return calculateConstraintSatisfaction(
206480093f4SDimitry Andric       S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
207480093f4SDimitry Andric         EnterExpressionEvaluationContext ConstantEvaluated(
208480093f4SDimitry Andric             S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
209480093f4SDimitry Andric 
210480093f4SDimitry Andric         // Atomic constraint - substitute arguments and check satisfaction.
211480093f4SDimitry Andric         ExprResult SubstitutedExpression;
212480093f4SDimitry Andric         {
213480093f4SDimitry Andric           TemplateDeductionInfo Info(TemplateNameLoc);
214480093f4SDimitry Andric           Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
21513138422SDimitry Andric               Sema::InstantiatingTemplate::ConstraintSubstitution{},
21613138422SDimitry Andric               const_cast<NamedDecl *>(Template), Info,
21713138422SDimitry Andric               AtomicExpr->getSourceRange());
218480093f4SDimitry Andric           if (Inst.isInvalid())
219480093f4SDimitry Andric             return ExprError();
220480093f4SDimitry Andric           // We do not want error diagnostics escaping here.
221480093f4SDimitry Andric           Sema::SFINAETrap Trap(S);
222480093f4SDimitry Andric           SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
223480093f4SDimitry Andric                                               MLTAL);
224fe6060f1SDimitry Andric           // Substitution might have stripped off a contextual conversion to
225fe6060f1SDimitry Andric           // bool if this is the operand of an '&&' or '||'. For example, we
226fe6060f1SDimitry Andric           // might lose an lvalue-to-rvalue conversion here. If so, put it back
227fe6060f1SDimitry Andric           // before we try to evaluate.
228fe6060f1SDimitry Andric           if (!SubstitutedExpression.isInvalid())
229fe6060f1SDimitry Andric             SubstitutedExpression =
230fe6060f1SDimitry Andric                 S.PerformContextuallyConvertToBool(SubstitutedExpression.get());
231480093f4SDimitry Andric           if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
232480093f4SDimitry Andric             // C++2a [temp.constr.atomic]p1
233480093f4SDimitry Andric             //   ...If substitution results in an invalid type or expression, the
234480093f4SDimitry Andric             //   constraint is not satisfied.
235480093f4SDimitry Andric             if (!Trap.hasErrorOccurred())
236349cc55cSDimitry Andric               // A non-SFINAE error has occurred as a result of this
237480093f4SDimitry Andric               // substitution.
238480093f4SDimitry Andric               return ExprError();
239480093f4SDimitry Andric 
240480093f4SDimitry Andric             PartialDiagnosticAt SubstDiag{SourceLocation(),
241480093f4SDimitry Andric                                           PartialDiagnostic::NullDiagnostic()};
242480093f4SDimitry Andric             Info.takeSFINAEDiagnostic(SubstDiag);
243480093f4SDimitry Andric             // FIXME: Concepts: This is an unfortunate consequence of there
244480093f4SDimitry Andric             //  being no serialization code for PartialDiagnostics and the fact
245480093f4SDimitry Andric             //  that serializing them would likely take a lot more storage than
246480093f4SDimitry Andric             //  just storing them as strings. We would still like, in the
247480093f4SDimitry Andric             //  future, to serialize the proper PartialDiagnostic as serializing
248480093f4SDimitry Andric             //  it as a string defeats the purpose of the diagnostic mechanism.
249480093f4SDimitry Andric             SmallString<128> DiagString;
250480093f4SDimitry Andric             DiagString = ": ";
251480093f4SDimitry Andric             SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
252480093f4SDimitry Andric             unsigned MessageSize = DiagString.size();
253480093f4SDimitry Andric             char *Mem = new (S.Context) char[MessageSize];
254480093f4SDimitry Andric             memcpy(Mem, DiagString.c_str(), MessageSize);
255480093f4SDimitry Andric             Satisfaction.Details.emplace_back(
256480093f4SDimitry Andric                 AtomicExpr,
257480093f4SDimitry Andric                 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
258480093f4SDimitry Andric                         SubstDiag.first, StringRef(Mem, MessageSize)});
259480093f4SDimitry Andric             Satisfaction.IsSatisfied = false;
260480093f4SDimitry Andric             return ExprEmpty();
261480093f4SDimitry Andric           }
262480093f4SDimitry Andric         }
263480093f4SDimitry Andric 
264480093f4SDimitry Andric         if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
265480093f4SDimitry Andric           return ExprError();
266480093f4SDimitry Andric 
267480093f4SDimitry Andric         return SubstitutedExpression;
268480093f4SDimitry Andric       });
269480093f4SDimitry Andric }
270480093f4SDimitry Andric 
27113138422SDimitry Andric static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
272480093f4SDimitry Andric                                         ArrayRef<const Expr *> ConstraintExprs,
273480093f4SDimitry Andric                                         ArrayRef<TemplateArgument> TemplateArgs,
274480093f4SDimitry Andric                                         SourceRange TemplateIDRange,
275480093f4SDimitry Andric                                         ConstraintSatisfaction &Satisfaction) {
276480093f4SDimitry Andric   if (ConstraintExprs.empty()) {
277480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
278480093f4SDimitry Andric     return false;
279480093f4SDimitry Andric   }
280480093f4SDimitry Andric 
281480093f4SDimitry Andric   for (auto& Arg : TemplateArgs)
282480093f4SDimitry Andric     if (Arg.isInstantiationDependent()) {
283480093f4SDimitry Andric       // No need to check satisfaction for dependent constraint expressions.
284480093f4SDimitry Andric       Satisfaction.IsSatisfied = true;
285480093f4SDimitry Andric       return false;
286480093f4SDimitry Andric     }
287480093f4SDimitry Andric 
288480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
28913138422SDimitry Andric       Sema::InstantiatingTemplate::ConstraintsCheck{},
29013138422SDimitry Andric       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
291480093f4SDimitry Andric   if (Inst.isInvalid())
292480093f4SDimitry Andric     return true;
293480093f4SDimitry Andric 
294480093f4SDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
295480093f4SDimitry Andric   MLTAL.addOuterTemplateArguments(TemplateArgs);
296480093f4SDimitry Andric 
297480093f4SDimitry Andric   for (const Expr *ConstraintExpr : ConstraintExprs) {
298480093f4SDimitry Andric     if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
299480093f4SDimitry Andric                                         TemplateIDRange.getBegin(), MLTAL,
300480093f4SDimitry Andric                                         ConstraintExpr, Satisfaction))
301480093f4SDimitry Andric       return true;
302480093f4SDimitry Andric     if (!Satisfaction.IsSatisfied)
303480093f4SDimitry Andric       // [temp.constr.op] p2
304480093f4SDimitry Andric       //   [...] To determine if a conjunction is satisfied, the satisfaction
305480093f4SDimitry Andric       //   of the first operand is checked. If that is not satisfied, the
306480093f4SDimitry Andric       //   conjunction is not satisfied. [...]
307480093f4SDimitry Andric       return false;
308480093f4SDimitry Andric   }
309480093f4SDimitry Andric   return false;
310480093f4SDimitry Andric }
311480093f4SDimitry Andric 
31255e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction(
31313138422SDimitry Andric     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
31455e4f9d5SDimitry Andric     ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
31555e4f9d5SDimitry Andric     ConstraintSatisfaction &OutSatisfaction) {
31655e4f9d5SDimitry Andric   if (ConstraintExprs.empty()) {
31755e4f9d5SDimitry Andric     OutSatisfaction.IsSatisfied = true;
31855e4f9d5SDimitry Andric     return false;
319480093f4SDimitry Andric   }
320*81ad6265SDimitry Andric   if (!Template) {
321*81ad6265SDimitry Andric     return ::CheckConstraintSatisfaction(*this, nullptr, ConstraintExprs,
322*81ad6265SDimitry Andric                                          TemplateArgs, TemplateIDRange,
323*81ad6265SDimitry Andric                                          OutSatisfaction);
324*81ad6265SDimitry Andric   }
32555e4f9d5SDimitry Andric   llvm::FoldingSetNodeID ID;
32655e4f9d5SDimitry Andric   ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
327*81ad6265SDimitry Andric   void *InsertPos;
328*81ad6265SDimitry Andric   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
329*81ad6265SDimitry Andric     OutSatisfaction = *Cached;
33055e4f9d5SDimitry Andric     return false;
33155e4f9d5SDimitry Andric   }
332*81ad6265SDimitry Andric   auto Satisfaction =
333*81ad6265SDimitry Andric       std::make_unique<ConstraintSatisfaction>(Template, TemplateArgs);
33413138422SDimitry Andric   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
335480093f4SDimitry Andric                                     TemplateArgs, TemplateIDRange,
33613138422SDimitry Andric                                     *Satisfaction)) {
33755e4f9d5SDimitry Andric     return true;
338480093f4SDimitry Andric   }
33955e4f9d5SDimitry Andric   OutSatisfaction = *Satisfaction;
340*81ad6265SDimitry Andric   // We cannot use InsertPos here because CheckConstraintSatisfaction might have
341*81ad6265SDimitry Andric   // invalidated it.
342*81ad6265SDimitry Andric   // Note that entries of SatisfactionCache are deleted in Sema's destructor.
343*81ad6265SDimitry Andric   SatisfactionCache.InsertNode(Satisfaction.release());
34455e4f9d5SDimitry Andric   return false;
345480093f4SDimitry Andric }
346480093f4SDimitry Andric 
347480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
348480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
349480093f4SDimitry Andric   return calculateConstraintSatisfaction(
350480093f4SDimitry Andric       *this, ConstraintExpr, Satisfaction,
351*81ad6265SDimitry Andric       [this](const Expr *AtomicExpr) -> ExprResult {
352*81ad6265SDimitry Andric         // We only do this to immitate lvalue-to-rvalue conversion.
353*81ad6265SDimitry Andric         return PerformContextuallyConvertToBool(const_cast<Expr *>(AtomicExpr));
354480093f4SDimitry Andric       });
355480093f4SDimitry Andric }
356480093f4SDimitry Andric 
35713138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
35813138422SDimitry Andric                                     ConstraintSatisfaction &Satisfaction,
35913138422SDimitry Andric                                     SourceLocation UsageLoc) {
36013138422SDimitry Andric   const Expr *RC = FD->getTrailingRequiresClause();
36113138422SDimitry Andric   if (RC->isInstantiationDependent()) {
36213138422SDimitry Andric     Satisfaction.IsSatisfied = true;
36313138422SDimitry Andric     return false;
36413138422SDimitry Andric   }
36513138422SDimitry Andric   Qualifiers ThisQuals;
36613138422SDimitry Andric   CXXRecordDecl *Record = nullptr;
36713138422SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
36813138422SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
36913138422SDimitry Andric     Record = const_cast<CXXRecordDecl *>(Method->getParent());
37013138422SDimitry Andric   }
37113138422SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
37213138422SDimitry Andric   // We substitute with empty arguments in order to rebuild the atomic
37313138422SDimitry Andric   // constraint in a constant-evaluated context.
37413138422SDimitry Andric   // FIXME: Should this be a dedicated TreeTransform?
37513138422SDimitry Andric   return CheckConstraintSatisfaction(
37613138422SDimitry Andric       FD, {RC}, /*TemplateArgs=*/{},
37713138422SDimitry Andric       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
37813138422SDimitry Andric       Satisfaction);
37913138422SDimitry Andric }
38013138422SDimitry Andric 
381480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints(
382480093f4SDimitry Andric     TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
383480093f4SDimitry Andric     SourceRange TemplateIDRange) {
384480093f4SDimitry Andric   ConstraintSatisfaction Satisfaction;
385480093f4SDimitry Andric   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
386480093f4SDimitry Andric   TD->getAssociatedConstraints(AssociatedConstraints);
387480093f4SDimitry Andric   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
388480093f4SDimitry Andric                                   TemplateIDRange, Satisfaction))
389480093f4SDimitry Andric     return true;
390480093f4SDimitry Andric 
391480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied) {
392480093f4SDimitry Andric     SmallString<128> TemplateArgString;
393480093f4SDimitry Andric     TemplateArgString = " ";
394480093f4SDimitry Andric     TemplateArgString += getTemplateArgumentBindingsText(
395480093f4SDimitry Andric         TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
396480093f4SDimitry Andric 
397480093f4SDimitry Andric     Diag(TemplateIDRange.getBegin(),
398480093f4SDimitry Andric          diag::err_template_arg_list_constraints_not_satisfied)
399480093f4SDimitry Andric         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
400480093f4SDimitry Andric         << TemplateArgString << TemplateIDRange;
401480093f4SDimitry Andric     DiagnoseUnsatisfiedConstraint(Satisfaction);
402480093f4SDimitry Andric     return true;
403480093f4SDimitry Andric   }
404480093f4SDimitry Andric   return false;
405480093f4SDimitry Andric }
406480093f4SDimitry Andric 
407*81ad6265SDimitry Andric bool Sema::CheckInstantiatedFunctionTemplateConstraints(
408*81ad6265SDimitry Andric     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
409*81ad6265SDimitry Andric     ArrayRef<TemplateArgument> TemplateArgs,
410*81ad6265SDimitry Andric     ConstraintSatisfaction &Satisfaction) {
411*81ad6265SDimitry Andric   // In most cases we're not going to have constraints, so check for that first.
412*81ad6265SDimitry Andric   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
413*81ad6265SDimitry Andric   // Note - code synthesis context for the constraints check is created
414*81ad6265SDimitry Andric   // inside CheckConstraintsSatisfaction.
415*81ad6265SDimitry Andric   SmallVector<const Expr *, 3> TemplateAC;
416*81ad6265SDimitry Andric   Template->getAssociatedConstraints(TemplateAC);
417*81ad6265SDimitry Andric   if (TemplateAC.empty()) {
418*81ad6265SDimitry Andric     Satisfaction.IsSatisfied = true;
419*81ad6265SDimitry Andric     return false;
420*81ad6265SDimitry Andric   }
421*81ad6265SDimitry Andric 
422*81ad6265SDimitry Andric   // Enter the scope of this instantiation. We don't use
423*81ad6265SDimitry Andric   // PushDeclContext because we don't have a scope.
424*81ad6265SDimitry Andric   Sema::ContextRAII savedContext(*this, Decl);
425*81ad6265SDimitry Andric   LocalInstantiationScope Scope(*this);
426*81ad6265SDimitry Andric 
427*81ad6265SDimitry Andric   // If this is not an explicit specialization - we need to get the instantiated
428*81ad6265SDimitry Andric   // version of the template arguments and add them to scope for the
429*81ad6265SDimitry Andric   // substitution.
430*81ad6265SDimitry Andric   if (Decl->isTemplateInstantiation()) {
431*81ad6265SDimitry Andric     InstantiatingTemplate Inst(*this, Decl->getPointOfInstantiation(),
432*81ad6265SDimitry Andric         InstantiatingTemplate::ConstraintsCheck{}, Decl->getPrimaryTemplate(),
433*81ad6265SDimitry Andric         TemplateArgs, SourceRange());
434*81ad6265SDimitry Andric     if (Inst.isInvalid())
435*81ad6265SDimitry Andric       return true;
436*81ad6265SDimitry Andric     MultiLevelTemplateArgumentList MLTAL(
437*81ad6265SDimitry Andric         *Decl->getTemplateSpecializationArgs());
438*81ad6265SDimitry Andric     if (addInstantiatedParametersToScope(
439*81ad6265SDimitry Andric             Decl, Decl->getPrimaryTemplate()->getTemplatedDecl(), Scope, MLTAL))
440*81ad6265SDimitry Andric       return true;
441*81ad6265SDimitry Andric   }
442*81ad6265SDimitry Andric   Qualifiers ThisQuals;
443*81ad6265SDimitry Andric   CXXRecordDecl *Record = nullptr;
444*81ad6265SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
445*81ad6265SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
446*81ad6265SDimitry Andric     Record = Method->getParent();
447*81ad6265SDimitry Andric   }
448*81ad6265SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
449*81ad6265SDimitry Andric   return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs,
450*81ad6265SDimitry Andric                                      PointOfInstantiation, Satisfaction);
451*81ad6265SDimitry Andric }
452*81ad6265SDimitry Andric 
45355e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
45455e4f9d5SDimitry Andric                                            concepts::ExprRequirement *Req,
45555e4f9d5SDimitry Andric                                            bool First) {
45655e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
45755e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
45855e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
45955e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Dependent:
46055e4f9d5SDimitry Andric       llvm_unreachable("Diagnosing a dependent requirement");
46155e4f9d5SDimitry Andric       break;
46255e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
46355e4f9d5SDimitry Andric       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
46455e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
46555e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
46655e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_substitution_error)
46755e4f9d5SDimitry Andric                << (int)First << SubstDiag->SubstitutedEntity
46855e4f9d5SDimitry Andric                << SubstDiag->DiagMessage;
46955e4f9d5SDimitry Andric       else
47055e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
47155e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_unknown_substitution_error)
47255e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
47355e4f9d5SDimitry Andric       break;
47455e4f9d5SDimitry Andric     }
47555e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_NoexceptNotMet:
47655e4f9d5SDimitry Andric       S.Diag(Req->getNoexceptLoc(),
47755e4f9d5SDimitry Andric              diag::note_expr_requirement_noexcept_not_met)
47855e4f9d5SDimitry Andric           << (int)First << Req->getExpr();
47955e4f9d5SDimitry Andric       break;
48055e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
48155e4f9d5SDimitry Andric       auto *SubstDiag =
48255e4f9d5SDimitry Andric           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
48355e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
48455e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
48555e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_substitution_error)
48655e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity
48755e4f9d5SDimitry Andric             << SubstDiag->DiagMessage;
48855e4f9d5SDimitry Andric       else
48955e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
49055e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
49155e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
49255e4f9d5SDimitry Andric       break;
49355e4f9d5SDimitry Andric     }
49455e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
49555e4f9d5SDimitry Andric       ConceptSpecializationExpr *ConstraintExpr =
49655e4f9d5SDimitry Andric           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
497fe6060f1SDimitry Andric       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
49855e4f9d5SDimitry Andric         // A simple case - expr type is the type being constrained and the concept
49955e4f9d5SDimitry Andric         // was not provided arguments.
500fe6060f1SDimitry Andric         Expr *e = Req->getExpr();
501fe6060f1SDimitry Andric         S.Diag(e->getBeginLoc(),
50255e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied_simple)
503349cc55cSDimitry Andric             << (int)First << S.Context.getReferenceQualifiedType(e)
50455e4f9d5SDimitry Andric             << ConstraintExpr->getNamedConcept();
505fe6060f1SDimitry Andric       } else {
50655e4f9d5SDimitry Andric         S.Diag(ConstraintExpr->getBeginLoc(),
50755e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied)
50855e4f9d5SDimitry Andric             << (int)First << ConstraintExpr;
509fe6060f1SDimitry Andric       }
51055e4f9d5SDimitry Andric       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
51155e4f9d5SDimitry Andric       break;
51255e4f9d5SDimitry Andric     }
51355e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Satisfied:
51455e4f9d5SDimitry Andric       llvm_unreachable("We checked this above");
51555e4f9d5SDimitry Andric   }
51655e4f9d5SDimitry Andric }
51755e4f9d5SDimitry Andric 
51855e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
51955e4f9d5SDimitry Andric                                            concepts::TypeRequirement *Req,
52055e4f9d5SDimitry Andric                                            bool First) {
52155e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
52255e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
52355e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
52455e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_Dependent:
52555e4f9d5SDimitry Andric     llvm_unreachable("Diagnosing a dependent requirement");
52655e4f9d5SDimitry Andric     return;
52755e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_SubstitutionFailure: {
52855e4f9d5SDimitry Andric     auto *SubstDiag = Req->getSubstitutionDiagnostic();
52955e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
53055e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
53155e4f9d5SDimitry Andric              diag::note_type_requirement_substitution_error) << (int)First
53255e4f9d5SDimitry Andric           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
53355e4f9d5SDimitry Andric     else
53455e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
53555e4f9d5SDimitry Andric              diag::note_type_requirement_unknown_substitution_error)
53655e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
53755e4f9d5SDimitry Andric     return;
53855e4f9d5SDimitry Andric   }
53955e4f9d5SDimitry Andric   default:
54055e4f9d5SDimitry Andric     llvm_unreachable("Unknown satisfaction status");
54155e4f9d5SDimitry Andric     return;
54255e4f9d5SDimitry Andric   }
54355e4f9d5SDimitry Andric }
54455e4f9d5SDimitry Andric 
54555e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
54655e4f9d5SDimitry Andric                                            concepts::NestedRequirement *Req,
54755e4f9d5SDimitry Andric                                            bool First) {
54855e4f9d5SDimitry Andric   if (Req->isSubstitutionFailure()) {
54955e4f9d5SDimitry Andric     concepts::Requirement::SubstitutionDiagnostic *SubstDiag =
55055e4f9d5SDimitry Andric         Req->getSubstitutionDiagnostic();
55155e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
55255e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
55355e4f9d5SDimitry Andric              diag::note_nested_requirement_substitution_error)
55455e4f9d5SDimitry Andric              << (int)First << SubstDiag->SubstitutedEntity
55555e4f9d5SDimitry Andric              << SubstDiag->DiagMessage;
55655e4f9d5SDimitry Andric     else
55755e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
55855e4f9d5SDimitry Andric              diag::note_nested_requirement_unknown_substitution_error)
55955e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
56055e4f9d5SDimitry Andric     return;
56155e4f9d5SDimitry Andric   }
56255e4f9d5SDimitry Andric   S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First);
56355e4f9d5SDimitry Andric }
56455e4f9d5SDimitry Andric 
56555e4f9d5SDimitry Andric 
566480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
567480093f4SDimitry Andric                                                         Expr *SubstExpr,
568480093f4SDimitry Andric                                                         bool First = true) {
569480093f4SDimitry Andric   SubstExpr = SubstExpr->IgnoreParenImpCasts();
570480093f4SDimitry Andric   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
571480093f4SDimitry Andric     switch (BO->getOpcode()) {
572480093f4SDimitry Andric     // These two cases will in practice only be reached when using fold
573480093f4SDimitry Andric     // expressions with || and &&, since otherwise the || and && will have been
574480093f4SDimitry Andric     // broken down into atomic constraints during satisfaction checking.
575480093f4SDimitry Andric     case BO_LOr:
576480093f4SDimitry Andric       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
577480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
578480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
579480093f4SDimitry Andric                                                   /*First=*/false);
580480093f4SDimitry Andric       return;
581fe6060f1SDimitry Andric     case BO_LAnd: {
582fe6060f1SDimitry Andric       bool LHSSatisfied =
583fe6060f1SDimitry Andric           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
584480093f4SDimitry Andric       if (LHSSatisfied) {
585480093f4SDimitry Andric         // LHS is true, so RHS must be false.
586480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
587480093f4SDimitry Andric         return;
588480093f4SDimitry Andric       }
589480093f4SDimitry Andric       // LHS is false
590480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
591480093f4SDimitry Andric 
592480093f4SDimitry Andric       // RHS might also be false
593fe6060f1SDimitry Andric       bool RHSSatisfied =
594fe6060f1SDimitry Andric           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
595480093f4SDimitry Andric       if (!RHSSatisfied)
596480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
597480093f4SDimitry Andric                                                     /*First=*/false);
598480093f4SDimitry Andric       return;
599fe6060f1SDimitry Andric     }
600480093f4SDimitry Andric     case BO_GE:
601480093f4SDimitry Andric     case BO_LE:
602480093f4SDimitry Andric     case BO_GT:
603480093f4SDimitry Andric     case BO_LT:
604480093f4SDimitry Andric     case BO_EQ:
605480093f4SDimitry Andric     case BO_NE:
606480093f4SDimitry Andric       if (BO->getLHS()->getType()->isIntegerType() &&
607480093f4SDimitry Andric           BO->getRHS()->getType()->isIntegerType()) {
608480093f4SDimitry Andric         Expr::EvalResult SimplifiedLHS;
609480093f4SDimitry Andric         Expr::EvalResult SimplifiedRHS;
610fe6060f1SDimitry Andric         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
611fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
612fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
613fe6060f1SDimitry Andric         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
614fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
615fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
616480093f4SDimitry Andric         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
617480093f4SDimitry Andric           S.Diag(SubstExpr->getBeginLoc(),
618480093f4SDimitry Andric                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
619480093f4SDimitry Andric               << (int)First << SubstExpr
620fe6060f1SDimitry Andric               << toString(SimplifiedLHS.Val.getInt(), 10)
621480093f4SDimitry Andric               << BinaryOperator::getOpcodeStr(BO->getOpcode())
622fe6060f1SDimitry Andric               << toString(SimplifiedRHS.Val.getInt(), 10);
623480093f4SDimitry Andric           return;
624480093f4SDimitry Andric         }
625480093f4SDimitry Andric       }
626480093f4SDimitry Andric       break;
627480093f4SDimitry Andric 
628480093f4SDimitry Andric     default:
629480093f4SDimitry Andric       break;
630480093f4SDimitry Andric     }
631480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
632480093f4SDimitry Andric     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
633480093f4SDimitry Andric       S.Diag(
634480093f4SDimitry Andric           CSE->getSourceRange().getBegin(),
635480093f4SDimitry Andric           diag::
636480093f4SDimitry Andric           note_single_arg_concept_specialization_constraint_evaluated_to_false)
637480093f4SDimitry Andric           << (int)First
638480093f4SDimitry Andric           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
639480093f4SDimitry Andric           << CSE->getNamedConcept();
640480093f4SDimitry Andric     } else {
641480093f4SDimitry Andric       S.Diag(SubstExpr->getSourceRange().getBegin(),
642480093f4SDimitry Andric              diag::note_concept_specialization_constraint_evaluated_to_false)
643480093f4SDimitry Andric           << (int)First << CSE;
644480093f4SDimitry Andric     }
645480093f4SDimitry Andric     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
646480093f4SDimitry Andric     return;
64755e4f9d5SDimitry Andric   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
64855e4f9d5SDimitry Andric     for (concepts::Requirement *Req : RE->getRequirements())
64955e4f9d5SDimitry Andric       if (!Req->isDependent() && !Req->isSatisfied()) {
65055e4f9d5SDimitry Andric         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
65155e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, E, First);
65255e4f9d5SDimitry Andric         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
65355e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, T, First);
65455e4f9d5SDimitry Andric         else
65555e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(
65655e4f9d5SDimitry Andric               S, cast<concepts::NestedRequirement>(Req), First);
65755e4f9d5SDimitry Andric         break;
65855e4f9d5SDimitry Andric       }
65955e4f9d5SDimitry Andric     return;
660480093f4SDimitry Andric   }
661480093f4SDimitry Andric 
662480093f4SDimitry Andric   S.Diag(SubstExpr->getSourceRange().getBegin(),
663480093f4SDimitry Andric          diag::note_atomic_constraint_evaluated_to_false)
664480093f4SDimitry Andric       << (int)First << SubstExpr;
665480093f4SDimitry Andric }
666480093f4SDimitry Andric 
667480093f4SDimitry Andric template<typename SubstitutionDiagnostic>
668480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr(
669480093f4SDimitry Andric     Sema &S, const Expr *E,
670480093f4SDimitry Andric     const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
671480093f4SDimitry Andric     bool First = true) {
672480093f4SDimitry Andric   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
673480093f4SDimitry Andric     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
674480093f4SDimitry Andric         << Diag->second;
675480093f4SDimitry Andric     return;
676480093f4SDimitry Andric   }
677480093f4SDimitry Andric 
678480093f4SDimitry Andric   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
679480093f4SDimitry Andric       Record.template get<Expr *>(), First);
680480093f4SDimitry Andric }
681480093f4SDimitry Andric 
68255e4f9d5SDimitry Andric void
68355e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
68455e4f9d5SDimitry Andric                                     bool First) {
685480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
686480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
687480093f4SDimitry Andric   for (auto &Pair : Satisfaction.Details) {
688480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
689480093f4SDimitry Andric     First = false;
690480093f4SDimitry Andric   }
691480093f4SDimitry Andric }
692480093f4SDimitry Andric 
693480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
69455e4f9d5SDimitry Andric     const ASTConstraintSatisfaction &Satisfaction,
69555e4f9d5SDimitry Andric     bool First) {
696480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
697480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
698480093f4SDimitry Andric   for (auto &Pair : Satisfaction) {
699480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
700480093f4SDimitry Andric     First = false;
701480093f4SDimitry Andric   }
702480093f4SDimitry Andric }
703480093f4SDimitry Andric 
704480093f4SDimitry Andric const NormalizedConstraint *
705480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints(
706480093f4SDimitry Andric     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
707480093f4SDimitry Andric   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
708480093f4SDimitry Andric   if (CacheEntry == NormalizationCache.end()) {
709480093f4SDimitry Andric     auto Normalized =
710480093f4SDimitry Andric         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
711480093f4SDimitry Andric                                                   AssociatedConstraints);
712480093f4SDimitry Andric     CacheEntry =
713480093f4SDimitry Andric         NormalizationCache
714480093f4SDimitry Andric             .try_emplace(ConstrainedDecl,
715480093f4SDimitry Andric                          Normalized
716480093f4SDimitry Andric                              ? new (Context) NormalizedConstraint(
717480093f4SDimitry Andric                                  std::move(*Normalized))
718480093f4SDimitry Andric                              : nullptr)
719480093f4SDimitry Andric             .first;
720480093f4SDimitry Andric   }
721480093f4SDimitry Andric   return CacheEntry->second;
722480093f4SDimitry Andric }
723480093f4SDimitry Andric 
724480093f4SDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
725480093f4SDimitry Andric     ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
726480093f4SDimitry Andric     const ASTTemplateArgumentListInfo *ArgsAsWritten) {
727480093f4SDimitry Andric   if (!N.isAtomic()) {
728480093f4SDimitry Andric     if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
729480093f4SDimitry Andric                                     ArgsAsWritten))
730480093f4SDimitry Andric       return true;
731480093f4SDimitry Andric     return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
732480093f4SDimitry Andric                                        ArgsAsWritten);
733480093f4SDimitry Andric   }
734480093f4SDimitry Andric   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
735480093f4SDimitry Andric 
736480093f4SDimitry Andric   AtomicConstraint &Atomic = *N.getAtomicConstraint();
737480093f4SDimitry Andric   TemplateArgumentListInfo SubstArgs;
738480093f4SDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
739480093f4SDimitry Andric   MLTAL.addOuterTemplateArguments(TemplateArgs);
740480093f4SDimitry Andric   if (!Atomic.ParameterMapping) {
741480093f4SDimitry Andric     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
742480093f4SDimitry Andric     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
743480093f4SDimitry Andric                                  /*Depth=*/0, OccurringIndices);
744480093f4SDimitry Andric     Atomic.ParameterMapping.emplace(
745480093f4SDimitry Andric         MutableArrayRef<TemplateArgumentLoc>(
746480093f4SDimitry Andric             new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
747480093f4SDimitry Andric             OccurringIndices.count()));
748480093f4SDimitry Andric     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
749480093f4SDimitry Andric       if (OccurringIndices[I])
750480093f4SDimitry Andric         new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
751480093f4SDimitry Andric             S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
752480093f4SDimitry Andric                 // Here we assume we do not support things like
753480093f4SDimitry Andric                 // template<typename A, typename B>
754480093f4SDimitry Andric                 // concept C = ...;
755480093f4SDimitry Andric                 //
756480093f4SDimitry Andric                 // template<typename... Ts> requires C<Ts...>
757480093f4SDimitry Andric                 // struct S { };
758480093f4SDimitry Andric                 // The above currently yields a diagnostic.
759480093f4SDimitry Andric                 // We still might have default arguments for concept parameters.
760480093f4SDimitry Andric                 ArgsAsWritten->NumTemplateArgs > I ?
761480093f4SDimitry Andric                 ArgsAsWritten->arguments()[I].getLocation() :
762480093f4SDimitry Andric                 SourceLocation()));
763480093f4SDimitry Andric   }
764480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(
765480093f4SDimitry Andric       S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
766480093f4SDimitry Andric       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
767480093f4SDimitry Andric       SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
768480093f4SDimitry Andric                   ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
769480093f4SDimitry Andric   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
770480093f4SDimitry Andric     return true;
77113138422SDimitry Andric   Atomic.ParameterMapping.emplace(
77213138422SDimitry Andric         MutableArrayRef<TemplateArgumentLoc>(
77313138422SDimitry Andric             new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
77413138422SDimitry Andric             SubstArgs.size()));
775480093f4SDimitry Andric   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
776480093f4SDimitry Andric             N.getAtomicConstraint()->ParameterMapping->begin());
777480093f4SDimitry Andric   return false;
778480093f4SDimitry Andric }
779480093f4SDimitry Andric 
780480093f4SDimitry Andric Optional<NormalizedConstraint>
781480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
782480093f4SDimitry Andric                                           ArrayRef<const Expr *> E) {
783480093f4SDimitry Andric   assert(E.size() != 0);
7846e75b2fbSDimitry Andric   auto Conjunction = fromConstraintExpr(S, D, E[0]);
7856e75b2fbSDimitry Andric   if (!Conjunction)
786480093f4SDimitry Andric     return None;
7876e75b2fbSDimitry Andric   for (unsigned I = 1; I < E.size(); ++I) {
788480093f4SDimitry Andric     auto Next = fromConstraintExpr(S, D, E[I]);
789480093f4SDimitry Andric     if (!Next)
7906e75b2fbSDimitry Andric       return None;
7916e75b2fbSDimitry Andric     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
792480093f4SDimitry Andric                                         std::move(*Next), CCK_Conjunction);
793480093f4SDimitry Andric   }
794480093f4SDimitry Andric   return Conjunction;
795480093f4SDimitry Andric }
796480093f4SDimitry Andric 
797480093f4SDimitry Andric llvm::Optional<NormalizedConstraint>
798480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
799480093f4SDimitry Andric   assert(E != nullptr);
800480093f4SDimitry Andric 
801480093f4SDimitry Andric   // C++ [temp.constr.normal]p1.1
802480093f4SDimitry Andric   // [...]
803480093f4SDimitry Andric   // - The normal form of an expression (E) is the normal form of E.
804480093f4SDimitry Andric   // [...]
805480093f4SDimitry Andric   E = E->IgnoreParenImpCasts();
8065ffd83dbSDimitry Andric   if (LogicalBinOp BO = E) {
8075ffd83dbSDimitry Andric     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
808480093f4SDimitry Andric     if (!LHS)
809480093f4SDimitry Andric       return None;
8105ffd83dbSDimitry Andric     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
811480093f4SDimitry Andric     if (!RHS)
812480093f4SDimitry Andric       return None;
813480093f4SDimitry Andric 
8145ffd83dbSDimitry Andric     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
8155ffd83dbSDimitry Andric                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
816480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
817480093f4SDimitry Andric     const NormalizedConstraint *SubNF;
818480093f4SDimitry Andric     {
819480093f4SDimitry Andric       Sema::InstantiatingTemplate Inst(
820480093f4SDimitry Andric           S, CSE->getExprLoc(),
821480093f4SDimitry Andric           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
822480093f4SDimitry Andric           CSE->getSourceRange());
823480093f4SDimitry Andric       // C++ [temp.constr.normal]p1.1
824480093f4SDimitry Andric       // [...]
825480093f4SDimitry Andric       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
826480093f4SDimitry Andric       // where C names a concept, is the normal form of the
827480093f4SDimitry Andric       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
828480093f4SDimitry Andric       // respective template parameters in the parameter mappings in each atomic
829480093f4SDimitry Andric       // constraint. If any such substitution results in an invalid type or
830480093f4SDimitry Andric       // expression, the program is ill-formed; no diagnostic is required.
831480093f4SDimitry Andric       // [...]
832480093f4SDimitry Andric       ConceptDecl *CD = CSE->getNamedConcept();
833480093f4SDimitry Andric       SubNF = S.getNormalizedAssociatedConstraints(CD,
834480093f4SDimitry Andric                                                    {CD->getConstraintExpr()});
835480093f4SDimitry Andric       if (!SubNF)
836480093f4SDimitry Andric         return None;
837480093f4SDimitry Andric     }
838480093f4SDimitry Andric 
839480093f4SDimitry Andric     Optional<NormalizedConstraint> New;
840480093f4SDimitry Andric     New.emplace(S.Context, *SubNF);
841480093f4SDimitry Andric 
842480093f4SDimitry Andric     if (substituteParameterMappings(
843480093f4SDimitry Andric             S, *New, CSE->getNamedConcept(),
844480093f4SDimitry Andric             CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
845480093f4SDimitry Andric       return None;
846480093f4SDimitry Andric 
847480093f4SDimitry Andric     return New;
848480093f4SDimitry Andric   }
849480093f4SDimitry Andric   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
850480093f4SDimitry Andric }
851480093f4SDimitry Andric 
852480093f4SDimitry Andric using NormalForm =
853480093f4SDimitry Andric     llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
854480093f4SDimitry Andric 
855480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
856480093f4SDimitry Andric   if (Normalized.isAtomic())
857480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
858480093f4SDimitry Andric 
859480093f4SDimitry Andric   NormalForm LCNF = makeCNF(Normalized.getLHS());
860480093f4SDimitry Andric   NormalForm RCNF = makeCNF(Normalized.getRHS());
861480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
862480093f4SDimitry Andric     LCNF.reserve(LCNF.size() + RCNF.size());
863480093f4SDimitry Andric     while (!RCNF.empty())
864480093f4SDimitry Andric       LCNF.push_back(RCNF.pop_back_val());
865480093f4SDimitry Andric     return LCNF;
866480093f4SDimitry Andric   }
867480093f4SDimitry Andric 
868480093f4SDimitry Andric   // Disjunction
869480093f4SDimitry Andric   NormalForm Res;
870480093f4SDimitry Andric   Res.reserve(LCNF.size() * RCNF.size());
871480093f4SDimitry Andric   for (auto &LDisjunction : LCNF)
872480093f4SDimitry Andric     for (auto &RDisjunction : RCNF) {
873480093f4SDimitry Andric       NormalForm::value_type Combined;
874480093f4SDimitry Andric       Combined.reserve(LDisjunction.size() + RDisjunction.size());
875480093f4SDimitry Andric       std::copy(LDisjunction.begin(), LDisjunction.end(),
876480093f4SDimitry Andric                 std::back_inserter(Combined));
877480093f4SDimitry Andric       std::copy(RDisjunction.begin(), RDisjunction.end(),
878480093f4SDimitry Andric                 std::back_inserter(Combined));
879480093f4SDimitry Andric       Res.emplace_back(Combined);
880480093f4SDimitry Andric     }
881480093f4SDimitry Andric   return Res;
882480093f4SDimitry Andric }
883480093f4SDimitry Andric 
884480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
885480093f4SDimitry Andric   if (Normalized.isAtomic())
886480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
887480093f4SDimitry Andric 
888480093f4SDimitry Andric   NormalForm LDNF = makeDNF(Normalized.getLHS());
889480093f4SDimitry Andric   NormalForm RDNF = makeDNF(Normalized.getRHS());
890480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
891480093f4SDimitry Andric     LDNF.reserve(LDNF.size() + RDNF.size());
892480093f4SDimitry Andric     while (!RDNF.empty())
893480093f4SDimitry Andric       LDNF.push_back(RDNF.pop_back_val());
894480093f4SDimitry Andric     return LDNF;
895480093f4SDimitry Andric   }
896480093f4SDimitry Andric 
897480093f4SDimitry Andric   // Conjunction
898480093f4SDimitry Andric   NormalForm Res;
899480093f4SDimitry Andric   Res.reserve(LDNF.size() * RDNF.size());
900480093f4SDimitry Andric   for (auto &LConjunction : LDNF) {
901480093f4SDimitry Andric     for (auto &RConjunction : RDNF) {
902480093f4SDimitry Andric       NormalForm::value_type Combined;
903480093f4SDimitry Andric       Combined.reserve(LConjunction.size() + RConjunction.size());
904480093f4SDimitry Andric       std::copy(LConjunction.begin(), LConjunction.end(),
905480093f4SDimitry Andric                 std::back_inserter(Combined));
906480093f4SDimitry Andric       std::copy(RConjunction.begin(), RConjunction.end(),
907480093f4SDimitry Andric                 std::back_inserter(Combined));
908480093f4SDimitry Andric       Res.emplace_back(Combined);
909480093f4SDimitry Andric     }
910480093f4SDimitry Andric   }
911480093f4SDimitry Andric   return Res;
912480093f4SDimitry Andric }
913480093f4SDimitry Andric 
914480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
915480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF,
916480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
917480093f4SDimitry Andric   // C++ [temp.constr.order] p2
918480093f4SDimitry Andric   //   Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
919480093f4SDimitry Andric   //   disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
920480093f4SDimitry Andric   //   the conjuctive normal form of Q, where [...]
921480093f4SDimitry Andric   for (const auto &Pi : PDNF) {
922480093f4SDimitry Andric     for (const auto &Qj : QCNF) {
923480093f4SDimitry Andric       // C++ [temp.constr.order] p2
924480093f4SDimitry Andric       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
925480093f4SDimitry Andric       //     and only if there exists an atomic constraint Pia in Pi for which
926480093f4SDimitry Andric       //     there exists an atomic constraint, Qjb, in Qj such that Pia
927480093f4SDimitry Andric       //     subsumes Qjb.
928480093f4SDimitry Andric       bool Found = false;
929480093f4SDimitry Andric       for (const AtomicConstraint *Pia : Pi) {
930480093f4SDimitry Andric         for (const AtomicConstraint *Qjb : Qj) {
931480093f4SDimitry Andric           if (E(*Pia, *Qjb)) {
932480093f4SDimitry Andric             Found = true;
933480093f4SDimitry Andric             break;
934480093f4SDimitry Andric           }
935480093f4SDimitry Andric         }
936480093f4SDimitry Andric         if (Found)
937480093f4SDimitry Andric           break;
938480093f4SDimitry Andric       }
939480093f4SDimitry Andric       if (!Found)
940480093f4SDimitry Andric         return false;
941480093f4SDimitry Andric     }
942480093f4SDimitry Andric   }
943480093f4SDimitry Andric   return true;
944480093f4SDimitry Andric }
945480093f4SDimitry Andric 
946480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
947480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
948480093f4SDimitry Andric                      NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
949480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
950480093f4SDimitry Andric   // C++ [temp.constr.order] p2
951480093f4SDimitry Andric   //   In order to determine if a constraint P subsumes a constraint Q, P is
952480093f4SDimitry Andric   //   transformed into disjunctive normal form, and Q is transformed into
953480093f4SDimitry Andric   //   conjunctive normal form. [...]
954480093f4SDimitry Andric   auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
955480093f4SDimitry Andric   if (!PNormalized)
956480093f4SDimitry Andric     return true;
957480093f4SDimitry Andric   const NormalForm PDNF = makeDNF(*PNormalized);
958480093f4SDimitry Andric 
959480093f4SDimitry Andric   auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
960480093f4SDimitry Andric   if (!QNormalized)
961480093f4SDimitry Andric     return true;
962480093f4SDimitry Andric   const NormalForm QCNF = makeCNF(*QNormalized);
963480093f4SDimitry Andric 
964480093f4SDimitry Andric   Subsumes = subsumes(PDNF, QCNF, E);
965480093f4SDimitry Andric   return false;
966480093f4SDimitry Andric }
967480093f4SDimitry Andric 
968480093f4SDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
969480093f4SDimitry Andric                                   NamedDecl *D2, ArrayRef<const Expr *> AC2,
970480093f4SDimitry Andric                                   bool &Result) {
971480093f4SDimitry Andric   if (AC1.empty()) {
972480093f4SDimitry Andric     Result = AC2.empty();
973480093f4SDimitry Andric     return false;
974480093f4SDimitry Andric   }
975480093f4SDimitry Andric   if (AC2.empty()) {
976480093f4SDimitry Andric     // TD1 has associated constraints and TD2 does not.
977480093f4SDimitry Andric     Result = true;
978480093f4SDimitry Andric     return false;
979480093f4SDimitry Andric   }
980480093f4SDimitry Andric 
981480093f4SDimitry Andric   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
982480093f4SDimitry Andric   auto CacheEntry = SubsumptionCache.find(Key);
983480093f4SDimitry Andric   if (CacheEntry != SubsumptionCache.end()) {
984480093f4SDimitry Andric     Result = CacheEntry->second;
985480093f4SDimitry Andric     return false;
986480093f4SDimitry Andric   }
987480093f4SDimitry Andric 
988480093f4SDimitry Andric   if (subsumes(*this, D1, AC1, D2, AC2, Result,
989480093f4SDimitry Andric         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
990480093f4SDimitry Andric           return A.subsumes(Context, B);
991480093f4SDimitry Andric         }))
992480093f4SDimitry Andric     return true;
993480093f4SDimitry Andric   SubsumptionCache.try_emplace(Key, Result);
994480093f4SDimitry Andric   return false;
995480093f4SDimitry Andric }
996480093f4SDimitry Andric 
997480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
998480093f4SDimitry Andric     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
999480093f4SDimitry Andric   if (isSFINAEContext())
1000480093f4SDimitry Andric     // No need to work here because our notes would be discarded.
1001480093f4SDimitry Andric     return false;
1002480093f4SDimitry Andric 
1003480093f4SDimitry Andric   if (AC1.empty() || AC2.empty())
1004480093f4SDimitry Andric     return false;
1005480093f4SDimitry Andric 
1006480093f4SDimitry Andric   auto NormalExprEvaluator =
1007480093f4SDimitry Andric       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
1008480093f4SDimitry Andric         return A.subsumes(Context, B);
1009480093f4SDimitry Andric       };
1010480093f4SDimitry Andric 
1011480093f4SDimitry Andric   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1012480093f4SDimitry Andric   auto IdenticalExprEvaluator =
1013480093f4SDimitry Andric       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
1014480093f4SDimitry Andric         if (!A.hasMatchingParameterMapping(Context, B))
1015480093f4SDimitry Andric           return false;
1016480093f4SDimitry Andric         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1017480093f4SDimitry Andric         if (EA == EB)
1018480093f4SDimitry Andric           return true;
1019480093f4SDimitry Andric 
1020480093f4SDimitry Andric         // Not the same source level expression - are the expressions
1021480093f4SDimitry Andric         // identical?
1022480093f4SDimitry Andric         llvm::FoldingSetNodeID IDA, IDB;
1023349cc55cSDimitry Andric         EA->Profile(IDA, Context, /*Canonical=*/true);
1024349cc55cSDimitry Andric         EB->Profile(IDB, Context, /*Canonical=*/true);
1025480093f4SDimitry Andric         if (IDA != IDB)
1026480093f4SDimitry Andric           return false;
1027480093f4SDimitry Andric 
1028480093f4SDimitry Andric         AmbiguousAtomic1 = EA;
1029480093f4SDimitry Andric         AmbiguousAtomic2 = EB;
1030480093f4SDimitry Andric         return true;
1031480093f4SDimitry Andric       };
1032480093f4SDimitry Andric 
1033480093f4SDimitry Andric   {
1034480093f4SDimitry Andric     // The subsumption checks might cause diagnostics
1035480093f4SDimitry Andric     SFINAETrap Trap(*this);
1036480093f4SDimitry Andric     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1037480093f4SDimitry Andric     if (!Normalized1)
1038480093f4SDimitry Andric       return false;
1039480093f4SDimitry Andric     const NormalForm DNF1 = makeDNF(*Normalized1);
1040480093f4SDimitry Andric     const NormalForm CNF1 = makeCNF(*Normalized1);
1041480093f4SDimitry Andric 
1042480093f4SDimitry Andric     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1043480093f4SDimitry Andric     if (!Normalized2)
1044480093f4SDimitry Andric       return false;
1045480093f4SDimitry Andric     const NormalForm DNF2 = makeDNF(*Normalized2);
1046480093f4SDimitry Andric     const NormalForm CNF2 = makeCNF(*Normalized2);
1047480093f4SDimitry Andric 
1048480093f4SDimitry Andric     bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1049480093f4SDimitry Andric     bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1050480093f4SDimitry Andric     bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1051480093f4SDimitry Andric     bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1052480093f4SDimitry Andric     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1053480093f4SDimitry Andric         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1054480093f4SDimitry Andric       // Same result - no ambiguity was caused by identical atomic expressions.
1055480093f4SDimitry Andric       return false;
1056480093f4SDimitry Andric   }
1057480093f4SDimitry Andric 
1058480093f4SDimitry Andric   // A different result! Some ambiguous atomic constraint(s) caused a difference
1059480093f4SDimitry Andric   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1060480093f4SDimitry Andric 
1061480093f4SDimitry Andric   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1062480093f4SDimitry Andric       << AmbiguousAtomic1->getSourceRange();
1063480093f4SDimitry Andric   Diag(AmbiguousAtomic2->getBeginLoc(),
1064480093f4SDimitry Andric        diag::note_ambiguous_atomic_constraints_similar_expression)
1065480093f4SDimitry Andric       << AmbiguousAtomic2->getSourceRange();
1066480093f4SDimitry Andric   return true;
1067480093f4SDimitry Andric }
106855e4f9d5SDimitry Andric 
106955e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
107055e4f9d5SDimitry Andric     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
107155e4f9d5SDimitry Andric     ReturnTypeRequirement Req, SatisfactionStatus Status,
107255e4f9d5SDimitry Andric     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
107355e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
107455e4f9d5SDimitry Andric                 Status == SS_Dependent &&
107555e4f9d5SDimitry Andric                 (E->containsUnexpandedParameterPack() ||
107655e4f9d5SDimitry Andric                  Req.containsUnexpandedParameterPack()),
107755e4f9d5SDimitry Andric                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
107855e4f9d5SDimitry Andric     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
107955e4f9d5SDimitry Andric     Status(Status) {
108055e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
108155e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
108255e4f9d5SDimitry Andric          "noexcept specification");
108355e4f9d5SDimitry Andric   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
108455e4f9d5SDimitry Andric          (SubstitutedConstraintExpr != nullptr));
108555e4f9d5SDimitry Andric }
108655e4f9d5SDimitry Andric 
108755e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
108855e4f9d5SDimitry Andric     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
108955e4f9d5SDimitry Andric     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
109055e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
109155e4f9d5SDimitry Andric                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
109255e4f9d5SDimitry Andric     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
109355e4f9d5SDimitry Andric     Status(SS_ExprSubstitutionFailure) {
109455e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
109555e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
109655e4f9d5SDimitry Andric          "noexcept specification");
109755e4f9d5SDimitry Andric }
109855e4f9d5SDimitry Andric 
109955e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement::
110055e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) :
110104eeddc0SDimitry Andric     TypeConstraintInfo(TPL, false) {
110255e4f9d5SDimitry Andric   assert(TPL->size() == 1);
110355e4f9d5SDimitry Andric   const TypeConstraint *TC =
110455e4f9d5SDimitry Andric       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
110555e4f9d5SDimitry Andric   assert(TC &&
110655e4f9d5SDimitry Andric          "TPL must have a template type parameter with a type constraint");
110755e4f9d5SDimitry Andric   auto *Constraint =
1108349cc55cSDimitry Andric       cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1109e8d8bef9SDimitry Andric   bool Dependent =
1110e8d8bef9SDimitry Andric       Constraint->getTemplateArgsAsWritten() &&
1111e8d8bef9SDimitry Andric       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1112e8d8bef9SDimitry Andric           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
111304eeddc0SDimitry Andric   TypeConstraintInfo.setInt(Dependent ? true : false);
111455e4f9d5SDimitry Andric }
111555e4f9d5SDimitry Andric 
111655e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1117e8d8bef9SDimitry Andric     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
111855e4f9d5SDimitry Andric                 T->getType()->containsUnexpandedParameterPack(),
111955e4f9d5SDimitry Andric                 // We reach this ctor with either dependent types (in which
112055e4f9d5SDimitry Andric                 // IsSatisfied doesn't matter) or with non-dependent type in
112155e4f9d5SDimitry Andric                 // which the existence of the type indicates satisfaction.
1122e8d8bef9SDimitry Andric                 /*IsSatisfied=*/true),
1123e8d8bef9SDimitry Andric     Value(T),
1124e8d8bef9SDimitry Andric     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1125e8d8bef9SDimitry Andric                                                         : SS_Satisfied) {}
1126