xref: /freebsd/contrib/llvm-project/clang/lib/Sema/SemaConcept.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
1 //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file implements semantic analysis for C++ constraints and concepts.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/Sema/SemaConcept.h"
14 #include "TreeTransform.h"
15 #include "clang/AST/ASTLambda.h"
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/ExprConcepts.h"
18 #include "clang/Basic/OperatorPrecedence.h"
19 #include "clang/Sema/EnterExpressionEvaluationContext.h"
20 #include "clang/Sema/Initialization.h"
21 #include "clang/Sema/Overload.h"
22 #include "clang/Sema/ScopeInfo.h"
23 #include "clang/Sema/Sema.h"
24 #include "clang/Sema/SemaInternal.h"
25 #include "clang/Sema/Template.h"
26 #include "clang/Sema/TemplateDeduction.h"
27 #include "llvm/ADT/DenseMap.h"
28 #include "llvm/ADT/PointerUnion.h"
29 #include "llvm/ADT/StringExtras.h"
30 #include <optional>
31 
32 using namespace clang;
33 using namespace sema;
34 
35 namespace {
36 class LogicalBinOp {
37   SourceLocation Loc;
38   OverloadedOperatorKind Op = OO_None;
39   const Expr *LHS = nullptr;
40   const Expr *RHS = nullptr;
41 
42 public:
LogicalBinOp(const Expr * E)43   LogicalBinOp(const Expr *E) {
44     if (auto *BO = dyn_cast<BinaryOperator>(E)) {
45       Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
46       LHS = BO->getLHS();
47       RHS = BO->getRHS();
48       Loc = BO->getExprLoc();
49     } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
50       // If OO is not || or && it might not have exactly 2 arguments.
51       if (OO->getNumArgs() == 2) {
52         Op = OO->getOperator();
53         LHS = OO->getArg(0);
54         RHS = OO->getArg(1);
55         Loc = OO->getOperatorLoc();
56       }
57     }
58   }
59 
isAnd() const60   bool isAnd() const { return Op == OO_AmpAmp; }
isOr() const61   bool isOr() const { return Op == OO_PipePipe; }
operator bool() const62   explicit operator bool() const { return isAnd() || isOr(); }
63 
getLHS() const64   const Expr *getLHS() const { return LHS; }
getRHS() const65   const Expr *getRHS() const { return RHS; }
getOp() const66   OverloadedOperatorKind getOp() const { return Op; }
67 
recreateBinOp(Sema & SemaRef,ExprResult LHS) const68   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const {
69     return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS()));
70   }
71 
recreateBinOp(Sema & SemaRef,ExprResult LHS,ExprResult RHS) const72   ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS,
73                            ExprResult RHS) const {
74     assert((isAnd() || isOr()) && "Not the right kind of op?");
75     assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?");
76 
77     if (!LHS.isUsable() || !RHS.isUsable())
78       return ExprEmpty();
79 
80     // We should just be able to 'normalize' these to the builtin Binary
81     // Operator, since that is how they are evaluated in constriant checks.
82     return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(),
83                                   BinaryOperator::getOverloadedOpcode(Op),
84                                   SemaRef.Context.BoolTy, VK_PRValue,
85                                   OK_Ordinary, Loc, FPOptionsOverride{});
86   }
87 };
88 }
89 
CheckConstraintExpression(const Expr * ConstraintExpression,Token NextToken,bool * PossibleNonPrimary,bool IsTrailingRequiresClause)90 bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
91                                      Token NextToken, bool *PossibleNonPrimary,
92                                      bool IsTrailingRequiresClause) {
93   // C++2a [temp.constr.atomic]p1
94   // ..E shall be a constant expression of type bool.
95 
96   ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
97 
98   if (LogicalBinOp BO = ConstraintExpression) {
99     return CheckConstraintExpression(BO.getLHS(), NextToken,
100                                      PossibleNonPrimary) &&
101            CheckConstraintExpression(BO.getRHS(), NextToken,
102                                      PossibleNonPrimary);
103   } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
104     return CheckConstraintExpression(C->getSubExpr(), NextToken,
105                                      PossibleNonPrimary);
106 
107   QualType Type = ConstraintExpression->getType();
108 
109   auto CheckForNonPrimary = [&] {
110     if (!PossibleNonPrimary)
111       return;
112 
113     *PossibleNonPrimary =
114         // We have the following case:
115         // template<typename> requires func(0) struct S { };
116         // The user probably isn't aware of the parentheses required around
117         // the function call, and we're only going to parse 'func' as the
118         // primary-expression, and complain that it is of non-bool type.
119         //
120         // However, if we're in a lambda, this might also be:
121         // []<typename> requires var () {};
122         // Which also looks like a function call due to the lambda parentheses,
123         // but unlike the first case, isn't an error, so this check is skipped.
124         (NextToken.is(tok::l_paren) &&
125          (IsTrailingRequiresClause ||
126           (Type->isDependentType() &&
127            isa<UnresolvedLookupExpr>(ConstraintExpression) &&
128            !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) ||
129           Type->isFunctionType() ||
130           Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
131         // We have the following case:
132         // template<typename T> requires size_<T> == 0 struct S { };
133         // The user probably isn't aware of the parentheses required around
134         // the binary operator, and we're only going to parse 'func' as the
135         // first operand, and complain that it is of non-bool type.
136         getBinOpPrecedence(NextToken.getKind(),
137                            /*GreaterThanIsOperator=*/true,
138                            getLangOpts().CPlusPlus11) > prec::LogicalAnd;
139   };
140 
141   // An atomic constraint!
142   if (ConstraintExpression->isTypeDependent()) {
143     CheckForNonPrimary();
144     return true;
145   }
146 
147   if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
148     Diag(ConstraintExpression->getExprLoc(),
149          diag::err_non_bool_atomic_constraint) << Type
150         << ConstraintExpression->getSourceRange();
151     CheckForNonPrimary();
152     return false;
153   }
154 
155   if (PossibleNonPrimary)
156       *PossibleNonPrimary = false;
157   return true;
158 }
159 
160 namespace {
161 struct SatisfactionStackRAII {
162   Sema &SemaRef;
163   bool Inserted = false;
SatisfactionStackRAII__anon0c0fec810311::SatisfactionStackRAII164   SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND,
165                         const llvm::FoldingSetNodeID &FSNID)
166       : SemaRef(SemaRef) {
167       if (ND) {
168       SemaRef.PushSatisfactionStackEntry(ND, FSNID);
169       Inserted = true;
170       }
171   }
~SatisfactionStackRAII__anon0c0fec810311::SatisfactionStackRAII172   ~SatisfactionStackRAII() {
173         if (Inserted)
174           SemaRef.PopSatisfactionStackEntry();
175   }
176 };
177 } // namespace
178 
179 static bool
DiagRecursiveConstraintEval(Sema & S,llvm::FoldingSetNodeID & ID,const NamedDecl * Templ,const Expr * E,const MultiLevelTemplateArgumentList & MLTAL)180 DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID,
181                             const NamedDecl *Templ, const Expr *E,
182                             const MultiLevelTemplateArgumentList &MLTAL) {
183   E->Profile(ID, S.Context, /*Canonical=*/true);
184   for (const auto &List : MLTAL)
185     for (const auto &TemplateArg : List.Args)
186       TemplateArg.Profile(ID, S.Context);
187 
188   // Note that we have to do this with our own collection, because there are
189   // times where a constraint-expression check can cause us to need to evaluate
190   // other constriants that are unrelated, such as when evaluating a recovery
191   // expression, or when trying to determine the constexpr-ness of special
192   // members. Otherwise we could just use the
193   // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function.
194   if (S.SatisfactionStackContains(Templ, ID)) {
195     S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self)
196         << const_cast<Expr *>(E) << E->getSourceRange();
197     return true;
198   }
199 
200   return false;
201 }
202 
EvaluateAtomicConstraint(Sema & S,const Expr * AtomicExpr,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,ConstraintSatisfaction & Satisfaction)203 static ExprResult EvaluateAtomicConstraint(
204     Sema &S, const Expr *AtomicExpr, const NamedDecl *Template,
205     SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
206     ConstraintSatisfaction &Satisfaction) {
207   EnterExpressionEvaluationContext ConstantEvaluated(
208       S, Sema::ExpressionEvaluationContext::ConstantEvaluated,
209       Sema::ReuseLambdaContextDecl);
210 
211   // Atomic constraint - substitute arguments and check satisfaction.
212   ExprResult SubstitutedExpression;
213   {
214     TemplateDeductionInfo Info(TemplateNameLoc);
215     Sema::InstantiatingTemplate Inst(
216         S, AtomicExpr->getBeginLoc(),
217         Sema::InstantiatingTemplate::ConstraintSubstitution{},
218         // FIXME: improve const-correctness of InstantiatingTemplate
219         const_cast<NamedDecl *>(Template), Info, AtomicExpr->getSourceRange());
220     if (Inst.isInvalid())
221       return ExprError();
222 
223     llvm::FoldingSetNodeID ID;
224     if (Template &&
225         DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) {
226       Satisfaction.IsSatisfied = false;
227       Satisfaction.ContainsErrors = true;
228       return ExprEmpty();
229     }
230 
231     SatisfactionStackRAII StackRAII(S, Template, ID);
232 
233     // We do not want error diagnostics escaping here.
234     Sema::SFINAETrap Trap(S);
235     SubstitutedExpression =
236         S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL);
237 
238     if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
239       // C++2a [temp.constr.atomic]p1
240       //   ...If substitution results in an invalid type or expression, the
241       //   constraint is not satisfied.
242       if (!Trap.hasErrorOccurred())
243         // A non-SFINAE error has occurred as a result of this
244         // substitution.
245         return ExprError();
246 
247       PartialDiagnosticAt SubstDiag{SourceLocation(),
248                                     PartialDiagnostic::NullDiagnostic()};
249       Info.takeSFINAEDiagnostic(SubstDiag);
250       // FIXME: Concepts: This is an unfortunate consequence of there
251       //  being no serialization code for PartialDiagnostics and the fact
252       //  that serializing them would likely take a lot more storage than
253       //  just storing them as strings. We would still like, in the
254       //  future, to serialize the proper PartialDiagnostic as serializing
255       //  it as a string defeats the purpose of the diagnostic mechanism.
256       SmallString<128> DiagString;
257       DiagString = ": ";
258       SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
259       unsigned MessageSize = DiagString.size();
260       char *Mem = new (S.Context) char[MessageSize];
261       memcpy(Mem, DiagString.c_str(), MessageSize);
262       Satisfaction.Details.emplace_back(
263           new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
264               SubstDiag.first, StringRef(Mem, MessageSize)});
265       Satisfaction.IsSatisfied = false;
266       return ExprEmpty();
267     }
268   }
269 
270   if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
271     return ExprError();
272 
273   // [temp.constr.atomic]p3: To determine if an atomic constraint is
274   // satisfied, the parameter mapping and template arguments are first
275   // substituted into its expression.  If substitution results in an
276   // invalid type or expression, the constraint is not satisfied.
277   // Otherwise, the lvalue-to-rvalue conversion is performed if necessary,
278   // and E shall be a constant expression of type bool.
279   //
280   // Perform the L to R Value conversion if necessary. We do so for all
281   // non-PRValue categories, else we fail to extend the lifetime of
282   // temporaries, and that fails the constant expression check.
283   if (!SubstitutedExpression.get()->isPRValue())
284     SubstitutedExpression = ImplicitCastExpr::Create(
285         S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue,
286         SubstitutedExpression.get(),
287         /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride());
288 
289   return SubstitutedExpression;
290 }
291 
EvaluateFoldExpandedConstraintSize(Sema & S,const CXXFoldExpr * FE,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,ConstraintSatisfaction & Satisfaction)292 static UnsignedOrNone EvaluateFoldExpandedConstraintSize(
293     Sema &S, const CXXFoldExpr *FE, const NamedDecl *Template,
294     SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
295     ConstraintSatisfaction &Satisfaction) {
296 
297   // We should ignore errors in the presence of packs of different size.
298   Sema::SFINAETrap Trap(S);
299 
300   Expr *Pattern = FE->getPattern();
301 
302   SmallVector<UnexpandedParameterPack, 2> Unexpanded;
303   S.collectUnexpandedParameterPacks(Pattern, Unexpanded);
304   assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
305   bool Expand = true;
306   bool RetainExpansion = false;
307   UnsignedOrNone NumExpansions = FE->getNumExpansions();
308   if (S.CheckParameterPacksForExpansion(
309           FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL,
310           Expand, RetainExpansion, NumExpansions) ||
311       !Expand || RetainExpansion)
312     return std::nullopt;
313 
314   if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) {
315     S.Diag(FE->getEllipsisLoc(),
316            clang::diag::err_fold_expression_limit_exceeded)
317         << *NumExpansions << S.getLangOpts().BracketDepth
318         << FE->getSourceRange();
319     S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth);
320     return std::nullopt;
321   }
322   return NumExpansions;
323 }
324 
325 static ExprResult calculateConstraintSatisfaction(
326     Sema &S, const Expr *ConstraintExpr, const NamedDecl *Template,
327     SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
328     ConstraintSatisfaction &Satisfaction);
329 
calculateConstraintSatisfaction(Sema & S,const Expr * LHS,OverloadedOperatorKind Op,const Expr * RHS,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,ConstraintSatisfaction & Satisfaction)330 static ExprResult calculateConstraintSatisfaction(
331     Sema &S, const Expr *LHS, OverloadedOperatorKind Op, const Expr *RHS,
332     const NamedDecl *Template, SourceLocation TemplateNameLoc,
333     const MultiLevelTemplateArgumentList &MLTAL,
334     ConstraintSatisfaction &Satisfaction) {
335   size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
336 
337   ExprResult LHSRes = calculateConstraintSatisfaction(
338       S, LHS, Template, TemplateNameLoc, MLTAL, Satisfaction);
339 
340   if (LHSRes.isInvalid())
341     return ExprError();
342 
343   bool IsLHSSatisfied = Satisfaction.IsSatisfied;
344 
345   if (Op == clang::OO_PipePipe && IsLHSSatisfied)
346     // [temp.constr.op] p3
347     //    A disjunction is a constraint taking two operands. To determine if
348     //    a disjunction is satisfied, the satisfaction of the first operand
349     //    is checked. If that is satisfied, the disjunction is satisfied.
350     //    Otherwise, the disjunction is satisfied if and only if the second
351     //    operand is satisfied.
352     // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
353     return LHSRes;
354 
355   if (Op == clang::OO_AmpAmp && !IsLHSSatisfied)
356     // [temp.constr.op] p2
357     //    A conjunction is a constraint taking two operands. To determine if
358     //    a conjunction is satisfied, the satisfaction of the first operand
359     //    is checked. If that is not satisfied, the conjunction is not
360     //    satisfied. Otherwise, the conjunction is satisfied if and only if
361     //    the second operand is satisfied.
362     // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp.
363     return LHSRes;
364 
365   ExprResult RHSRes = calculateConstraintSatisfaction(
366       S, RHS, Template, TemplateNameLoc, MLTAL, Satisfaction);
367   if (RHSRes.isInvalid())
368     return ExprError();
369 
370   bool IsRHSSatisfied = Satisfaction.IsSatisfied;
371   // Current implementation adds diagnostic information about the falsity
372   // of each false atomic constraint expression when it evaluates them.
373   // When the evaluation results to `false || true`, the information
374   // generated during the evaluation of left-hand side is meaningless
375   // because the whole expression evaluates to true.
376   // The following code removes the irrelevant diagnostic information.
377   // FIXME: We should probably delay the addition of diagnostic information
378   // until we know the entire expression is false.
379   if (Op == clang::OO_PipePipe && IsRHSSatisfied) {
380     auto EffectiveDetailEnd = Satisfaction.Details.begin();
381     std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
382     Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end());
383   }
384 
385   if (!LHSRes.isUsable() || !RHSRes.isUsable())
386     return ExprEmpty();
387 
388   return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(),
389                                 BinaryOperator::getOverloadedOpcode(Op),
390                                 S.Context.BoolTy, VK_PRValue, OK_Ordinary,
391                                 LHS->getBeginLoc(), FPOptionsOverride{});
392 }
393 
calculateConstraintSatisfaction(Sema & S,const CXXFoldExpr * FE,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,ConstraintSatisfaction & Satisfaction)394 static ExprResult calculateConstraintSatisfaction(
395     Sema &S, const CXXFoldExpr *FE, const NamedDecl *Template,
396     SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
397     ConstraintSatisfaction &Satisfaction) {
398   bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd;
399   size_t EffectiveDetailEndIndex = Satisfaction.Details.size();
400 
401   ExprResult Out;
402   if (FE->isLeftFold() && FE->getInit()) {
403     Out = calculateConstraintSatisfaction(S, FE->getInit(), Template,
404                                           TemplateNameLoc, MLTAL, Satisfaction);
405     if (Out.isInvalid())
406       return ExprError();
407 
408     // If the first clause of a conjunction is not satisfied,
409     // or if the first clause of a disjection is satisfied,
410     // we have established satisfaction of the whole constraint
411     // and we should not continue further.
412     if (Conjunction != Satisfaction.IsSatisfied)
413       return Out;
414   }
415   UnsignedOrNone NumExpansions = EvaluateFoldExpandedConstraintSize(
416       S, FE, Template, TemplateNameLoc, MLTAL, Satisfaction);
417   if (!NumExpansions)
418     return ExprError();
419   for (unsigned I = 0; I < *NumExpansions; I++) {
420     Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
421     ExprResult Res = calculateConstraintSatisfaction(
422         S, FE->getPattern(), Template, TemplateNameLoc, MLTAL, Satisfaction);
423     if (Res.isInvalid())
424       return ExprError();
425     bool IsRHSSatisfied = Satisfaction.IsSatisfied;
426     if (!Conjunction && IsRHSSatisfied) {
427       auto EffectiveDetailEnd = Satisfaction.Details.begin();
428       std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
429       Satisfaction.Details.erase(EffectiveDetailEnd,
430                                  Satisfaction.Details.end());
431     }
432     if (Out.isUnset())
433       Out = Res;
434     else if (!Res.isUnset()) {
435       Out = BinaryOperator::Create(
436           S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
437           VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});
438     }
439     if (Conjunction != IsRHSSatisfied)
440       return Out;
441   }
442 
443   if (FE->isRightFold() && FE->getInit()) {
444     ExprResult Res = calculateConstraintSatisfaction(
445         S, FE->getInit(), Template, TemplateNameLoc, MLTAL, Satisfaction);
446     if (Out.isInvalid())
447       return ExprError();
448 
449     if (Out.isUnset())
450       Out = Res;
451     else if (!Res.isUnset()) {
452       Out = BinaryOperator::Create(
453           S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy,
454           VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{});
455     }
456   }
457 
458   if (Out.isUnset()) {
459     Satisfaction.IsSatisfied = Conjunction;
460     Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator());
461   }
462   return Out;
463 }
464 
calculateConstraintSatisfaction(Sema & S,const Expr * ConstraintExpr,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,ConstraintSatisfaction & Satisfaction)465 static ExprResult calculateConstraintSatisfaction(
466     Sema &S, const Expr *ConstraintExpr, const NamedDecl *Template,
467     SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
468     ConstraintSatisfaction &Satisfaction) {
469   ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
470 
471   if (LogicalBinOp BO = ConstraintExpr)
472     return calculateConstraintSatisfaction(
473         S, BO.getLHS(), BO.getOp(), BO.getRHS(), Template, TemplateNameLoc,
474         MLTAL, Satisfaction);
475 
476   if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
477     // These aren't evaluated, so we don't care about cleanups, so we can just
478     // evaluate these as if the cleanups didn't exist.
479     return calculateConstraintSatisfaction(
480         S, C->getSubExpr(), Template, TemplateNameLoc, MLTAL, Satisfaction);
481   }
482 
483   if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr);
484       FE && S.getLangOpts().CPlusPlus26 &&
485       (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
486        FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
487     return calculateConstraintSatisfaction(S, FE, Template, TemplateNameLoc,
488                                            MLTAL, Satisfaction);
489   }
490 
491   // FIXME: We should not treat ConceptSpecializationExpr as atomic constraints.
492 
493   // An atomic constraint expression
494   ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
495       S, ConstraintExpr, Template, TemplateNameLoc, MLTAL, Satisfaction);
496 
497   if (SubstitutedAtomicExpr.isInvalid())
498     return ExprError();
499 
500   if (!SubstitutedAtomicExpr.isUsable())
501     // Evaluator has decided satisfaction without yielding an expression.
502     return ExprEmpty();
503 
504   // We don't have the ability to evaluate this, since it contains a
505   // RecoveryExpr, so we want to fail overload resolution.  Otherwise,
506   // we'd potentially pick up a different overload, and cause confusing
507   // diagnostics. SO, add a failure detail that will cause us to make this
508   // overload set not viable.
509   if (SubstitutedAtomicExpr.get()->containsErrors()) {
510     Satisfaction.IsSatisfied = false;
511     Satisfaction.ContainsErrors = true;
512 
513     PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
514     SmallString<128> DiagString;
515     DiagString = ": ";
516     Msg.EmitToString(S.getDiagnostics(), DiagString);
517     unsigned MessageSize = DiagString.size();
518     char *Mem = new (S.Context) char[MessageSize];
519     memcpy(Mem, DiagString.c_str(), MessageSize);
520     Satisfaction.Details.emplace_back(
521         new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
522             SubstitutedAtomicExpr.get()->getBeginLoc(),
523             StringRef(Mem, MessageSize)});
524     return SubstitutedAtomicExpr;
525   }
526 
527   EnterExpressionEvaluationContext ConstantEvaluated(
528       S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
529   SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
530   Expr::EvalResult EvalResult;
531   EvalResult.Diag = &EvaluationDiags;
532   if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
533                                                            S.Context) ||
534       !EvaluationDiags.empty()) {
535     // C++2a [temp.constr.atomic]p1
536     //   ...E shall be a constant expression of type bool.
537     S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
538            diag::err_non_constant_constraint_expression)
539         << SubstitutedAtomicExpr.get()->getSourceRange();
540     for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
541       S.Diag(PDiag.first, PDiag.second);
542     return ExprError();
543   }
544 
545   assert(EvalResult.Val.isInt() &&
546          "evaluating bool expression didn't produce int");
547   Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
548   if (!Satisfaction.IsSatisfied)
549     Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get());
550 
551   return SubstitutedAtomicExpr;
552 }
553 
calculateConstraintSatisfaction(Sema & S,const NamedDecl * Template,SourceLocation TemplateNameLoc,const MultiLevelTemplateArgumentList & MLTAL,const Expr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)554 static ExprResult calculateConstraintSatisfaction(
555     Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc,
556     const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr,
557     ConstraintSatisfaction &Satisfaction) {
558 
559   return calculateConstraintSatisfaction(S, ConstraintExpr, Template,
560                                          TemplateNameLoc, MLTAL, Satisfaction);
561 }
562 
CheckConstraintSatisfaction(Sema & S,const NamedDecl * Template,ArrayRef<AssociatedConstraint> AssociatedConstraints,llvm::SmallVectorImpl<Expr * > & Converted,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & Satisfaction)563 static bool CheckConstraintSatisfaction(
564     Sema &S, const NamedDecl *Template,
565     ArrayRef<AssociatedConstraint> AssociatedConstraints,
566     llvm::SmallVectorImpl<Expr *> &Converted,
567     const MultiLevelTemplateArgumentList &TemplateArgsLists,
568     SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) {
569   if (AssociatedConstraints.empty()) {
570     Satisfaction.IsSatisfied = true;
571     return false;
572   }
573 
574   if (TemplateArgsLists.isAnyArgInstantiationDependent()) {
575     // No need to check satisfaction for dependent constraint expressions.
576     Satisfaction.IsSatisfied = true;
577     return false;
578   }
579 
580   ArrayRef<TemplateArgument> TemplateArgs =
581       TemplateArgsLists.getNumSubstitutedLevels() > 0
582           ? TemplateArgsLists.getOutermost()
583           : ArrayRef<TemplateArgument>{};
584   Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
585       Sema::InstantiatingTemplate::ConstraintsCheck{},
586       const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
587   if (Inst.isInvalid())
588     return true;
589 
590   for (const AssociatedConstraint &AC : AssociatedConstraints) {
591     Sema::ArgPackSubstIndexRAII _(S, AC.ArgPackSubstIndex);
592     ExprResult Res = calculateConstraintSatisfaction(
593         S, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
594         AC.ConstraintExpr, Satisfaction);
595     if (Res.isInvalid())
596       return true;
597 
598     Converted.push_back(Res.get());
599     if (!Satisfaction.IsSatisfied) {
600       // Backfill the 'converted' list with nulls so we can keep the Converted
601       // and unconverted lists in sync.
602       Converted.append(AssociatedConstraints.size() - Converted.size(),
603                        nullptr);
604       // [temp.constr.op] p2
605       // [...] To determine if a conjunction is satisfied, the satisfaction
606       // of the first operand is checked. If that is not satisfied, the
607       // conjunction is not satisfied. [...]
608       return false;
609     }
610   }
611   return false;
612 }
613 
CheckConstraintSatisfaction(const NamedDecl * Template,ArrayRef<AssociatedConstraint> AssociatedConstraints,llvm::SmallVectorImpl<Expr * > & ConvertedConstraints,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange,ConstraintSatisfaction & OutSatisfaction)614 bool Sema::CheckConstraintSatisfaction(
615     const NamedDecl *Template,
616     ArrayRef<AssociatedConstraint> AssociatedConstraints,
617     llvm::SmallVectorImpl<Expr *> &ConvertedConstraints,
618     const MultiLevelTemplateArgumentList &TemplateArgsLists,
619     SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) {
620   if (AssociatedConstraints.empty()) {
621     OutSatisfaction.IsSatisfied = true;
622     return false;
623   }
624   if (!Template) {
625     return ::CheckConstraintSatisfaction(
626         *this, nullptr, AssociatedConstraints, ConvertedConstraints,
627         TemplateArgsLists, TemplateIDRange, OutSatisfaction);
628   }
629   // Invalid templates could make their way here. Substituting them could result
630   // in dependent expressions.
631   if (Template->isInvalidDecl()) {
632     OutSatisfaction.IsSatisfied = false;
633     return true;
634   }
635 
636   // A list of the template argument list flattened in a predictible manner for
637   // the purposes of caching. The ConstraintSatisfaction type is in AST so it
638   // has no access to the MultiLevelTemplateArgumentList, so this has to happen
639   // here.
640   llvm::SmallVector<TemplateArgument, 4> FlattenedArgs;
641   for (auto List : TemplateArgsLists)
642     llvm::append_range(FlattenedArgs, List.Args);
643 
644   llvm::FoldingSetNodeID ID;
645   ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs);
646   void *InsertPos;
647   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
648     OutSatisfaction = *Cached;
649     return false;
650   }
651 
652   auto Satisfaction =
653       std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
654   if (::CheckConstraintSatisfaction(*this, Template, AssociatedConstraints,
655                                     ConvertedConstraints, TemplateArgsLists,
656                                     TemplateIDRange, *Satisfaction)) {
657     OutSatisfaction = *Satisfaction;
658     return true;
659   }
660 
661   if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
662     // The evaluation of this constraint resulted in us trying to re-evaluate it
663     // recursively. This isn't really possible, except we try to form a
664     // RecoveryExpr as a part of the evaluation.  If this is the case, just
665     // return the 'cached' version (which will have the same result), and save
666     // ourselves the extra-insert. If it ever becomes possible to legitimately
667     // recursively check a constraint, we should skip checking the 'inner' one
668     // above, and replace the cached version with this one, as it would be more
669     // specific.
670     OutSatisfaction = *Cached;
671     return false;
672   }
673 
674   // Else we can simply add this satisfaction to the list.
675   OutSatisfaction = *Satisfaction;
676   // We cannot use InsertPos here because CheckConstraintSatisfaction might have
677   // invalidated it.
678   // Note that entries of SatisfactionCache are deleted in Sema's destructor.
679   SatisfactionCache.InsertNode(Satisfaction.release());
680   return false;
681 }
682 
CheckConstraintSatisfaction(const ConceptSpecializationExpr * ConstraintExpr,ConstraintSatisfaction & Satisfaction)683 bool Sema::CheckConstraintSatisfaction(
684     const ConceptSpecializationExpr *ConstraintExpr,
685     ConstraintSatisfaction &Satisfaction) {
686 
687   MultiLevelTemplateArgumentList MLTAL(ConstraintExpr->getNamedConcept(),
688                                        ConstraintExpr->getTemplateArguments(),
689                                        true);
690 
691   return calculateConstraintSatisfaction(
692              *this, ConstraintExpr, ConstraintExpr->getNamedConcept(),
693              ConstraintExpr->getConceptNameLoc(), MLTAL, Satisfaction)
694       .isInvalid();
695 }
696 
SetupConstraintScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,const MultiLevelTemplateArgumentList & MLTAL,LocalInstantiationScope & Scope)697 bool Sema::SetupConstraintScope(
698     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
699     const MultiLevelTemplateArgumentList &MLTAL,
700     LocalInstantiationScope &Scope) {
701   assert(!isLambdaCallOperator(FD) &&
702          "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
703          "instantiations");
704   if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
705     FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
706     InstantiatingTemplate Inst(
707         *this, FD->getPointOfInstantiation(),
708         Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
709         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
710         SourceRange());
711     if (Inst.isInvalid())
712       return true;
713 
714     // addInstantiatedParametersToScope creates a map of 'uninstantiated' to
715     // 'instantiated' parameters and adds it to the context. For the case where
716     // this function is a template being instantiated NOW, we also need to add
717     // the list of current template arguments to the list so that they also can
718     // be picked out of the map.
719     if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) {
720       MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
721                                                    /*Final=*/false);
722       if (addInstantiatedParametersToScope(
723               FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs))
724         return true;
725     }
726 
727     // If this is a member function, make sure we get the parameters that
728     // reference the original primary template.
729     if (FunctionTemplateDecl *FromMemTempl =
730             PrimaryTemplate->getInstantiatedFromMemberTemplate()) {
731       if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
732                                            Scope, MLTAL))
733         return true;
734     }
735 
736     return false;
737   }
738 
739   if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization ||
740       FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) {
741     FunctionDecl *InstantiatedFrom =
742         FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization
743             ? FD->getInstantiatedFromMemberFunction()
744             : FD->getInstantiatedFromDecl();
745 
746     InstantiatingTemplate Inst(
747         *this, FD->getPointOfInstantiation(),
748         Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
749         TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
750         SourceRange());
751     if (Inst.isInvalid())
752       return true;
753 
754     // Case where this was not a template, but instantiated as a
755     // child-function.
756     if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
757       return true;
758   }
759 
760   return false;
761 }
762 
763 // This function collects all of the template arguments for the purposes of
764 // constraint-instantiation and checking.
765 std::optional<MultiLevelTemplateArgumentList>
SetupConstraintCheckingTemplateArgumentsAndScope(FunctionDecl * FD,std::optional<ArrayRef<TemplateArgument>> TemplateArgs,LocalInstantiationScope & Scope)766 Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
767     FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
768     LocalInstantiationScope &Scope) {
769   MultiLevelTemplateArgumentList MLTAL;
770 
771   // Collect the list of template arguments relative to the 'primary' template.
772   // We need the entire list, since the constraint is completely uninstantiated
773   // at this point.
774   MLTAL =
775       getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
776                                    /*Final=*/false, /*Innermost=*/std::nullopt,
777                                    /*RelativeToPrimary=*/true,
778                                    /*Pattern=*/nullptr,
779                                    /*ForConstraintInstantiation=*/true);
780   // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
781   if (isLambdaCallOperator(FD))
782     return MLTAL;
783   if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
784     return std::nullopt;
785 
786   return MLTAL;
787 }
788 
CheckFunctionConstraints(const FunctionDecl * FD,ConstraintSatisfaction & Satisfaction,SourceLocation UsageLoc,bool ForOverloadResolution)789 bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
790                                     ConstraintSatisfaction &Satisfaction,
791                                     SourceLocation UsageLoc,
792                                     bool ForOverloadResolution) {
793   // Don't check constraints if the function is dependent. Also don't check if
794   // this is a function template specialization, as the call to
795   // CheckFunctionTemplateConstraints after this will check it
796   // better.
797   if (FD->isDependentContext() ||
798       FD->getTemplatedKind() ==
799           FunctionDecl::TK_FunctionTemplateSpecialization) {
800     Satisfaction.IsSatisfied = true;
801     return false;
802   }
803 
804   // A lambda conversion operator has the same constraints as the call operator
805   // and constraints checking relies on whether we are in a lambda call operator
806   // (and may refer to its parameters), so check the call operator instead.
807   // Note that the declarations outside of the lambda should also be
808   // considered. Turning on the 'ForOverloadResolution' flag results in the
809   // LocalInstantiationScope not looking into its parents, but we can still
810   // access Decls from the parents while building a lambda RAII scope later.
811   if (const auto *MD = dyn_cast<CXXConversionDecl>(FD);
812       MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD)))
813     return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(),
814                                     Satisfaction, UsageLoc,
815                                     /*ShouldAddDeclsFromParentScope=*/true);
816 
817   DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD);
818 
819   while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) {
820     if (isLambdaCallOperator(CtxToSave))
821       CtxToSave = CtxToSave->getParent()->getParent();
822     else
823       CtxToSave = CtxToSave->getNonTransparentContext();
824   }
825 
826   ContextRAII SavedContext{*this, CtxToSave};
827   LocalInstantiationScope Scope(*this, !ForOverloadResolution);
828   std::optional<MultiLevelTemplateArgumentList> MLTAL =
829       SetupConstraintCheckingTemplateArgumentsAndScope(
830           const_cast<FunctionDecl *>(FD), {}, Scope);
831 
832   if (!MLTAL)
833     return true;
834 
835   Qualifiers ThisQuals;
836   CXXRecordDecl *Record = nullptr;
837   if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
838     ThisQuals = Method->getMethodQualifiers();
839     Record = const_cast<CXXRecordDecl *>(Method->getParent());
840   }
841   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
842 
843   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
844       *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope,
845       ForOverloadResolution);
846 
847   return CheckConstraintSatisfaction(
848       FD, FD->getTrailingRequiresClause(), *MLTAL,
849       SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
850       Satisfaction);
851 }
852 
853 
854 // Figure out the to-translation-unit depth for this function declaration for
855 // the purpose of seeing if they differ by constraints. This isn't the same as
856 // getTemplateDepth, because it includes already instantiated parents.
857 static unsigned
CalculateTemplateDepthForConstraints(Sema & S,const NamedDecl * ND,bool SkipForSpecialization=false)858 CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
859                                      bool SkipForSpecialization = false) {
860   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
861       ND, ND->getLexicalDeclContext(), /*Final=*/false,
862       /*Innermost=*/std::nullopt,
863       /*RelativeToPrimary=*/true,
864       /*Pattern=*/nullptr,
865       /*ForConstraintInstantiation=*/true, SkipForSpecialization);
866   return MLTAL.getNumLevels();
867 }
868 
869 namespace {
870   class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> {
871   unsigned TemplateDepth = 0;
872   public:
873   using inherited = TreeTransform<AdjustConstraintDepth>;
AdjustConstraintDepth(Sema & SemaRef,unsigned TemplateDepth)874   AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth)
875       : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
876 
877   using inherited::TransformTemplateTypeParmType;
TransformTemplateTypeParmType(TypeLocBuilder & TLB,TemplateTypeParmTypeLoc TL,bool)878   QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
879                                          TemplateTypeParmTypeLoc TL, bool) {
880     const TemplateTypeParmType *T = TL.getTypePtr();
881 
882     TemplateTypeParmDecl *NewTTPDecl = nullptr;
883     if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
884       NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
885           TransformDecl(TL.getNameLoc(), OldTTPDecl));
886 
887     QualType Result = getSema().Context.getTemplateTypeParmType(
888         T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
889         NewTTPDecl);
890     TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result);
891     NewTL.setNameLoc(TL.getNameLoc());
892     return Result;
893   }
894   };
895 } // namespace
896 
SubstituteConstraintExpressionWithoutSatisfaction(Sema & S,const Sema::TemplateCompareNewDeclInfo & DeclInfo,const Expr * ConstrExpr)897 static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
898     Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
899     const Expr *ConstrExpr) {
900   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
901       DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
902       /*Innermost=*/std::nullopt,
903       /*RelativeToPrimary=*/true,
904       /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
905       /*SkipForSpecialization*/ false);
906 
907   if (MLTAL.getNumSubstitutedLevels() == 0)
908     return ConstrExpr;
909 
910   Sema::SFINAETrap SFINAE(S);
911 
912   Sema::InstantiatingTemplate Inst(
913       S, DeclInfo.getLocation(),
914       Sema::InstantiatingTemplate::ConstraintNormalization{},
915       const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{});
916   if (Inst.isInvalid())
917     return nullptr;
918 
919   // Set up a dummy 'instantiation' scope in the case of reference to function
920   // parameters that the surrounding function hasn't been instantiated yet. Note
921   // this may happen while we're comparing two templates' constraint
922   // equivalence.
923   std::optional<LocalInstantiationScope> ScopeForParameters;
924   if (const NamedDecl *ND = DeclInfo.getDecl();
925       ND && ND->isFunctionOrFunctionTemplate()) {
926     ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
927     const FunctionDecl *FD = ND->getAsFunction();
928     for (auto *PVD : FD->parameters()) {
929       if (!PVD->isParameterPack()) {
930         ScopeForParameters->InstantiatedLocal(PVD, PVD);
931         continue;
932       }
933       // This is hacky: we're mapping the parameter pack to a size-of-1 argument
934       // to avoid building SubstTemplateTypeParmPackTypes for
935       // PackExpansionTypes. The SubstTemplateTypeParmPackType node would
936       // otherwise reference the AssociatedDecl of the template arguments, which
937       // is, in this case, the template declaration.
938       //
939       // However, as we are in the process of comparing potential
940       // re-declarations, the canonical declaration is the declaration itself at
941       // this point. So if we didn't expand these packs, we would end up with an
942       // incorrect profile difference because we will be profiling the
943       // canonical types!
944       //
945       // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so
946       // that we can eliminate the Scope in the cases where the declarations are
947       // not necessarily instantiated. It would also benefit the noexcept
948       // specifier comparison.
949       ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
950       ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
951     }
952   }
953 
954   std::optional<Sema::CXXThisScopeRAII> ThisScope;
955 
956   // See TreeTransform::RebuildTemplateSpecializationType. A context scope is
957   // essential for having an injected class as the canonical type for a template
958   // specialization type at the rebuilding stage. This guarantees that, for
959   // out-of-line definitions, injected class name types and their equivalent
960   // template specializations can be profiled to the same value, which makes it
961   // possible that e.g. constraints involving C<Class<T>> and C<Class> are
962   // perceived identical.
963   std::optional<Sema::ContextRAII> ContextScope;
964   const DeclContext *DC = [&] {
965     if (!DeclInfo.getDecl())
966       return DeclInfo.getDeclContext();
967     return DeclInfo.getDecl()->getFriendObjectKind()
968                ? DeclInfo.getLexicalDeclContext()
969                : DeclInfo.getDeclContext();
970   }();
971   if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
972     ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
973     ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
974                          /*NewThisContext=*/false);
975   }
976   EnterExpressionEvaluationContext UnevaluatedContext(
977       S, Sema::ExpressionEvaluationContext::Unevaluated,
978       Sema::ReuseLambdaContextDecl);
979   ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction(
980       const_cast<clang::Expr *>(ConstrExpr), MLTAL);
981   if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable())
982     return nullptr;
983   return SubstConstr.get();
984 }
985 
AreConstraintExpressionsEqual(const NamedDecl * Old,const Expr * OldConstr,const TemplateCompareNewDeclInfo & New,const Expr * NewConstr)986 bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
987                                          const Expr *OldConstr,
988                                          const TemplateCompareNewDeclInfo &New,
989                                          const Expr *NewConstr) {
990   if (OldConstr == NewConstr)
991     return true;
992   // C++ [temp.constr.decl]p4
993   if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
994       Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
995     if (const Expr *SubstConstr =
996             SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
997                                                               OldConstr))
998       OldConstr = SubstConstr;
999     else
1000       return false;
1001     if (const Expr *SubstConstr =
1002             SubstituteConstraintExpressionWithoutSatisfaction(*this, New,
1003                                                               NewConstr))
1004       NewConstr = SubstConstr;
1005     else
1006       return false;
1007   }
1008 
1009   llvm::FoldingSetNodeID ID1, ID2;
1010   OldConstr->Profile(ID1, Context, /*Canonical=*/true);
1011   NewConstr->Profile(ID2, Context, /*Canonical=*/true);
1012   return ID1 == ID2;
1013 }
1014 
FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl * FD)1015 bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
1016   assert(FD->getFriendObjectKind() && "Must be a friend!");
1017 
1018   // The logic for non-templates is handled in ASTContext::isSameEntity, so we
1019   // don't have to bother checking 'DependsOnEnclosingTemplate' for a
1020   // non-function-template.
1021   assert(FD->getDescribedFunctionTemplate() &&
1022          "Non-function templates don't need to be checked");
1023 
1024   SmallVector<AssociatedConstraint, 3> ACs;
1025   FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
1026 
1027   unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
1028   for (const AssociatedConstraint &AC : ACs)
1029     if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
1030                                                        AC.ConstraintExpr))
1031       return true;
1032 
1033   return false;
1034 }
1035 
EnsureTemplateArgumentListConstraints(TemplateDecl * TD,const MultiLevelTemplateArgumentList & TemplateArgsLists,SourceRange TemplateIDRange)1036 bool Sema::EnsureTemplateArgumentListConstraints(
1037     TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists,
1038     SourceRange TemplateIDRange) {
1039   ConstraintSatisfaction Satisfaction;
1040   llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
1041   TD->getAssociatedConstraints(AssociatedConstraints);
1042   if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists,
1043                                   TemplateIDRange, Satisfaction))
1044     return true;
1045 
1046   if (!Satisfaction.IsSatisfied) {
1047     SmallString<128> TemplateArgString;
1048     TemplateArgString = " ";
1049     TemplateArgString += getTemplateArgumentBindingsText(
1050         TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(),
1051         TemplateArgsLists.getInnermost().size());
1052 
1053     Diag(TemplateIDRange.getBegin(),
1054          diag::err_template_arg_list_constraints_not_satisfied)
1055         << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
1056         << TemplateArgString << TemplateIDRange;
1057     DiagnoseUnsatisfiedConstraint(Satisfaction);
1058     return true;
1059   }
1060   return false;
1061 }
1062 
CheckFunctionConstraintsWithoutInstantiation(Sema & SemaRef,SourceLocation PointOfInstantiation,FunctionTemplateDecl * Template,ArrayRef<TemplateArgument> TemplateArgs,ConstraintSatisfaction & Satisfaction)1063 static bool CheckFunctionConstraintsWithoutInstantiation(
1064     Sema &SemaRef, SourceLocation PointOfInstantiation,
1065     FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
1066     ConstraintSatisfaction &Satisfaction) {
1067   SmallVector<AssociatedConstraint, 3> TemplateAC;
1068   Template->getAssociatedConstraints(TemplateAC);
1069   if (TemplateAC.empty()) {
1070     Satisfaction.IsSatisfied = true;
1071     return false;
1072   }
1073 
1074   LocalInstantiationScope Scope(SemaRef);
1075 
1076   FunctionDecl *FD = Template->getTemplatedDecl();
1077   // Collect the list of template arguments relative to the 'primary'
1078   // template. We need the entire list, since the constraint is completely
1079   // uninstantiated at this point.
1080 
1081   MultiLevelTemplateArgumentList MLTAL;
1082   {
1083     // getTemplateInstantiationArgs uses this instantiation context to find out
1084     // template arguments for uninstantiated functions.
1085     // We don't want this RAII object to persist, because there would be
1086     // otherwise duplicate diagnostic notes.
1087     Sema::InstantiatingTemplate Inst(
1088         SemaRef, PointOfInstantiation,
1089         Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
1090         PointOfInstantiation);
1091     if (Inst.isInvalid())
1092       return true;
1093     MLTAL = SemaRef.getTemplateInstantiationArgs(
1094         /*D=*/FD, FD,
1095         /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
1096         /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
1097   }
1098 
1099   Sema::ContextRAII SavedContext(SemaRef, FD);
1100   return SemaRef.CheckConstraintSatisfaction(
1101       Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1102 }
1103 
CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation,FunctionDecl * Decl,ArrayRef<TemplateArgument> TemplateArgs,ConstraintSatisfaction & Satisfaction)1104 bool Sema::CheckFunctionTemplateConstraints(
1105     SourceLocation PointOfInstantiation, FunctionDecl *Decl,
1106     ArrayRef<TemplateArgument> TemplateArgs,
1107     ConstraintSatisfaction &Satisfaction) {
1108   // In most cases we're not going to have constraints, so check for that first.
1109   FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
1110 
1111   if (!Template)
1112     return ::CheckFunctionConstraintsWithoutInstantiation(
1113         *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
1114         TemplateArgs, Satisfaction);
1115 
1116   // Note - code synthesis context for the constraints check is created
1117   // inside CheckConstraintsSatisfaction.
1118   SmallVector<AssociatedConstraint, 3> TemplateAC;
1119   Template->getAssociatedConstraints(TemplateAC);
1120   if (TemplateAC.empty()) {
1121     Satisfaction.IsSatisfied = true;
1122     return false;
1123   }
1124 
1125   // Enter the scope of this instantiation. We don't use
1126   // PushDeclContext because we don't have a scope.
1127   Sema::ContextRAII savedContext(*this, Decl);
1128   LocalInstantiationScope Scope(*this);
1129 
1130   std::optional<MultiLevelTemplateArgumentList> MLTAL =
1131       SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
1132                                                        Scope);
1133 
1134   if (!MLTAL)
1135     return true;
1136 
1137   Qualifiers ThisQuals;
1138   CXXRecordDecl *Record = nullptr;
1139   if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
1140     ThisQuals = Method->getMethodQualifiers();
1141     Record = Method->getParent();
1142   }
1143 
1144   CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
1145   LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL,
1146                                                           Scope);
1147 
1148   return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL,
1149                                      PointOfInstantiation, Satisfaction);
1150 }
1151 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::ExprRequirement * Req,bool First)1152 static void diagnoseUnsatisfiedRequirement(Sema &S,
1153                                            concepts::ExprRequirement *Req,
1154                                            bool First) {
1155   assert(!Req->isSatisfied()
1156          && "Diagnose() can only be used on an unsatisfied requirement");
1157   switch (Req->getSatisfactionStatus()) {
1158     case concepts::ExprRequirement::SS_Dependent:
1159       llvm_unreachable("Diagnosing a dependent requirement");
1160       break;
1161     case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
1162       auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
1163       if (!SubstDiag->DiagMessage.empty())
1164         S.Diag(SubstDiag->DiagLoc,
1165                diag::note_expr_requirement_expr_substitution_error)
1166                << (int)First << SubstDiag->SubstitutedEntity
1167                << SubstDiag->DiagMessage;
1168       else
1169         S.Diag(SubstDiag->DiagLoc,
1170                diag::note_expr_requirement_expr_unknown_substitution_error)
1171             << (int)First << SubstDiag->SubstitutedEntity;
1172       break;
1173     }
1174     case concepts::ExprRequirement::SS_NoexceptNotMet:
1175       S.Diag(Req->getNoexceptLoc(),
1176              diag::note_expr_requirement_noexcept_not_met)
1177           << (int)First << Req->getExpr();
1178       break;
1179     case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
1180       auto *SubstDiag =
1181           Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
1182       if (!SubstDiag->DiagMessage.empty())
1183         S.Diag(SubstDiag->DiagLoc,
1184                diag::note_expr_requirement_type_requirement_substitution_error)
1185             << (int)First << SubstDiag->SubstitutedEntity
1186             << SubstDiag->DiagMessage;
1187       else
1188         S.Diag(SubstDiag->DiagLoc,
1189                diag::note_expr_requirement_type_requirement_unknown_substitution_error)
1190             << (int)First << SubstDiag->SubstitutedEntity;
1191       break;
1192     }
1193     case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
1194       ConceptSpecializationExpr *ConstraintExpr =
1195           Req->getReturnTypeRequirementSubstitutedConstraintExpr();
1196       if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1197         // A simple case - expr type is the type being constrained and the concept
1198         // was not provided arguments.
1199         Expr *e = Req->getExpr();
1200         S.Diag(e->getBeginLoc(),
1201                diag::note_expr_requirement_constraints_not_satisfied_simple)
1202             << (int)First << S.Context.getReferenceQualifiedType(e)
1203             << ConstraintExpr->getNamedConcept();
1204       } else {
1205         S.Diag(ConstraintExpr->getBeginLoc(),
1206                diag::note_expr_requirement_constraints_not_satisfied)
1207             << (int)First << ConstraintExpr;
1208       }
1209       S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
1210       break;
1211     }
1212     case concepts::ExprRequirement::SS_Satisfied:
1213       llvm_unreachable("We checked this above");
1214   }
1215 }
1216 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::TypeRequirement * Req,bool First)1217 static void diagnoseUnsatisfiedRequirement(Sema &S,
1218                                            concepts::TypeRequirement *Req,
1219                                            bool First) {
1220   assert(!Req->isSatisfied()
1221          && "Diagnose() can only be used on an unsatisfied requirement");
1222   switch (Req->getSatisfactionStatus()) {
1223   case concepts::TypeRequirement::SS_Dependent:
1224     llvm_unreachable("Diagnosing a dependent requirement");
1225     return;
1226   case concepts::TypeRequirement::SS_SubstitutionFailure: {
1227     auto *SubstDiag = Req->getSubstitutionDiagnostic();
1228     if (!SubstDiag->DiagMessage.empty())
1229       S.Diag(SubstDiag->DiagLoc,
1230              diag::note_type_requirement_substitution_error) << (int)First
1231           << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
1232     else
1233       S.Diag(SubstDiag->DiagLoc,
1234              diag::note_type_requirement_unknown_substitution_error)
1235           << (int)First << SubstDiag->SubstitutedEntity;
1236     return;
1237   }
1238   default:
1239     llvm_unreachable("Unknown satisfaction status");
1240     return;
1241   }
1242 }
1243 static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1244                                                         Expr *SubstExpr,
1245                                                         bool First = true);
1246 
diagnoseUnsatisfiedRequirement(Sema & S,concepts::NestedRequirement * Req,bool First)1247 static void diagnoseUnsatisfiedRequirement(Sema &S,
1248                                            concepts::NestedRequirement *Req,
1249                                            bool First) {
1250   using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1251   for (auto &Record : Req->getConstraintSatisfaction()) {
1252     if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>())
1253       S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1254           << (int)First << Req->getInvalidConstraintEntity()
1255           << SubstDiag->second;
1256     else
1257       diagnoseWellFormedUnsatisfiedConstraintExpr(S, Record.dyn_cast<Expr *>(),
1258                                                   First);
1259     First = false;
1260   }
1261 }
1262 
diagnoseWellFormedUnsatisfiedConstraintExpr(Sema & S,Expr * SubstExpr,bool First)1263 static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
1264                                                         Expr *SubstExpr,
1265                                                         bool First) {
1266   SubstExpr = SubstExpr->IgnoreParenImpCasts();
1267   if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1268     switch (BO->getOpcode()) {
1269     // These two cases will in practice only be reached when using fold
1270     // expressions with || and &&, since otherwise the || and && will have been
1271     // broken down into atomic constraints during satisfaction checking.
1272     case BO_LOr:
1273       // Or evaluated to false - meaning both RHS and LHS evaluated to false.
1274       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1275       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1276                                                   /*First=*/false);
1277       return;
1278     case BO_LAnd: {
1279       bool LHSSatisfied =
1280           BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1281       if (LHSSatisfied) {
1282         // LHS is true, so RHS must be false.
1283         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
1284         return;
1285       }
1286       // LHS is false
1287       diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
1288 
1289       // RHS might also be false
1290       bool RHSSatisfied =
1291           BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
1292       if (!RHSSatisfied)
1293         diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
1294                                                     /*First=*/false);
1295       return;
1296     }
1297     case BO_GE:
1298     case BO_LE:
1299     case BO_GT:
1300     case BO_LT:
1301     case BO_EQ:
1302     case BO_NE:
1303       if (BO->getLHS()->getType()->isIntegerType() &&
1304           BO->getRHS()->getType()->isIntegerType()) {
1305         Expr::EvalResult SimplifiedLHS;
1306         Expr::EvalResult SimplifiedRHS;
1307         BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
1308                                     Expr::SE_NoSideEffects,
1309                                     /*InConstantContext=*/true);
1310         BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
1311                                     Expr::SE_NoSideEffects,
1312                                     /*InConstantContext=*/true);
1313         if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
1314           S.Diag(SubstExpr->getBeginLoc(),
1315                  diag::note_atomic_constraint_evaluated_to_false_elaborated)
1316               << (int)First << SubstExpr
1317               << toString(SimplifiedLHS.Val.getInt(), 10)
1318               << BinaryOperator::getOpcodeStr(BO->getOpcode())
1319               << toString(SimplifiedRHS.Val.getInt(), 10);
1320           return;
1321         }
1322       }
1323       break;
1324 
1325     default:
1326       break;
1327     }
1328   } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1329     if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1330       S.Diag(
1331           CSE->getSourceRange().getBegin(),
1332           diag::
1333           note_single_arg_concept_specialization_constraint_evaluated_to_false)
1334           << (int)First
1335           << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1336           << CSE->getNamedConcept();
1337     } else {
1338       S.Diag(SubstExpr->getSourceRange().getBegin(),
1339              diag::note_concept_specialization_constraint_evaluated_to_false)
1340           << (int)First << CSE;
1341     }
1342     S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
1343     return;
1344   } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1345     // FIXME: RequiresExpr should store dependent diagnostics.
1346     for (concepts::Requirement *Req : RE->getRequirements())
1347       if (!Req->isDependent() && !Req->isSatisfied()) {
1348         if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1349           diagnoseUnsatisfiedRequirement(S, E, First);
1350         else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1351           diagnoseUnsatisfiedRequirement(S, T, First);
1352         else
1353           diagnoseUnsatisfiedRequirement(
1354               S, cast<concepts::NestedRequirement>(Req), First);
1355         break;
1356       }
1357     return;
1358   } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1359              TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1360     assert(TTE->getNumArgs() == 2);
1361     S.Diag(SubstExpr->getSourceRange().getBegin(),
1362            diag::note_is_deducible_constraint_evaluated_to_false)
1363         << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1364     return;
1365   }
1366 
1367   S.Diag(SubstExpr->getSourceRange().getBegin(),
1368          diag::note_atomic_constraint_evaluated_to_false)
1369       << (int)First << SubstExpr;
1370   S.DiagnoseTypeTraitDetails(SubstExpr);
1371 }
1372 
1373 template <typename SubstitutionDiagnostic>
diagnoseUnsatisfiedConstraintExpr(Sema & S,const llvm::PointerUnion<Expr *,SubstitutionDiagnostic * > & Record,bool First=true)1374 static void diagnoseUnsatisfiedConstraintExpr(
1375     Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1376     bool First = true) {
1377   if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) {
1378     S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1379         << Diag->second;
1380     return;
1381   }
1382 
1383   diagnoseWellFormedUnsatisfiedConstraintExpr(S, cast<Expr *>(Record), First);
1384 }
1385 
1386 void
DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction & Satisfaction,bool First)1387 Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
1388                                     bool First) {
1389   assert(!Satisfaction.IsSatisfied &&
1390          "Attempted to diagnose a satisfied constraint");
1391   for (auto &Record : Satisfaction.Details) {
1392     diagnoseUnsatisfiedConstraintExpr(*this, Record, First);
1393     First = false;
1394   }
1395 }
1396 
DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction & Satisfaction,bool First)1397 void Sema::DiagnoseUnsatisfiedConstraint(
1398     const ASTConstraintSatisfaction &Satisfaction,
1399     bool First) {
1400   assert(!Satisfaction.IsSatisfied &&
1401          "Attempted to diagnose a satisfied constraint");
1402   for (auto &Record : Satisfaction) {
1403     diagnoseUnsatisfiedConstraintExpr(*this, Record, First);
1404     First = false;
1405   }
1406 }
1407 
getNormalizedAssociatedConstraints(const NamedDecl * ConstrainedDecl,ArrayRef<AssociatedConstraint> AssociatedConstraints)1408 const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
1409     const NamedDecl *ConstrainedDecl,
1410     ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1411   // In case the ConstrainedDecl comes from modules, it is necessary to use
1412   // the canonical decl to avoid different atomic constraints with the 'same'
1413   // declarations.
1414   ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl());
1415 
1416   auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1417   if (CacheEntry == NormalizationCache.end()) {
1418     auto Normalized = NormalizedConstraint::fromAssociatedConstraints(
1419         *this, ConstrainedDecl, AssociatedConstraints);
1420     CacheEntry =
1421         NormalizationCache
1422             .try_emplace(ConstrainedDecl,
1423                          Normalized
1424                              ? new (Context) NormalizedConstraint(
1425                                  std::move(*Normalized))
1426                              : nullptr)
1427             .first;
1428   }
1429   return CacheEntry->second;
1430 }
1431 
getNormalizedAssociatedConstraints(Sema & S,const NamedDecl * ConstrainedDecl,ArrayRef<AssociatedConstraint> AssociatedConstraints)1432 const NormalizedConstraint *clang::getNormalizedAssociatedConstraints(
1433     Sema &S, const NamedDecl *ConstrainedDecl,
1434     ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1435   return S.getNormalizedAssociatedConstraints(ConstrainedDecl,
1436                                               AssociatedConstraints);
1437 }
1438 
1439 static bool
substituteParameterMappings(Sema & S,NormalizedConstraint & N,ConceptDecl * Concept,const MultiLevelTemplateArgumentList & MLTAL,const ASTTemplateArgumentListInfo * ArgsAsWritten)1440 substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1441                             ConceptDecl *Concept,
1442                             const MultiLevelTemplateArgumentList &MLTAL,
1443                             const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1444 
1445   if (N.isCompound()) {
1446     if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL,
1447                                     ArgsAsWritten))
1448       return true;
1449     return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL,
1450                                        ArgsAsWritten);
1451   }
1452 
1453   if (N.isFoldExpanded()) {
1454     Sema::ArgPackSubstIndexRAII _(S, std::nullopt);
1455     return substituteParameterMappings(
1456         S, N.getFoldExpandedConstraint()->Constraint, Concept, MLTAL,
1457         ArgsAsWritten);
1458   }
1459 
1460   TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
1461 
1462   AtomicConstraint &Atomic = *N.getAtomicConstraint();
1463   TemplateArgumentListInfo SubstArgs;
1464   if (!Atomic.ParameterMapping) {
1465     llvm::SmallBitVector OccurringIndices(TemplateParams->size());
1466     S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
1467                                  /*Depth=*/0, OccurringIndices);
1468     TemplateArgumentLoc *TempArgs =
1469         new (S.Context) TemplateArgumentLoc[OccurringIndices.count()];
1470     for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
1471       if (OccurringIndices[I])
1472         new (&(TempArgs)[J++])
1473             TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc(
1474                 TemplateParams->begin()[I],
1475                 // Here we assume we do not support things like
1476                 // template<typename A, typename B>
1477                 // concept C = ...;
1478                 //
1479                 // template<typename... Ts> requires C<Ts...>
1480                 // struct S { };
1481                 // The above currently yields a diagnostic.
1482                 // We still might have default arguments for concept parameters.
1483                 ArgsAsWritten->NumTemplateArgs > I
1484                     ? ArgsAsWritten->arguments()[I].getLocation()
1485                     : SourceLocation()));
1486     Atomic.ParameterMapping.emplace(TempArgs,  OccurringIndices.count());
1487   }
1488   SourceLocation InstLocBegin =
1489       ArgsAsWritten->arguments().empty()
1490           ? ArgsAsWritten->getLAngleLoc()
1491           : ArgsAsWritten->arguments().front().getSourceRange().getBegin();
1492   SourceLocation InstLocEnd =
1493       ArgsAsWritten->arguments().empty()
1494           ? ArgsAsWritten->getRAngleLoc()
1495           : ArgsAsWritten->arguments().front().getSourceRange().getEnd();
1496   Sema::InstantiatingTemplate Inst(
1497       S, InstLocBegin,
1498       Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
1499       const_cast<NamedDecl *>(Atomic.ConstraintDecl),
1500       {InstLocBegin, InstLocEnd});
1501   if (Inst.isInvalid())
1502     return true;
1503   if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
1504     return true;
1505 
1506   TemplateArgumentLoc *TempArgs =
1507       new (S.Context) TemplateArgumentLoc[SubstArgs.size()];
1508   std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
1509             TempArgs);
1510   Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size());
1511   return false;
1512 }
1513 
substituteParameterMappings(Sema & S,NormalizedConstraint & N,const ConceptSpecializationExpr * CSE)1514 static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1515                                         const ConceptSpecializationExpr *CSE) {
1516   MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
1517       CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
1518       /*Final=*/false, CSE->getTemplateArguments(),
1519       /*RelativeToPrimary=*/true,
1520       /*Pattern=*/nullptr,
1521       /*ForConstraintInstantiation=*/true);
1522 
1523   return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
1524                                      CSE->getTemplateArgsAsWritten());
1525 }
1526 
NormalizedConstraint(ASTContext & C,NormalizedConstraint LHS,NormalizedConstraint RHS,CompoundConstraintKind Kind)1527 NormalizedConstraint::NormalizedConstraint(ASTContext &C,
1528                                            NormalizedConstraint LHS,
1529                                            NormalizedConstraint RHS,
1530                                            CompoundConstraintKind Kind)
1531     : Constraint{CompoundConstraint{
1532           new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)},
1533           Kind}} {}
1534 
NormalizedConstraint(ASTContext & C,const NormalizedConstraint & Other)1535 NormalizedConstraint::NormalizedConstraint(ASTContext &C,
1536                                            const NormalizedConstraint &Other) {
1537   if (Other.isAtomic()) {
1538     Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint());
1539   } else if (Other.isFoldExpanded()) {
1540     Constraint = new (C) FoldExpandedConstraint(
1541         Other.getFoldExpandedConstraint()->Kind,
1542         NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint),
1543         Other.getFoldExpandedConstraint()->Pattern);
1544   } else {
1545     Constraint = CompoundConstraint(
1546         new (C)
1547             NormalizedConstraintPair{NormalizedConstraint(C, Other.getLHS()),
1548                                      NormalizedConstraint(C, Other.getRHS())},
1549         Other.getCompoundKind());
1550   }
1551 }
1552 
getLHS() const1553 NormalizedConstraint &NormalizedConstraint::getLHS() const {
1554   assert(isCompound() && "getLHS called on a non-compound constraint.");
1555   return cast<CompoundConstraint>(Constraint).getPointer()->LHS;
1556 }
1557 
getRHS() const1558 NormalizedConstraint &NormalizedConstraint::getRHS() const {
1559   assert(isCompound() && "getRHS called on a non-compound constraint.");
1560   return cast<CompoundConstraint>(Constraint).getPointer()->RHS;
1561 }
1562 
1563 std::optional<NormalizedConstraint>
fromAssociatedConstraints(Sema & S,const NamedDecl * D,ArrayRef<AssociatedConstraint> ACs)1564 NormalizedConstraint::fromAssociatedConstraints(
1565     Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
1566   assert(ACs.size() != 0);
1567   auto Conjunction = fromConstraintExpr(S, D, ACs[0].ConstraintExpr);
1568   if (!Conjunction)
1569     return std::nullopt;
1570   for (unsigned I = 1; I < ACs.size(); ++I) {
1571     auto Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr);
1572     if (!Next)
1573       return std::nullopt;
1574     *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction),
1575                                         std::move(*Next), CCK_Conjunction);
1576   }
1577   return Conjunction;
1578 }
1579 
1580 std::optional<NormalizedConstraint>
fromConstraintExpr(Sema & S,const NamedDecl * D,const Expr * E)1581 NormalizedConstraint::fromConstraintExpr(Sema &S, const NamedDecl *D,
1582                                          const Expr *E) {
1583   assert(E != nullptr);
1584 
1585   // C++ [temp.constr.normal]p1.1
1586   // [...]
1587   // - The normal form of an expression (E) is the normal form of E.
1588   // [...]
1589   E = E->IgnoreParenImpCasts();
1590 
1591   // C++2a [temp.param]p4:
1592   //     [...] If T is not a pack, then E is E', otherwise E is (E' && ...).
1593   // Fold expression is considered atomic constraints per current wording.
1594   // See http://cplusplus.github.io/concepts-ts/ts-active.html#28
1595 
1596   if (LogicalBinOp BO = E) {
1597     auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1598     if (!LHS)
1599       return std::nullopt;
1600     auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1601     if (!RHS)
1602       return std::nullopt;
1603 
1604     return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
1605                                 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
1606   } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1607     const NormalizedConstraint *SubNF;
1608     {
1609       Sema::InstantiatingTemplate Inst(
1610           S, CSE->getExprLoc(),
1611           Sema::InstantiatingTemplate::ConstraintNormalization{},
1612           // FIXME: improve const-correctness of InstantiatingTemplate
1613           const_cast<NamedDecl *>(D), CSE->getSourceRange());
1614       if (Inst.isInvalid())
1615         return std::nullopt;
1616       // C++ [temp.constr.normal]p1.1
1617       // [...]
1618       // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
1619       // where C names a concept, is the normal form of the
1620       // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
1621       // respective template parameters in the parameter mappings in each atomic
1622       // constraint. If any such substitution results in an invalid type or
1623       // expression, the program is ill-formed; no diagnostic is required.
1624       // [...]
1625       ConceptDecl *CD = CSE->getNamedConcept();
1626       SubNF = S.getNormalizedAssociatedConstraints(
1627           CD, AssociatedConstraint(CD->getConstraintExpr()));
1628       if (!SubNF)
1629         return std::nullopt;
1630     }
1631 
1632     std::optional<NormalizedConstraint> New;
1633     New.emplace(S.Context, *SubNF);
1634 
1635     if (substituteParameterMappings(S, *New, CSE))
1636       return std::nullopt;
1637 
1638     return New;
1639   } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
1640              FE && S.getLangOpts().CPlusPlus26 &&
1641              (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
1642               FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
1643 
1644     // Normalize fold expressions in C++26.
1645 
1646     FoldExpandedConstraint::FoldOperatorKind Kind =
1647         FE->getOperator() == BinaryOperatorKind::BO_LAnd
1648             ? FoldExpandedConstraint::FoldOperatorKind::And
1649             : FoldExpandedConstraint::FoldOperatorKind::Or;
1650 
1651     if (FE->getInit()) {
1652       auto LHS = fromConstraintExpr(S, D, FE->getLHS());
1653       auto RHS = fromConstraintExpr(S, D, FE->getRHS());
1654       if (!LHS || !RHS)
1655         return std::nullopt;
1656 
1657       if (FE->isRightFold())
1658         RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1659             Kind, std::move(*RHS), FE->getPattern()}};
1660       else
1661         LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1662             Kind, std::move(*LHS), FE->getPattern()}};
1663 
1664       return NormalizedConstraint(
1665           S.Context, std::move(*LHS), std::move(*RHS),
1666           FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction
1667                                                            : CCK_Disjunction);
1668     }
1669     auto Sub = fromConstraintExpr(S, D, FE->getPattern());
1670     if (!Sub)
1671       return std::nullopt;
1672     return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{
1673         Kind, std::move(*Sub), FE->getPattern()}};
1674   }
1675 
1676   return NormalizedConstraint{new (S.Context) AtomicConstraint(E, D)};
1677 }
1678 
AreCompatibleForSubsumption(const FoldExpandedConstraint & A,const FoldExpandedConstraint & B)1679 bool FoldExpandedConstraint::AreCompatibleForSubsumption(
1680     const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {
1681 
1682   // [C++26] [temp.constr.fold]
1683   // Two fold expanded constraints are compatible for subsumption
1684   // if their respective constraints both contain an equivalent unexpanded pack.
1685 
1686   llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks;
1687   Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks);
1688   Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks);
1689 
1690   for (const UnexpandedParameterPack &APack : APacks) {
1691     std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack);
1692     auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) {
1693       return getDepthAndIndex(BPack) == DepthAndIndex;
1694     });
1695     if (it != BPacks.end())
1696       return true;
1697   }
1698   return false;
1699 }
1700 
IsAtLeastAsConstrained(const NamedDecl * D1,MutableArrayRef<AssociatedConstraint> AC1,const NamedDecl * D2,MutableArrayRef<AssociatedConstraint> AC2,bool & Result)1701 bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1,
1702                                   MutableArrayRef<AssociatedConstraint> AC1,
1703                                   const NamedDecl *D2,
1704                                   MutableArrayRef<AssociatedConstraint> AC2,
1705                                   bool &Result) {
1706 #ifndef NDEBUG
1707   if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1708     auto IsExpectedEntity = [](const FunctionDecl *FD) {
1709       FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind();
1710       return Kind == FunctionDecl::TK_NonTemplate ||
1711              Kind == FunctionDecl::TK_FunctionTemplate;
1712     };
1713     const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1714     assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1715            "use non-instantiated function declaration for constraints partial "
1716            "ordering");
1717   }
1718 #endif
1719 
1720   if (AC1.empty()) {
1721     Result = AC2.empty();
1722     return false;
1723   }
1724   if (AC2.empty()) {
1725     // TD1 has associated constraints and TD2 does not.
1726     Result = true;
1727     return false;
1728   }
1729 
1730   std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
1731   auto CacheEntry = SubsumptionCache.find(Key);
1732   if (CacheEntry != SubsumptionCache.end()) {
1733     Result = CacheEntry->second;
1734     return false;
1735   }
1736 
1737   unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
1738   unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
1739 
1740   for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1741     if (Depth2 > Depth1) {
1742       AC1[I].ConstraintExpr =
1743           AdjustConstraintDepth(*this, Depth2 - Depth1)
1744               .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr))
1745               .get();
1746     } else if (Depth1 > Depth2) {
1747       AC2[I].ConstraintExpr =
1748           AdjustConstraintDepth(*this, Depth1 - Depth2)
1749               .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr))
1750               .get();
1751     }
1752   }
1753 
1754   SubsumptionChecker SC(*this);
1755   std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2);
1756   if (!Subsumes) {
1757     // Normalization failed
1758     return true;
1759   }
1760   Result = *Subsumes;
1761   SubsumptionCache.try_emplace(Key, *Subsumes);
1762   return false;
1763 }
1764 
MaybeEmitAmbiguousAtomicConstraintsDiagnostic(const NamedDecl * D1,ArrayRef<AssociatedConstraint> AC1,const NamedDecl * D2,ArrayRef<AssociatedConstraint> AC2)1765 bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(
1766     const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1,
1767     const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2) {
1768   if (isSFINAEContext())
1769     // No need to work here because our notes would be discarded.
1770     return false;
1771 
1772   if (AC1.empty() || AC2.empty())
1773     return false;
1774 
1775   const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
1776   auto IdenticalExprEvaluator = [&](const AtomicConstraint &A,
1777                                     const AtomicConstraint &B) {
1778     if (!A.hasMatchingParameterMapping(Context, B))
1779       return false;
1780     const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
1781     if (EA == EB)
1782       return true;
1783 
1784     // Not the same source level expression - are the expressions
1785     // identical?
1786     llvm::FoldingSetNodeID IDA, IDB;
1787     EA->Profile(IDA, Context, /*Canonical=*/true);
1788     EB->Profile(IDB, Context, /*Canonical=*/true);
1789     if (IDA != IDB)
1790       return false;
1791 
1792     AmbiguousAtomic1 = EA;
1793     AmbiguousAtomic2 = EB;
1794     return true;
1795   };
1796 
1797   {
1798     // The subsumption checks might cause diagnostics
1799     SFINAETrap Trap(*this);
1800     auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1801     if (!Normalized1)
1802       return false;
1803 
1804     auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1805     if (!Normalized2)
1806       return false;
1807 
1808     SubsumptionChecker SC(*this);
1809 
1810     bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2);
1811     bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1);
1812 
1813     SubsumptionChecker SC2(*this, IdenticalExprEvaluator);
1814     bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2);
1815     bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1);
1816 
1817     if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1818         Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1819       // Same result - no ambiguity was caused by identical atomic expressions.
1820       return false;
1821   }
1822   // A different result! Some ambiguous atomic constraint(s) caused a difference
1823   assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1824 
1825   Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1826       << AmbiguousAtomic1->getSourceRange();
1827   Diag(AmbiguousAtomic2->getBeginLoc(),
1828        diag::note_ambiguous_atomic_constraints_similar_expression)
1829       << AmbiguousAtomic2->getSourceRange();
1830   return true;
1831 }
1832 
1833 NormalizedConstraint::CompoundConstraintKind
getCompoundKind() const1834 NormalizedConstraint::getCompoundKind() const {
1835   assert(isCompound() && "getCompoundKind on a non-compound constraint..");
1836   return cast<CompoundConstraint>(Constraint).getInt();
1837 }
1838 
getAtomicConstraint() const1839 AtomicConstraint *NormalizedConstraint::getAtomicConstraint() const {
1840   assert(isAtomic() && "getAtomicConstraint called on non-atomic constraint.");
1841   return cast<AtomicConstraint *>(Constraint);
1842 }
1843 
1844 FoldExpandedConstraint *
getFoldExpandedConstraint() const1845 NormalizedConstraint::getFoldExpandedConstraint() const {
1846   assert(isFoldExpanded() &&
1847          "getFoldExpandedConstraint called on non-fold-expanded constraint.");
1848   return cast<FoldExpandedConstraint *>(Constraint);
1849 }
1850 
1851 //
1852 //
1853 // ------------------------ Subsumption -----------------------------------
1854 //
1855 //
1856 
1857 template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
1858 
getEmptyKeyllvm::DenseMapInfo1859   static FoldingSetNodeID getEmptyKey() {
1860     FoldingSetNodeID ID;
1861     ID.AddInteger(std::numeric_limits<unsigned>::max());
1862     return ID;
1863   }
1864 
getTombstoneKeyllvm::DenseMapInfo1865   static FoldingSetNodeID getTombstoneKey() {
1866     FoldingSetNodeID ID;
1867     for (unsigned I = 0; I < sizeof(ID) / sizeof(unsigned); ++I) {
1868       ID.AddInteger(std::numeric_limits<unsigned>::max());
1869     }
1870     return ID;
1871   }
1872 
getHashValuellvm::DenseMapInfo1873   static unsigned getHashValue(const FoldingSetNodeID &Val) {
1874     return Val.ComputeHash();
1875   }
1876 
isEqualllvm::DenseMapInfo1877   static bool isEqual(const FoldingSetNodeID &LHS,
1878                       const FoldingSetNodeID &RHS) {
1879     return LHS == RHS;
1880   }
1881 };
1882 
SubsumptionChecker(Sema & SemaRef,SubsumptionCallable Callable)1883 SubsumptionChecker::SubsumptionChecker(Sema &SemaRef,
1884                                        SubsumptionCallable Callable)
1885     : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
1886 
getNewLiteralId()1887 uint16_t SubsumptionChecker::getNewLiteralId() {
1888   assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
1889          "too many constraints!");
1890   return NextID++;
1891 }
1892 
find(AtomicConstraint * Ori)1893 auto SubsumptionChecker::find(AtomicConstraint *Ori) -> Literal {
1894   auto &Elems = AtomicMap[Ori->ConstraintExpr];
1895   // C++ [temp.constr.order] p2
1896   //   - an atomic constraint A subsumes another atomic constraint B
1897   //     if and only if the A and B are identical [...]
1898   //
1899   // C++ [temp.constr.atomic] p2
1900   //   Two atomic constraints are identical if they are formed from the
1901   //   same expression and the targets of the parameter mappings are
1902   //   equivalent according to the rules for expressions [...]
1903 
1904   // Because subsumption of atomic constraints is an identity
1905   // relationship that does not require further analysis
1906   // We cache the results such that if an atomic constraint literal
1907   // subsumes another, their literal will be the same
1908 
1909   llvm::FoldingSetNodeID ID;
1910   const auto &Mapping = Ori->ParameterMapping;
1911   ID.AddBoolean(Mapping.has_value());
1912   if (Mapping) {
1913     for (const TemplateArgumentLoc &TAL : *Mapping) {
1914       SemaRef.getASTContext()
1915           .getCanonicalTemplateArgument(TAL.getArgument())
1916           .Profile(ID, SemaRef.getASTContext());
1917     }
1918   }
1919   auto It = Elems.find(ID);
1920   if (It == Elems.end()) {
1921     It = Elems
1922              .insert({ID,
1923                       MappedAtomicConstraint{
1924                           Ori, {getNewLiteralId(), Literal::Atomic}}})
1925              .first;
1926     ReverseMap[It->second.ID.Value] = Ori;
1927   }
1928   return It->getSecond().ID;
1929 }
1930 
find(FoldExpandedConstraint * Ori)1931 auto SubsumptionChecker::find(FoldExpandedConstraint *Ori) -> Literal {
1932   auto &Elems = FoldMap[Ori->Pattern];
1933 
1934   FoldExpendedConstraintKey K;
1935   K.Kind = Ori->Kind;
1936 
1937   auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) {
1938     return K.Kind == Other.Kind;
1939   });
1940   if (It == Elems.end()) {
1941     K.ID = {getNewLiteralId(), Literal::FoldExpanded};
1942     It = Elems.insert(Elems.end(), std::move(K));
1943     ReverseMap[It->ID.Value] = Ori;
1944   }
1945   return It->ID;
1946 }
1947 
CNF(const NormalizedConstraint & C)1948 auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula {
1949   return SubsumptionChecker::Normalize<CNFFormula>(C);
1950 }
DNF(const NormalizedConstraint & C)1951 auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula {
1952   return SubsumptionChecker::Normalize<DNFFormula>(C);
1953 }
1954 
1955 ///
1956 /// \brief SubsumptionChecker::Normalize
1957 ///
1958 /// Normalize a formula to Conjunctive Normal Form or
1959 /// Disjunctive normal form.
1960 ///
1961 /// Each Atomic (and Fold Expanded) constraint gets represented by
1962 /// a single id to reduce space.
1963 ///
1964 /// To minimize risks of exponential blow up, if two atomic
1965 /// constraints subsumes each other (same constraint and mapping),
1966 /// they are represented by the same literal.
1967 ///
1968 template <typename FormulaType>
Normalize(const NormalizedConstraint & NC)1969 FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) {
1970   FormulaType Res;
1971 
1972   auto Add = [&, this](Clause C) {
1973     // Sort each clause and remove duplicates for faster comparisons.
1974     llvm::sort(C);
1975     C.erase(llvm::unique(C), C.end());
1976     AddUniqueClauseToFormula(Res, std::move(C));
1977   };
1978 
1979   if (NC.isAtomic())
1980     return {{find(NC.getAtomicConstraint())}};
1981 
1982   if (NC.isFoldExpanded())
1983     return {{find(NC.getFoldExpandedConstraint())}};
1984 
1985   FormulaType Left, Right;
1986   SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
1987     Left = Normalize<FormulaType>(NC.getLHS());
1988     Right = Normalize<FormulaType>(NC.getRHS());
1989   });
1990 
1991   if (NC.getCompoundKind() == FormulaType::Kind) {
1992     auto SizeLeft = Left.size();
1993     Res = std::move(Left);
1994     Res.reserve(SizeLeft + Right.size());
1995     std::for_each(std::make_move_iterator(Right.begin()),
1996                   std::make_move_iterator(Right.end()), Add);
1997     return Res;
1998   }
1999 
2000   Res.reserve(Left.size() * Right.size());
2001   for (const auto &LTransform : Left) {
2002     for (const auto &RTransform : Right) {
2003       Clause Combined;
2004       Combined.reserve(LTransform.size() + RTransform.size());
2005       llvm::append_range(Combined, LTransform);
2006       llvm::append_range(Combined, RTransform);
2007       Add(std::move(Combined));
2008     }
2009   }
2010   return Res;
2011 }
2012 
AddUniqueClauseToFormula(Formula & F,Clause C)2013 void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) {
2014   for (auto &Other : F) {
2015     if (llvm::equal(C, Other))
2016       return;
2017   }
2018   F.push_back(C);
2019 }
2020 
Subsumes(const NamedDecl * DP,ArrayRef<AssociatedConstraint> P,const NamedDecl * DQ,ArrayRef<AssociatedConstraint> Q)2021 std::optional<bool> SubsumptionChecker::Subsumes(
2022     const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ,
2023     ArrayRef<AssociatedConstraint> Q) {
2024   const NormalizedConstraint *PNormalized =
2025       getNormalizedAssociatedConstraints(SemaRef, DP, P);
2026   if (!PNormalized)
2027     return std::nullopt;
2028 
2029   const NormalizedConstraint *QNormalized =
2030       getNormalizedAssociatedConstraints(SemaRef, DQ, Q);
2031   if (!QNormalized)
2032     return std::nullopt;
2033 
2034   return Subsumes(PNormalized, QNormalized);
2035 }
2036 
Subsumes(const NormalizedConstraint * P,const NormalizedConstraint * Q)2037 bool SubsumptionChecker::Subsumes(const NormalizedConstraint *P,
2038                                   const NormalizedConstraint *Q) {
2039 
2040   DNFFormula DNFP = DNF(*P);
2041   CNFFormula CNFQ = CNF(*Q);
2042   return Subsumes(DNFP, CNFQ);
2043 }
2044 
Subsumes(const DNFFormula & PDNF,const CNFFormula & QCNF)2045 bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF,
2046                                   const CNFFormula &QCNF) {
2047   for (const auto &Pi : PDNF) {
2048     for (const auto &Qj : QCNF) {
2049       // C++ [temp.constr.order] p2
2050       //   - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
2051       //     and only if there exists an atomic constraint Pia in Pi for which
2052       //     there exists an atomic constraint, Qjb, in Qj such that Pia
2053       //     subsumes Qjb.
2054       if (!DNFSubsumes(Pi, Qj))
2055         return false;
2056     }
2057   }
2058   return true;
2059 }
2060 
DNFSubsumes(const Clause & P,const Clause & Q)2061 bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) {
2062 
2063   return llvm::any_of(P, [&](Literal LP) {
2064     return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); });
2065   });
2066 }
2067 
Subsumes(const FoldExpandedConstraint * A,const FoldExpandedConstraint * B)2068 bool SubsumptionChecker::Subsumes(const FoldExpandedConstraint *A,
2069                                   const FoldExpandedConstraint *B) {
2070   std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2071       A, B};
2072 
2073   auto It = FoldSubsumptionCache.find(Key);
2074   if (It == FoldSubsumptionCache.end()) {
2075     // C++ [temp.constr.order]
2076     // a fold expanded constraint A subsumes another fold expanded
2077     // constraint B if they are compatible for subsumption, have the same
2078     // fold-operator, and the constraint of A subsumes that of B.
2079     bool DoesSubsume =
2080         A->Kind == B->Kind &&
2081         FoldExpandedConstraint::AreCompatibleForSubsumption(*A, *B) &&
2082         Subsumes(&A->Constraint, &B->Constraint);
2083     It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2084   }
2085   return It->second;
2086 }
2087 
Subsumes(Literal A,Literal B)2088 bool SubsumptionChecker::Subsumes(Literal A, Literal B) {
2089   if (A.Kind != B.Kind)
2090     return false;
2091   switch (A.Kind) {
2092   case Literal::Atomic:
2093     if (!Callable)
2094       return A.Value == B.Value;
2095     return Callable(
2096         *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]),
2097         *static_cast<const AtomicConstraint *>(ReverseMap[B.Value]));
2098   case Literal::FoldExpanded:
2099     return Subsumes(
2100         static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]),
2101         static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value]));
2102   }
2103   llvm_unreachable("unknown literal kind");
2104 }
2105