xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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   }
320480093f4SDimitry Andric 
32155e4f9d5SDimitry Andric   llvm::FoldingSetNodeID ID;
32255e4f9d5SDimitry Andric   void *InsertPos;
32355e4f9d5SDimitry Andric   ConstraintSatisfaction *Satisfaction = nullptr;
32413138422SDimitry Andric   bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
32513138422SDimitry Andric   if (ShouldCache) {
32655e4f9d5SDimitry Andric     ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
32755e4f9d5SDimitry Andric     Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
32855e4f9d5SDimitry Andric     if (Satisfaction) {
32955e4f9d5SDimitry Andric       OutSatisfaction = *Satisfaction;
33055e4f9d5SDimitry Andric       return false;
33155e4f9d5SDimitry Andric     }
33255e4f9d5SDimitry Andric     Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs);
33355e4f9d5SDimitry Andric   } else {
33455e4f9d5SDimitry Andric     Satisfaction = &OutSatisfaction;
33555e4f9d5SDimitry Andric   }
33613138422SDimitry Andric   if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
337480093f4SDimitry Andric                                     TemplateArgs, TemplateIDRange,
33813138422SDimitry Andric                                     *Satisfaction)) {
33913138422SDimitry Andric     if (ShouldCache)
34055e4f9d5SDimitry Andric       delete Satisfaction;
34155e4f9d5SDimitry Andric     return true;
342480093f4SDimitry Andric   }
343480093f4SDimitry Andric 
34413138422SDimitry Andric   if (ShouldCache) {
34555e4f9d5SDimitry Andric     // We cannot use InsertNode here because CheckConstraintSatisfaction might
34655e4f9d5SDimitry Andric     // have invalidated it.
34755e4f9d5SDimitry Andric     SatisfactionCache.InsertNode(Satisfaction);
34855e4f9d5SDimitry Andric     OutSatisfaction = *Satisfaction;
34955e4f9d5SDimitry Andric   }
35055e4f9d5SDimitry Andric   return false;
351480093f4SDimitry Andric }
352480093f4SDimitry Andric 
353480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
354480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
355480093f4SDimitry Andric   return calculateConstraintSatisfaction(
356480093f4SDimitry Andric       *this, ConstraintExpr, Satisfaction,
357480093f4SDimitry Andric       [](const Expr *AtomicExpr) -> ExprResult {
358480093f4SDimitry Andric         return ExprResult(const_cast<Expr *>(AtomicExpr));
359480093f4SDimitry Andric       });
360480093f4SDimitry Andric }
361480093f4SDimitry Andric 
36213138422SDimitry Andric bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
36313138422SDimitry Andric                                     ConstraintSatisfaction &Satisfaction,
36413138422SDimitry Andric                                     SourceLocation UsageLoc) {
36513138422SDimitry Andric   const Expr *RC = FD->getTrailingRequiresClause();
36613138422SDimitry Andric   if (RC->isInstantiationDependent()) {
36713138422SDimitry Andric     Satisfaction.IsSatisfied = true;
36813138422SDimitry Andric     return false;
36913138422SDimitry Andric   }
37013138422SDimitry Andric   Qualifiers ThisQuals;
37113138422SDimitry Andric   CXXRecordDecl *Record = nullptr;
37213138422SDimitry Andric   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
37313138422SDimitry Andric     ThisQuals = Method->getMethodQualifiers();
37413138422SDimitry Andric     Record = const_cast<CXXRecordDecl *>(Method->getParent());
37513138422SDimitry Andric   }
37613138422SDimitry Andric   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
37713138422SDimitry Andric   // We substitute with empty arguments in order to rebuild the atomic
37813138422SDimitry Andric   // constraint in a constant-evaluated context.
37913138422SDimitry Andric   // FIXME: Should this be a dedicated TreeTransform?
38013138422SDimitry Andric   return CheckConstraintSatisfaction(
38113138422SDimitry Andric       FD, {RC}, /*TemplateArgs=*/{},
38213138422SDimitry Andric       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
38313138422SDimitry Andric       Satisfaction);
38413138422SDimitry Andric }
38513138422SDimitry Andric 
386480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints(
387480093f4SDimitry Andric     TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
388480093f4SDimitry Andric     SourceRange TemplateIDRange) {
389480093f4SDimitry Andric   ConstraintSatisfaction Satisfaction;
390480093f4SDimitry Andric   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
391480093f4SDimitry Andric   TD->getAssociatedConstraints(AssociatedConstraints);
392480093f4SDimitry Andric   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
393480093f4SDimitry Andric                                   TemplateIDRange, Satisfaction))
394480093f4SDimitry Andric     return true;
395480093f4SDimitry Andric 
396480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied) {
397480093f4SDimitry Andric     SmallString<128> TemplateArgString;
398480093f4SDimitry Andric     TemplateArgString = " ";
399480093f4SDimitry Andric     TemplateArgString += getTemplateArgumentBindingsText(
400480093f4SDimitry Andric         TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
401480093f4SDimitry Andric 
402480093f4SDimitry Andric     Diag(TemplateIDRange.getBegin(),
403480093f4SDimitry Andric          diag::err_template_arg_list_constraints_not_satisfied)
404480093f4SDimitry Andric         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
405480093f4SDimitry Andric         << TemplateArgString << TemplateIDRange;
406480093f4SDimitry Andric     DiagnoseUnsatisfiedConstraint(Satisfaction);
407480093f4SDimitry Andric     return true;
408480093f4SDimitry Andric   }
409480093f4SDimitry Andric   return false;
410480093f4SDimitry Andric }
411480093f4SDimitry Andric 
41255e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
41355e4f9d5SDimitry Andric                                            concepts::ExprRequirement *Req,
41455e4f9d5SDimitry Andric                                            bool First) {
41555e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
41655e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
41755e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
41855e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Dependent:
41955e4f9d5SDimitry Andric       llvm_unreachable("Diagnosing a dependent requirement");
42055e4f9d5SDimitry Andric       break;
42155e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
42255e4f9d5SDimitry Andric       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
42355e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
42455e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
42555e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_substitution_error)
42655e4f9d5SDimitry Andric                << (int)First << SubstDiag->SubstitutedEntity
42755e4f9d5SDimitry Andric                << SubstDiag->DiagMessage;
42855e4f9d5SDimitry Andric       else
42955e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
43055e4f9d5SDimitry Andric                diag::note_expr_requirement_expr_unknown_substitution_error)
43155e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
43255e4f9d5SDimitry Andric       break;
43355e4f9d5SDimitry Andric     }
43455e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_NoexceptNotMet:
43555e4f9d5SDimitry Andric       S.Diag(Req->getNoexceptLoc(),
43655e4f9d5SDimitry Andric              diag::note_expr_requirement_noexcept_not_met)
43755e4f9d5SDimitry Andric           << (int)First << Req->getExpr();
43855e4f9d5SDimitry Andric       break;
43955e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
44055e4f9d5SDimitry Andric       auto *SubstDiag =
44155e4f9d5SDimitry Andric           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
44255e4f9d5SDimitry Andric       if (!SubstDiag->DiagMessage.empty())
44355e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
44455e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_substitution_error)
44555e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity
44655e4f9d5SDimitry Andric             << SubstDiag->DiagMessage;
44755e4f9d5SDimitry Andric       else
44855e4f9d5SDimitry Andric         S.Diag(SubstDiag->DiagLoc,
44955e4f9d5SDimitry Andric                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
45055e4f9d5SDimitry Andric             << (int)First << SubstDiag->SubstitutedEntity;
45155e4f9d5SDimitry Andric       break;
45255e4f9d5SDimitry Andric     }
45355e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
45455e4f9d5SDimitry Andric       ConceptSpecializationExpr *ConstraintExpr =
45555e4f9d5SDimitry Andric           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
456fe6060f1SDimitry Andric       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
45755e4f9d5SDimitry Andric         // A simple case - expr type is the type being constrained and the concept
45855e4f9d5SDimitry Andric         // was not provided arguments.
459fe6060f1SDimitry Andric         Expr *e = Req->getExpr();
460fe6060f1SDimitry Andric         S.Diag(e->getBeginLoc(),
46155e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied_simple)
462349cc55cSDimitry Andric             << (int)First << S.Context.getReferenceQualifiedType(e)
46355e4f9d5SDimitry Andric             << ConstraintExpr->getNamedConcept();
464fe6060f1SDimitry Andric       } else {
46555e4f9d5SDimitry Andric         S.Diag(ConstraintExpr->getBeginLoc(),
46655e4f9d5SDimitry Andric                diag::note_expr_requirement_constraints_not_satisfied)
46755e4f9d5SDimitry Andric             << (int)First << ConstraintExpr;
468fe6060f1SDimitry Andric       }
46955e4f9d5SDimitry Andric       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
47055e4f9d5SDimitry Andric       break;
47155e4f9d5SDimitry Andric     }
47255e4f9d5SDimitry Andric     case concepts::ExprRequirement::SS_Satisfied:
47355e4f9d5SDimitry Andric       llvm_unreachable("We checked this above");
47455e4f9d5SDimitry Andric   }
47555e4f9d5SDimitry Andric }
47655e4f9d5SDimitry Andric 
47755e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
47855e4f9d5SDimitry Andric                                            concepts::TypeRequirement *Req,
47955e4f9d5SDimitry Andric                                            bool First) {
48055e4f9d5SDimitry Andric   assert(!Req->isSatisfied()
48155e4f9d5SDimitry Andric          && "Diagnose() can only be used on an unsatisfied requirement");
48255e4f9d5SDimitry Andric   switch (Req->getSatisfactionStatus()) {
48355e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_Dependent:
48455e4f9d5SDimitry Andric     llvm_unreachable("Diagnosing a dependent requirement");
48555e4f9d5SDimitry Andric     return;
48655e4f9d5SDimitry Andric   case concepts::TypeRequirement::SS_SubstitutionFailure: {
48755e4f9d5SDimitry Andric     auto *SubstDiag = Req->getSubstitutionDiagnostic();
48855e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
48955e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
49055e4f9d5SDimitry Andric              diag::note_type_requirement_substitution_error) << (int)First
49155e4f9d5SDimitry Andric           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
49255e4f9d5SDimitry Andric     else
49355e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
49455e4f9d5SDimitry Andric              diag::note_type_requirement_unknown_substitution_error)
49555e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
49655e4f9d5SDimitry Andric     return;
49755e4f9d5SDimitry Andric   }
49855e4f9d5SDimitry Andric   default:
49955e4f9d5SDimitry Andric     llvm_unreachable("Unknown satisfaction status");
50055e4f9d5SDimitry Andric     return;
50155e4f9d5SDimitry Andric   }
50255e4f9d5SDimitry Andric }
50355e4f9d5SDimitry Andric 
50455e4f9d5SDimitry Andric static void diagnoseUnsatisfiedRequirement(Sema &S,
50555e4f9d5SDimitry Andric                                            concepts::NestedRequirement *Req,
50655e4f9d5SDimitry Andric                                            bool First) {
50755e4f9d5SDimitry Andric   if (Req->isSubstitutionFailure()) {
50855e4f9d5SDimitry Andric     concepts::Requirement::SubstitutionDiagnostic *SubstDiag =
50955e4f9d5SDimitry Andric         Req->getSubstitutionDiagnostic();
51055e4f9d5SDimitry Andric     if (!SubstDiag->DiagMessage.empty())
51155e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
51255e4f9d5SDimitry Andric              diag::note_nested_requirement_substitution_error)
51355e4f9d5SDimitry Andric              << (int)First << SubstDiag->SubstitutedEntity
51455e4f9d5SDimitry Andric              << SubstDiag->DiagMessage;
51555e4f9d5SDimitry Andric     else
51655e4f9d5SDimitry Andric       S.Diag(SubstDiag->DiagLoc,
51755e4f9d5SDimitry Andric              diag::note_nested_requirement_unknown_substitution_error)
51855e4f9d5SDimitry Andric           << (int)First << SubstDiag->SubstitutedEntity;
51955e4f9d5SDimitry Andric     return;
52055e4f9d5SDimitry Andric   }
52155e4f9d5SDimitry Andric   S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First);
52255e4f9d5SDimitry Andric }
52355e4f9d5SDimitry Andric 
52455e4f9d5SDimitry Andric 
525480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
526480093f4SDimitry Andric                                                         Expr *SubstExpr,
527480093f4SDimitry Andric                                                         bool First = true) {
528480093f4SDimitry Andric   SubstExpr = SubstExpr->IgnoreParenImpCasts();
529480093f4SDimitry Andric   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
530480093f4SDimitry Andric     switch (BO->getOpcode()) {
531480093f4SDimitry Andric     // These two cases will in practice only be reached when using fold
532480093f4SDimitry Andric     // expressions with || and &&, since otherwise the || and && will have been
533480093f4SDimitry Andric     // broken down into atomic constraints during satisfaction checking.
534480093f4SDimitry Andric     case BO_LOr:
535480093f4SDimitry Andric       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
536480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
537480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
538480093f4SDimitry Andric                                                   /*First=*/false);
539480093f4SDimitry Andric       return;
540fe6060f1SDimitry Andric     case BO_LAnd: {
541fe6060f1SDimitry Andric       bool LHSSatisfied =
542fe6060f1SDimitry Andric           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
543480093f4SDimitry Andric       if (LHSSatisfied) {
544480093f4SDimitry Andric         // LHS is true, so RHS must be false.
545480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
546480093f4SDimitry Andric         return;
547480093f4SDimitry Andric       }
548480093f4SDimitry Andric       // LHS is false
549480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
550480093f4SDimitry Andric 
551480093f4SDimitry Andric       // RHS might also be false
552fe6060f1SDimitry Andric       bool RHSSatisfied =
553fe6060f1SDimitry Andric           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
554480093f4SDimitry Andric       if (!RHSSatisfied)
555480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
556480093f4SDimitry Andric                                                     /*First=*/false);
557480093f4SDimitry Andric       return;
558fe6060f1SDimitry Andric     }
559480093f4SDimitry Andric     case BO_GE:
560480093f4SDimitry Andric     case BO_LE:
561480093f4SDimitry Andric     case BO_GT:
562480093f4SDimitry Andric     case BO_LT:
563480093f4SDimitry Andric     case BO_EQ:
564480093f4SDimitry Andric     case BO_NE:
565480093f4SDimitry Andric       if (BO->getLHS()->getType()->isIntegerType() &&
566480093f4SDimitry Andric           BO->getRHS()->getType()->isIntegerType()) {
567480093f4SDimitry Andric         Expr::EvalResult SimplifiedLHS;
568480093f4SDimitry Andric         Expr::EvalResult SimplifiedRHS;
569fe6060f1SDimitry Andric         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
570fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
571fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
572fe6060f1SDimitry Andric         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
573fe6060f1SDimitry Andric                                     Expr::SE_NoSideEffects,
574fe6060f1SDimitry Andric                                     /*InConstantContext=*/true);
575480093f4SDimitry Andric         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
576480093f4SDimitry Andric           S.Diag(SubstExpr->getBeginLoc(),
577480093f4SDimitry Andric                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
578480093f4SDimitry Andric               << (int)First << SubstExpr
579fe6060f1SDimitry Andric               << toString(SimplifiedLHS.Val.getInt(), 10)
580480093f4SDimitry Andric               << BinaryOperator::getOpcodeStr(BO->getOpcode())
581fe6060f1SDimitry Andric               << toString(SimplifiedRHS.Val.getInt(), 10);
582480093f4SDimitry Andric           return;
583480093f4SDimitry Andric         }
584480093f4SDimitry Andric       }
585480093f4SDimitry Andric       break;
586480093f4SDimitry Andric 
587480093f4SDimitry Andric     default:
588480093f4SDimitry Andric       break;
589480093f4SDimitry Andric     }
590480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
591480093f4SDimitry Andric     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
592480093f4SDimitry Andric       S.Diag(
593480093f4SDimitry Andric           CSE->getSourceRange().getBegin(),
594480093f4SDimitry Andric           diag::
595480093f4SDimitry Andric           note_single_arg_concept_specialization_constraint_evaluated_to_false)
596480093f4SDimitry Andric           << (int)First
597480093f4SDimitry Andric           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
598480093f4SDimitry Andric           << CSE->getNamedConcept();
599480093f4SDimitry Andric     } else {
600480093f4SDimitry Andric       S.Diag(SubstExpr->getSourceRange().getBegin(),
601480093f4SDimitry Andric              diag::note_concept_specialization_constraint_evaluated_to_false)
602480093f4SDimitry Andric           << (int)First << CSE;
603480093f4SDimitry Andric     }
604480093f4SDimitry Andric     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
605480093f4SDimitry Andric     return;
60655e4f9d5SDimitry Andric   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
60755e4f9d5SDimitry Andric     for (concepts::Requirement *Req : RE->getRequirements())
60855e4f9d5SDimitry Andric       if (!Req->isDependent() && !Req->isSatisfied()) {
60955e4f9d5SDimitry Andric         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
61055e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, E, First);
61155e4f9d5SDimitry Andric         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
61255e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(S, T, First);
61355e4f9d5SDimitry Andric         else
61455e4f9d5SDimitry Andric           diagnoseUnsatisfiedRequirement(
61555e4f9d5SDimitry Andric               S, cast<concepts::NestedRequirement>(Req), First);
61655e4f9d5SDimitry Andric         break;
61755e4f9d5SDimitry Andric       }
61855e4f9d5SDimitry Andric     return;
619480093f4SDimitry Andric   }
620480093f4SDimitry Andric 
621480093f4SDimitry Andric   S.Diag(SubstExpr->getSourceRange().getBegin(),
622480093f4SDimitry Andric          diag::note_atomic_constraint_evaluated_to_false)
623480093f4SDimitry Andric       << (int)First << SubstExpr;
624480093f4SDimitry Andric }
625480093f4SDimitry Andric 
626480093f4SDimitry Andric template<typename SubstitutionDiagnostic>
627480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr(
628480093f4SDimitry Andric     Sema &S, const Expr *E,
629480093f4SDimitry Andric     const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
630480093f4SDimitry Andric     bool First = true) {
631480093f4SDimitry Andric   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
632480093f4SDimitry Andric     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
633480093f4SDimitry Andric         << Diag->second;
634480093f4SDimitry Andric     return;
635480093f4SDimitry Andric   }
636480093f4SDimitry Andric 
637480093f4SDimitry Andric   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
638480093f4SDimitry Andric       Record.template get<Expr *>(), First);
639480093f4SDimitry Andric }
640480093f4SDimitry Andric 
64155e4f9d5SDimitry Andric void
64255e4f9d5SDimitry Andric Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
64355e4f9d5SDimitry Andric                                     bool First) {
644480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
645480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
646480093f4SDimitry Andric   for (auto &Pair : Satisfaction.Details) {
647480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
648480093f4SDimitry Andric     First = false;
649480093f4SDimitry Andric   }
650480093f4SDimitry Andric }
651480093f4SDimitry Andric 
652480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
65355e4f9d5SDimitry Andric     const ASTConstraintSatisfaction &Satisfaction,
65455e4f9d5SDimitry Andric     bool First) {
655480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
656480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
657480093f4SDimitry Andric   for (auto &Pair : Satisfaction) {
658480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
659480093f4SDimitry Andric     First = false;
660480093f4SDimitry Andric   }
661480093f4SDimitry Andric }
662480093f4SDimitry Andric 
663480093f4SDimitry Andric const NormalizedConstraint *
664480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints(
665480093f4SDimitry Andric     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
666480093f4SDimitry Andric   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
667480093f4SDimitry Andric   if (CacheEntry == NormalizationCache.end()) {
668480093f4SDimitry Andric     auto Normalized =
669480093f4SDimitry Andric         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
670480093f4SDimitry Andric                                                   AssociatedConstraints);
671480093f4SDimitry Andric     CacheEntry =
672480093f4SDimitry Andric         NormalizationCache
673480093f4SDimitry Andric             .try_emplace(ConstrainedDecl,
674480093f4SDimitry Andric                          Normalized
675480093f4SDimitry Andric                              ? new (Context) NormalizedConstraint(
676480093f4SDimitry Andric                                  std::move(*Normalized))
677480093f4SDimitry Andric                              : nullptr)
678480093f4SDimitry Andric             .first;
679480093f4SDimitry Andric   }
680480093f4SDimitry Andric   return CacheEntry->second;
681480093f4SDimitry Andric }
682480093f4SDimitry Andric 
683480093f4SDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
684480093f4SDimitry Andric     ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
685480093f4SDimitry Andric     const ASTTemplateArgumentListInfo *ArgsAsWritten) {
686480093f4SDimitry Andric   if (!N.isAtomic()) {
687480093f4SDimitry Andric     if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
688480093f4SDimitry Andric                                     ArgsAsWritten))
689480093f4SDimitry Andric       return true;
690480093f4SDimitry Andric     return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
691480093f4SDimitry Andric                                        ArgsAsWritten);
692480093f4SDimitry Andric   }
693480093f4SDimitry Andric   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
694480093f4SDimitry Andric 
695480093f4SDimitry Andric   AtomicConstraint &Atomic = *N.getAtomicConstraint();
696480093f4SDimitry Andric   TemplateArgumentListInfo SubstArgs;
697480093f4SDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
698480093f4SDimitry Andric   MLTAL.addOuterTemplateArguments(TemplateArgs);
699480093f4SDimitry Andric   if (!Atomic.ParameterMapping) {
700480093f4SDimitry Andric     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
701480093f4SDimitry Andric     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
702480093f4SDimitry Andric                                  /*Depth=*/0, OccurringIndices);
703480093f4SDimitry Andric     Atomic.ParameterMapping.emplace(
704480093f4SDimitry Andric         MutableArrayRef<TemplateArgumentLoc>(
705480093f4SDimitry Andric             new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
706480093f4SDimitry Andric             OccurringIndices.count()));
707480093f4SDimitry Andric     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
708480093f4SDimitry Andric       if (OccurringIndices[I])
709480093f4SDimitry Andric         new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
710480093f4SDimitry Andric             S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
711480093f4SDimitry Andric                 // Here we assume we do not support things like
712480093f4SDimitry Andric                 // template<typename A, typename B>
713480093f4SDimitry Andric                 // concept C = ...;
714480093f4SDimitry Andric                 //
715480093f4SDimitry Andric                 // template<typename... Ts> requires C<Ts...>
716480093f4SDimitry Andric                 // struct S { };
717480093f4SDimitry Andric                 // The above currently yields a diagnostic.
718480093f4SDimitry Andric                 // We still might have default arguments for concept parameters.
719480093f4SDimitry Andric                 ArgsAsWritten->NumTemplateArgs > I ?
720480093f4SDimitry Andric                 ArgsAsWritten->arguments()[I].getLocation() :
721480093f4SDimitry Andric                 SourceLocation()));
722480093f4SDimitry Andric   }
723480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(
724480093f4SDimitry Andric       S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
725480093f4SDimitry Andric       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
726480093f4SDimitry Andric       SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
727480093f4SDimitry Andric                   ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
728480093f4SDimitry Andric   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
729480093f4SDimitry Andric     return true;
73013138422SDimitry Andric   Atomic.ParameterMapping.emplace(
73113138422SDimitry Andric         MutableArrayRef<TemplateArgumentLoc>(
73213138422SDimitry Andric             new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
73313138422SDimitry Andric             SubstArgs.size()));
734480093f4SDimitry Andric   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
735480093f4SDimitry Andric             N.getAtomicConstraint()->ParameterMapping->begin());
736480093f4SDimitry Andric   return false;
737480093f4SDimitry Andric }
738480093f4SDimitry Andric 
739480093f4SDimitry Andric Optional<NormalizedConstraint>
740480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
741480093f4SDimitry Andric                                           ArrayRef<const Expr *> E) {
742480093f4SDimitry Andric   assert(E.size() != 0);
7436e75b2fbSDimitry Andric   auto Conjunction = fromConstraintExpr(S, D, E[0]);
7446e75b2fbSDimitry Andric   if (!Conjunction)
745480093f4SDimitry Andric     return None;
7466e75b2fbSDimitry Andric   for (unsigned I = 1; I < E.size(); ++I) {
747480093f4SDimitry Andric     auto Next = fromConstraintExpr(S, D, E[I]);
748480093f4SDimitry Andric     if (!Next)
7496e75b2fbSDimitry Andric       return None;
7506e75b2fbSDimitry Andric     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
751480093f4SDimitry Andric                                         std::move(*Next), CCK_Conjunction);
752480093f4SDimitry Andric   }
753480093f4SDimitry Andric   return Conjunction;
754480093f4SDimitry Andric }
755480093f4SDimitry Andric 
756480093f4SDimitry Andric llvm::Optional<NormalizedConstraint>
757480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
758480093f4SDimitry Andric   assert(E != nullptr);
759480093f4SDimitry Andric 
760480093f4SDimitry Andric   // C++ [temp.constr.normal]p1.1
761480093f4SDimitry Andric   // [...]
762480093f4SDimitry Andric   // - The normal form of an expression (E) is the normal form of E.
763480093f4SDimitry Andric   // [...]
764480093f4SDimitry Andric   E = E->IgnoreParenImpCasts();
7655ffd83dbSDimitry Andric   if (LogicalBinOp BO = E) {
7665ffd83dbSDimitry Andric     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
767480093f4SDimitry Andric     if (!LHS)
768480093f4SDimitry Andric       return None;
7695ffd83dbSDimitry Andric     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
770480093f4SDimitry Andric     if (!RHS)
771480093f4SDimitry Andric       return None;
772480093f4SDimitry Andric 
7735ffd83dbSDimitry Andric     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
7745ffd83dbSDimitry Andric                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
775480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
776480093f4SDimitry Andric     const NormalizedConstraint *SubNF;
777480093f4SDimitry Andric     {
778480093f4SDimitry Andric       Sema::InstantiatingTemplate Inst(
779480093f4SDimitry Andric           S, CSE->getExprLoc(),
780480093f4SDimitry Andric           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
781480093f4SDimitry Andric           CSE->getSourceRange());
782480093f4SDimitry Andric       // C++ [temp.constr.normal]p1.1
783480093f4SDimitry Andric       // [...]
784480093f4SDimitry Andric       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
785480093f4SDimitry Andric       // where C names a concept, is the normal form of the
786480093f4SDimitry Andric       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
787480093f4SDimitry Andric       // respective template parameters in the parameter mappings in each atomic
788480093f4SDimitry Andric       // constraint. If any such substitution results in an invalid type or
789480093f4SDimitry Andric       // expression, the program is ill-formed; no diagnostic is required.
790480093f4SDimitry Andric       // [...]
791480093f4SDimitry Andric       ConceptDecl *CD = CSE->getNamedConcept();
792480093f4SDimitry Andric       SubNF = S.getNormalizedAssociatedConstraints(CD,
793480093f4SDimitry Andric                                                    {CD->getConstraintExpr()});
794480093f4SDimitry Andric       if (!SubNF)
795480093f4SDimitry Andric         return None;
796480093f4SDimitry Andric     }
797480093f4SDimitry Andric 
798480093f4SDimitry Andric     Optional<NormalizedConstraint> New;
799480093f4SDimitry Andric     New.emplace(S.Context, *SubNF);
800480093f4SDimitry Andric 
801480093f4SDimitry Andric     if (substituteParameterMappings(
802480093f4SDimitry Andric             S, *New, CSE->getNamedConcept(),
803480093f4SDimitry Andric             CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
804480093f4SDimitry Andric       return None;
805480093f4SDimitry Andric 
806480093f4SDimitry Andric     return New;
807480093f4SDimitry Andric   }
808480093f4SDimitry Andric   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
809480093f4SDimitry Andric }
810480093f4SDimitry Andric 
811480093f4SDimitry Andric using NormalForm =
812480093f4SDimitry Andric     llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
813480093f4SDimitry Andric 
814480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
815480093f4SDimitry Andric   if (Normalized.isAtomic())
816480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
817480093f4SDimitry Andric 
818480093f4SDimitry Andric   NormalForm LCNF = makeCNF(Normalized.getLHS());
819480093f4SDimitry Andric   NormalForm RCNF = makeCNF(Normalized.getRHS());
820480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
821480093f4SDimitry Andric     LCNF.reserve(LCNF.size() + RCNF.size());
822480093f4SDimitry Andric     while (!RCNF.empty())
823480093f4SDimitry Andric       LCNF.push_back(RCNF.pop_back_val());
824480093f4SDimitry Andric     return LCNF;
825480093f4SDimitry Andric   }
826480093f4SDimitry Andric 
827480093f4SDimitry Andric   // Disjunction
828480093f4SDimitry Andric   NormalForm Res;
829480093f4SDimitry Andric   Res.reserve(LCNF.size() * RCNF.size());
830480093f4SDimitry Andric   for (auto &LDisjunction : LCNF)
831480093f4SDimitry Andric     for (auto &RDisjunction : RCNF) {
832480093f4SDimitry Andric       NormalForm::value_type Combined;
833480093f4SDimitry Andric       Combined.reserve(LDisjunction.size() + RDisjunction.size());
834480093f4SDimitry Andric       std::copy(LDisjunction.begin(), LDisjunction.end(),
835480093f4SDimitry Andric                 std::back_inserter(Combined));
836480093f4SDimitry Andric       std::copy(RDisjunction.begin(), RDisjunction.end(),
837480093f4SDimitry Andric                 std::back_inserter(Combined));
838480093f4SDimitry Andric       Res.emplace_back(Combined);
839480093f4SDimitry Andric     }
840480093f4SDimitry Andric   return Res;
841480093f4SDimitry Andric }
842480093f4SDimitry Andric 
843480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
844480093f4SDimitry Andric   if (Normalized.isAtomic())
845480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
846480093f4SDimitry Andric 
847480093f4SDimitry Andric   NormalForm LDNF = makeDNF(Normalized.getLHS());
848480093f4SDimitry Andric   NormalForm RDNF = makeDNF(Normalized.getRHS());
849480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
850480093f4SDimitry Andric     LDNF.reserve(LDNF.size() + RDNF.size());
851480093f4SDimitry Andric     while (!RDNF.empty())
852480093f4SDimitry Andric       LDNF.push_back(RDNF.pop_back_val());
853480093f4SDimitry Andric     return LDNF;
854480093f4SDimitry Andric   }
855480093f4SDimitry Andric 
856480093f4SDimitry Andric   // Conjunction
857480093f4SDimitry Andric   NormalForm Res;
858480093f4SDimitry Andric   Res.reserve(LDNF.size() * RDNF.size());
859480093f4SDimitry Andric   for (auto &LConjunction : LDNF) {
860480093f4SDimitry Andric     for (auto &RConjunction : RDNF) {
861480093f4SDimitry Andric       NormalForm::value_type Combined;
862480093f4SDimitry Andric       Combined.reserve(LConjunction.size() + RConjunction.size());
863480093f4SDimitry Andric       std::copy(LConjunction.begin(), LConjunction.end(),
864480093f4SDimitry Andric                 std::back_inserter(Combined));
865480093f4SDimitry Andric       std::copy(RConjunction.begin(), RConjunction.end(),
866480093f4SDimitry Andric                 std::back_inserter(Combined));
867480093f4SDimitry Andric       Res.emplace_back(Combined);
868480093f4SDimitry Andric     }
869480093f4SDimitry Andric   }
870480093f4SDimitry Andric   return Res;
871480093f4SDimitry Andric }
872480093f4SDimitry Andric 
873480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
874480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF,
875480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
876480093f4SDimitry Andric   // C++ [temp.constr.order] p2
877480093f4SDimitry Andric   //   Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
878480093f4SDimitry Andric   //   disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
879480093f4SDimitry Andric   //   the conjuctive normal form of Q, where [...]
880480093f4SDimitry Andric   for (const auto &Pi : PDNF) {
881480093f4SDimitry Andric     for (const auto &Qj : QCNF) {
882480093f4SDimitry Andric       // C++ [temp.constr.order] p2
883480093f4SDimitry Andric       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
884480093f4SDimitry Andric       //     and only if there exists an atomic constraint Pia in Pi for which
885480093f4SDimitry Andric       //     there exists an atomic constraint, Qjb, in Qj such that Pia
886480093f4SDimitry Andric       //     subsumes Qjb.
887480093f4SDimitry Andric       bool Found = false;
888480093f4SDimitry Andric       for (const AtomicConstraint *Pia : Pi) {
889480093f4SDimitry Andric         for (const AtomicConstraint *Qjb : Qj) {
890480093f4SDimitry Andric           if (E(*Pia, *Qjb)) {
891480093f4SDimitry Andric             Found = true;
892480093f4SDimitry Andric             break;
893480093f4SDimitry Andric           }
894480093f4SDimitry Andric         }
895480093f4SDimitry Andric         if (Found)
896480093f4SDimitry Andric           break;
897480093f4SDimitry Andric       }
898480093f4SDimitry Andric       if (!Found)
899480093f4SDimitry Andric         return false;
900480093f4SDimitry Andric     }
901480093f4SDimitry Andric   }
902480093f4SDimitry Andric   return true;
903480093f4SDimitry Andric }
904480093f4SDimitry Andric 
905480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
906480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
907480093f4SDimitry Andric                      NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
908480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
909480093f4SDimitry Andric   // C++ [temp.constr.order] p2
910480093f4SDimitry Andric   //   In order to determine if a constraint P subsumes a constraint Q, P is
911480093f4SDimitry Andric   //   transformed into disjunctive normal form, and Q is transformed into
912480093f4SDimitry Andric   //   conjunctive normal form. [...]
913480093f4SDimitry Andric   auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
914480093f4SDimitry Andric   if (!PNormalized)
915480093f4SDimitry Andric     return true;
916480093f4SDimitry Andric   const NormalForm PDNF = makeDNF(*PNormalized);
917480093f4SDimitry Andric 
918480093f4SDimitry Andric   auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
919480093f4SDimitry Andric   if (!QNormalized)
920480093f4SDimitry Andric     return true;
921480093f4SDimitry Andric   const NormalForm QCNF = makeCNF(*QNormalized);
922480093f4SDimitry Andric 
923480093f4SDimitry Andric   Subsumes = subsumes(PDNF, QCNF, E);
924480093f4SDimitry Andric   return false;
925480093f4SDimitry Andric }
926480093f4SDimitry Andric 
927480093f4SDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
928480093f4SDimitry Andric                                   NamedDecl *D2, ArrayRef<const Expr *> AC2,
929480093f4SDimitry Andric                                   bool &Result) {
930480093f4SDimitry Andric   if (AC1.empty()) {
931480093f4SDimitry Andric     Result = AC2.empty();
932480093f4SDimitry Andric     return false;
933480093f4SDimitry Andric   }
934480093f4SDimitry Andric   if (AC2.empty()) {
935480093f4SDimitry Andric     // TD1 has associated constraints and TD2 does not.
936480093f4SDimitry Andric     Result = true;
937480093f4SDimitry Andric     return false;
938480093f4SDimitry Andric   }
939480093f4SDimitry Andric 
940480093f4SDimitry Andric   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
941480093f4SDimitry Andric   auto CacheEntry = SubsumptionCache.find(Key);
942480093f4SDimitry Andric   if (CacheEntry != SubsumptionCache.end()) {
943480093f4SDimitry Andric     Result = CacheEntry->second;
944480093f4SDimitry Andric     return false;
945480093f4SDimitry Andric   }
946480093f4SDimitry Andric 
947480093f4SDimitry Andric   if (subsumes(*this, D1, AC1, D2, AC2, Result,
948480093f4SDimitry Andric         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
949480093f4SDimitry Andric           return A.subsumes(Context, B);
950480093f4SDimitry Andric         }))
951480093f4SDimitry Andric     return true;
952480093f4SDimitry Andric   SubsumptionCache.try_emplace(Key, Result);
953480093f4SDimitry Andric   return false;
954480093f4SDimitry Andric }
955480093f4SDimitry Andric 
956480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
957480093f4SDimitry Andric     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
958480093f4SDimitry Andric   if (isSFINAEContext())
959480093f4SDimitry Andric     // No need to work here because our notes would be discarded.
960480093f4SDimitry Andric     return false;
961480093f4SDimitry Andric 
962480093f4SDimitry Andric   if (AC1.empty() || AC2.empty())
963480093f4SDimitry Andric     return false;
964480093f4SDimitry Andric 
965480093f4SDimitry Andric   auto NormalExprEvaluator =
966480093f4SDimitry Andric       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
967480093f4SDimitry Andric         return A.subsumes(Context, B);
968480093f4SDimitry Andric       };
969480093f4SDimitry Andric 
970480093f4SDimitry Andric   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
971480093f4SDimitry Andric   auto IdenticalExprEvaluator =
972480093f4SDimitry Andric       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
973480093f4SDimitry Andric         if (!A.hasMatchingParameterMapping(Context, B))
974480093f4SDimitry Andric           return false;
975480093f4SDimitry Andric         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
976480093f4SDimitry Andric         if (EA == EB)
977480093f4SDimitry Andric           return true;
978480093f4SDimitry Andric 
979480093f4SDimitry Andric         // Not the same source level expression - are the expressions
980480093f4SDimitry Andric         // identical?
981480093f4SDimitry Andric         llvm::FoldingSetNodeID IDA, IDB;
982349cc55cSDimitry Andric         EA->Profile(IDA, Context, /*Canonical=*/true);
983349cc55cSDimitry Andric         EB->Profile(IDB, Context, /*Canonical=*/true);
984480093f4SDimitry Andric         if (IDA != IDB)
985480093f4SDimitry Andric           return false;
986480093f4SDimitry Andric 
987480093f4SDimitry Andric         AmbiguousAtomic1 = EA;
988480093f4SDimitry Andric         AmbiguousAtomic2 = EB;
989480093f4SDimitry Andric         return true;
990480093f4SDimitry Andric       };
991480093f4SDimitry Andric 
992480093f4SDimitry Andric   {
993480093f4SDimitry Andric     // The subsumption checks might cause diagnostics
994480093f4SDimitry Andric     SFINAETrap Trap(*this);
995480093f4SDimitry Andric     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
996480093f4SDimitry Andric     if (!Normalized1)
997480093f4SDimitry Andric       return false;
998480093f4SDimitry Andric     const NormalForm DNF1 = makeDNF(*Normalized1);
999480093f4SDimitry Andric     const NormalForm CNF1 = makeCNF(*Normalized1);
1000480093f4SDimitry Andric 
1001480093f4SDimitry Andric     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1002480093f4SDimitry Andric     if (!Normalized2)
1003480093f4SDimitry Andric       return false;
1004480093f4SDimitry Andric     const NormalForm DNF2 = makeDNF(*Normalized2);
1005480093f4SDimitry Andric     const NormalForm CNF2 = makeCNF(*Normalized2);
1006480093f4SDimitry Andric 
1007480093f4SDimitry Andric     bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1008480093f4SDimitry Andric     bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1009480093f4SDimitry Andric     bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1010480093f4SDimitry Andric     bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1011480093f4SDimitry Andric     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1012480093f4SDimitry Andric         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1013480093f4SDimitry Andric       // Same result - no ambiguity was caused by identical atomic expressions.
1014480093f4SDimitry Andric       return false;
1015480093f4SDimitry Andric   }
1016480093f4SDimitry Andric 
1017480093f4SDimitry Andric   // A different result! Some ambiguous atomic constraint(s) caused a difference
1018480093f4SDimitry Andric   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1019480093f4SDimitry Andric 
1020480093f4SDimitry Andric   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1021480093f4SDimitry Andric       << AmbiguousAtomic1->getSourceRange();
1022480093f4SDimitry Andric   Diag(AmbiguousAtomic2->getBeginLoc(),
1023480093f4SDimitry Andric        diag::note_ambiguous_atomic_constraints_similar_expression)
1024480093f4SDimitry Andric       << AmbiguousAtomic2->getSourceRange();
1025480093f4SDimitry Andric   return true;
1026480093f4SDimitry Andric }
102755e4f9d5SDimitry Andric 
102855e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
102955e4f9d5SDimitry Andric     Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
103055e4f9d5SDimitry Andric     ReturnTypeRequirement Req, SatisfactionStatus Status,
103155e4f9d5SDimitry Andric     ConceptSpecializationExpr *SubstitutedConstraintExpr) :
103255e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
103355e4f9d5SDimitry Andric                 Status == SS_Dependent &&
103455e4f9d5SDimitry Andric                 (E->containsUnexpandedParameterPack() ||
103555e4f9d5SDimitry Andric                  Req.containsUnexpandedParameterPack()),
103655e4f9d5SDimitry Andric                 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
103755e4f9d5SDimitry Andric     TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
103855e4f9d5SDimitry Andric     Status(Status) {
103955e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
104055e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
104155e4f9d5SDimitry Andric          "noexcept specification");
104255e4f9d5SDimitry Andric   assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
104355e4f9d5SDimitry Andric          (SubstitutedConstraintExpr != nullptr));
104455e4f9d5SDimitry Andric }
104555e4f9d5SDimitry Andric 
104655e4f9d5SDimitry Andric concepts::ExprRequirement::ExprRequirement(
104755e4f9d5SDimitry Andric     SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
104855e4f9d5SDimitry Andric     SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
104955e4f9d5SDimitry Andric     Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
105055e4f9d5SDimitry Andric                 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
105155e4f9d5SDimitry Andric     Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
105255e4f9d5SDimitry Andric     Status(SS_ExprSubstitutionFailure) {
105355e4f9d5SDimitry Andric   assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
105455e4f9d5SDimitry Andric          "Simple requirement must not have a return type requirement or a "
105555e4f9d5SDimitry Andric          "noexcept specification");
105655e4f9d5SDimitry Andric }
105755e4f9d5SDimitry Andric 
105855e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement::
105955e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL) :
1060*04eeddc0SDimitry Andric     TypeConstraintInfo(TPL, false) {
106155e4f9d5SDimitry Andric   assert(TPL->size() == 1);
106255e4f9d5SDimitry Andric   const TypeConstraint *TC =
106355e4f9d5SDimitry Andric       cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
106455e4f9d5SDimitry Andric   assert(TC &&
106555e4f9d5SDimitry Andric          "TPL must have a template type parameter with a type constraint");
106655e4f9d5SDimitry Andric   auto *Constraint =
1067349cc55cSDimitry Andric       cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());
1068e8d8bef9SDimitry Andric   bool Dependent =
1069e8d8bef9SDimitry Andric       Constraint->getTemplateArgsAsWritten() &&
1070e8d8bef9SDimitry Andric       TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1071e8d8bef9SDimitry Andric           Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1072*04eeddc0SDimitry Andric   TypeConstraintInfo.setInt(Dependent ? true : false);
107355e4f9d5SDimitry Andric }
107455e4f9d5SDimitry Andric 
107555e4f9d5SDimitry Andric concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1076e8d8bef9SDimitry Andric     Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
107755e4f9d5SDimitry Andric                 T->getType()->containsUnexpandedParameterPack(),
107855e4f9d5SDimitry Andric                 // We reach this ctor with either dependent types (in which
107955e4f9d5SDimitry Andric                 // IsSatisfied doesn't matter) or with non-dependent type in
108055e4f9d5SDimitry Andric                 // which the existence of the type indicates satisfaction.
1081e8d8bef9SDimitry Andric                 /*IsSatisfied=*/true),
1082e8d8bef9SDimitry Andric     Value(T),
1083e8d8bef9SDimitry Andric     Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1084e8d8bef9SDimitry Andric                                                         : SS_Satisfied) {}
1085