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