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