xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision 6e75b2fbf9a03e6876e0a3c089e0b3ad71876125)
1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2a7dea167SDimitry Andric //
3a7dea167SDimitry Andric //                     The LLVM Compiler Infrastructure
4a7dea167SDimitry Andric //
5a7dea167SDimitry Andric // This file is distributed under the University of Illinois Open Source
6a7dea167SDimitry Andric // License. See LICENSE.TXT for details.
7a7dea167SDimitry Andric //
8a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
9a7dea167SDimitry Andric //
10a7dea167SDimitry Andric //  This file implements semantic analysis for C++ constraints and concepts.
11a7dea167SDimitry Andric //
12a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
13a7dea167SDimitry Andric 
14480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h"
15a7dea167SDimitry Andric #include "clang/Sema/Sema.h"
16480093f4SDimitry Andric #include "clang/Sema/SemaInternal.h"
17a7dea167SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
18a7dea167SDimitry Andric #include "clang/Sema/TemplateDeduction.h"
19a7dea167SDimitry Andric #include "clang/Sema/Template.h"
2055e4f9d5SDimitry Andric #include "clang/Sema/Overload.h"
2155e4f9d5SDimitry Andric #include "clang/Sema/Initialization.h"
2255e4f9d5SDimitry Andric #include "clang/Sema/SemaInternal.h"
2355e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h"
24480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
25480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h"
26480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h"
27480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h"
28fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
29fe6060f1SDimitry Andric 
30a7dea167SDimitry Andric using namespace clang;
31a7dea167SDimitry Andric using namespace sema;
32a7dea167SDimitry Andric 
335ffd83dbSDimitry Andric namespace {
345ffd83dbSDimitry Andric class LogicalBinOp {
355ffd83dbSDimitry Andric   OverloadedOperatorKind Op = OO_None;
365ffd83dbSDimitry Andric   const Expr *LHS = nullptr;
375ffd83dbSDimitry Andric   const Expr *RHS = nullptr;
385ffd83dbSDimitry Andric 
395ffd83dbSDimitry Andric public:
405ffd83dbSDimitry Andric   LogicalBinOp(const Expr *E) {
415ffd83dbSDimitry Andric     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
425ffd83dbSDimitry Andric       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
435ffd83dbSDimitry Andric       LHS = BO->getLHS();
445ffd83dbSDimitry Andric       RHS = BO->getRHS();
455ffd83dbSDimitry Andric     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
46fe6060f1SDimitry Andric       // If OO is not || or && it might not have exactly 2 arguments.
47fe6060f1SDimitry Andric       if (OO->getNumArgs() == 2) {
485ffd83dbSDimitry Andric         Op = OO->getOperator();
495ffd83dbSDimitry Andric         LHS = OO->getArg(0);
505ffd83dbSDimitry Andric         RHS = OO->getArg(1);
515ffd83dbSDimitry Andric       }
525ffd83dbSDimitry Andric     }
53fe6060f1SDimitry Andric   }
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric   bool isAnd() const { return Op == OO_AmpAmp; }
565ffd83dbSDimitry Andric   bool isOr() const { return Op == OO_PipePipe; }
575ffd83dbSDimitry Andric   explicit operator bool() const { return isAnd() || isOr(); }
585ffd83dbSDimitry Andric 
595ffd83dbSDimitry Andric   const Expr *getLHS() const { return LHS; }
605ffd83dbSDimitry Andric   const Expr *getRHS() const { return RHS; }
615ffd83dbSDimitry Andric };
625ffd83dbSDimitry Andric }
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
655ffd83dbSDimitry Andric                                      Token NextToken, bool *PossibleNonPrimary,
66480093f4SDimitry Andric                                      bool IsTrailingRequiresClause) {
67a7dea167SDimitry Andric   // C++2a [temp.constr.atomic]p1
68a7dea167SDimitry Andric   // ..E shall be a constant expression of type bool.
69a7dea167SDimitry Andric 
70a7dea167SDimitry Andric   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
71a7dea167SDimitry Andric 
725ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpression) {
735ffd83dbSDimitry Andric     return CheckConstraintExpression(BO.getLHS(), NextToken,
74480093f4SDimitry Andric                                      PossibleNonPrimary) &&
755ffd83dbSDimitry Andric            CheckConstraintExpression(BO.getRHS(), NextToken,
76480093f4SDimitry Andric                                      PossibleNonPrimary);
77a7dea167SDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
78480093f4SDimitry Andric     return CheckConstraintExpression(C->getSubExpr(), NextToken,
79480093f4SDimitry Andric                                      PossibleNonPrimary);
80a7dea167SDimitry Andric 
81a7dea167SDimitry Andric   QualType Type = ConstraintExpression->getType();
82480093f4SDimitry Andric 
83480093f4SDimitry Andric   auto CheckForNonPrimary = [&] {
84480093f4SDimitry Andric     if (PossibleNonPrimary)
85480093f4SDimitry Andric       *PossibleNonPrimary =
86480093f4SDimitry Andric           // We have the following case:
87480093f4SDimitry Andric           // template<typename> requires func(0) struct S { };
88480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
89480093f4SDimitry Andric           // the function call, and we're only going to parse 'func' as the
90480093f4SDimitry Andric           // primary-expression, and complain that it is of non-bool type.
91480093f4SDimitry Andric           (NextToken.is(tok::l_paren) &&
92480093f4SDimitry Andric            (IsTrailingRequiresClause ||
93480093f4SDimitry Andric             (Type->isDependentType() &&
945ffd83dbSDimitry Andric              isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
95480093f4SDimitry Andric             Type->isFunctionType() ||
96480093f4SDimitry Andric             Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
97480093f4SDimitry Andric           // We have the following case:
98480093f4SDimitry Andric           // template<typename T> requires size_<T> == 0 struct S { };
99480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
100480093f4SDimitry Andric           // the binary operator, and we're only going to parse 'func' as the
101480093f4SDimitry Andric           // first operand, and complain that it is of non-bool type.
102480093f4SDimitry Andric           getBinOpPrecedence(NextToken.getKind(),
103480093f4SDimitry Andric                              /*GreaterThanIsOperator=*/true,
104480093f4SDimitry Andric                              getLangOpts().CPlusPlus11) > prec::LogicalAnd;
105480093f4SDimitry Andric   };
106480093f4SDimitry Andric 
107480093f4SDimitry Andric   // An atomic constraint!
108480093f4SDimitry Andric   if (ConstraintExpression->isTypeDependent()) {
109480093f4SDimitry Andric     CheckForNonPrimary();
110480093f4SDimitry Andric     return true;
111480093f4SDimitry Andric   }
112480093f4SDimitry Andric 
113a7dea167SDimitry Andric   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
114a7dea167SDimitry Andric     Diag(ConstraintExpression->getExprLoc(),
115a7dea167SDimitry Andric          diag::err_non_bool_atomic_constraint) << Type
116a7dea167SDimitry Andric         << ConstraintExpression->getSourceRange();
117480093f4SDimitry Andric     CheckForNonPrimary();
118a7dea167SDimitry Andric     return false;
119a7dea167SDimitry Andric   }
120480093f4SDimitry Andric 
121480093f4SDimitry Andric   if (PossibleNonPrimary)
122480093f4SDimitry Andric       *PossibleNonPrimary = false;
123a7dea167SDimitry Andric   return true;
124a7dea167SDimitry Andric }
125a7dea167SDimitry Andric 
126480093f4SDimitry Andric template <typename AtomicEvaluator>
127480093f4SDimitry Andric static bool
128480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
129480093f4SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
130480093f4SDimitry Andric                                 AtomicEvaluator &&Evaluator) {
131a7dea167SDimitry Andric   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
132a7dea167SDimitry Andric 
1335ffd83dbSDimitry Andric   if (LogicalBinOp BO = ConstraintExpr) {
1345ffd83dbSDimitry Andric     if (calculateConstraintSatisfaction(S, BO.getLHS(), Satisfaction,
135480093f4SDimitry Andric                                         Evaluator))
136a7dea167SDimitry Andric       return true;
137480093f4SDimitry Andric 
138480093f4SDimitry Andric     bool IsLHSSatisfied = Satisfaction.IsSatisfied;
139480093f4SDimitry Andric 
1405ffd83dbSDimitry Andric     if (BO.isOr() && IsLHSSatisfied)
141480093f4SDimitry Andric       // [temp.constr.op] p3
142480093f4SDimitry Andric       //    A disjunction is a constraint taking two operands. To determine if
143480093f4SDimitry Andric       //    a disjunction is satisfied, the satisfaction of the first operand
144480093f4SDimitry Andric       //    is checked. If that is satisfied, the disjunction is satisfied.
145480093f4SDimitry Andric       //    Otherwise, the disjunction is satisfied if and only if the second
146480093f4SDimitry Andric       //    operand is satisfied.
147a7dea167SDimitry Andric       return false;
148480093f4SDimitry Andric 
1495ffd83dbSDimitry Andric     if (BO.isAnd() && !IsLHSSatisfied)
150480093f4SDimitry Andric       // [temp.constr.op] p2
151480093f4SDimitry Andric       //    A conjunction is a constraint taking two operands. To determine if
152480093f4SDimitry Andric       //    a conjunction is satisfied, the satisfaction of the first operand
153480093f4SDimitry Andric       //    is checked. If that is not satisfied, the conjunction is not
154480093f4SDimitry Andric       //    satisfied. Otherwise, the conjunction is satisfied if and only if
155480093f4SDimitry Andric       //    the second operand is satisfied.
156a7dea167SDimitry Andric       return false;
157480093f4SDimitry Andric 
1585ffd83dbSDimitry Andric     return calculateConstraintSatisfaction(
1595ffd83dbSDimitry Andric         S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
1605ffd83dbSDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
161480093f4SDimitry Andric     return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
162480093f4SDimitry Andric         std::forward<AtomicEvaluator>(Evaluator));
1635ffd83dbSDimitry Andric   }
164480093f4SDimitry Andric 
165480093f4SDimitry Andric   // An atomic constraint expression
166480093f4SDimitry Andric   ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
167480093f4SDimitry Andric 
168480093f4SDimitry Andric   if (SubstitutedAtomicExpr.isInvalid())
169480093f4SDimitry Andric     return true;
170480093f4SDimitry Andric 
171480093f4SDimitry Andric   if (!SubstitutedAtomicExpr.isUsable())
172480093f4SDimitry Andric     // Evaluator has decided satisfaction without yielding an expression.
173480093f4SDimitry Andric     return false;
174a7dea167SDimitry Andric 
175a7dea167SDimitry Andric   EnterExpressionEvaluationContext ConstantEvaluated(
176480093f4SDimitry Andric       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
177a7dea167SDimitry Andric   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
178a7dea167SDimitry Andric   Expr::EvalResult EvalResult;
179a7dea167SDimitry Andric   EvalResult.Diag = &EvaluationDiags;
180fe6060f1SDimitry Andric   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
181fe6060f1SDimitry Andric                                                            S.Context) ||
182fe6060f1SDimitry Andric       !EvaluationDiags.empty()) {
183a7dea167SDimitry Andric     // C++2a [temp.constr.atomic]p1
184a7dea167SDimitry Andric     //   ...E shall be a constant expression of type bool.
185480093f4SDimitry Andric     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
186a7dea167SDimitry Andric            diag::err_non_constant_constraint_expression)
187480093f4SDimitry Andric         << SubstitutedAtomicExpr.get()->getSourceRange();
188a7dea167SDimitry Andric     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
189480093f4SDimitry Andric       S.Diag(PDiag.first, PDiag.second);
190a7dea167SDimitry Andric     return true;
191a7dea167SDimitry Andric   }
192a7dea167SDimitry Andric 
193fe6060f1SDimitry Andric   assert(EvalResult.Val.isInt() &&
194fe6060f1SDimitry Andric          "evaluating bool expression didn't produce int");
195480093f4SDimitry Andric   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
196480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied)
197480093f4SDimitry Andric     Satisfaction.Details.emplace_back(ConstraintExpr,
198480093f4SDimitry Andric                                       SubstitutedAtomicExpr.get());
199a7dea167SDimitry Andric 
200a7dea167SDimitry Andric   return false;
201a7dea167SDimitry Andric }
202480093f4SDimitry Andric 
203480093f4SDimitry Andric static bool calculateConstraintSatisfaction(
20413138422SDimitry Andric     Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
205480093f4SDimitry Andric     SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
206480093f4SDimitry Andric     const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
207480093f4SDimitry Andric   return calculateConstraintSatisfaction(
208480093f4SDimitry Andric       S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
209480093f4SDimitry Andric         EnterExpressionEvaluationContext ConstantEvaluated(
210480093f4SDimitry Andric             S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
211480093f4SDimitry Andric 
212480093f4SDimitry Andric         // Atomic constraint - substitute arguments and check satisfaction.
213480093f4SDimitry Andric         ExprResult SubstitutedExpression;
214480093f4SDimitry Andric         {
215480093f4SDimitry Andric           TemplateDeductionInfo Info(TemplateNameLoc);
216480093f4SDimitry Andric           Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
21713138422SDimitry Andric               Sema::InstantiatingTemplate::ConstraintSubstitution{},
21813138422SDimitry Andric               const_cast<NamedDecl *>(Template), Info,
21913138422SDimitry Andric               AtomicExpr->getSourceRange());
220480093f4SDimitry Andric           if (Inst.isInvalid())
221480093f4SDimitry Andric             return ExprError();
222480093f4SDimitry Andric           // We do not want error diagnostics escaping here.
223480093f4SDimitry Andric           Sema::SFINAETrap Trap(S);
224480093f4SDimitry Andric           SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
225480093f4SDimitry Andric                                               MLTAL);
226fe6060f1SDimitry Andric           // Substitution might have stripped off a contextual conversion to
227fe6060f1SDimitry Andric           // bool if this is the operand of an '&&' or '||'. For example, we
228fe6060f1SDimitry Andric           // might lose an lvalue-to-rvalue conversion here. If so, put it back
229fe6060f1SDimitry Andric           // before we try to evaluate.
230fe6060f1SDimitry Andric           if (!SubstitutedExpression.isInvalid())
231fe6060f1SDimitry Andric             SubstitutedExpression =
232fe6060f1SDimitry Andric                 S.PerformContextuallyConvertToBool(SubstitutedExpression.get());
233480093f4SDimitry Andric           if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
234480093f4SDimitry Andric             // C++2a [temp.constr.atomic]p1
235480093f4SDimitry Andric             //   ...If substitution results in an invalid type or expression, the
236480093f4SDimitry Andric             //   constraint is not satisfied.
237480093f4SDimitry Andric             if (!Trap.hasErrorOccurred())
238480093f4SDimitry Andric               // A non-SFINAE error has occured as a result of this
239480093f4SDimitry Andric               // substitution.
240480093f4SDimitry Andric               return ExprError();
241480093f4SDimitry Andric 
242480093f4SDimitry Andric             PartialDiagnosticAt SubstDiag{SourceLocation(),
243480093f4SDimitry Andric                                           PartialDiagnostic::NullDiagnostic()};
244480093f4SDimitry Andric             Info.takeSFINAEDiagnostic(SubstDiag);
245480093f4SDimitry Andric             // FIXME: Concepts: This is an unfortunate consequence of there
246480093f4SDimitry Andric             //  being no serialization code for PartialDiagnostics and the fact
247480093f4SDimitry Andric             //  that serializing them would likely take a lot more storage than
248480093f4SDimitry Andric             //  just storing them as strings. We would still like, in the
249480093f4SDimitry Andric             //  future, to serialize the proper PartialDiagnostic as serializing
250480093f4SDimitry Andric             //  it as a string defeats the purpose of the diagnostic mechanism.
251480093f4SDimitry Andric             SmallString<128> DiagString;
252480093f4SDimitry Andric             DiagString = ": ";
253480093f4SDimitry Andric             SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
254480093f4SDimitry Andric             unsigned MessageSize = DiagString.size();
255480093f4SDimitry Andric             char *Mem = new (S.Context) char[MessageSize];
256480093f4SDimitry Andric             memcpy(Mem, DiagString.c_str(), MessageSize);
257480093f4SDimitry Andric             Satisfaction.Details.emplace_back(
258480093f4SDimitry Andric                 AtomicExpr,
259480093f4SDimitry Andric                 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
260480093f4SDimitry Andric                         SubstDiag.first, StringRef(Mem, MessageSize)});
261480093f4SDimitry Andric             Satisfaction.IsSatisfied = false;
262480093f4SDimitry Andric             return ExprEmpty();
263480093f4SDimitry Andric           }
264480093f4SDimitry Andric         }
265480093f4SDimitry Andric 
266480093f4SDimitry Andric         if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
267480093f4SDimitry Andric           return ExprError();
268480093f4SDimitry Andric 
269480093f4SDimitry Andric         return SubstitutedExpression;
270480093f4SDimitry Andric       });
271480093f4SDimitry Andric }
272480093f4SDimitry Andric 
27313138422SDimitry Andric static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
274480093f4SDimitry Andric                                         ArrayRef<const Expr *> ConstraintExprs,
275480093f4SDimitry Andric                                         ArrayRef<TemplateArgument> TemplateArgs,
276480093f4SDimitry Andric                                         SourceRange TemplateIDRange,
277480093f4SDimitry Andric                                         ConstraintSatisfaction &Satisfaction) {
278480093f4SDimitry Andric   if (ConstraintExprs.empty()) {
279480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
280480093f4SDimitry Andric     return false;
281480093f4SDimitry Andric   }
282480093f4SDimitry Andric 
283480093f4SDimitry Andric   for (auto& Arg : TemplateArgs)
284480093f4SDimitry Andric     if (Arg.isInstantiationDependent()) {
285480093f4SDimitry Andric       // No need to check satisfaction for dependent constraint expressions.
286480093f4SDimitry Andric       Satisfaction.IsSatisfied = true;
287480093f4SDimitry Andric       return false;
288480093f4SDimitry Andric     }
289480093f4SDimitry Andric 
290480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
29113138422SDimitry Andric       Sema::InstantiatingTemplate::ConstraintsCheck{},
29213138422SDimitry Andric       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
293480093f4SDimitry Andric   if (Inst.isInvalid())
294480093f4SDimitry Andric     return true;
295480093f4SDimitry Andric 
296480093f4SDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
297480093f4SDimitry Andric   MLTAL.addOuterTemplateArguments(TemplateArgs);
298480093f4SDimitry Andric 
299480093f4SDimitry Andric   for (const Expr *ConstraintExpr : ConstraintExprs) {
300480093f4SDimitry Andric     if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
301480093f4SDimitry Andric                                         TemplateIDRange.getBegin(), MLTAL,
302480093f4SDimitry Andric                                         ConstraintExpr, Satisfaction))
303480093f4SDimitry Andric       return true;
304480093f4SDimitry Andric     if (!Satisfaction.IsSatisfied)
305480093f4SDimitry Andric       // [temp.constr.op] p2
306480093f4SDimitry Andric       //   [...] To determine if a conjunction is satisfied, the satisfaction
307480093f4SDimitry Andric       //   of the first operand is checked. If that is not satisfied, the
308480093f4SDimitry Andric       //   conjunction is not satisfied. [...]
309480093f4SDimitry Andric       return false;
310480093f4SDimitry Andric   }
311480093f4SDimitry Andric   return false;
312480093f4SDimitry Andric }
313480093f4SDimitry Andric 
31455e4f9d5SDimitry Andric bool Sema::CheckConstraintSatisfaction(
31513138422SDimitry Andric     const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
31655e4f9d5SDimitry Andric     ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
31755e4f9d5SDimitry Andric     ConstraintSatisfaction &OutSatisfaction) {
31855e4f9d5SDimitry Andric   if (ConstraintExprs.empty()) {
31955e4f9d5SDimitry Andric     OutSatisfaction.IsSatisfied = true;
32055e4f9d5SDimitry Andric     return false;
321480093f4SDimitry Andric   }
322480093f4SDimitry Andric 
32355e4f9d5SDimitry Andric   llvm::FoldingSetNodeID ID;
32455e4f9d5SDimitry Andric   void *InsertPos;
32555e4f9d5SDimitry Andric   ConstraintSatisfaction *Satisfaction = nullptr;
32613138422SDimitry Andric   bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
32713138422SDimitry Andric   if (ShouldCache) {
32855e4f9d5SDimitry Andric     ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
32955e4f9d5SDimitry Andric     Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
33055e4f9d5SDimitry Andric     if (Satisfaction) {
33155e4f9d5SDimitry Andric       OutSatisfaction = *Satisfaction;
33255e4f9d5SDimitry Andric       return false;
33355e4f9d5SDimitry Andric     }
33455e4f9d5SDimitry Andric     Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs);
33555e4f9d5SDimitry Andric   } else {
33655e4f9d5SDimitry Andric     Satisfaction = &OutSatisfaction;
33755e4f9d5SDimitry Andric   }
33813138422SDimitry Andric   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
339480093f4SDimitry Andric                                     TemplateArgs, TemplateIDRange,
34013138422SDimitry Andric                                     *Satisfaction)) {
34113138422SDimitry Andric     if (ShouldCache)
34255e4f9d5SDimitry Andric       delete Satisfaction;
34355e4f9d5SDimitry Andric     return true;
344480093f4SDimitry Andric   }
345480093f4SDimitry Andric 
34613138422SDimitry Andric   if (ShouldCache) {
34755e4f9d5SDimitry Andric     // We cannot use InsertNode here because CheckConstraintSatisfaction might
34855e4f9d5SDimitry Andric     // have invalidated it.
34955e4f9d5SDimitry Andric     SatisfactionCache.InsertNode(Satisfaction);
35055e4f9d5SDimitry Andric     OutSatisfaction = *Satisfaction;
35155e4f9d5SDimitry Andric   }
35255e4f9d5SDimitry Andric   return false;
353480093f4SDimitry Andric }
354480093f4SDimitry Andric 
355480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
356480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
357480093f4SDimitry Andric   return calculateConstraintSatisfaction(
358480093f4SDimitry Andric       *this, ConstraintExpr, Satisfaction,
359480093f4SDimitry Andric       [](const Expr *AtomicExpr) -> ExprResult {
360480093f4SDimitry Andric         return ExprResult(const_cast<Expr *>(AtomicExpr));
361480093f4SDimitry Andric       });
362480093f4SDimitry Andric }
363480093f4SDimitry Andric 
36413138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
36513138422SDimitry Andric                                     ConstraintSatisfaction &Satisfaction,
36613138422SDimitry Andric                                     SourceLocation UsageLoc) {
36713138422SDimitry Andric   const Expr *RC = FD->getTrailingRequiresClause();
36813138422SDimitry Andric   if (RC->isInstantiationDependent()) {
36913138422SDimitry Andric     Satisfaction.IsSatisfied = true;
37013138422SDimitry Andric     return false;
37113138422SDimitry Andric   }
37213138422SDimitry Andric   Qualifiers ThisQuals;
37313138422SDimitry Andric   CXXRecordDecl *Record = nullptr;
37413138422SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
37513138422SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
37613138422SDimitry Andric     Record = const_cast<CXXRecordDecl *>(Method->getParent());
37713138422SDimitry Andric   }
37813138422SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
37913138422SDimitry Andric   // We substitute with empty arguments in order to rebuild the atomic
38013138422SDimitry Andric   // constraint in a constant-evaluated context.
38113138422SDimitry Andric   // FIXME: Should this be a dedicated TreeTransform?
38213138422SDimitry Andric   return CheckConstraintSatisfaction(
38313138422SDimitry Andric       FD, {RC}, /*TemplateArgs=*/{},
38413138422SDimitry Andric       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
38513138422SDimitry Andric       Satisfaction);
38613138422SDimitry Andric }
38713138422SDimitry Andric 
388480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints(
389480093f4SDimitry Andric     TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
390480093f4SDimitry Andric     SourceRange TemplateIDRange) {
391480093f4SDimitry Andric   ConstraintSatisfaction Satisfaction;
392480093f4SDimitry Andric   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
393480093f4SDimitry Andric   TD->getAssociatedConstraints(AssociatedConstraints);
394480093f4SDimitry Andric   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
395480093f4SDimitry Andric                                   TemplateIDRange, Satisfaction))
396480093f4SDimitry Andric     return true;
397480093f4SDimitry Andric 
398480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied) {
399480093f4SDimitry Andric     SmallString<128> TemplateArgString;
400480093f4SDimitry Andric     TemplateArgString = " ";
401480093f4SDimitry Andric     TemplateArgString += getTemplateArgumentBindingsText(
402480093f4SDimitry Andric         TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
403480093f4SDimitry Andric 
404480093f4SDimitry Andric     Diag(TemplateIDRange.getBegin(),
405480093f4SDimitry Andric          diag::err_template_arg_list_constraints_not_satisfied)
406480093f4SDimitry Andric         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
407480093f4SDimitry Andric         << TemplateArgString << TemplateIDRange;
408480093f4SDimitry Andric     DiagnoseUnsatisfiedConstraint(Satisfaction);
409480093f4SDimitry Andric     return true;
410480093f4SDimitry Andric   }
411480093f4SDimitry Andric   return false;
412480093f4SDimitry Andric }
413480093f4SDimitry Andric 
41455e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
41555e4f9d5SDimitry Andric                                            concepts::ExprRequirement *Req,
41655e4f9d5SDimitry Andric                                            bool First) {
41755e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
41855e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
41955e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
42055e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Dependent:
42155e4f9d5SDimitry Andric       llvm_unreachable("Diagnosing a dependent requirement");
42255e4f9d5SDimitry Andric       break;
42355e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
42455e4f9d5SDimitry Andric       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
42555e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
42655e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
42755e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_substitution_error)
42855e4f9d5SDimitry Andric                << (int)First << SubstDiag->SubstitutedEntity
42955e4f9d5SDimitry Andric                << SubstDiag->DiagMessage;
43055e4f9d5SDimitry Andric       else
43155e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
43255e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_unknown_substitution_error)
43355e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
43455e4f9d5SDimitry Andric       break;
43555e4f9d5SDimitry Andric     }
43655e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_NoexceptNotMet:
43755e4f9d5SDimitry Andric       S.Diag(Req->getNoexceptLoc(),
43855e4f9d5SDimitry Andric              diag::note_expr_requirement_noexcept_not_met)
43955e4f9d5SDimitry Andric           << (int)First << Req->getExpr();
44055e4f9d5SDimitry Andric       break;
44155e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
44255e4f9d5SDimitry Andric       auto *SubstDiag =
44355e4f9d5SDimitry Andric           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
44455e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
44555e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
44655e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_substitution_error)
44755e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity
44855e4f9d5SDimitry Andric             << SubstDiag->DiagMessage;
44955e4f9d5SDimitry Andric       else
45055e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
45155e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
45255e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
45355e4f9d5SDimitry Andric       break;
45455e4f9d5SDimitry Andric     }
45555e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
45655e4f9d5SDimitry Andric       ConceptSpecializationExpr *ConstraintExpr =
45755e4f9d5SDimitry Andric           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
458fe6060f1SDimitry Andric       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
45955e4f9d5SDimitry Andric         // A simple case - expr type is the type being constrained and the concept
46055e4f9d5SDimitry Andric         // was not provided arguments.
461fe6060f1SDimitry Andric         Expr *e = Req->getExpr();
462fe6060f1SDimitry Andric         S.Diag(e->getBeginLoc(),
46355e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied_simple)
464fe6060f1SDimitry Andric             << (int)First << S.getDecltypeForParenthesizedExpr(e)
46555e4f9d5SDimitry Andric             << ConstraintExpr->getNamedConcept();
466fe6060f1SDimitry Andric       } else {
46755e4f9d5SDimitry Andric         S.Diag(ConstraintExpr->getBeginLoc(),
46855e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied)
46955e4f9d5SDimitry Andric             << (int)First << ConstraintExpr;
470fe6060f1SDimitry Andric       }
47155e4f9d5SDimitry Andric       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
47255e4f9d5SDimitry Andric       break;
47355e4f9d5SDimitry Andric     }
47455e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Satisfied:
47555e4f9d5SDimitry Andric       llvm_unreachable("We checked this above");
47655e4f9d5SDimitry Andric   }
47755e4f9d5SDimitry Andric }
47855e4f9d5SDimitry Andric 
47955e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
48055e4f9d5SDimitry Andric                                            concepts::TypeRequirement *Req,
48155e4f9d5SDimitry Andric                                            bool First) {
48255e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
48355e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
48455e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
48555e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_Dependent:
48655e4f9d5SDimitry Andric     llvm_unreachable("Diagnosing a dependent requirement");
48755e4f9d5SDimitry Andric     return;
48855e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_SubstitutionFailure: {
48955e4f9d5SDimitry Andric     auto *SubstDiag = Req->getSubstitutionDiagnostic();
49055e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
49155e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
49255e4f9d5SDimitry Andric              diag::note_type_requirement_substitution_error) << (int)First
49355e4f9d5SDimitry Andric           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
49455e4f9d5SDimitry Andric     else
49555e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
49655e4f9d5SDimitry Andric              diag::note_type_requirement_unknown_substitution_error)
49755e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
49855e4f9d5SDimitry Andric     return;
49955e4f9d5SDimitry Andric   }
50055e4f9d5SDimitry Andric   default:
50155e4f9d5SDimitry Andric     llvm_unreachable("Unknown satisfaction status");
50255e4f9d5SDimitry Andric     return;
50355e4f9d5SDimitry Andric   }
50455e4f9d5SDimitry Andric }
50555e4f9d5SDimitry Andric 
50655e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
50755e4f9d5SDimitry Andric                                            concepts::NestedRequirement *Req,
50855e4f9d5SDimitry Andric                                            bool First) {
50955e4f9d5SDimitry Andric   if (Req->isSubstitutionFailure()) {
51055e4f9d5SDimitry Andric     concepts::Requirement::SubstitutionDiagnostic *SubstDiag =
51155e4f9d5SDimitry Andric         Req->getSubstitutionDiagnostic();
51255e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
51355e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
51455e4f9d5SDimitry Andric              diag::note_nested_requirement_substitution_error)
51555e4f9d5SDimitry Andric              << (int)First << SubstDiag->SubstitutedEntity
51655e4f9d5SDimitry Andric              << SubstDiag->DiagMessage;
51755e4f9d5SDimitry Andric     else
51855e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
51955e4f9d5SDimitry Andric              diag::note_nested_requirement_unknown_substitution_error)
52055e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
52155e4f9d5SDimitry Andric     return;
52255e4f9d5SDimitry Andric   }
52355e4f9d5SDimitry Andric   S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First);
52455e4f9d5SDimitry Andric }
52555e4f9d5SDimitry Andric 
52655e4f9d5SDimitry Andric 
527480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
528480093f4SDimitry Andric                                                         Expr *SubstExpr,
529480093f4SDimitry Andric                                                         bool First = true) {
530480093f4SDimitry Andric   SubstExpr = SubstExpr->IgnoreParenImpCasts();
531480093f4SDimitry Andric   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
532480093f4SDimitry Andric     switch (BO->getOpcode()) {
533480093f4SDimitry Andric     // These two cases will in practice only be reached when using fold
534480093f4SDimitry Andric     // expressions with || and &&, since otherwise the || and && will have been
535480093f4SDimitry Andric     // broken down into atomic constraints during satisfaction checking.
536480093f4SDimitry Andric     case BO_LOr:
537480093f4SDimitry Andric       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
538480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
539480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
540480093f4SDimitry Andric                                                   /*First=*/false);
541480093f4SDimitry Andric       return;
542fe6060f1SDimitry Andric     case BO_LAnd: {
543fe6060f1SDimitry Andric       bool LHSSatisfied =
544fe6060f1SDimitry Andric           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
545480093f4SDimitry Andric       if (LHSSatisfied) {
546480093f4SDimitry Andric         // LHS is true, so RHS must be false.
547480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
548480093f4SDimitry Andric         return;
549480093f4SDimitry Andric       }
550480093f4SDimitry Andric       // LHS is false
551480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
552480093f4SDimitry Andric 
553480093f4SDimitry Andric       // RHS might also be false
554fe6060f1SDimitry Andric       bool RHSSatisfied =
555fe6060f1SDimitry Andric           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
556480093f4SDimitry Andric       if (!RHSSatisfied)
557480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
558480093f4SDimitry Andric                                                     /*First=*/false);
559480093f4SDimitry Andric       return;
560fe6060f1SDimitry Andric     }
561480093f4SDimitry Andric     case BO_GE:
562480093f4SDimitry Andric     case BO_LE:
563480093f4SDimitry Andric     case BO_GT:
564480093f4SDimitry Andric     case BO_LT:
565480093f4SDimitry Andric     case BO_EQ:
566480093f4SDimitry Andric     case BO_NE:
567480093f4SDimitry Andric       if (BO->getLHS()->getType()->isIntegerType() &&
568480093f4SDimitry Andric           BO->getRHS()->getType()->isIntegerType()) {
569480093f4SDimitry Andric         Expr::EvalResult SimplifiedLHS;
570480093f4SDimitry Andric         Expr::EvalResult SimplifiedRHS;
571fe6060f1SDimitry Andric         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
572fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
573fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
574fe6060f1SDimitry Andric         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
575fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
576fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
577480093f4SDimitry Andric         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
578480093f4SDimitry Andric           S.Diag(SubstExpr->getBeginLoc(),
579480093f4SDimitry Andric                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
580480093f4SDimitry Andric               << (int)First << SubstExpr
581fe6060f1SDimitry Andric               << toString(SimplifiedLHS.Val.getInt(), 10)
582480093f4SDimitry Andric               << BinaryOperator::getOpcodeStr(BO->getOpcode())
583fe6060f1SDimitry Andric               << toString(SimplifiedRHS.Val.getInt(), 10);
584480093f4SDimitry Andric           return;
585480093f4SDimitry Andric         }
586480093f4SDimitry Andric       }
587480093f4SDimitry Andric       break;
588480093f4SDimitry Andric 
589480093f4SDimitry Andric     default:
590480093f4SDimitry Andric       break;
591480093f4SDimitry Andric     }
592480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
593480093f4SDimitry Andric     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
594480093f4SDimitry Andric       S.Diag(
595480093f4SDimitry Andric           CSE->getSourceRange().getBegin(),
596480093f4SDimitry Andric           diag::
597480093f4SDimitry Andric           note_single_arg_concept_specialization_constraint_evaluated_to_false)
598480093f4SDimitry Andric           << (int)First
599480093f4SDimitry Andric           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
600480093f4SDimitry Andric           << CSE->getNamedConcept();
601480093f4SDimitry Andric     } else {
602480093f4SDimitry Andric       S.Diag(SubstExpr->getSourceRange().getBegin(),
603480093f4SDimitry Andric              diag::note_concept_specialization_constraint_evaluated_to_false)
604480093f4SDimitry Andric           << (int)First << CSE;
605480093f4SDimitry Andric     }
606480093f4SDimitry Andric     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
607480093f4SDimitry Andric     return;
60855e4f9d5SDimitry Andric   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
60955e4f9d5SDimitry Andric     for (concepts::Requirement *Req : RE->getRequirements())
61055e4f9d5SDimitry Andric       if (!Req->isDependent() && !Req->isSatisfied()) {
61155e4f9d5SDimitry Andric         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
61255e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, E, First);
61355e4f9d5SDimitry Andric         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
61455e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, T, First);
61555e4f9d5SDimitry Andric         else
61655e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(
61755e4f9d5SDimitry Andric               S, cast<concepts::NestedRequirement>(Req), First);
61855e4f9d5SDimitry Andric         break;
61955e4f9d5SDimitry Andric       }
62055e4f9d5SDimitry Andric     return;
621480093f4SDimitry Andric   }
622480093f4SDimitry Andric 
623480093f4SDimitry Andric   S.Diag(SubstExpr->getSourceRange().getBegin(),
624480093f4SDimitry Andric          diag::note_atomic_constraint_evaluated_to_false)
625480093f4SDimitry Andric       << (int)First << SubstExpr;
626480093f4SDimitry Andric }
627480093f4SDimitry Andric 
628480093f4SDimitry Andric template<typename SubstitutionDiagnostic>
629480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr(
630480093f4SDimitry Andric     Sema &S, const Expr *E,
631480093f4SDimitry Andric     const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
632480093f4SDimitry Andric     bool First = true) {
633480093f4SDimitry Andric   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
634480093f4SDimitry Andric     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
635480093f4SDimitry Andric         << Diag->second;
636480093f4SDimitry Andric     return;
637480093f4SDimitry Andric   }
638480093f4SDimitry Andric 
639480093f4SDimitry Andric   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
640480093f4SDimitry Andric       Record.template get<Expr *>(), First);
641480093f4SDimitry Andric }
642480093f4SDimitry Andric 
64355e4f9d5SDimitry Andric void
64455e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
64555e4f9d5SDimitry Andric                                     bool First) {
646480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
647480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
648480093f4SDimitry Andric   for (auto &Pair : Satisfaction.Details) {
649480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
650480093f4SDimitry Andric     First = false;
651480093f4SDimitry Andric   }
652480093f4SDimitry Andric }
653480093f4SDimitry Andric 
654480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
65555e4f9d5SDimitry Andric     const ASTConstraintSatisfaction &Satisfaction,
65655e4f9d5SDimitry Andric     bool First) {
657480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
658480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
659480093f4SDimitry Andric   for (auto &Pair : Satisfaction) {
660480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
661480093f4SDimitry Andric     First = false;
662480093f4SDimitry Andric   }
663480093f4SDimitry Andric }
664480093f4SDimitry Andric 
665480093f4SDimitry Andric const NormalizedConstraint *
666480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints(
667480093f4SDimitry Andric     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
668480093f4SDimitry Andric   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
669480093f4SDimitry Andric   if (CacheEntry == NormalizationCache.end()) {
670480093f4SDimitry Andric     auto Normalized =
671480093f4SDimitry Andric         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
672480093f4SDimitry Andric                                                   AssociatedConstraints);
673480093f4SDimitry Andric     CacheEntry =
674480093f4SDimitry Andric         NormalizationCache
675480093f4SDimitry Andric             .try_emplace(ConstrainedDecl,
676480093f4SDimitry Andric                          Normalized
677480093f4SDimitry Andric                              ? new (Context) NormalizedConstraint(
678480093f4SDimitry Andric                                  std::move(*Normalized))
679480093f4SDimitry Andric                              : nullptr)
680480093f4SDimitry Andric             .first;
681480093f4SDimitry Andric   }
682480093f4SDimitry Andric   return CacheEntry->second;
683480093f4SDimitry Andric }
684480093f4SDimitry Andric 
685480093f4SDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
686480093f4SDimitry Andric     ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
687480093f4SDimitry Andric     const ASTTemplateArgumentListInfo *ArgsAsWritten) {
688480093f4SDimitry Andric   if (!N.isAtomic()) {
689480093f4SDimitry Andric     if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
690480093f4SDimitry Andric                                     ArgsAsWritten))
691480093f4SDimitry Andric       return true;
692480093f4SDimitry Andric     return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
693480093f4SDimitry Andric                                        ArgsAsWritten);
694480093f4SDimitry Andric   }
695480093f4SDimitry Andric   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
696480093f4SDimitry Andric 
697480093f4SDimitry Andric   AtomicConstraint &Atomic = *N.getAtomicConstraint();
698480093f4SDimitry Andric   TemplateArgumentListInfo SubstArgs;
699480093f4SDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
700480093f4SDimitry Andric   MLTAL.addOuterTemplateArguments(TemplateArgs);
701480093f4SDimitry Andric   if (!Atomic.ParameterMapping) {
702480093f4SDimitry Andric     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
703480093f4SDimitry Andric     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
704480093f4SDimitry Andric                                  /*Depth=*/0, OccurringIndices);
705480093f4SDimitry Andric     Atomic.ParameterMapping.emplace(
706480093f4SDimitry Andric         MutableArrayRef<TemplateArgumentLoc>(
707480093f4SDimitry Andric             new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
708480093f4SDimitry Andric             OccurringIndices.count()));
709480093f4SDimitry Andric     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
710480093f4SDimitry Andric       if (OccurringIndices[I])
711480093f4SDimitry Andric         new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
712480093f4SDimitry Andric             S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
713480093f4SDimitry Andric                 // Here we assume we do not support things like
714480093f4SDimitry Andric                 // template<typename A, typename B>
715480093f4SDimitry Andric                 // concept C = ...;
716480093f4SDimitry Andric                 //
717480093f4SDimitry Andric                 // template<typename... Ts> requires C<Ts...>
718480093f4SDimitry Andric                 // struct S { };
719480093f4SDimitry Andric                 // The above currently yields a diagnostic.
720480093f4SDimitry Andric                 // We still might have default arguments for concept parameters.
721480093f4SDimitry Andric                 ArgsAsWritten->NumTemplateArgs > I ?
722480093f4SDimitry Andric                 ArgsAsWritten->arguments()[I].getLocation() :
723480093f4SDimitry Andric                 SourceLocation()));
724480093f4SDimitry Andric   }
725480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(
726480093f4SDimitry Andric       S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
727480093f4SDimitry Andric       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
728480093f4SDimitry Andric       SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
729480093f4SDimitry Andric                   ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
730480093f4SDimitry Andric   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
731480093f4SDimitry Andric     return true;
73213138422SDimitry Andric   Atomic.ParameterMapping.emplace(
73313138422SDimitry Andric         MutableArrayRef<TemplateArgumentLoc>(
73413138422SDimitry Andric             new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
73513138422SDimitry Andric             SubstArgs.size()));
736480093f4SDimitry Andric   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
737480093f4SDimitry Andric             N.getAtomicConstraint()->ParameterMapping->begin());
738480093f4SDimitry Andric   return false;
739480093f4SDimitry Andric }
740480093f4SDimitry Andric 
741480093f4SDimitry Andric Optional<NormalizedConstraint>
742480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
743480093f4SDimitry Andric                                           ArrayRef<const Expr *> E) {
744480093f4SDimitry Andric   assert(E.size() != 0);
745*6e75b2fbSDimitry Andric   auto Conjunction = fromConstraintExpr(S, D, E[0]);
746*6e75b2fbSDimitry Andric   if (!Conjunction)
747480093f4SDimitry Andric     return None;
748*6e75b2fbSDimitry Andric   for (unsigned I = 1; I < E.size(); ++I) {
749480093f4SDimitry Andric     auto Next = fromConstraintExpr(S, D, E[I]);
750480093f4SDimitry Andric     if (!Next)
751*6e75b2fbSDimitry Andric       return None;
752*6e75b2fbSDimitry Andric     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
753480093f4SDimitry Andric                                         std::move(*Next), CCK_Conjunction);
754480093f4SDimitry Andric   }
755480093f4SDimitry Andric   return Conjunction;
756480093f4SDimitry Andric }
757480093f4SDimitry Andric 
758480093f4SDimitry Andric llvm::Optional<NormalizedConstraint>
759480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
760480093f4SDimitry Andric   assert(E != nullptr);
761480093f4SDimitry Andric 
762480093f4SDimitry Andric   // C++ [temp.constr.normal]p1.1
763480093f4SDimitry Andric   // [...]
764480093f4SDimitry Andric   // - The normal form of an expression (E) is the normal form of E.
765480093f4SDimitry Andric   // [...]
766480093f4SDimitry Andric   E = E->IgnoreParenImpCasts();
7675ffd83dbSDimitry Andric   if (LogicalBinOp BO = E) {
7685ffd83dbSDimitry Andric     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
769480093f4SDimitry Andric     if (!LHS)
770480093f4SDimitry Andric       return None;
7715ffd83dbSDimitry Andric     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
772480093f4SDimitry Andric     if (!RHS)
773480093f4SDimitry Andric       return None;
774480093f4SDimitry Andric 
7755ffd83dbSDimitry Andric     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
7765ffd83dbSDimitry Andric                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
777480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
778480093f4SDimitry Andric     const NormalizedConstraint *SubNF;
779480093f4SDimitry Andric     {
780480093f4SDimitry Andric       Sema::InstantiatingTemplate Inst(
781480093f4SDimitry Andric           S, CSE->getExprLoc(),
782480093f4SDimitry Andric           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
783480093f4SDimitry Andric           CSE->getSourceRange());
784480093f4SDimitry Andric       // C++ [temp.constr.normal]p1.1
785480093f4SDimitry Andric       // [...]
786480093f4SDimitry Andric       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
787480093f4SDimitry Andric       // where C names a concept, is the normal form of the
788480093f4SDimitry Andric       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
789480093f4SDimitry Andric       // respective template parameters in the parameter mappings in each atomic
790480093f4SDimitry Andric       // constraint. If any such substitution results in an invalid type or
791480093f4SDimitry Andric       // expression, the program is ill-formed; no diagnostic is required.
792480093f4SDimitry Andric       // [...]
793480093f4SDimitry Andric       ConceptDecl *CD = CSE->getNamedConcept();
794480093f4SDimitry Andric       SubNF = S.getNormalizedAssociatedConstraints(CD,
795480093f4SDimitry Andric                                                    {CD->getConstraintExpr()});
796480093f4SDimitry Andric       if (!SubNF)
797480093f4SDimitry Andric         return None;
798480093f4SDimitry Andric     }
799480093f4SDimitry Andric 
800480093f4SDimitry Andric     Optional<NormalizedConstraint> New;
801480093f4SDimitry Andric     New.emplace(S.Context, *SubNF);
802480093f4SDimitry Andric 
803480093f4SDimitry Andric     if (substituteParameterMappings(
804480093f4SDimitry Andric             S, *New, CSE->getNamedConcept(),
805480093f4SDimitry Andric             CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
806480093f4SDimitry Andric       return None;
807480093f4SDimitry Andric 
808480093f4SDimitry Andric     return New;
809480093f4SDimitry Andric   }
810480093f4SDimitry Andric   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
811480093f4SDimitry Andric }
812480093f4SDimitry Andric 
813480093f4SDimitry Andric using NormalForm =
814480093f4SDimitry Andric     llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
815480093f4SDimitry Andric 
816480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
817480093f4SDimitry Andric   if (Normalized.isAtomic())
818480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
819480093f4SDimitry Andric 
820480093f4SDimitry Andric   NormalForm LCNF = makeCNF(Normalized.getLHS());
821480093f4SDimitry Andric   NormalForm RCNF = makeCNF(Normalized.getRHS());
822480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
823480093f4SDimitry Andric     LCNF.reserve(LCNF.size() + RCNF.size());
824480093f4SDimitry Andric     while (!RCNF.empty())
825480093f4SDimitry Andric       LCNF.push_back(RCNF.pop_back_val());
826480093f4SDimitry Andric     return LCNF;
827480093f4SDimitry Andric   }
828480093f4SDimitry Andric 
829480093f4SDimitry Andric   // Disjunction
830480093f4SDimitry Andric   NormalForm Res;
831480093f4SDimitry Andric   Res.reserve(LCNF.size() * RCNF.size());
832480093f4SDimitry Andric   for (auto &LDisjunction : LCNF)
833480093f4SDimitry Andric     for (auto &RDisjunction : RCNF) {
834480093f4SDimitry Andric       NormalForm::value_type Combined;
835480093f4SDimitry Andric       Combined.reserve(LDisjunction.size() + RDisjunction.size());
836480093f4SDimitry Andric       std::copy(LDisjunction.begin(), LDisjunction.end(),
837480093f4SDimitry Andric                 std::back_inserter(Combined));
838480093f4SDimitry Andric       std::copy(RDisjunction.begin(), RDisjunction.end(),
839480093f4SDimitry Andric                 std::back_inserter(Combined));
840480093f4SDimitry Andric       Res.emplace_back(Combined);
841480093f4SDimitry Andric     }
842480093f4SDimitry Andric   return Res;
843480093f4SDimitry Andric }
844480093f4SDimitry Andric 
845480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
846480093f4SDimitry Andric   if (Normalized.isAtomic())
847480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
848480093f4SDimitry Andric 
849480093f4SDimitry Andric   NormalForm LDNF = makeDNF(Normalized.getLHS());
850480093f4SDimitry Andric   NormalForm RDNF = makeDNF(Normalized.getRHS());
851480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
852480093f4SDimitry Andric     LDNF.reserve(LDNF.size() + RDNF.size());
853480093f4SDimitry Andric     while (!RDNF.empty())
854480093f4SDimitry Andric       LDNF.push_back(RDNF.pop_back_val());
855480093f4SDimitry Andric     return LDNF;
856480093f4SDimitry Andric   }
857480093f4SDimitry Andric 
858480093f4SDimitry Andric   // Conjunction
859480093f4SDimitry Andric   NormalForm Res;
860480093f4SDimitry Andric   Res.reserve(LDNF.size() * RDNF.size());
861480093f4SDimitry Andric   for (auto &LConjunction : LDNF) {
862480093f4SDimitry Andric     for (auto &RConjunction : RDNF) {
863480093f4SDimitry Andric       NormalForm::value_type Combined;
864480093f4SDimitry Andric       Combined.reserve(LConjunction.size() + RConjunction.size());
865480093f4SDimitry Andric       std::copy(LConjunction.begin(), LConjunction.end(),
866480093f4SDimitry Andric                 std::back_inserter(Combined));
867480093f4SDimitry Andric       std::copy(RConjunction.begin(), RConjunction.end(),
868480093f4SDimitry Andric                 std::back_inserter(Combined));
869480093f4SDimitry Andric       Res.emplace_back(Combined);
870480093f4SDimitry Andric     }
871480093f4SDimitry Andric   }
872480093f4SDimitry Andric   return Res;
873480093f4SDimitry Andric }
874480093f4SDimitry Andric 
875480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
876480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF,
877480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
878480093f4SDimitry Andric   // C++ [temp.constr.order] p2
879480093f4SDimitry Andric   //   Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
880480093f4SDimitry Andric   //   disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
881480093f4SDimitry Andric   //   the conjuctive normal form of Q, where [...]
882480093f4SDimitry Andric   for (const auto &Pi : PDNF) {
883480093f4SDimitry Andric     for (const auto &Qj : QCNF) {
884480093f4SDimitry Andric       // C++ [temp.constr.order] p2
885480093f4SDimitry Andric       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
886480093f4SDimitry Andric       //     and only if there exists an atomic constraint Pia in Pi for which
887480093f4SDimitry Andric       //     there exists an atomic constraint, Qjb, in Qj such that Pia
888480093f4SDimitry Andric       //     subsumes Qjb.
889480093f4SDimitry Andric       bool Found = false;
890480093f4SDimitry Andric       for (const AtomicConstraint *Pia : Pi) {
891480093f4SDimitry Andric         for (const AtomicConstraint *Qjb : Qj) {
892480093f4SDimitry Andric           if (E(*Pia, *Qjb)) {
893480093f4SDimitry Andric             Found = true;
894480093f4SDimitry Andric             break;
895480093f4SDimitry Andric           }
896480093f4SDimitry Andric         }
897480093f4SDimitry Andric         if (Found)
898480093f4SDimitry Andric           break;
899480093f4SDimitry Andric       }
900480093f4SDimitry Andric       if (!Found)
901480093f4SDimitry Andric         return false;
902480093f4SDimitry Andric     }
903480093f4SDimitry Andric   }
904480093f4SDimitry Andric   return true;
905480093f4SDimitry Andric }
906480093f4SDimitry Andric 
907480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
908480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
909480093f4SDimitry Andric                      NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
910480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
911480093f4SDimitry Andric   // C++ [temp.constr.order] p2
912480093f4SDimitry Andric   //   In order to determine if a constraint P subsumes a constraint Q, P is
913480093f4SDimitry Andric   //   transformed into disjunctive normal form, and Q is transformed into
914480093f4SDimitry Andric   //   conjunctive normal form. [...]
915480093f4SDimitry Andric   auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
916480093f4SDimitry Andric   if (!PNormalized)
917480093f4SDimitry Andric     return true;
918480093f4SDimitry Andric   const NormalForm PDNF = makeDNF(*PNormalized);
919480093f4SDimitry Andric 
920480093f4SDimitry Andric   auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
921480093f4SDimitry Andric   if (!QNormalized)
922480093f4SDimitry Andric     return true;
923480093f4SDimitry Andric   const NormalForm QCNF = makeCNF(*QNormalized);
924480093f4SDimitry Andric 
925480093f4SDimitry Andric   Subsumes = subsumes(PDNF, QCNF, E);
926480093f4SDimitry Andric   return false;
927480093f4SDimitry Andric }
928480093f4SDimitry Andric 
929480093f4SDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
930480093f4SDimitry Andric                                   NamedDecl *D2, ArrayRef<const Expr *> AC2,
931480093f4SDimitry Andric                                   bool &Result) {
932480093f4SDimitry Andric   if (AC1.empty()) {
933480093f4SDimitry Andric     Result = AC2.empty();
934480093f4SDimitry Andric     return false;
935480093f4SDimitry Andric   }
936480093f4SDimitry Andric   if (AC2.empty()) {
937480093f4SDimitry Andric     // TD1 has associated constraints and TD2 does not.
938480093f4SDimitry Andric     Result = true;
939480093f4SDimitry Andric     return false;
940480093f4SDimitry Andric   }
941480093f4SDimitry Andric 
942480093f4SDimitry Andric   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
943480093f4SDimitry Andric   auto CacheEntry = SubsumptionCache.find(Key);
944480093f4SDimitry Andric   if (CacheEntry != SubsumptionCache.end()) {
945480093f4SDimitry Andric     Result = CacheEntry->second;
946480093f4SDimitry Andric     return false;
947480093f4SDimitry Andric   }
948480093f4SDimitry Andric 
949480093f4SDimitry Andric   if (subsumes(*this, D1, AC1, D2, AC2, Result,
950480093f4SDimitry Andric         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
951480093f4SDimitry Andric           return A.subsumes(Context, B);
952480093f4SDimitry Andric         }))
953480093f4SDimitry Andric     return true;
954480093f4SDimitry Andric   SubsumptionCache.try_emplace(Key, Result);
955480093f4SDimitry Andric   return false;
956480093f4SDimitry Andric }
957480093f4SDimitry Andric 
958480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
959480093f4SDimitry Andric     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
960480093f4SDimitry Andric   if (isSFINAEContext())
961480093f4SDimitry Andric     // No need to work here because our notes would be discarded.
962480093f4SDimitry Andric     return false;
963480093f4SDimitry Andric 
964480093f4SDimitry Andric   if (AC1.empty() || AC2.empty())
965480093f4SDimitry Andric     return false;
966480093f4SDimitry Andric 
967480093f4SDimitry Andric   auto NormalExprEvaluator =
968480093f4SDimitry Andric       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
969480093f4SDimitry Andric         return A.subsumes(Context, B);
970480093f4SDimitry Andric       };
971480093f4SDimitry Andric 
972480093f4SDimitry Andric   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
973480093f4SDimitry Andric   auto IdenticalExprEvaluator =
974480093f4SDimitry Andric       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
975480093f4SDimitry Andric         if (!A.hasMatchingParameterMapping(Context, B))
976480093f4SDimitry Andric           return false;
977480093f4SDimitry Andric         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
978480093f4SDimitry Andric         if (EA == EB)
979480093f4SDimitry Andric           return true;
980480093f4SDimitry Andric 
981480093f4SDimitry Andric         // Not the same source level expression - are the expressions
982480093f4SDimitry Andric         // identical?
983480093f4SDimitry Andric         llvm::FoldingSetNodeID IDA, IDB;
984480093f4SDimitry Andric         EA->Profile(IDA, Context, /*Cannonical=*/true);
985480093f4SDimitry Andric         EB->Profile(IDB, Context, /*Cannonical=*/true);
986480093f4SDimitry Andric         if (IDA != IDB)
987480093f4SDimitry Andric           return false;
988480093f4SDimitry Andric 
989480093f4SDimitry Andric         AmbiguousAtomic1 = EA;
990480093f4SDimitry Andric         AmbiguousAtomic2 = EB;
991480093f4SDimitry Andric         return true;
992480093f4SDimitry Andric       };
993480093f4SDimitry Andric 
994480093f4SDimitry Andric   {
995480093f4SDimitry Andric     // The subsumption checks might cause diagnostics
996480093f4SDimitry Andric     SFINAETrap Trap(*this);
997480093f4SDimitry Andric     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
998480093f4SDimitry Andric     if (!Normalized1)
999480093f4SDimitry Andric       return false;
1000480093f4SDimitry Andric     const NormalForm DNF1 = makeDNF(*Normalized1);
1001480093f4SDimitry Andric     const NormalForm CNF1 = makeCNF(*Normalized1);
1002480093f4SDimitry Andric 
1003480093f4SDimitry Andric     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1004480093f4SDimitry Andric     if (!Normalized2)
1005480093f4SDimitry Andric       return false;
1006480093f4SDimitry Andric     const NormalForm DNF2 = makeDNF(*Normalized2);
1007480093f4SDimitry Andric     const NormalForm CNF2 = makeCNF(*Normalized2);
1008480093f4SDimitry Andric 
1009480093f4SDimitry Andric     bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1010480093f4SDimitry Andric     bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1011480093f4SDimitry Andric     bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1012480093f4SDimitry Andric     bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1013480093f4SDimitry Andric     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1014480093f4SDimitry Andric         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1015480093f4SDimitry Andric       // Same result - no ambiguity was caused by identical atomic expressions.
1016480093f4SDimitry Andric       return false;
1017480093f4SDimitry Andric   }
1018480093f4SDimitry Andric 
1019480093f4SDimitry Andric   // A different result! Some ambiguous atomic constraint(s) caused a difference
1020480093f4SDimitry Andric   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1021480093f4SDimitry Andric 
1022480093f4SDimitry Andric   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1023480093f4SDimitry Andric       << AmbiguousAtomic1->getSourceRange();
1024480093f4SDimitry Andric   Diag(AmbiguousAtomic2->getBeginLoc(),
1025480093f4SDimitry Andric        diag::note_ambiguous_atomic_constraints_similar_expression)
1026480093f4SDimitry Andric       << AmbiguousAtomic2->getSourceRange();
1027480093f4SDimitry Andric   return true;
1028480093f4SDimitry Andric }
102955e4f9d5SDimitry Andric 
103055e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
103155e4f9d5SDimitry Andric     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
103255e4f9d5SDimitry Andric     ReturnTypeRequirement Req, SatisfactionStatus Status,
103355e4f9d5SDimitry Andric     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
103455e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
103555e4f9d5SDimitry Andric                 Status == SS_Dependent &&
103655e4f9d5SDimitry Andric                 (E->containsUnexpandedParameterPack() ||
103755e4f9d5SDimitry Andric                  Req.containsUnexpandedParameterPack()),
103855e4f9d5SDimitry Andric                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
103955e4f9d5SDimitry Andric     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
104055e4f9d5SDimitry Andric     Status(Status) {
104155e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
104255e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
104355e4f9d5SDimitry Andric          "noexcept specification");
104455e4f9d5SDimitry Andric   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
104555e4f9d5SDimitry Andric          (SubstitutedConstraintExpr != nullptr));
104655e4f9d5SDimitry Andric }
104755e4f9d5SDimitry Andric 
104855e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
104955e4f9d5SDimitry Andric     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
105055e4f9d5SDimitry Andric     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
105155e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
105255e4f9d5SDimitry Andric                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
105355e4f9d5SDimitry Andric     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
105455e4f9d5SDimitry Andric     Status(SS_ExprSubstitutionFailure) {
105555e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
105655e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
105755e4f9d5SDimitry Andric          "noexcept specification");
105855e4f9d5SDimitry Andric }
105955e4f9d5SDimitry Andric 
106055e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement::
106155e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) :
106255e4f9d5SDimitry Andric     TypeConstraintInfo(TPL, 0) {
106355e4f9d5SDimitry Andric   assert(TPL->size() == 1);
106455e4f9d5SDimitry Andric   const TypeConstraint *TC =
106555e4f9d5SDimitry Andric       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
106655e4f9d5SDimitry Andric   assert(TC &&
106755e4f9d5SDimitry Andric          "TPL must have a template type parameter with a type constraint");
106855e4f9d5SDimitry Andric   auto *Constraint =
106955e4f9d5SDimitry Andric       cast_or_null<ConceptSpecializationExpr>(
107055e4f9d5SDimitry Andric           TC->getImmediatelyDeclaredConstraint());
1071e8d8bef9SDimitry Andric   bool Dependent =
1072e8d8bef9SDimitry Andric       Constraint->getTemplateArgsAsWritten() &&
1073e8d8bef9SDimitry Andric       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1074e8d8bef9SDimitry Andric           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
107555e4f9d5SDimitry Andric   TypeConstraintInfo.setInt(Dependent ? 1 : 0);
107655e4f9d5SDimitry Andric }
107755e4f9d5SDimitry Andric 
107855e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1079e8d8bef9SDimitry Andric     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
108055e4f9d5SDimitry Andric                 T->getType()->containsUnexpandedParameterPack(),
108155e4f9d5SDimitry Andric                 // We reach this ctor with either dependent types (in which
108255e4f9d5SDimitry Andric                 // IsSatisfied doesn't matter) or with non-dependent type in
108355e4f9d5SDimitry Andric                 // which the existence of the type indicates satisfaction.
1084e8d8bef9SDimitry Andric                 /*IsSatisfied=*/true),
1085e8d8bef9SDimitry Andric     Value(T),
1086e8d8bef9SDimitry Andric     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1087e8d8bef9SDimitry Andric                                                         : SS_Satisfied) {}
1088