clang  13.0.0git
SemaConcept.cpp
Go to the documentation of this file.
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/SemaConcept.h"
15 #include "clang/Sema/Sema.h"
19 #include "clang/Sema/Template.h"
20 #include "clang/Sema/Overload.h"
23 #include "clang/AST/ExprConcepts.h"
26 #include "llvm/ADT/DenseMap.h"
27 #include "llvm/ADT/PointerUnion.h"
28 using namespace clang;
29 using namespace sema;
30 
31 namespace {
32 class LogicalBinOp {
34  const Expr *LHS = nullptr;
35  const Expr *RHS = nullptr;
36 
37 public:
38  LogicalBinOp(const Expr *E) {
39  if (auto *BO = dyn_cast<BinaryOperator>(E)) {
40  Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
41  LHS = BO->getLHS();
42  RHS = BO->getRHS();
43  } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
44  Op = OO->getOperator();
45  LHS = OO->getArg(0);
46  RHS = OO->getArg(1);
47  }
48  }
49 
50  bool isAnd() const { return Op == OO_AmpAmp; }
51  bool isOr() const { return Op == OO_PipePipe; }
52  explicit operator bool() const { return isAnd() || isOr(); }
53 
54  const Expr *getLHS() const { return LHS; }
55  const Expr *getRHS() const { return RHS; }
56 };
57 }
58 
59 bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
60  Token NextToken, bool *PossibleNonPrimary,
61  bool IsTrailingRequiresClause) {
62  // C++2a [temp.constr.atomic]p1
63  // ..E shall be a constant expression of type bool.
64 
65  ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
66 
67  if (LogicalBinOp BO = ConstraintExpression) {
68  return CheckConstraintExpression(BO.getLHS(), NextToken,
69  PossibleNonPrimary) &&
70  CheckConstraintExpression(BO.getRHS(), NextToken,
71  PossibleNonPrimary);
72  } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
73  return CheckConstraintExpression(C->getSubExpr(), NextToken,
74  PossibleNonPrimary);
75 
76  QualType Type = ConstraintExpression->getType();
77 
78  auto CheckForNonPrimary = [&] {
79  if (PossibleNonPrimary)
80  *PossibleNonPrimary =
81  // We have the following case:
82  // template<typename> requires func(0) struct S { };
83  // The user probably isn't aware of the parentheses required around
84  // the function call, and we're only going to parse 'func' as the
85  // primary-expression, and complain that it is of non-bool type.
86  (NextToken.is(tok::l_paren) &&
87  (IsTrailingRequiresClause ||
88  (Type->isDependentType() &&
89  isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
90  Type->isFunctionType() ||
91  Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
92  // We have the following case:
93  // template<typename T> requires size_<T> == 0 struct S { };
94  // The user probably isn't aware of the parentheses required around
95  // the binary operator, and we're only going to parse 'func' as the
96  // first operand, and complain that it is of non-bool type.
97  getBinOpPrecedence(NextToken.getKind(),
98  /*GreaterThanIsOperator=*/true,
99  getLangOpts().CPlusPlus11) > prec::LogicalAnd;
100  };
101 
102  // An atomic constraint!
103  if (ConstraintExpression->isTypeDependent()) {
104  CheckForNonPrimary();
105  return true;
106  }
107 
108  if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
109  Diag(ConstraintExpression->getExprLoc(),
110  diag::err_non_bool_atomic_constraint) << Type
111  << ConstraintExpression->getSourceRange();
112  CheckForNonPrimary();
113  return false;
114  }
115 
116  if (PossibleNonPrimary)
117  *PossibleNonPrimary = false;
118  return true;
119 }
120 
121 template <typename AtomicEvaluator>
122 static bool
123 calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
124  ConstraintSatisfaction &Satisfaction,
125  AtomicEvaluator &&Evaluator) {
126  ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
127 
128  if (LogicalBinOp BO = ConstraintExpr) {
129  if (calculateConstraintSatisfaction(S, BO.getLHS(), Satisfaction,
130  Evaluator))
131  return true;
132 
133  bool IsLHSSatisfied = Satisfaction.IsSatisfied;
134 
135  if (BO.isOr() && IsLHSSatisfied)
136  // [temp.constr.op] p3
137  // A disjunction is a constraint taking two operands. To determine if
138  // a disjunction is satisfied, the satisfaction of the first operand
139  // is checked. If that is satisfied, the disjunction is satisfied.
140  // Otherwise, the disjunction is satisfied if and only if the second
141  // operand is satisfied.
142  return false;
143 
144  if (BO.isAnd() && !IsLHSSatisfied)
145  // [temp.constr.op] p2
146  // A conjunction is a constraint taking two operands. To determine if
147  // a conjunction is satisfied, the satisfaction of the first operand
148  // is checked. If that is not satisfied, the conjunction is not
149  // satisfied. Otherwise, the conjunction is satisfied if and only if
150  // the second operand is satisfied.
151  return false;
152 
154  S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
155  } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
156  return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
157  std::forward<AtomicEvaluator>(Evaluator));
158  }
159 
160  // An atomic constraint expression
161  ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
162 
163  if (SubstitutedAtomicExpr.isInvalid())
164  return true;
165 
166  if (!SubstitutedAtomicExpr.isUsable())
167  // Evaluator has decided satisfaction without yielding an expression.
168  return false;
169 
170  EnterExpressionEvaluationContext ConstantEvaluated(
172  SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
173  Expr::EvalResult EvalResult;
174  EvalResult.Diag = &EvaluationDiags;
175  if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
176  // C++2a [temp.constr.atomic]p1
177  // ...E shall be a constant expression of type bool.
178  S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
179  diag::err_non_constant_constraint_expression)
180  << SubstitutedAtomicExpr.get()->getSourceRange();
181  for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
182  S.Diag(PDiag.first, PDiag.second);
183  return true;
184  }
185 
186  Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
187  if (!Satisfaction.IsSatisfied)
188  Satisfaction.Details.emplace_back(ConstraintExpr,
189  SubstitutedAtomicExpr.get());
190 
191  return false;
192 }
193 
195  Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
196  SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
197  const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
199  S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
200  EnterExpressionEvaluationContext ConstantEvaluated(
202 
203  // Atomic constraint - substitute arguments and check satisfaction.
204  ExprResult SubstitutedExpression;
205  {
206  TemplateDeductionInfo Info(TemplateNameLoc);
209  const_cast<NamedDecl *>(Template), Info,
211  if (Inst.isInvalid())
212  return ExprError();
213  // We do not want error diagnostics escaping here.
214  Sema::SFINAETrap Trap(S);
215  SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
216  MLTAL);
217  if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
218  // C++2a [temp.constr.atomic]p1
219  // ...If substitution results in an invalid type or expression, the
220  // constraint is not satisfied.
221  if (!Trap.hasErrorOccurred())
222  // A non-SFINAE error has occured as a result of this
223  // substitution.
224  return ExprError();
225 
228  Info.takeSFINAEDiagnostic(SubstDiag);
229  // FIXME: Concepts: This is an unfortunate consequence of there
230  // being no serialization code for PartialDiagnostics and the fact
231  // that serializing them would likely take a lot more storage than
232  // just storing them as strings. We would still like, in the
233  // future, to serialize the proper PartialDiagnostic as serializing
234  // it as a string defeats the purpose of the diagnostic mechanism.
235  SmallString<128> DiagString;
236  DiagString = ": ";
237  SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
238  unsigned MessageSize = DiagString.size();
239  char *Mem = new (S.Context) char[MessageSize];
240  memcpy(Mem, DiagString.c_str(), MessageSize);
241  Satisfaction.Details.emplace_back(
242  AtomicExpr,
244  SubstDiag.first, StringRef(Mem, MessageSize)});
245  Satisfaction.IsSatisfied = false;
246  return ExprEmpty();
247  }
248  }
249 
250  if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
251  return ExprError();
252 
253  return SubstitutedExpression;
254  });
255 }
256 
257 static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
258  ArrayRef<const Expr *> ConstraintExprs,
259  ArrayRef<TemplateArgument> TemplateArgs,
260  SourceRange TemplateIDRange,
261  ConstraintSatisfaction &Satisfaction) {
262  if (ConstraintExprs.empty()) {
263  Satisfaction.IsSatisfied = true;
264  return false;
265  }
266 
267  for (auto& Arg : TemplateArgs)
268  if (Arg.isInstantiationDependent()) {
269  // No need to check satisfaction for dependent constraint expressions.
270  Satisfaction.IsSatisfied = true;
271  return false;
272  }
273 
274  Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
276  const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
277  if (Inst.isInvalid())
278  return true;
279 
281  MLTAL.addOuterTemplateArguments(TemplateArgs);
282 
283  for (const Expr *ConstraintExpr : ConstraintExprs) {
284  if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
285  TemplateIDRange.getBegin(), MLTAL,
286  ConstraintExpr, Satisfaction))
287  return true;
288  if (!Satisfaction.IsSatisfied)
289  // [temp.constr.op] p2
290  // [...] To determine if a conjunction is satisfied, the satisfaction
291  // of the first operand is checked. If that is not satisfied, the
292  // conjunction is not satisfied. [...]
293  return false;
294  }
295  return false;
296 }
297 
299  const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
300  ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
301  ConstraintSatisfaction &OutSatisfaction) {
302  if (ConstraintExprs.empty()) {
303  OutSatisfaction.IsSatisfied = true;
304  return false;
305  }
306 
307  llvm::FoldingSetNodeID ID;
308  void *InsertPos;
309  ConstraintSatisfaction *Satisfaction = nullptr;
310  bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
311  if (ShouldCache) {
312  ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
313  Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
314  if (Satisfaction) {
315  OutSatisfaction = *Satisfaction;
316  return false;
317  }
318  Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs);
319  } else {
320  Satisfaction = &OutSatisfaction;
321  }
322  if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
323  TemplateArgs, TemplateIDRange,
324  *Satisfaction)) {
325  if (ShouldCache)
326  delete Satisfaction;
327  return true;
328  }
329 
330  if (ShouldCache) {
331  // We cannot use InsertNode here because CheckConstraintSatisfaction might
332  // have invalidated it.
333  SatisfactionCache.InsertNode(Satisfaction);
334  OutSatisfaction = *Satisfaction;
335  }
336  return false;
337 }
338 
339 bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
340  ConstraintSatisfaction &Satisfaction) {
342  *this, ConstraintExpr, Satisfaction,
343  [](const Expr *AtomicExpr) -> ExprResult {
344  return ExprResult(const_cast<Expr *>(AtomicExpr));
345  });
346 }
347 
349  ConstraintSatisfaction &Satisfaction,
350  SourceLocation UsageLoc) {
351  const Expr *RC = FD->getTrailingRequiresClause();
352  if (RC->isInstantiationDependent()) {
353  Satisfaction.IsSatisfied = true;
354  return false;
355  }
356  Qualifiers ThisQuals;
357  CXXRecordDecl *Record = nullptr;
358  if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
359  ThisQuals = Method->getMethodQualifiers();
360  Record = const_cast<CXXRecordDecl *>(Method->getParent());
361  }
362  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
363  // We substitute with empty arguments in order to rebuild the atomic
364  // constraint in a constant-evaluated context.
365  // FIXME: Should this be a dedicated TreeTransform?
367  FD, {RC}, /*TemplateArgs=*/{},
368  SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
369  Satisfaction);
370 }
371 
373  TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
374  SourceRange TemplateIDRange) {
375  ConstraintSatisfaction Satisfaction;
376  llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
377  TD->getAssociatedConstraints(AssociatedConstraints);
378  if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
379  TemplateIDRange, Satisfaction))
380  return true;
381 
382  if (!Satisfaction.IsSatisfied) {
383  SmallString<128> TemplateArgString;
384  TemplateArgString = " ";
385  TemplateArgString += getTemplateArgumentBindingsText(
386  TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
387 
388  Diag(TemplateIDRange.getBegin(),
389  diag::err_template_arg_list_constraints_not_satisfied)
390  << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
391  << TemplateArgString << TemplateIDRange;
392  DiagnoseUnsatisfiedConstraint(Satisfaction);
393  return true;
394  }
395  return false;
396 }
397 
400  bool First) {
401  assert(!Req->isSatisfied()
402  && "Diagnose() can only be used on an unsatisfied requirement");
403  switch (Req->getSatisfactionStatus()) {
405  llvm_unreachable("Diagnosing a dependent requirement");
406  break;
408  auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
409  if (!SubstDiag->DiagMessage.empty())
410  S.Diag(SubstDiag->DiagLoc,
411  diag::note_expr_requirement_expr_substitution_error)
412  << (int)First << SubstDiag->SubstitutedEntity
413  << SubstDiag->DiagMessage;
414  else
415  S.Diag(SubstDiag->DiagLoc,
416  diag::note_expr_requirement_expr_unknown_substitution_error)
417  << (int)First << SubstDiag->SubstitutedEntity;
418  break;
419  }
421  S.Diag(Req->getNoexceptLoc(),
422  diag::note_expr_requirement_noexcept_not_met)
423  << (int)First << Req->getExpr();
424  break;
426  auto *SubstDiag =
428  if (!SubstDiag->DiagMessage.empty())
429  S.Diag(SubstDiag->DiagLoc,
430  diag::note_expr_requirement_type_requirement_substitution_error)
431  << (int)First << SubstDiag->SubstitutedEntity
432  << SubstDiag->DiagMessage;
433  else
434  S.Diag(SubstDiag->DiagLoc,
435  diag::note_expr_requirement_type_requirement_unknown_substitution_error)
436  << (int)First << SubstDiag->SubstitutedEntity;
437  break;
438  }
440  ConceptSpecializationExpr *ConstraintExpr =
442  if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
443  // A simple case - expr type is the type being constrained and the concept
444  // was not provided arguments.
445  Expr *e = Req->getExpr();
446  S.Diag(e->getBeginLoc(),
447  diag::note_expr_requirement_constraints_not_satisfied_simple)
448  << (int)First << S.getDecltypeForParenthesizedExpr(e)
449  << ConstraintExpr->getNamedConcept();
450  } else {
451  S.Diag(ConstraintExpr->getBeginLoc(),
452  diag::note_expr_requirement_constraints_not_satisfied)
453  << (int)First << ConstraintExpr;
454  }
455  S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
456  break;
457  }
459  llvm_unreachable("We checked this above");
460  }
461 }
462 
465  bool First) {
466  assert(!Req->isSatisfied()
467  && "Diagnose() can only be used on an unsatisfied requirement");
468  switch (Req->getSatisfactionStatus()) {
470  llvm_unreachable("Diagnosing a dependent requirement");
471  return;
473  auto *SubstDiag = Req->getSubstitutionDiagnostic();
474  if (!SubstDiag->DiagMessage.empty())
475  S.Diag(SubstDiag->DiagLoc,
476  diag::note_type_requirement_substitution_error) << (int)First
477  << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
478  else
479  S.Diag(SubstDiag->DiagLoc,
480  diag::note_type_requirement_unknown_substitution_error)
481  << (int)First << SubstDiag->SubstitutedEntity;
482  return;
483  }
484  default:
485  llvm_unreachable("Unknown satisfaction status");
486  return;
487  }
488 }
489 
492  bool First) {
493  if (Req->isSubstitutionFailure()) {
496  if (!SubstDiag->DiagMessage.empty())
497  S.Diag(SubstDiag->DiagLoc,
498  diag::note_nested_requirement_substitution_error)
499  << (int)First << SubstDiag->SubstitutedEntity
500  << SubstDiag->DiagMessage;
501  else
502  S.Diag(SubstDiag->DiagLoc,
503  diag::note_nested_requirement_unknown_substitution_error)
504  << (int)First << SubstDiag->SubstitutedEntity;
505  return;
506  }
508 }
509 
510 
512  Expr *SubstExpr,
513  bool First = true) {
514  SubstExpr = SubstExpr->IgnoreParenImpCasts();
515  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
516  switch (BO->getOpcode()) {
517  // These two cases will in practice only be reached when using fold
518  // expressions with || and &&, since otherwise the || and && will have been
519  // broken down into atomic constraints during satisfaction checking.
520  case BO_LOr:
521  // Or evaluated to false - meaning both RHS and LHS evaluated to false.
524  /*First=*/false);
525  return;
526  case BO_LAnd:
527  bool LHSSatisfied;
528  BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
529  if (LHSSatisfied) {
530  // LHS is true, so RHS must be false.
532  return;
533  }
534  // LHS is false
536 
537  // RHS might also be false
538  bool RHSSatisfied;
539  BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
540  if (!RHSSatisfied)
542  /*First=*/false);
543  return;
544  case BO_GE:
545  case BO_LE:
546  case BO_GT:
547  case BO_LT:
548  case BO_EQ:
549  case BO_NE:
550  if (BO->getLHS()->getType()->isIntegerType() &&
551  BO->getRHS()->getType()->isIntegerType()) {
552  Expr::EvalResult SimplifiedLHS;
553  Expr::EvalResult SimplifiedRHS;
554  BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
555  BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
556  if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
557  S.Diag(SubstExpr->getBeginLoc(),
558  diag::note_atomic_constraint_evaluated_to_false_elaborated)
559  << (int)First << SubstExpr
560  << SimplifiedLHS.Val.getInt().toString(10)
561  << BinaryOperator::getOpcodeStr(BO->getOpcode())
562  << SimplifiedRHS.Val.getInt().toString(10);
563  return;
564  }
565  }
566  break;
567 
568  default:
569  break;
570  }
571  } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
572  if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
573  S.Diag(
574  CSE->getSourceRange().getBegin(),
575  diag::
576  note_single_arg_concept_specialization_constraint_evaluated_to_false)
577  << (int)First
578  << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
579  << CSE->getNamedConcept();
580  } else {
581  S.Diag(SubstExpr->getSourceRange().getBegin(),
582  diag::note_concept_specialization_constraint_evaluated_to_false)
583  << (int)First << CSE;
584  }
585  S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
586  return;
587  } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
588  for (concepts::Requirement *Req : RE->getRequirements())
589  if (!Req->isDependent() && !Req->isSatisfied()) {
590  if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
592  else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
594  else
596  S, cast<concepts::NestedRequirement>(Req), First);
597  break;
598  }
599  return;
600  }
601 
602  S.Diag(SubstExpr->getSourceRange().getBegin(),
603  diag::note_atomic_constraint_evaluated_to_false)
604  << (int)First << SubstExpr;
605 }
606 
607 template<typename SubstitutionDiagnostic>
609  Sema &S, const Expr *E,
610  const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
611  bool First = true) {
612  if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
613  S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
614  << Diag->second;
615  return;
616  }
617 
619  Record.template get<Expr *>(), First);
620 }
621 
622 void
624  bool First) {
625  assert(!Satisfaction.IsSatisfied &&
626  "Attempted to diagnose a satisfied constraint");
627  for (auto &Pair : Satisfaction.Details) {
628  diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
629  First = false;
630  }
631 }
632 
634  const ASTConstraintSatisfaction &Satisfaction,
635  bool First) {
636  assert(!Satisfaction.IsSatisfied &&
637  "Attempted to diagnose a satisfied constraint");
638  for (auto &Pair : Satisfaction) {
639  diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
640  First = false;
641  }
642 }
643 
644 const NormalizedConstraint *
646  NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
647  auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
648  if (CacheEntry == NormalizationCache.end()) {
649  auto Normalized =
650  NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
651  AssociatedConstraints);
652  CacheEntry =
653  NormalizationCache
654  .try_emplace(ConstrainedDecl,
655  Normalized
656  ? new (Context) NormalizedConstraint(
657  std::move(*Normalized))
658  : nullptr)
659  .first;
660  }
661  return CacheEntry->second;
662 }
663 
665  ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
666  const ASTTemplateArgumentListInfo *ArgsAsWritten) {
667  if (!N.isAtomic()) {
668  if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
669  ArgsAsWritten))
670  return true;
671  return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
672  ArgsAsWritten);
673  }
674  TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
675 
676  AtomicConstraint &Atomic = *N.getAtomicConstraint();
677  TemplateArgumentListInfo SubstArgs;
679  MLTAL.addOuterTemplateArguments(TemplateArgs);
680  if (!Atomic.ParameterMapping) {
681  llvm::SmallBitVector OccurringIndices(TemplateParams->size());
682  S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
683  /*Depth=*/0, OccurringIndices);
684  Atomic.ParameterMapping.emplace(
686  new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
687  OccurringIndices.count()));
688  for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
689  if (OccurringIndices[I])
690  new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
691  S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
692  // Here we assume we do not support things like
693  // template<typename A, typename B>
694  // concept C = ...;
695  //
696  // template<typename... Ts> requires C<Ts...>
697  // struct S { };
698  // The above currently yields a diagnostic.
699  // We still might have default arguments for concept parameters.
700  ArgsAsWritten->NumTemplateArgs > I ?
701  ArgsAsWritten->arguments()[I].getLocation() :
702  SourceLocation()));
703  }
705  S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
707  SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
708  ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
709  if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
710  return true;
711  Atomic.ParameterMapping.emplace(
713  new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
714  SubstArgs.size()));
715  std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
716  N.getAtomicConstraint()->ParameterMapping->begin());
717  return false;
718 }
719 
721 NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
723  assert(E.size() != 0);
724  auto First = fromConstraintExpr(S, D, E[0]);
725  if (E.size() == 1)
726  return First;
727  auto Second = fromConstraintExpr(S, D, E[1]);
728  if (!Second)
729  return None;
731  Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
732  CCK_Conjunction);
733  for (unsigned I = 2; I < E.size(); ++I) {
734  auto Next = fromConstraintExpr(S, D, E[I]);
735  if (!Next)
737  NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
738  std::move(*Next), CCK_Conjunction);
739  *Conjunction = std::move(NewConjunction);
740  }
741  return Conjunction;
742 }
743 
745 NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
746  assert(E != nullptr);
747 
748  // C++ [temp.constr.normal]p1.1
749  // [...]
750  // - The normal form of an expression (E) is the normal form of E.
751  // [...]
752  E = E->IgnoreParenImpCasts();
753  if (LogicalBinOp BO = E) {
754  auto LHS = fromConstraintExpr(S, D, BO.getLHS());
755  if (!LHS)
756  return None;
757  auto RHS = fromConstraintExpr(S, D, BO.getRHS());
758  if (!RHS)
759  return None;
760 
761  return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
762  BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
763  } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
764  const NormalizedConstraint *SubNF;
765  {
767  S, CSE->getExprLoc(),
769  CSE->getSourceRange());
770  // C++ [temp.constr.normal]p1.1
771  // [...]
772  // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
773  // where C names a concept, is the normal form of the
774  // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
775  // respective template parameters in the parameter mappings in each atomic
776  // constraint. If any such substitution results in an invalid type or
777  // expression, the program is ill-formed; no diagnostic is required.
778  // [...]
779  ConceptDecl *CD = CSE->getNamedConcept();
781  {CD->getConstraintExpr()});
782  if (!SubNF)
783  return None;
784  }
785 
787  New.emplace(S.Context, *SubNF);
788 
790  S, *New, CSE->getNamedConcept(),
791  CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
792  return None;
793 
794  return New;
795  }
796  return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
797 }
798 
799 using NormalForm =
801 
802 static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
803  if (Normalized.isAtomic())
804  return {{Normalized.getAtomicConstraint()}};
805 
806  NormalForm LCNF = makeCNF(Normalized.getLHS());
807  NormalForm RCNF = makeCNF(Normalized.getRHS());
809  LCNF.reserve(LCNF.size() + RCNF.size());
810  while (!RCNF.empty())
811  LCNF.push_back(RCNF.pop_back_val());
812  return LCNF;
813  }
814 
815  // Disjunction
816  NormalForm Res;
817  Res.reserve(LCNF.size() * RCNF.size());
818  for (auto &LDisjunction : LCNF)
819  for (auto &RDisjunction : RCNF) {
820  NormalForm::value_type Combined;
821  Combined.reserve(LDisjunction.size() + RDisjunction.size());
822  std::copy(LDisjunction.begin(), LDisjunction.end(),
823  std::back_inserter(Combined));
824  std::copy(RDisjunction.begin(), RDisjunction.end(),
825  std::back_inserter(Combined));
826  Res.emplace_back(Combined);
827  }
828  return Res;
829 }
830 
831 static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
832  if (Normalized.isAtomic())
833  return {{Normalized.getAtomicConstraint()}};
834 
835  NormalForm LDNF = makeDNF(Normalized.getLHS());
836  NormalForm RDNF = makeDNF(Normalized.getRHS());
838  LDNF.reserve(LDNF.size() + RDNF.size());
839  while (!RDNF.empty())
840  LDNF.push_back(RDNF.pop_back_val());
841  return LDNF;
842  }
843 
844  // Conjunction
845  NormalForm Res;
846  Res.reserve(LDNF.size() * RDNF.size());
847  for (auto &LConjunction : LDNF) {
848  for (auto &RConjunction : RDNF) {
849  NormalForm::value_type Combined;
850  Combined.reserve(LConjunction.size() + RConjunction.size());
851  std::copy(LConjunction.begin(), LConjunction.end(),
852  std::back_inserter(Combined));
853  std::copy(RConjunction.begin(), RConjunction.end(),
854  std::back_inserter(Combined));
855  Res.emplace_back(Combined);
856  }
857  }
858  return Res;
859 }
860 
861 template<typename AtomicSubsumptionEvaluator>
862 static bool subsumes(NormalForm PDNF, NormalForm QCNF,
863  AtomicSubsumptionEvaluator E) {
864  // C++ [temp.constr.order] p2
865  // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
866  // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
867  // the conjuctive normal form of Q, where [...]
868  for (const auto &Pi : PDNF) {
869  for (const auto &Qj : QCNF) {
870  // C++ [temp.constr.order] p2
871  // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
872  // and only if there exists an atomic constraint Pia in Pi for which
873  // there exists an atomic constraint, Qjb, in Qj such that Pia
874  // subsumes Qjb.
875  bool Found = false;
876  for (const AtomicConstraint *Pia : Pi) {
877  for (const AtomicConstraint *Qjb : Qj) {
878  if (E(*Pia, *Qjb)) {
879  Found = true;
880  break;
881  }
882  }
883  if (Found)
884  break;
885  }
886  if (!Found)
887  return false;
888  }
889  }
890  return true;
891 }
892 
893 template<typename AtomicSubsumptionEvaluator>
895  NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
896  AtomicSubsumptionEvaluator E) {
897  // C++ [temp.constr.order] p2
898  // In order to determine if a constraint P subsumes a constraint Q, P is
899  // transformed into disjunctive normal form, and Q is transformed into
900  // conjunctive normal form. [...]
901  auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
902  if (!PNormalized)
903  return true;
904  const NormalForm PDNF = makeDNF(*PNormalized);
905 
906  auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
907  if (!QNormalized)
908  return true;
909  const NormalForm QCNF = makeCNF(*QNormalized);
910 
911  Subsumes = subsumes(PDNF, QCNF, E);
912  return false;
913 }
914 
917  bool &Result) {
918  if (AC1.empty()) {
919  Result = AC2.empty();
920  return false;
921  }
922  if (AC2.empty()) {
923  // TD1 has associated constraints and TD2 does not.
924  Result = true;
925  return false;
926  }
927 
928  std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
929  auto CacheEntry = SubsumptionCache.find(Key);
930  if (CacheEntry != SubsumptionCache.end()) {
931  Result = CacheEntry->second;
932  return false;
933  }
934 
935  if (subsumes(*this, D1, AC1, D2, AC2, Result,
936  [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
937  return A.subsumes(Context, B);
938  }))
939  return true;
940  SubsumptionCache.try_emplace(Key, Result);
941  return false;
942 }
943 
946  if (isSFINAEContext())
947  // No need to work here because our notes would be discarded.
948  return false;
949 
950  if (AC1.empty() || AC2.empty())
951  return false;
952 
953  auto NormalExprEvaluator =
954  [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
955  return A.subsumes(Context, B);
956  };
957 
958  const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
959  auto IdenticalExprEvaluator =
960  [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
961  if (!A.hasMatchingParameterMapping(Context, B))
962  return false;
963  const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
964  if (EA == EB)
965  return true;
966 
967  // Not the same source level expression - are the expressions
968  // identical?
969  llvm::FoldingSetNodeID IDA, IDB;
970  EA->Profile(IDA, Context, /*Cannonical=*/true);
971  EB->Profile(IDB, Context, /*Cannonical=*/true);
972  if (IDA != IDB)
973  return false;
974 
975  AmbiguousAtomic1 = EA;
976  AmbiguousAtomic2 = EB;
977  return true;
978  };
979 
980  {
981  // The subsumption checks might cause diagnostics
982  SFINAETrap Trap(*this);
983  auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
984  if (!Normalized1)
985  return false;
986  const NormalForm DNF1 = makeDNF(*Normalized1);
987  const NormalForm CNF1 = makeCNF(*Normalized1);
988 
989  auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
990  if (!Normalized2)
991  return false;
992  const NormalForm DNF2 = makeDNF(*Normalized2);
993  const NormalForm CNF2 = makeCNF(*Normalized2);
994 
995  bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
996  bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
997  bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
998  bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
999  if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1000  Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1001  // Same result - no ambiguity was caused by identical atomic expressions.
1002  return false;
1003  }
1004 
1005  // A different result! Some ambiguous atomic constraint(s) caused a difference
1006  assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1007 
1008  Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1009  << AmbiguousAtomic1->getSourceRange();
1010  Diag(AmbiguousAtomic2->getBeginLoc(),
1011  diag::note_ambiguous_atomic_constraints_similar_expression)
1012  << AmbiguousAtomic2->getSourceRange();
1013  return true;
1014 }
1015 
1017  Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1019  ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1020  Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1021  Status == SS_Dependent &&
1022  (E->containsUnexpandedParameterPack() ||
1023  Req.containsUnexpandedParameterPack()),
1024  Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1025  TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1026  Status(Status) {
1027  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1028  "Simple requirement must not have a return type requirement or a "
1029  "noexcept specification");
1030  assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1031  (SubstitutedConstraintExpr != nullptr));
1032 }
1033 
1035  SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1036  SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1037  Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1038  Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1039  Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1040  Status(SS_ExprSubstitutionFailure) {
1041  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1042  "Simple requirement must not have a return type requirement or a "
1043  "noexcept specification");
1044 }
1045 
1048  TypeConstraintInfo(TPL, 0) {
1049  assert(TPL->size() == 1);
1050  const TypeConstraint *TC =
1051  cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1052  assert(TC &&
1053  "TPL must have a template type parameter with a type constraint");
1054  auto *Constraint =
1055  cast_or_null<ConceptSpecializationExpr>(
1057  bool Dependent =
1058  Constraint->getTemplateArgsAsWritten() &&
1060  Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1061  TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1062 }
1063 
1065  Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1066  T->getType()->containsUnexpandedParameterPack(),
1067  // We reach this ctor with either dependent types (in which
1068  // IsSatisfied doesn't matter) or with non-dependent type in
1069  // which the existence of the type indicates satisfaction.
1070  /*IsSatisfied=*/true),
1071  Value(T),
1072  Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1073  : SS_Satisfied) {}
clang::concepts::TypeRequirement::TypeRequirement
TypeRequirement(TypeSourceInfo *T)
Construct a type requirement from a type.
Definition: SemaConcept.cpp:1064
clang::NormalizedConstraint
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
Definition: SemaConcept.h:82
clang::AtomicExpr
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
Definition: Expr.h:6153
clang::ConceptDecl::getConstraintExpr
Expr * getConstraintExpr() const
Definition: DeclTemplate.h:3245
clang::concepts::ExprRequirement::getExprSubstitutionDiagnostic
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
Definition: ExprConcepts.h:386
diagnoseWellFormedUnsatisfiedConstraintExpr
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
Definition: SemaConcept.cpp:511
clang::ASTConstraintSatisfaction
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:77
clang::Sema::InstantiatingTemplate::ParameterMappingSubstitution
Definition: Sema.h:8911
clang::concepts::Requirement::SubstitutionDiagnostic::DiagLoc
SourceLocation DiagLoc
Definition: ExprConcepts.h:166
clang::Sema::getDecltypeForParenthesizedExpr
QualType getDecltypeForParenthesizedExpr(Expr *E)
getDecltypeForParenthesizedExpr - Given an expr, will return the type for that expression,...
Definition: SemaType.cpp:8836
clang::prec::LogicalAnd
@ LogicalAnd
Definition: OperatorPrecedence.h:32
clang::concepts::TypeRequirement::getSubstitutionDiagnostic
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:238
clang::Sema::CXXThisScopeRAII
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
Definition: Sema.h:6115
calculateConstraintSatisfaction
static bool calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, AtomicEvaluator &&Evaluator)
Definition: SemaConcept.cpp:123
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:212
clang::NormalizedConstraint::getCompoundKind
CompoundConstraintKind getCompoundKind() const
Definition: SemaConcept.h:124
CheckConstraintSatisfaction
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
Definition: SemaConcept.cpp:257
clang::PartialDiagnostic::NullDiagnostic
Definition: PartialDiagnostic.h:43
clang::Sema::getIdentityTemplateArgumentLoc
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
Definition: SemaTemplateDeduction.cpp:2697
clang::AtomicConstraint
Definition: SemaConcept.h:30
Diag
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Definition: LiteralSupport.cpp:78
SemaInternal.h
clang::concepts::TypeRequirement::SS_SubstitutionFailure
@ SS_SubstitutionFailure
Definition: ExprConcepts.h:207
llvm::SmallVector
Definition: LLVM.h:38
clang::APValue::getInt
APSInt & getInt()
Definition: APValue.h:415
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:89
clang::NamedDecl
This represents a decl that may have a name.
Definition: Decl.h:223
clang::SourceRange::getBegin
SourceLocation getBegin() const
Definition: SourceLocation.h:221
clang::Stmt::getSourceRange
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:324
clang::ConceptReference::getNamedConcept
ConceptDecl * getNamedConcept() const
Definition: ASTConcept.h:154
clang::QualType
A (possibly-)qualified type.
Definition: Type.h:661
clang::concepts::ExprRequirement::ReturnTypeRequirement::isEmpty
bool isEmpty() const
Definition: ExprConcepts.h:304
clang::TemplateDecl::getAssociatedConstraints
void getAssociatedConstraints(llvm::SmallVectorImpl< const Expr * > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
Definition: DeclTemplate.cpp:190
clang::TypeConstraint::getImmediatelyDeclaredConstraint
Expr * getImmediatelyDeclaredConstraint() const
Get the immediately-declared constraint expression introduced by this type-constraint,...
Definition: ASTConcept.h:187
clang::Sema::getNormalizedAssociatedConstraints
const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)
Definition: SemaConcept.cpp:645
clang::concepts::Requirement::SubstitutionDiagnostic
Definition: ExprConcepts.h:161
clang::Qualifiers
The collection of all-type qualifiers we support.
Definition: Type.h:145
clang::Sema::Diag
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: Sema.cpp:1778
memcpy
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
Definition: __clang_cuda_device_functions.h:1477
int
__device__ int
Definition: __clang_hip_libdevice_declares.h:63
clang::concepts::NestedRequirement::getSubstitutionDiagnostic
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:441
subsumes
static bool subsumes(NormalForm PDNF, NormalForm QCNF, AtomicSubsumptionEvaluator E)
Definition: SemaConcept.cpp:862
clang::BinaryOperator::getOpcodeStr
StringRef getOpcodeStr() const
Definition: Expr.h:3792
clang::Expr::EvalStatus::Diag
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition: Expr.h:595
diagnoseUnsatisfiedRequirement
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
Definition: SemaConcept.cpp:398
clang::concepts::ExprRequirement::getExpr
Expr * getExpr() const
Definition: ExprConcepts.h:393
llvm::Optional
Definition: LLVM.h:40
clang::ComparisonCategoryType::First
@ First
clang::concepts::ExprRequirement::ReturnTypeRequirement::isTypeConstraint
bool isTypeConstraint() const
Definition: ExprConcepts.h:313
clang::concepts::Requirement::isSatisfied
bool isSatisfied() const
Definition: ExprConcepts.h:178
clang::ASTTemplateArgumentListInfo::NumTemplateArgs
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
Definition: TemplateBase.h:628
clang::concepts::TypeRequirement::getSatisfactionStatus
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:229
clang::Token
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
clang::concepts::ExprRequirement::getReturnTypeRequirementSubstitutedConstraintExpr
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
Definition: ExprConcepts.h:381
clang::Expr::EvalResult::Val
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:610
clang::concepts::Requirement::containsUnexpandedParameterPack
bool containsUnexpandedParameterPack() const
Definition: ExprConcepts.h:196
clang::concepts::TypeRequirement::SS_Dependent
@ SS_Dependent
Definition: ExprConcepts.h:206
clang::AtomicExpr::getBeginLoc
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Expr.h:6246
clang::ASTTemplateArgumentListInfo::arguments
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:639
clang::Sema::Context
ASTContext & Context
Definition: Sema.h:411
clang::Type
The base class of the type hierarchy.
Definition: Type.h:1478
Overload.h
clang::ExprError
ExprResult ExprError()
Definition: Ownership.h:278
clang::concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement
ReturnTypeRequirement()
No return type requirement was specified.
Definition: ExprConcepts.h:278
clang::Sema::SFINAETrap
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition: Sema.h:9006
clang::ConstraintSatisfaction::Details
llvm::SmallVector< std::pair< const Expr *, Detail >, 4 > Details
Pairs of unsatisfied atomic constraint expressions along with the substituted constraint expr,...
Definition: ASTConcept.h:53
clang::Sema::InstantiatingTemplate::ConstraintsCheck
Definition: Sema.h:8887
clang::concepts::NestedRequirement::getConstraintSatisfaction
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
Definition: ExprConcepts.h:455
clang::concepts::Requirement::SubstitutionDiagnostic::SubstitutedEntity
StringRef SubstitutedEntity
Definition: ExprConcepts.h:162
ExprConcepts.h
clang::ExprEmpty
ExprResult ExprEmpty()
Definition: Ownership.h:289
llvm::MutableArrayRef
Definition: LLVM.h:35
Template.h
clang::ConceptReference::getTemplateArgsAsWritten
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition: ASTConcept.h:158
makeCNF
static NormalForm makeCNF(const NormalizedConstraint &Normalized)
Definition: SemaConcept.cpp:802
clang::Expr::isTypeDependent
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:185
clang::TemplateParameterList::getParam
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:138
clang::PartialDiagnosticAt
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
Definition: PartialDiagnostic.h:208
clang::Sema::getDiagnostics
DiagnosticsEngine & getDiagnostics() const
Definition: Sema.h:1534
clang::TemplateArgumentListInfo
A convenient class for passing around template argument information.
Definition: TemplateBase.h:562
clang::NormalizedConstraint::getLHS
NormalizedConstraint & getLHS() const
Definition: SemaConcept.h:131
clang::BinaryOperator
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3727
clang::concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure
@ SS_TypeRequirementSubstitutionFailure
Definition: ExprConcepts.h:264
clang::XRayInstrKind::None
constexpr XRayInstrMask None
Definition: XRayInstr.h:38
clang::ConceptDecl
Declaration of a C++2a concept.
Definition: DeclTemplate.h:3230
clang::Sema::IsAtLeastAsConstrained
bool IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef< const Expr * > AC1, NamedDecl *D2, ArrayRef< const Expr * > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
Definition: SemaConcept.cpp:915
clang::TemplateSpecializationType::anyInstantiationDependentTemplateArguments
static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)
Definition: Type.cpp:3622
clang::ConceptSpecializationExpr
Represents the specialization of a concept - evaluates to a prvalue of type bool.
Definition: ExprConcepts.h:40
clang::Token::getKind
tok::TokenKind getKind() const
Definition: Token.h:92
clang::Sema::InstantiatingTemplate::ConstraintSubstitution
Definition: Sema.h:8896
diagnoseUnsatisfiedConstraintExpr
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const Expr *E, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)
Definition: SemaConcept.cpp:608
clang::ExprResult
ActionResult< Expr * > ExprResult
Definition: Ownership.h:262
clang::concepts::NestedRequirement
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
Definition: ExprConcepts.h:407
clang::Sema::SFINAETrap::hasErrorOccurred
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition: Sema.h:9037
clang::Sema::SubstTemplateArguments
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
Definition: SemaTemplateInstantiate.cpp:3464
clang::concepts::Requirement
A static requirement that can be used in a requires-expression to check properties of types and expre...
Definition: ExprConcepts.h:149
clang::NormalizedConstraint::getAtomicConstraint
AtomicConstraint * getAtomicConstraint() const
Definition: SemaConcept.h:141
clang::MultiLevelTemplateArgumentList
Data structure that captures multiple levels of template argument lists for use in template instantia...
Definition: Template.h:75
clang::Token::is
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
Definition: Token.h:97
clang::Sema::InstantiatingTemplate::isInvalid
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition: Sema.h:8938
clang::Type::isFunctionType
bool isFunctionType() const
Definition: Type.h:6664
clang::TemplateArgumentLoc
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:457
clang::Expr::isInstantiationDependent
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:214
llvm::SmallString< 128 >
clang::Expr::EvalResult
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:608
bool
#define bool
Definition: stdbool.h:15
clang::Sema::SubstExpr
ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
Definition: SemaTemplateInstantiate.cpp:3476
clang::concepts::ExprRequirement::SS_Dependent
@ SS_Dependent
Definition: ExprConcepts.h:261
clang::TemplateParameterList
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:69
clang::Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, ArrayRef< const Expr * > AC1, NamedDecl *D2, ArrayRef< const Expr * > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
Definition: SemaConcept.cpp:944
clang::DeclaratorDecl::getTrailingRequiresClause
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition: Decl.h:772
clang::Stmt::Profile
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const
Produce a unique representation of the given statement.
Definition: StmtProfile.cpp:2282
clang::Sema::InstantiatingTemplate::ConstraintNormalization
Definition: Sema.h:8905
Sema.h
clang::OverloadedOperatorKind
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
clang::ConstraintSatisfaction::IsSatisfied
bool IsSatisfied
Definition: ASTConcept.h:47
clang::TemplateDecl::getTemplateParameters
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:417
clang::NormalizedConstraint::CCK_Disjunction
@ CCK_Disjunction
Definition: SemaConcept.h:85
clang::concepts::ExprRequirement::getSatisfactionStatus
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:370
clang::concepts::ExprRequirement::ExprRequirement
ExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, ReturnTypeRequirement Req, SatisfactionStatus Status, ConceptSpecializationExpr *SubstitutedConstraintExpr=nullptr)
Construct a compound requirement.
Definition: SemaConcept.cpp:1016
clang::TemplateArgumentListInfo::arguments
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:590
clang::concepts::ExprRequirement::ReturnTypeRequirement::getSubstitutionDiagnostic
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:318
clang::CXXRecordDecl
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
clang::Sema::EnsureTemplateArgumentListConstraints
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
Definition: SemaConcept.cpp:372
clang::OO_None
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
P
StringRef P
Definition: ASTMatchersInternal.cpp:563
clang::Type::isDependentType
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2161
clang::ConstraintSatisfaction::Profile
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition: ASTConcept.h:55
clang::ConceptSpecializationExpr::getBeginLoc
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: ExprConcepts.h:124
clang::concepts::ExprRequirement::SS_Satisfied
@ SS_Satisfied
Definition: ExprConcepts.h:266
false
#define false
Definition: stdbool.h:17
clang::concepts::TypeRequirement
A requires-expression requirement which queries the existence of a type name or type template special...
Definition: ExprConcepts.h:203
clang::ActionResult::get
PtrTy get() const
Definition: Ownership.h:169
SemaDiagnostic.h
makeDNF
static NormalForm makeDNF(const NormalizedConstraint &Normalized)
Definition: SemaConcept.cpp:831
clang::TemplateName
Represents a C++ template name within the type system.
Definition: TemplateName.h:192
substituteParameterMappings
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, ArrayRef< TemplateArgument > TemplateArgs, const ASTTemplateArgumentListInfo *ArgsAsWritten)
Definition: SemaConcept.cpp:664
clang::TemplateArgumentListInfo::size
unsigned size() const
Definition: TemplateBase.h:584
clang::Expr::getExprLoc
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:228
TemplateDeduction.h
clang::TemplateDecl
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:398
clang::ASTConstraintSatisfaction::IsSatisfied
bool IsSatisfied
Definition: ASTConcept.h:81
llvm::ArrayRef
Definition: LLVM.h:34
Value
Value
Definition: UninitializedValues.cpp:102
clang::AtomicConstraint::ParameterMapping
Optional< MutableArrayRef< TemplateArgumentLoc > > ParameterMapping
Definition: SemaConcept.h:32
clang::EnterExpressionEvaluationContext
RAII object that enters a new expression evaluation context.
Definition: Sema.h:12884
clang::Expr::IgnoreParenImpCasts
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:2775
clang::Sema
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:352
clang::ActionResult::isInvalid
bool isInvalid() const
Definition: Ownership.h:165
clang::concepts::ExprRequirement::SatisfactionStatus
SatisfactionStatus
Definition: ExprConcepts.h:260
clang::concepts::ExprRequirement::SS_NoexceptNotMet
@ SS_NoexceptNotMet
Definition: ExprConcepts.h:263
clang::concepts::ExprRequirement::SS_ExprSubstitutionFailure
@ SS_ExprSubstitutionFailure
Definition: ExprConcepts.h:262
clang::TemplateParameterList::size
unsigned size() const
Definition: DeclTemplate.h:129
clang::sema::TemplateDeductionInfo
Provides information about an attempted template argument deduction, whose success or failure was des...
Definition: TemplateDeduction.h:42
clang::Expr::EvaluateAsRValue
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
Definition: ExprConstant.cpp:14713
clang::Sema::CheckConstraintSatisfaction
bool CheckConstraintSatisfaction(const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
Definition: SemaConcept.cpp:298
clang::AtomicConstraint::ConstraintExpr
const Expr * ConstraintExpr
Definition: SemaConcept.h:31
clang::Sema::InstantiatingTemplate
A stack object to be created when performing template instantiation.
Definition: Sema.h:8799
clang::NormalizedConstraint::CCK_Conjunction
@ CCK_Conjunction
Definition: SemaConcept.h:85
clang::ActionResult< Expr * >
clang::Sema::ExpressionEvaluationContext::ConstantEvaluated
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
clang::concepts::ExprRequirement::ReturnTypeRequirement
Definition: ExprConcepts.h:268
clang::Builtin::ID
ID
Definition: Builtins.h:47
clang::SourceLocation::isInvalid
bool isInvalid() const
Definition: SourceLocation.h:111
clang
Dataflow Directional Tag Classes.
Definition: CalledOnceCheck.h:17
clang::concepts::Requirement::SubstitutionDiagnostic::DiagMessage
StringRef DiagMessage
Definition: ExprConcepts.h:167
RecursiveASTVisitor.h
clang::sema::TemplateDeductionInfo::takeSFINAEDiagnostic
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
Definition: TemplateDeduction.h:102
clang::ConceptSpecializationExpr::getSatisfaction
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
Definition: ExprConcepts.h:114
clang::Sema::MarkUsedTemplateParameters
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
Definition: SemaTemplateDeduction.cpp:6145
clang::Expr::getType
QualType getType() const
Definition: Expr.h:141
clang::SourceLocation::isValid
bool isValid() const
Return true if this is a valid SourceLocation object.
Definition: SourceLocation.h:110
clang::TypeSourceInfo
A container of type source information.
Definition: Type.h:6391
clang::BinaryOperator::getOverloadedOperator
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:1963
clang::TemplateParameterList::begin
iterator begin()
Definition: DeclTemplate.h:124
clang::getBinOpPrecedence
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
Definition: OperatorPrecedence.cpp:17
clang::Sema::CheckFunctionConstraints
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation())
Check whether the given function decl's trailing requires clause is satisfied, if any.
Definition: SemaConcept.cpp:348
clang::Stmt::getBeginLoc
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:336
clang::concepts::ExprRequirement::getNoexceptLoc
SourceLocation getNoexceptLoc() const
Definition: ExprConcepts.h:368
clang::ConstraintSatisfaction::SubstitutionDiagnostic
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
Definition: ASTConcept.h:44
clang::ConstraintSatisfaction
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:29
clang::CPlusPlus11
@ CPlusPlus11
Definition: LangStandard.h:49
clang::Sema::DiagnoseUnsatisfiedConstraint
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
Definition: SemaConcept.cpp:623
OperatorPrecedence.h
clang::ASTTemplateArgumentListInfo
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Definition: TemplateBase.h:611
true
#define true
Definition: stdbool.h:16
clang::ASTContext::hasSameUnqualifiedType
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2415
clang::AtomicConstraint::subsumes
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:58
clang::Expr
This represents one expression.
Definition: Expr.h:109
clang::Type::isSpecificBuiltinType
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:6920
clang::concepts::ExprRequirement
A requires-expression requirement which queries the validity and properties of an expression ('simple...
Definition: ExprConcepts.h:258
clang::concepts::NestedRequirement::isSubstitutionFailure
bool isSubstitutionFailure() const
Definition: ExprConcepts.h:437
clang::concepts::Requirement::RK_Type
@ RK_Type
Definition: ExprConcepts.h:153
clang::NormalizedConstraint::isAtomic
bool isAtomic() const
Definition: SemaConcept.h:129
clang::Decl::getLocation
SourceLocation getLocation() const
Definition: DeclBase.h:430
clang::ASTContext::BoolTy
CanQualType BoolTy
Definition: ASTContext.h:996
clang::FunctionDecl
Represents a function declaration or definition.
Definition: Decl.h:1821
clang::NormalizedConstraint::getRHS
NormalizedConstraint & getRHS() const
Definition: SemaConcept.h:136
clang::AtomicConstraint::hasMatchingParameterMapping
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:37
clang::Sema::CheckConstraintExpression
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
Definition: SemaConcept.cpp:59
SemaConcept.h
clang::TypeConstraint
Definition: ASTConcept.h:169
clang::ActionResult::isUsable
bool isUsable() const
Definition: Ownership.h:166
clang::concepts::ExprRequirement::SS_ConstraintsNotSatisfied
@ SS_ConstraintsNotSatisfied
Definition: ExprConcepts.h:265
clang::concepts::ExprRequirement::getReturnTypeRequirement
const ReturnTypeRequirement & getReturnTypeRequirement() const
Definition: ExprConcepts.h:376
Initialization.h
clang::MultiLevelTemplateArgumentList::addOuterTemplateArguments
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs)
Add a new outermost level to the multi-level template argument list.
Definition: Template.h:173