xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
1a7dea167SDimitry Andric //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2a7dea167SDimitry Andric //
3a7dea167SDimitry Andric //                     The LLVM Compiler Infrastructure
4a7dea167SDimitry Andric //
5a7dea167SDimitry Andric // This file is distributed under the University of Illinois Open Source
6a7dea167SDimitry Andric // License. See LICENSE.TXT for details.
7a7dea167SDimitry Andric //
8a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
9a7dea167SDimitry Andric //
10a7dea167SDimitry Andric //  This file implements semantic analysis for C++ constraints and concepts.
11a7dea167SDimitry Andric //
12a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
13a7dea167SDimitry Andric 
14*480093f4SDimitry Andric #include "clang/Sema/SemaConcept.h"
15a7dea167SDimitry Andric #include "clang/Sema/Sema.h"
16*480093f4SDimitry Andric #include "clang/Sema/SemaInternal.h"
17a7dea167SDimitry Andric #include "clang/Sema/SemaDiagnostic.h"
18a7dea167SDimitry Andric #include "clang/Sema/TemplateDeduction.h"
19a7dea167SDimitry Andric #include "clang/Sema/Template.h"
20a7dea167SDimitry Andric #include "clang/AST/ExprCXX.h"
21*480093f4SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
22*480093f4SDimitry Andric #include "clang/Basic/OperatorPrecedence.h"
23*480093f4SDimitry Andric #include "llvm/ADT/DenseMap.h"
24*480093f4SDimitry Andric #include "llvm/ADT/PointerUnion.h"
25a7dea167SDimitry Andric using namespace clang;
26a7dea167SDimitry Andric using namespace sema;
27a7dea167SDimitry Andric 
28*480093f4SDimitry Andric bool
29*480093f4SDimitry Andric Sema::CheckConstraintExpression(Expr *ConstraintExpression, Token NextToken,
30*480093f4SDimitry Andric                                 bool *PossibleNonPrimary,
31*480093f4SDimitry Andric                                 bool IsTrailingRequiresClause) {
32a7dea167SDimitry Andric   // C++2a [temp.constr.atomic]p1
33a7dea167SDimitry Andric   // ..E shall be a constant expression of type bool.
34a7dea167SDimitry Andric 
35a7dea167SDimitry Andric   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
36a7dea167SDimitry Andric 
37a7dea167SDimitry Andric   if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
38a7dea167SDimitry Andric     if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)
39*480093f4SDimitry Andric       return CheckConstraintExpression(BinOp->getLHS(), NextToken,
40*480093f4SDimitry Andric                                        PossibleNonPrimary) &&
41*480093f4SDimitry Andric              CheckConstraintExpression(BinOp->getRHS(), NextToken,
42*480093f4SDimitry Andric                                        PossibleNonPrimary);
43a7dea167SDimitry Andric   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
44*480093f4SDimitry Andric     return CheckConstraintExpression(C->getSubExpr(), NextToken,
45*480093f4SDimitry Andric                                      PossibleNonPrimary);
46a7dea167SDimitry Andric 
47a7dea167SDimitry Andric   QualType Type = ConstraintExpression->getType();
48*480093f4SDimitry Andric 
49*480093f4SDimitry Andric   auto CheckForNonPrimary = [&] {
50*480093f4SDimitry Andric     if (PossibleNonPrimary)
51*480093f4SDimitry Andric       *PossibleNonPrimary =
52*480093f4SDimitry Andric           // We have the following case:
53*480093f4SDimitry Andric           // template<typename> requires func(0) struct S { };
54*480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
55*480093f4SDimitry Andric           // the function call, and we're only going to parse 'func' as the
56*480093f4SDimitry Andric           // primary-expression, and complain that it is of non-bool type.
57*480093f4SDimitry Andric           (NextToken.is(tok::l_paren) &&
58*480093f4SDimitry Andric            (IsTrailingRequiresClause ||
59*480093f4SDimitry Andric             (Type->isDependentType() &&
60*480093f4SDimitry Andric              IsDependentFunctionNameExpr(ConstraintExpression)) ||
61*480093f4SDimitry Andric             Type->isFunctionType() ||
62*480093f4SDimitry Andric             Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
63*480093f4SDimitry Andric           // We have the following case:
64*480093f4SDimitry Andric           // template<typename T> requires size_<T> == 0 struct S { };
65*480093f4SDimitry Andric           // The user probably isn't aware of the parentheses required around
66*480093f4SDimitry Andric           // the binary operator, and we're only going to parse 'func' as the
67*480093f4SDimitry Andric           // first operand, and complain that it is of non-bool type.
68*480093f4SDimitry Andric           getBinOpPrecedence(NextToken.getKind(),
69*480093f4SDimitry Andric                              /*GreaterThanIsOperator=*/true,
70*480093f4SDimitry Andric                              getLangOpts().CPlusPlus11) > prec::LogicalAnd;
71*480093f4SDimitry Andric   };
72*480093f4SDimitry Andric 
73*480093f4SDimitry Andric   // An atomic constraint!
74*480093f4SDimitry Andric   if (ConstraintExpression->isTypeDependent()) {
75*480093f4SDimitry Andric     CheckForNonPrimary();
76*480093f4SDimitry Andric     return true;
77*480093f4SDimitry Andric   }
78*480093f4SDimitry Andric 
79a7dea167SDimitry Andric   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
80a7dea167SDimitry Andric     Diag(ConstraintExpression->getExprLoc(),
81a7dea167SDimitry Andric          diag::err_non_bool_atomic_constraint) << Type
82a7dea167SDimitry Andric         << ConstraintExpression->getSourceRange();
83*480093f4SDimitry Andric     CheckForNonPrimary();
84a7dea167SDimitry Andric     return false;
85a7dea167SDimitry Andric   }
86*480093f4SDimitry Andric 
87*480093f4SDimitry Andric   if (PossibleNonPrimary)
88*480093f4SDimitry Andric       *PossibleNonPrimary = false;
89a7dea167SDimitry Andric   return true;
90a7dea167SDimitry Andric }
91a7dea167SDimitry Andric 
92*480093f4SDimitry Andric template <typename AtomicEvaluator>
93*480093f4SDimitry Andric static bool
94*480093f4SDimitry Andric calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
95*480093f4SDimitry Andric                                 ConstraintSatisfaction &Satisfaction,
96*480093f4SDimitry Andric                                 AtomicEvaluator &&Evaluator) {
97a7dea167SDimitry Andric   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
98a7dea167SDimitry Andric 
99a7dea167SDimitry Andric   if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
100*480093f4SDimitry Andric     if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
101*480093f4SDimitry Andric       if (calculateConstraintSatisfaction(S, BO->getLHS(), Satisfaction,
102*480093f4SDimitry Andric                                           Evaluator))
103a7dea167SDimitry Andric         return true;
104*480093f4SDimitry Andric 
105*480093f4SDimitry Andric       bool IsLHSSatisfied = Satisfaction.IsSatisfied;
106*480093f4SDimitry Andric 
107*480093f4SDimitry Andric       if (BO->getOpcode() == BO_LOr && IsLHSSatisfied)
108*480093f4SDimitry Andric         // [temp.constr.op] p3
109*480093f4SDimitry Andric         //    A disjunction is a constraint taking two operands. To determine if
110*480093f4SDimitry Andric         //    a disjunction is satisfied, the satisfaction of the first operand
111*480093f4SDimitry Andric         //    is checked. If that is satisfied, the disjunction is satisfied.
112*480093f4SDimitry Andric         //    Otherwise, the disjunction is satisfied if and only if the second
113*480093f4SDimitry Andric         //    operand is satisfied.
114a7dea167SDimitry Andric         return false;
115*480093f4SDimitry Andric 
116*480093f4SDimitry Andric       if (BO->getOpcode() == BO_LAnd && !IsLHSSatisfied)
117*480093f4SDimitry Andric         // [temp.constr.op] p2
118*480093f4SDimitry Andric         //    A conjunction is a constraint taking two operands. To determine if
119*480093f4SDimitry Andric         //    a conjunction is satisfied, the satisfaction of the first operand
120*480093f4SDimitry Andric         //    is checked. If that is not satisfied, the conjunction is not
121*480093f4SDimitry Andric         //    satisfied. Otherwise, the conjunction is satisfied if and only if
122*480093f4SDimitry Andric         //    the second operand is satisfied.
123a7dea167SDimitry Andric         return false;
124*480093f4SDimitry Andric 
125*480093f4SDimitry Andric       return calculateConstraintSatisfaction(S, BO->getRHS(), Satisfaction,
126*480093f4SDimitry Andric           std::forward<AtomicEvaluator>(Evaluator));
127a7dea167SDimitry Andric     }
128a7dea167SDimitry Andric   }
129a7dea167SDimitry Andric   else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
130*480093f4SDimitry Andric     return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
131*480093f4SDimitry Andric         std::forward<AtomicEvaluator>(Evaluator));
132*480093f4SDimitry Andric 
133*480093f4SDimitry Andric   // An atomic constraint expression
134*480093f4SDimitry Andric   ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
135*480093f4SDimitry Andric 
136*480093f4SDimitry Andric   if (SubstitutedAtomicExpr.isInvalid())
137*480093f4SDimitry Andric     return true;
138*480093f4SDimitry Andric 
139*480093f4SDimitry Andric   if (!SubstitutedAtomicExpr.isUsable())
140*480093f4SDimitry Andric     // Evaluator has decided satisfaction without yielding an expression.
141*480093f4SDimitry Andric     return false;
142a7dea167SDimitry Andric 
143a7dea167SDimitry Andric   EnterExpressionEvaluationContext ConstantEvaluated(
144*480093f4SDimitry Andric       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
145a7dea167SDimitry Andric   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
146a7dea167SDimitry Andric   Expr::EvalResult EvalResult;
147a7dea167SDimitry Andric   EvalResult.Diag = &EvaluationDiags;
148*480093f4SDimitry Andric   if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
149a7dea167SDimitry Andric       // C++2a [temp.constr.atomic]p1
150a7dea167SDimitry Andric       //   ...E shall be a constant expression of type bool.
151*480093f4SDimitry Andric     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
152a7dea167SDimitry Andric            diag::err_non_constant_constraint_expression)
153*480093f4SDimitry Andric         << SubstitutedAtomicExpr.get()->getSourceRange();
154a7dea167SDimitry Andric     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
155*480093f4SDimitry Andric       S.Diag(PDiag.first, PDiag.second);
156a7dea167SDimitry Andric     return true;
157a7dea167SDimitry Andric   }
158a7dea167SDimitry Andric 
159*480093f4SDimitry Andric   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
160*480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied)
161*480093f4SDimitry Andric     Satisfaction.Details.emplace_back(ConstraintExpr,
162*480093f4SDimitry Andric                                       SubstitutedAtomicExpr.get());
163a7dea167SDimitry Andric 
164a7dea167SDimitry Andric   return false;
165a7dea167SDimitry Andric }
166*480093f4SDimitry Andric 
167*480093f4SDimitry Andric template <typename TemplateDeclT>
168*480093f4SDimitry Andric static bool calculateConstraintSatisfaction(
169*480093f4SDimitry Andric     Sema &S, TemplateDeclT *Template, ArrayRef<TemplateArgument> TemplateArgs,
170*480093f4SDimitry Andric     SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
171*480093f4SDimitry Andric     const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
172*480093f4SDimitry Andric   return calculateConstraintSatisfaction(
173*480093f4SDimitry Andric       S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
174*480093f4SDimitry Andric         EnterExpressionEvaluationContext ConstantEvaluated(
175*480093f4SDimitry Andric             S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
176*480093f4SDimitry Andric 
177*480093f4SDimitry Andric         // Atomic constraint - substitute arguments and check satisfaction.
178*480093f4SDimitry Andric         ExprResult SubstitutedExpression;
179*480093f4SDimitry Andric         {
180*480093f4SDimitry Andric           TemplateDeductionInfo Info(TemplateNameLoc);
181*480093f4SDimitry Andric           Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
182*480093f4SDimitry Andric               Sema::InstantiatingTemplate::ConstraintSubstitution{}, Template,
183*480093f4SDimitry Andric               Info, AtomicExpr->getSourceRange());
184*480093f4SDimitry Andric           if (Inst.isInvalid())
185*480093f4SDimitry Andric             return ExprError();
186*480093f4SDimitry Andric           // We do not want error diagnostics escaping here.
187*480093f4SDimitry Andric           Sema::SFINAETrap Trap(S);
188*480093f4SDimitry Andric           SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
189*480093f4SDimitry Andric                                               MLTAL);
190*480093f4SDimitry Andric           if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
191*480093f4SDimitry Andric             // C++2a [temp.constr.atomic]p1
192*480093f4SDimitry Andric             //   ...If substitution results in an invalid type or expression, the
193*480093f4SDimitry Andric             //   constraint is not satisfied.
194*480093f4SDimitry Andric             if (!Trap.hasErrorOccurred())
195*480093f4SDimitry Andric               // A non-SFINAE error has occured as a result of this
196*480093f4SDimitry Andric               // substitution.
197*480093f4SDimitry Andric               return ExprError();
198*480093f4SDimitry Andric 
199*480093f4SDimitry Andric             PartialDiagnosticAt SubstDiag{SourceLocation(),
200*480093f4SDimitry Andric                                           PartialDiagnostic::NullDiagnostic()};
201*480093f4SDimitry Andric             Info.takeSFINAEDiagnostic(SubstDiag);
202*480093f4SDimitry Andric             // FIXME: Concepts: This is an unfortunate consequence of there
203*480093f4SDimitry Andric             //  being no serialization code for PartialDiagnostics and the fact
204*480093f4SDimitry Andric             //  that serializing them would likely take a lot more storage than
205*480093f4SDimitry Andric             //  just storing them as strings. We would still like, in the
206*480093f4SDimitry Andric             //  future, to serialize the proper PartialDiagnostic as serializing
207*480093f4SDimitry Andric             //  it as a string defeats the purpose of the diagnostic mechanism.
208*480093f4SDimitry Andric             SmallString<128> DiagString;
209*480093f4SDimitry Andric             DiagString = ": ";
210*480093f4SDimitry Andric             SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
211*480093f4SDimitry Andric             unsigned MessageSize = DiagString.size();
212*480093f4SDimitry Andric             char *Mem = new (S.Context) char[MessageSize];
213*480093f4SDimitry Andric             memcpy(Mem, DiagString.c_str(), MessageSize);
214*480093f4SDimitry Andric             Satisfaction.Details.emplace_back(
215*480093f4SDimitry Andric                 AtomicExpr,
216*480093f4SDimitry Andric                 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
217*480093f4SDimitry Andric                         SubstDiag.first, StringRef(Mem, MessageSize)});
218*480093f4SDimitry Andric             Satisfaction.IsSatisfied = false;
219*480093f4SDimitry Andric             return ExprEmpty();
220*480093f4SDimitry Andric           }
221*480093f4SDimitry Andric         }
222*480093f4SDimitry Andric 
223*480093f4SDimitry Andric         if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
224*480093f4SDimitry Andric           return ExprError();
225*480093f4SDimitry Andric 
226*480093f4SDimitry Andric         return SubstitutedExpression;
227*480093f4SDimitry Andric       });
228*480093f4SDimitry Andric }
229*480093f4SDimitry Andric 
230*480093f4SDimitry Andric template<typename TemplateDeclT>
231*480093f4SDimitry Andric static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
232*480093f4SDimitry Andric                                         ArrayRef<const Expr *> ConstraintExprs,
233*480093f4SDimitry Andric                                         ArrayRef<TemplateArgument> TemplateArgs,
234*480093f4SDimitry Andric                                         SourceRange TemplateIDRange,
235*480093f4SDimitry Andric                                         ConstraintSatisfaction &Satisfaction) {
236*480093f4SDimitry Andric   if (ConstraintExprs.empty()) {
237*480093f4SDimitry Andric     Satisfaction.IsSatisfied = true;
238*480093f4SDimitry Andric     return false;
239*480093f4SDimitry Andric   }
240*480093f4SDimitry Andric 
241*480093f4SDimitry Andric   for (auto& Arg : TemplateArgs)
242*480093f4SDimitry Andric     if (Arg.isInstantiationDependent()) {
243*480093f4SDimitry Andric       // No need to check satisfaction for dependent constraint expressions.
244*480093f4SDimitry Andric       Satisfaction.IsSatisfied = true;
245*480093f4SDimitry Andric       return false;
246*480093f4SDimitry Andric     }
247*480093f4SDimitry Andric 
248*480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
249*480093f4SDimitry Andric       Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
250*480093f4SDimitry Andric       TemplateIDRange);
251*480093f4SDimitry Andric   if (Inst.isInvalid())
252*480093f4SDimitry Andric     return true;
253*480093f4SDimitry Andric 
254*480093f4SDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
255*480093f4SDimitry Andric   MLTAL.addOuterTemplateArguments(TemplateArgs);
256*480093f4SDimitry Andric 
257*480093f4SDimitry Andric   for (const Expr *ConstraintExpr : ConstraintExprs) {
258*480093f4SDimitry Andric     if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
259*480093f4SDimitry Andric                                         TemplateIDRange.getBegin(), MLTAL,
260*480093f4SDimitry Andric                                         ConstraintExpr, Satisfaction))
261*480093f4SDimitry Andric       return true;
262*480093f4SDimitry Andric     if (!Satisfaction.IsSatisfied)
263*480093f4SDimitry Andric       // [temp.constr.op] p2
264*480093f4SDimitry Andric       //   [...] To determine if a conjunction is satisfied, the satisfaction
265*480093f4SDimitry Andric       //   of the first operand is checked. If that is not satisfied, the
266*480093f4SDimitry Andric       //   conjunction is not satisfied. [...]
267*480093f4SDimitry Andric       return false;
268*480093f4SDimitry Andric   }
269*480093f4SDimitry Andric   return false;
270*480093f4SDimitry Andric }
271*480093f4SDimitry Andric 
272*480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(TemplateDecl *Template,
273*480093f4SDimitry Andric                                        ArrayRef<const Expr *> ConstraintExprs,
274*480093f4SDimitry Andric                                        ArrayRef<TemplateArgument> TemplateArgs,
275*480093f4SDimitry Andric                                        SourceRange TemplateIDRange,
276*480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
277*480093f4SDimitry Andric   return ::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
278*480093f4SDimitry Andric                                        TemplateArgs, TemplateIDRange,
279*480093f4SDimitry Andric                                        Satisfaction);
280*480093f4SDimitry Andric }
281*480093f4SDimitry Andric 
282*480093f4SDimitry Andric bool
283*480093f4SDimitry Andric Sema::CheckConstraintSatisfaction(ClassTemplatePartialSpecializationDecl* Part,
284*480093f4SDimitry Andric                                   ArrayRef<const Expr *> ConstraintExprs,
285*480093f4SDimitry Andric                                   ArrayRef<TemplateArgument> TemplateArgs,
286*480093f4SDimitry Andric                                   SourceRange TemplateIDRange,
287*480093f4SDimitry Andric                                   ConstraintSatisfaction &Satisfaction) {
288*480093f4SDimitry Andric   return ::CheckConstraintSatisfaction(*this, Part, ConstraintExprs,
289*480093f4SDimitry Andric                                        TemplateArgs, TemplateIDRange,
290*480093f4SDimitry Andric                                        Satisfaction);
291*480093f4SDimitry Andric }
292*480093f4SDimitry Andric 
293*480093f4SDimitry Andric bool
294*480093f4SDimitry Andric Sema::CheckConstraintSatisfaction(VarTemplatePartialSpecializationDecl* Partial,
295*480093f4SDimitry Andric                                   ArrayRef<const Expr *> ConstraintExprs,
296*480093f4SDimitry Andric                                   ArrayRef<TemplateArgument> TemplateArgs,
297*480093f4SDimitry Andric                                   SourceRange TemplateIDRange,
298*480093f4SDimitry Andric                                   ConstraintSatisfaction &Satisfaction) {
299*480093f4SDimitry Andric   return ::CheckConstraintSatisfaction(*this, Partial, ConstraintExprs,
300*480093f4SDimitry Andric                                        TemplateArgs, TemplateIDRange,
301*480093f4SDimitry Andric                                        Satisfaction);
302*480093f4SDimitry Andric }
303*480093f4SDimitry Andric 
304*480093f4SDimitry Andric bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
305*480093f4SDimitry Andric                                        ConstraintSatisfaction &Satisfaction) {
306*480093f4SDimitry Andric   return calculateConstraintSatisfaction(
307*480093f4SDimitry Andric       *this, ConstraintExpr, Satisfaction,
308*480093f4SDimitry Andric       [](const Expr *AtomicExpr) -> ExprResult {
309*480093f4SDimitry Andric         return ExprResult(const_cast<Expr *>(AtomicExpr));
310*480093f4SDimitry Andric       });
311*480093f4SDimitry Andric }
312*480093f4SDimitry Andric 
313*480093f4SDimitry Andric bool Sema::EnsureTemplateArgumentListConstraints(
314*480093f4SDimitry Andric     TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
315*480093f4SDimitry Andric     SourceRange TemplateIDRange) {
316*480093f4SDimitry Andric   ConstraintSatisfaction Satisfaction;
317*480093f4SDimitry Andric   llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
318*480093f4SDimitry Andric   TD->getAssociatedConstraints(AssociatedConstraints);
319*480093f4SDimitry Andric   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
320*480093f4SDimitry Andric                                   TemplateIDRange, Satisfaction))
321*480093f4SDimitry Andric     return true;
322*480093f4SDimitry Andric 
323*480093f4SDimitry Andric   if (!Satisfaction.IsSatisfied) {
324*480093f4SDimitry Andric     SmallString<128> TemplateArgString;
325*480093f4SDimitry Andric     TemplateArgString = " ";
326*480093f4SDimitry Andric     TemplateArgString += getTemplateArgumentBindingsText(
327*480093f4SDimitry Andric         TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
328*480093f4SDimitry Andric 
329*480093f4SDimitry Andric     Diag(TemplateIDRange.getBegin(),
330*480093f4SDimitry Andric          diag::err_template_arg_list_constraints_not_satisfied)
331*480093f4SDimitry Andric         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
332*480093f4SDimitry Andric         << TemplateArgString << TemplateIDRange;
333*480093f4SDimitry Andric     DiagnoseUnsatisfiedConstraint(Satisfaction);
334*480093f4SDimitry Andric     return true;
335*480093f4SDimitry Andric   }
336*480093f4SDimitry Andric   return false;
337*480093f4SDimitry Andric }
338*480093f4SDimitry Andric 
339*480093f4SDimitry Andric static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
340*480093f4SDimitry Andric                                                         Expr *SubstExpr,
341*480093f4SDimitry Andric                                                         bool First = true) {
342*480093f4SDimitry Andric   SubstExpr = SubstExpr->IgnoreParenImpCasts();
343*480093f4SDimitry Andric   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
344*480093f4SDimitry Andric     switch (BO->getOpcode()) {
345*480093f4SDimitry Andric     // These two cases will in practice only be reached when using fold
346*480093f4SDimitry Andric     // expressions with || and &&, since otherwise the || and && will have been
347*480093f4SDimitry Andric     // broken down into atomic constraints during satisfaction checking.
348*480093f4SDimitry Andric     case BO_LOr:
349*480093f4SDimitry Andric       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
350*480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
351*480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
352*480093f4SDimitry Andric                                                   /*First=*/false);
353*480093f4SDimitry Andric       return;
354*480093f4SDimitry Andric     case BO_LAnd:
355*480093f4SDimitry Andric       bool LHSSatisfied;
356*480093f4SDimitry Andric       BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
357*480093f4SDimitry Andric       if (LHSSatisfied) {
358*480093f4SDimitry Andric         // LHS is true, so RHS must be false.
359*480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
360*480093f4SDimitry Andric         return;
361*480093f4SDimitry Andric       }
362*480093f4SDimitry Andric       // LHS is false
363*480093f4SDimitry Andric       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
364*480093f4SDimitry Andric 
365*480093f4SDimitry Andric       // RHS might also be false
366*480093f4SDimitry Andric       bool RHSSatisfied;
367*480093f4SDimitry Andric       BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
368*480093f4SDimitry Andric       if (!RHSSatisfied)
369*480093f4SDimitry Andric         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
370*480093f4SDimitry Andric                                                     /*First=*/false);
371*480093f4SDimitry Andric       return;
372*480093f4SDimitry Andric     case BO_GE:
373*480093f4SDimitry Andric     case BO_LE:
374*480093f4SDimitry Andric     case BO_GT:
375*480093f4SDimitry Andric     case BO_LT:
376*480093f4SDimitry Andric     case BO_EQ:
377*480093f4SDimitry Andric     case BO_NE:
378*480093f4SDimitry Andric       if (BO->getLHS()->getType()->isIntegerType() &&
379*480093f4SDimitry Andric           BO->getRHS()->getType()->isIntegerType()) {
380*480093f4SDimitry Andric         Expr::EvalResult SimplifiedLHS;
381*480093f4SDimitry Andric         Expr::EvalResult SimplifiedRHS;
382*480093f4SDimitry Andric         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
383*480093f4SDimitry Andric         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
384*480093f4SDimitry Andric         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
385*480093f4SDimitry Andric           S.Diag(SubstExpr->getBeginLoc(),
386*480093f4SDimitry Andric                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
387*480093f4SDimitry Andric               << (int)First << SubstExpr
388*480093f4SDimitry Andric               << SimplifiedLHS.Val.getInt().toString(10)
389*480093f4SDimitry Andric               << BinaryOperator::getOpcodeStr(BO->getOpcode())
390*480093f4SDimitry Andric               << SimplifiedRHS.Val.getInt().toString(10);
391*480093f4SDimitry Andric           return;
392*480093f4SDimitry Andric         }
393*480093f4SDimitry Andric       }
394*480093f4SDimitry Andric       break;
395*480093f4SDimitry Andric 
396*480093f4SDimitry Andric     default:
397*480093f4SDimitry Andric       break;
398*480093f4SDimitry Andric     }
399*480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
400*480093f4SDimitry Andric     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
401*480093f4SDimitry Andric       S.Diag(
402*480093f4SDimitry Andric           CSE->getSourceRange().getBegin(),
403*480093f4SDimitry Andric           diag::
404*480093f4SDimitry Andric           note_single_arg_concept_specialization_constraint_evaluated_to_false)
405*480093f4SDimitry Andric           << (int)First
406*480093f4SDimitry Andric           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
407*480093f4SDimitry Andric           << CSE->getNamedConcept();
408*480093f4SDimitry Andric     } else {
409*480093f4SDimitry Andric       S.Diag(SubstExpr->getSourceRange().getBegin(),
410*480093f4SDimitry Andric              diag::note_concept_specialization_constraint_evaluated_to_false)
411*480093f4SDimitry Andric           << (int)First << CSE;
412*480093f4SDimitry Andric     }
413*480093f4SDimitry Andric     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
414*480093f4SDimitry Andric     return;
415*480093f4SDimitry Andric   }
416*480093f4SDimitry Andric 
417*480093f4SDimitry Andric   S.Diag(SubstExpr->getSourceRange().getBegin(),
418*480093f4SDimitry Andric          diag::note_atomic_constraint_evaluated_to_false)
419*480093f4SDimitry Andric       << (int)First << SubstExpr;
420*480093f4SDimitry Andric }
421*480093f4SDimitry Andric 
422*480093f4SDimitry Andric template<typename SubstitutionDiagnostic>
423*480093f4SDimitry Andric static void diagnoseUnsatisfiedConstraintExpr(
424*480093f4SDimitry Andric     Sema &S, const Expr *E,
425*480093f4SDimitry Andric     const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
426*480093f4SDimitry Andric     bool First = true) {
427*480093f4SDimitry Andric   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
428*480093f4SDimitry Andric     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
429*480093f4SDimitry Andric         << Diag->second;
430*480093f4SDimitry Andric     return;
431*480093f4SDimitry Andric   }
432*480093f4SDimitry Andric 
433*480093f4SDimitry Andric   diagnoseWellFormedUnsatisfiedConstraintExpr(S,
434*480093f4SDimitry Andric       Record.template get<Expr *>(), First);
435*480093f4SDimitry Andric }
436*480093f4SDimitry Andric 
437*480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
438*480093f4SDimitry Andric     const ConstraintSatisfaction& Satisfaction) {
439*480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
440*480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
441*480093f4SDimitry Andric   bool First = true;
442*480093f4SDimitry Andric   for (auto &Pair : Satisfaction.Details) {
443*480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
444*480093f4SDimitry Andric     First = false;
445*480093f4SDimitry Andric   }
446*480093f4SDimitry Andric }
447*480093f4SDimitry Andric 
448*480093f4SDimitry Andric void Sema::DiagnoseUnsatisfiedConstraint(
449*480093f4SDimitry Andric     const ASTConstraintSatisfaction &Satisfaction) {
450*480093f4SDimitry Andric   assert(!Satisfaction.IsSatisfied &&
451*480093f4SDimitry Andric          "Attempted to diagnose a satisfied constraint");
452*480093f4SDimitry Andric   bool First = true;
453*480093f4SDimitry Andric   for (auto &Pair : Satisfaction) {
454*480093f4SDimitry Andric     diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
455*480093f4SDimitry Andric     First = false;
456*480093f4SDimitry Andric   }
457*480093f4SDimitry Andric }
458*480093f4SDimitry Andric 
459*480093f4SDimitry Andric const NormalizedConstraint *
460*480093f4SDimitry Andric Sema::getNormalizedAssociatedConstraints(
461*480093f4SDimitry Andric     NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
462*480093f4SDimitry Andric   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
463*480093f4SDimitry Andric   if (CacheEntry == NormalizationCache.end()) {
464*480093f4SDimitry Andric     auto Normalized =
465*480093f4SDimitry Andric         NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
466*480093f4SDimitry Andric                                                   AssociatedConstraints);
467*480093f4SDimitry Andric     CacheEntry =
468*480093f4SDimitry Andric         NormalizationCache
469*480093f4SDimitry Andric             .try_emplace(ConstrainedDecl,
470*480093f4SDimitry Andric                          Normalized
471*480093f4SDimitry Andric                              ? new (Context) NormalizedConstraint(
472*480093f4SDimitry Andric                                  std::move(*Normalized))
473*480093f4SDimitry Andric                              : nullptr)
474*480093f4SDimitry Andric             .first;
475*480093f4SDimitry Andric   }
476*480093f4SDimitry Andric   return CacheEntry->second;
477*480093f4SDimitry Andric }
478*480093f4SDimitry Andric 
479*480093f4SDimitry Andric static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
480*480093f4SDimitry Andric     ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
481*480093f4SDimitry Andric     const ASTTemplateArgumentListInfo *ArgsAsWritten) {
482*480093f4SDimitry Andric   if (!N.isAtomic()) {
483*480093f4SDimitry Andric     if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
484*480093f4SDimitry Andric                                     ArgsAsWritten))
485*480093f4SDimitry Andric       return true;
486*480093f4SDimitry Andric     return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
487*480093f4SDimitry Andric                                        ArgsAsWritten);
488*480093f4SDimitry Andric   }
489*480093f4SDimitry Andric   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
490*480093f4SDimitry Andric 
491*480093f4SDimitry Andric   AtomicConstraint &Atomic = *N.getAtomicConstraint();
492*480093f4SDimitry Andric   TemplateArgumentListInfo SubstArgs;
493*480093f4SDimitry Andric   MultiLevelTemplateArgumentList MLTAL;
494*480093f4SDimitry Andric   MLTAL.addOuterTemplateArguments(TemplateArgs);
495*480093f4SDimitry Andric   if (!Atomic.ParameterMapping) {
496*480093f4SDimitry Andric     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
497*480093f4SDimitry Andric     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
498*480093f4SDimitry Andric                                  /*Depth=*/0, OccurringIndices);
499*480093f4SDimitry Andric     Atomic.ParameterMapping.emplace(
500*480093f4SDimitry Andric         MutableArrayRef<TemplateArgumentLoc>(
501*480093f4SDimitry Andric             new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
502*480093f4SDimitry Andric             OccurringIndices.count()));
503*480093f4SDimitry Andric     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
504*480093f4SDimitry Andric       if (OccurringIndices[I])
505*480093f4SDimitry Andric         new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
506*480093f4SDimitry Andric             S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
507*480093f4SDimitry Andric                 // Here we assume we do not support things like
508*480093f4SDimitry Andric                 // template<typename A, typename B>
509*480093f4SDimitry Andric                 // concept C = ...;
510*480093f4SDimitry Andric                 //
511*480093f4SDimitry Andric                 // template<typename... Ts> requires C<Ts...>
512*480093f4SDimitry Andric                 // struct S { };
513*480093f4SDimitry Andric                 // The above currently yields a diagnostic.
514*480093f4SDimitry Andric                 // We still might have default arguments for concept parameters.
515*480093f4SDimitry Andric                 ArgsAsWritten->NumTemplateArgs > I ?
516*480093f4SDimitry Andric                 ArgsAsWritten->arguments()[I].getLocation() :
517*480093f4SDimitry Andric                 SourceLocation()));
518*480093f4SDimitry Andric   }
519*480093f4SDimitry Andric   Sema::InstantiatingTemplate Inst(
520*480093f4SDimitry Andric       S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
521*480093f4SDimitry Andric       Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
522*480093f4SDimitry Andric       SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
523*480093f4SDimitry Andric                   ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
524*480093f4SDimitry Andric   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
525*480093f4SDimitry Andric     return true;
526*480093f4SDimitry Andric   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
527*480093f4SDimitry Andric             N.getAtomicConstraint()->ParameterMapping->begin());
528*480093f4SDimitry Andric   return false;
529*480093f4SDimitry Andric }
530*480093f4SDimitry Andric 
531*480093f4SDimitry Andric Optional<NormalizedConstraint>
532*480093f4SDimitry Andric NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
533*480093f4SDimitry Andric                                           ArrayRef<const Expr *> E) {
534*480093f4SDimitry Andric   assert(E.size() != 0);
535*480093f4SDimitry Andric   auto First = fromConstraintExpr(S, D, E[0]);
536*480093f4SDimitry Andric   if (E.size() == 1)
537*480093f4SDimitry Andric     return First;
538*480093f4SDimitry Andric   auto Second = fromConstraintExpr(S, D, E[1]);
539*480093f4SDimitry Andric   if (!Second)
540*480093f4SDimitry Andric     return None;
541*480093f4SDimitry Andric   llvm::Optional<NormalizedConstraint> Conjunction;
542*480093f4SDimitry Andric   Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
543*480093f4SDimitry Andric                       CCK_Conjunction);
544*480093f4SDimitry Andric   for (unsigned I = 2; I < E.size(); ++I) {
545*480093f4SDimitry Andric     auto Next = fromConstraintExpr(S, D, E[I]);
546*480093f4SDimitry Andric     if (!Next)
547*480093f4SDimitry Andric       return llvm::Optional<NormalizedConstraint>{};
548*480093f4SDimitry Andric     NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
549*480093f4SDimitry Andric                                         std::move(*Next), CCK_Conjunction);
550*480093f4SDimitry Andric     *Conjunction = std::move(NewConjunction);
551*480093f4SDimitry Andric   }
552*480093f4SDimitry Andric   return Conjunction;
553*480093f4SDimitry Andric }
554*480093f4SDimitry Andric 
555*480093f4SDimitry Andric llvm::Optional<NormalizedConstraint>
556*480093f4SDimitry Andric NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
557*480093f4SDimitry Andric   assert(E != nullptr);
558*480093f4SDimitry Andric 
559*480093f4SDimitry Andric   // C++ [temp.constr.normal]p1.1
560*480093f4SDimitry Andric   // [...]
561*480093f4SDimitry Andric   // - The normal form of an expression (E) is the normal form of E.
562*480093f4SDimitry Andric   // [...]
563*480093f4SDimitry Andric   E = E->IgnoreParenImpCasts();
564*480093f4SDimitry Andric   if (auto *BO = dyn_cast<const BinaryOperator>(E)) {
565*480093f4SDimitry Andric     if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
566*480093f4SDimitry Andric       auto LHS = fromConstraintExpr(S, D, BO->getLHS());
567*480093f4SDimitry Andric       if (!LHS)
568*480093f4SDimitry Andric         return None;
569*480093f4SDimitry Andric       auto RHS = fromConstraintExpr(S, D, BO->getRHS());
570*480093f4SDimitry Andric       if (!RHS)
571*480093f4SDimitry Andric         return None;
572*480093f4SDimitry Andric 
573*480093f4SDimitry Andric       return NormalizedConstraint(
574*480093f4SDimitry Andric           S.Context, std::move(*LHS), std::move(*RHS),
575*480093f4SDimitry Andric           BO->getOpcode() == BO_LAnd ? CCK_Conjunction : CCK_Disjunction);
576*480093f4SDimitry Andric     }
577*480093f4SDimitry Andric   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
578*480093f4SDimitry Andric     const NormalizedConstraint *SubNF;
579*480093f4SDimitry Andric     {
580*480093f4SDimitry Andric       Sema::InstantiatingTemplate Inst(
581*480093f4SDimitry Andric           S, CSE->getExprLoc(),
582*480093f4SDimitry Andric           Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
583*480093f4SDimitry Andric           CSE->getSourceRange());
584*480093f4SDimitry Andric       // C++ [temp.constr.normal]p1.1
585*480093f4SDimitry Andric       // [...]
586*480093f4SDimitry Andric       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
587*480093f4SDimitry Andric       // where C names a concept, is the normal form of the
588*480093f4SDimitry Andric       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
589*480093f4SDimitry Andric       // respective template parameters in the parameter mappings in each atomic
590*480093f4SDimitry Andric       // constraint. If any such substitution results in an invalid type or
591*480093f4SDimitry Andric       // expression, the program is ill-formed; no diagnostic is required.
592*480093f4SDimitry Andric       // [...]
593*480093f4SDimitry Andric       ConceptDecl *CD = CSE->getNamedConcept();
594*480093f4SDimitry Andric       SubNF = S.getNormalizedAssociatedConstraints(CD,
595*480093f4SDimitry Andric                                                    {CD->getConstraintExpr()});
596*480093f4SDimitry Andric       if (!SubNF)
597*480093f4SDimitry Andric         return None;
598*480093f4SDimitry Andric     }
599*480093f4SDimitry Andric 
600*480093f4SDimitry Andric     Optional<NormalizedConstraint> New;
601*480093f4SDimitry Andric     New.emplace(S.Context, *SubNF);
602*480093f4SDimitry Andric 
603*480093f4SDimitry Andric     if (substituteParameterMappings(
604*480093f4SDimitry Andric             S, *New, CSE->getNamedConcept(),
605*480093f4SDimitry Andric             CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
606*480093f4SDimitry Andric       return None;
607*480093f4SDimitry Andric 
608*480093f4SDimitry Andric     return New;
609*480093f4SDimitry Andric   }
610*480093f4SDimitry Andric   return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
611*480093f4SDimitry Andric }
612*480093f4SDimitry Andric 
613*480093f4SDimitry Andric using NormalForm =
614*480093f4SDimitry Andric     llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
615*480093f4SDimitry Andric 
616*480093f4SDimitry Andric static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
617*480093f4SDimitry Andric   if (Normalized.isAtomic())
618*480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
619*480093f4SDimitry Andric 
620*480093f4SDimitry Andric   NormalForm LCNF = makeCNF(Normalized.getLHS());
621*480093f4SDimitry Andric   NormalForm RCNF = makeCNF(Normalized.getRHS());
622*480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
623*480093f4SDimitry Andric     LCNF.reserve(LCNF.size() + RCNF.size());
624*480093f4SDimitry Andric     while (!RCNF.empty())
625*480093f4SDimitry Andric       LCNF.push_back(RCNF.pop_back_val());
626*480093f4SDimitry Andric     return LCNF;
627*480093f4SDimitry Andric   }
628*480093f4SDimitry Andric 
629*480093f4SDimitry Andric   // Disjunction
630*480093f4SDimitry Andric   NormalForm Res;
631*480093f4SDimitry Andric   Res.reserve(LCNF.size() * RCNF.size());
632*480093f4SDimitry Andric   for (auto &LDisjunction : LCNF)
633*480093f4SDimitry Andric     for (auto &RDisjunction : RCNF) {
634*480093f4SDimitry Andric       NormalForm::value_type Combined;
635*480093f4SDimitry Andric       Combined.reserve(LDisjunction.size() + RDisjunction.size());
636*480093f4SDimitry Andric       std::copy(LDisjunction.begin(), LDisjunction.end(),
637*480093f4SDimitry Andric                 std::back_inserter(Combined));
638*480093f4SDimitry Andric       std::copy(RDisjunction.begin(), RDisjunction.end(),
639*480093f4SDimitry Andric                 std::back_inserter(Combined));
640*480093f4SDimitry Andric       Res.emplace_back(Combined);
641*480093f4SDimitry Andric     }
642*480093f4SDimitry Andric   return Res;
643*480093f4SDimitry Andric }
644*480093f4SDimitry Andric 
645*480093f4SDimitry Andric static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
646*480093f4SDimitry Andric   if (Normalized.isAtomic())
647*480093f4SDimitry Andric     return {{Normalized.getAtomicConstraint()}};
648*480093f4SDimitry Andric 
649*480093f4SDimitry Andric   NormalForm LDNF = makeDNF(Normalized.getLHS());
650*480093f4SDimitry Andric   NormalForm RDNF = makeDNF(Normalized.getRHS());
651*480093f4SDimitry Andric   if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
652*480093f4SDimitry Andric     LDNF.reserve(LDNF.size() + RDNF.size());
653*480093f4SDimitry Andric     while (!RDNF.empty())
654*480093f4SDimitry Andric       LDNF.push_back(RDNF.pop_back_val());
655*480093f4SDimitry Andric     return LDNF;
656*480093f4SDimitry Andric   }
657*480093f4SDimitry Andric 
658*480093f4SDimitry Andric   // Conjunction
659*480093f4SDimitry Andric   NormalForm Res;
660*480093f4SDimitry Andric   Res.reserve(LDNF.size() * RDNF.size());
661*480093f4SDimitry Andric   for (auto &LConjunction : LDNF) {
662*480093f4SDimitry Andric     for (auto &RConjunction : RDNF) {
663*480093f4SDimitry Andric       NormalForm::value_type Combined;
664*480093f4SDimitry Andric       Combined.reserve(LConjunction.size() + RConjunction.size());
665*480093f4SDimitry Andric       std::copy(LConjunction.begin(), LConjunction.end(),
666*480093f4SDimitry Andric                 std::back_inserter(Combined));
667*480093f4SDimitry Andric       std::copy(RConjunction.begin(), RConjunction.end(),
668*480093f4SDimitry Andric                 std::back_inserter(Combined));
669*480093f4SDimitry Andric       Res.emplace_back(Combined);
670*480093f4SDimitry Andric     }
671*480093f4SDimitry Andric   }
672*480093f4SDimitry Andric   return Res;
673*480093f4SDimitry Andric }
674*480093f4SDimitry Andric 
675*480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
676*480093f4SDimitry Andric static bool subsumes(NormalForm PDNF, NormalForm QCNF,
677*480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
678*480093f4SDimitry Andric   // C++ [temp.constr.order] p2
679*480093f4SDimitry Andric   //   Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
680*480093f4SDimitry Andric   //   disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
681*480093f4SDimitry Andric   //   the conjuctive normal form of Q, where [...]
682*480093f4SDimitry Andric   for (const auto &Pi : PDNF) {
683*480093f4SDimitry Andric     for (const auto &Qj : QCNF) {
684*480093f4SDimitry Andric       // C++ [temp.constr.order] p2
685*480093f4SDimitry Andric       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
686*480093f4SDimitry Andric       //     and only if there exists an atomic constraint Pia in Pi for which
687*480093f4SDimitry Andric       //     there exists an atomic constraint, Qjb, in Qj such that Pia
688*480093f4SDimitry Andric       //     subsumes Qjb.
689*480093f4SDimitry Andric       bool Found = false;
690*480093f4SDimitry Andric       for (const AtomicConstraint *Pia : Pi) {
691*480093f4SDimitry Andric         for (const AtomicConstraint *Qjb : Qj) {
692*480093f4SDimitry Andric           if (E(*Pia, *Qjb)) {
693*480093f4SDimitry Andric             Found = true;
694*480093f4SDimitry Andric             break;
695*480093f4SDimitry Andric           }
696*480093f4SDimitry Andric         }
697*480093f4SDimitry Andric         if (Found)
698*480093f4SDimitry Andric           break;
699*480093f4SDimitry Andric       }
700*480093f4SDimitry Andric       if (!Found)
701*480093f4SDimitry Andric         return false;
702*480093f4SDimitry Andric     }
703*480093f4SDimitry Andric   }
704*480093f4SDimitry Andric   return true;
705*480093f4SDimitry Andric }
706*480093f4SDimitry Andric 
707*480093f4SDimitry Andric template<typename AtomicSubsumptionEvaluator>
708*480093f4SDimitry Andric static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
709*480093f4SDimitry Andric                      NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
710*480093f4SDimitry Andric                      AtomicSubsumptionEvaluator E) {
711*480093f4SDimitry Andric   // C++ [temp.constr.order] p2
712*480093f4SDimitry Andric   //   In order to determine if a constraint P subsumes a constraint Q, P is
713*480093f4SDimitry Andric   //   transformed into disjunctive normal form, and Q is transformed into
714*480093f4SDimitry Andric   //   conjunctive normal form. [...]
715*480093f4SDimitry Andric   auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
716*480093f4SDimitry Andric   if (!PNormalized)
717*480093f4SDimitry Andric     return true;
718*480093f4SDimitry Andric   const NormalForm PDNF = makeDNF(*PNormalized);
719*480093f4SDimitry Andric 
720*480093f4SDimitry Andric   auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
721*480093f4SDimitry Andric   if (!QNormalized)
722*480093f4SDimitry Andric     return true;
723*480093f4SDimitry Andric   const NormalForm QCNF = makeCNF(*QNormalized);
724*480093f4SDimitry Andric 
725*480093f4SDimitry Andric   Subsumes = subsumes(PDNF, QCNF, E);
726*480093f4SDimitry Andric   return false;
727*480093f4SDimitry Andric }
728*480093f4SDimitry Andric 
729*480093f4SDimitry Andric bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
730*480093f4SDimitry Andric                                   NamedDecl *D2, ArrayRef<const Expr *> AC2,
731*480093f4SDimitry Andric                                   bool &Result) {
732*480093f4SDimitry Andric   if (AC1.empty()) {
733*480093f4SDimitry Andric     Result = AC2.empty();
734*480093f4SDimitry Andric     return false;
735*480093f4SDimitry Andric   }
736*480093f4SDimitry Andric   if (AC2.empty()) {
737*480093f4SDimitry Andric     // TD1 has associated constraints and TD2 does not.
738*480093f4SDimitry Andric     Result = true;
739*480093f4SDimitry Andric     return false;
740*480093f4SDimitry Andric   }
741*480093f4SDimitry Andric 
742*480093f4SDimitry Andric   std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
743*480093f4SDimitry Andric   auto CacheEntry = SubsumptionCache.find(Key);
744*480093f4SDimitry Andric   if (CacheEntry != SubsumptionCache.end()) {
745*480093f4SDimitry Andric     Result = CacheEntry->second;
746*480093f4SDimitry Andric     return false;
747*480093f4SDimitry Andric   }
748*480093f4SDimitry Andric 
749*480093f4SDimitry Andric   if (subsumes(*this, D1, AC1, D2, AC2, Result,
750*480093f4SDimitry Andric         [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
751*480093f4SDimitry Andric           return A.subsumes(Context, B);
752*480093f4SDimitry Andric         }))
753*480093f4SDimitry Andric     return true;
754*480093f4SDimitry Andric   SubsumptionCache.try_emplace(Key, Result);
755*480093f4SDimitry Andric   return false;
756*480093f4SDimitry Andric }
757*480093f4SDimitry Andric 
758*480093f4SDimitry Andric bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
759*480093f4SDimitry Andric     ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
760*480093f4SDimitry Andric   if (isSFINAEContext())
761*480093f4SDimitry Andric     // No need to work here because our notes would be discarded.
762*480093f4SDimitry Andric     return false;
763*480093f4SDimitry Andric 
764*480093f4SDimitry Andric   if (AC1.empty() || AC2.empty())
765*480093f4SDimitry Andric     return false;
766*480093f4SDimitry Andric 
767*480093f4SDimitry Andric   auto NormalExprEvaluator =
768*480093f4SDimitry Andric       [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
769*480093f4SDimitry Andric         return A.subsumes(Context, B);
770*480093f4SDimitry Andric       };
771*480093f4SDimitry Andric 
772*480093f4SDimitry Andric   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
773*480093f4SDimitry Andric   auto IdenticalExprEvaluator =
774*480093f4SDimitry Andric       [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
775*480093f4SDimitry Andric         if (!A.hasMatchingParameterMapping(Context, B))
776*480093f4SDimitry Andric           return false;
777*480093f4SDimitry Andric         const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
778*480093f4SDimitry Andric         if (EA == EB)
779*480093f4SDimitry Andric           return true;
780*480093f4SDimitry Andric 
781*480093f4SDimitry Andric         // Not the same source level expression - are the expressions
782*480093f4SDimitry Andric         // identical?
783*480093f4SDimitry Andric         llvm::FoldingSetNodeID IDA, IDB;
784*480093f4SDimitry Andric         EA->Profile(IDA, Context, /*Cannonical=*/true);
785*480093f4SDimitry Andric         EB->Profile(IDB, Context, /*Cannonical=*/true);
786*480093f4SDimitry Andric         if (IDA != IDB)
787*480093f4SDimitry Andric           return false;
788*480093f4SDimitry Andric 
789*480093f4SDimitry Andric         AmbiguousAtomic1 = EA;
790*480093f4SDimitry Andric         AmbiguousAtomic2 = EB;
791*480093f4SDimitry Andric         return true;
792*480093f4SDimitry Andric       };
793*480093f4SDimitry Andric 
794*480093f4SDimitry Andric   {
795*480093f4SDimitry Andric     // The subsumption checks might cause diagnostics
796*480093f4SDimitry Andric     SFINAETrap Trap(*this);
797*480093f4SDimitry Andric     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
798*480093f4SDimitry Andric     if (!Normalized1)
799*480093f4SDimitry Andric       return false;
800*480093f4SDimitry Andric     const NormalForm DNF1 = makeDNF(*Normalized1);
801*480093f4SDimitry Andric     const NormalForm CNF1 = makeCNF(*Normalized1);
802*480093f4SDimitry Andric 
803*480093f4SDimitry Andric     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
804*480093f4SDimitry Andric     if (!Normalized2)
805*480093f4SDimitry Andric       return false;
806*480093f4SDimitry Andric     const NormalForm DNF2 = makeDNF(*Normalized2);
807*480093f4SDimitry Andric     const NormalForm CNF2 = makeCNF(*Normalized2);
808*480093f4SDimitry Andric 
809*480093f4SDimitry Andric     bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
810*480093f4SDimitry Andric     bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
811*480093f4SDimitry Andric     bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
812*480093f4SDimitry Andric     bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
813*480093f4SDimitry Andric     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
814*480093f4SDimitry Andric         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
815*480093f4SDimitry Andric       // Same result - no ambiguity was caused by identical atomic expressions.
816*480093f4SDimitry Andric       return false;
817*480093f4SDimitry Andric   }
818*480093f4SDimitry Andric 
819*480093f4SDimitry Andric   // A different result! Some ambiguous atomic constraint(s) caused a difference
820*480093f4SDimitry Andric   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
821*480093f4SDimitry Andric 
822*480093f4SDimitry Andric   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
823*480093f4SDimitry Andric       << AmbiguousAtomic1->getSourceRange();
824*480093f4SDimitry Andric   Diag(AmbiguousAtomic2->getBeginLoc(),
825*480093f4SDimitry Andric        diag::note_ambiguous_atomic_constraints_similar_expression)
826*480093f4SDimitry Andric       << AmbiguousAtomic2->getSourceRange();
827*480093f4SDimitry Andric   return true;
828*480093f4SDimitry Andric }
829