clang  12.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);
207  Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
209  const_cast<NamedDecl *>(Template), Info,
210  AtomicExpr->getSourceRange());
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  S.Diag(ConstraintExpr->getBeginLoc(),
446  diag::note_expr_requirement_constraints_not_satisfied_simple)
447  << (int)First << S.BuildDecltypeType(Req->getExpr(),
448  Req->getExpr()->getBeginLoc())
449  << ConstraintExpr->getNamedConcept();
450  else
451  S.Diag(ConstraintExpr->getBeginLoc(),
452  diag::note_expr_requirement_constraints_not_satisfied)
453  << (int)First << ConstraintExpr;
454  S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
455  break;
456  }
458  llvm_unreachable("We checked this above");
459  }
460 }
461 
464  bool First) {
465  assert(!Req->isSatisfied()
466  && "Diagnose() can only be used on an unsatisfied requirement");
467  switch (Req->getSatisfactionStatus()) {
469  llvm_unreachable("Diagnosing a dependent requirement");
470  return;
472  auto *SubstDiag = Req->getSubstitutionDiagnostic();
473  if (!SubstDiag->DiagMessage.empty())
474  S.Diag(SubstDiag->DiagLoc,
475  diag::note_type_requirement_substitution_error) << (int)First
476  << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
477  else
478  S.Diag(SubstDiag->DiagLoc,
479  diag::note_type_requirement_unknown_substitution_error)
480  << (int)First << SubstDiag->SubstitutedEntity;
481  return;
482  }
483  default:
484  llvm_unreachable("Unknown satisfaction status");
485  return;
486  }
487 }
488 
491  bool First) {
492  if (Req->isSubstitutionFailure()) {
495  if (!SubstDiag->DiagMessage.empty())
496  S.Diag(SubstDiag->DiagLoc,
497  diag::note_nested_requirement_substitution_error)
498  << (int)First << SubstDiag->SubstitutedEntity
499  << SubstDiag->DiagMessage;
500  else
501  S.Diag(SubstDiag->DiagLoc,
502  diag::note_nested_requirement_unknown_substitution_error)
503  << (int)First << SubstDiag->SubstitutedEntity;
504  return;
505  }
507 }
508 
509 
511  Expr *SubstExpr,
512  bool First = true) {
513  SubstExpr = SubstExpr->IgnoreParenImpCasts();
514  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
515  switch (BO->getOpcode()) {
516  // These two cases will in practice only be reached when using fold
517  // expressions with || and &&, since otherwise the || and && will have been
518  // broken down into atomic constraints during satisfaction checking.
519  case BO_LOr:
520  // Or evaluated to false - meaning both RHS and LHS evaluated to false.
523  /*First=*/false);
524  return;
525  case BO_LAnd:
526  bool LHSSatisfied;
527  BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
528  if (LHSSatisfied) {
529  // LHS is true, so RHS must be false.
531  return;
532  }
533  // LHS is false
535 
536  // RHS might also be false
537  bool RHSSatisfied;
538  BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
539  if (!RHSSatisfied)
541  /*First=*/false);
542  return;
543  case BO_GE:
544  case BO_LE:
545  case BO_GT:
546  case BO_LT:
547  case BO_EQ:
548  case BO_NE:
549  if (BO->getLHS()->getType()->isIntegerType() &&
550  BO->getRHS()->getType()->isIntegerType()) {
551  Expr::EvalResult SimplifiedLHS;
552  Expr::EvalResult SimplifiedRHS;
553  BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
554  BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
555  if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
556  S.Diag(SubstExpr->getBeginLoc(),
557  diag::note_atomic_constraint_evaluated_to_false_elaborated)
558  << (int)First << SubstExpr
559  << SimplifiedLHS.Val.getInt().toString(10)
560  << BinaryOperator::getOpcodeStr(BO->getOpcode())
561  << SimplifiedRHS.Val.getInt().toString(10);
562  return;
563  }
564  }
565  break;
566 
567  default:
568  break;
569  }
570  } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
571  if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
572  S.Diag(
573  CSE->getSourceRange().getBegin(),
574  diag::
575  note_single_arg_concept_specialization_constraint_evaluated_to_false)
576  << (int)First
577  << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
578  << CSE->getNamedConcept();
579  } else {
580  S.Diag(SubstExpr->getSourceRange().getBegin(),
581  diag::note_concept_specialization_constraint_evaluated_to_false)
582  << (int)First << CSE;
583  }
584  S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
585  return;
586  } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
587  for (concepts::Requirement *Req : RE->getRequirements())
588  if (!Req->isDependent() && !Req->isSatisfied()) {
589  if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
591  else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
593  else
595  S, cast<concepts::NestedRequirement>(Req), First);
596  break;
597  }
598  return;
599  }
600 
601  S.Diag(SubstExpr->getSourceRange().getBegin(),
602  diag::note_atomic_constraint_evaluated_to_false)
603  << (int)First << SubstExpr;
604 }
605 
606 template<typename SubstitutionDiagnostic>
608  Sema &S, const Expr *E,
609  const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
610  bool First = true) {
611  if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
612  S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
613  << Diag->second;
614  return;
615  }
616 
618  Record.template get<Expr *>(), First);
619 }
620 
621 void
623  bool First) {
624  assert(!Satisfaction.IsSatisfied &&
625  "Attempted to diagnose a satisfied constraint");
626  for (auto &Pair : Satisfaction.Details) {
627  diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
628  First = false;
629  }
630 }
631 
633  const ASTConstraintSatisfaction &Satisfaction,
634  bool First) {
635  assert(!Satisfaction.IsSatisfied &&
636  "Attempted to diagnose a satisfied constraint");
637  for (auto &Pair : Satisfaction) {
638  diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
639  First = false;
640  }
641 }
642 
643 const NormalizedConstraint *
645  NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
646  auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
647  if (CacheEntry == NormalizationCache.end()) {
648  auto Normalized =
649  NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
650  AssociatedConstraints);
651  CacheEntry =
652  NormalizationCache
653  .try_emplace(ConstrainedDecl,
654  Normalized
655  ? new (Context) NormalizedConstraint(
656  std::move(*Normalized))
657  : nullptr)
658  .first;
659  }
660  return CacheEntry->second;
661 }
662 
664  ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
665  const ASTTemplateArgumentListInfo *ArgsAsWritten) {
666  if (!N.isAtomic()) {
667  if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
668  ArgsAsWritten))
669  return true;
670  return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
671  ArgsAsWritten);
672  }
673  TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
674 
675  AtomicConstraint &Atomic = *N.getAtomicConstraint();
676  TemplateArgumentListInfo SubstArgs;
678  MLTAL.addOuterTemplateArguments(TemplateArgs);
679  if (!Atomic.ParameterMapping) {
680  llvm::SmallBitVector OccurringIndices(TemplateParams->size());
681  S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
682  /*Depth=*/0, OccurringIndices);
683  Atomic.ParameterMapping.emplace(
685  new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
686  OccurringIndices.count()));
687  for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
688  if (OccurringIndices[I])
689  new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
690  S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
691  // Here we assume we do not support things like
692  // template<typename A, typename B>
693  // concept C = ...;
694  //
695  // template<typename... Ts> requires C<Ts...>
696  // struct S { };
697  // The above currently yields a diagnostic.
698  // We still might have default arguments for concept parameters.
699  ArgsAsWritten->NumTemplateArgs > I ?
700  ArgsAsWritten->arguments()[I].getLocation() :
701  SourceLocation()));
702  }
704  S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
706  SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
707  ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
708  if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
709  return true;
710  Atomic.ParameterMapping.emplace(
712  new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
713  SubstArgs.size()));
714  std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
715  N.getAtomicConstraint()->ParameterMapping->begin());
716  return false;
717 }
718 
720 NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
722  assert(E.size() != 0);
723  auto First = fromConstraintExpr(S, D, E[0]);
724  if (E.size() == 1)
725  return First;
726  auto Second = fromConstraintExpr(S, D, E[1]);
727  if (!Second)
728  return None;
730  Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
731  CCK_Conjunction);
732  for (unsigned I = 2; I < E.size(); ++I) {
733  auto Next = fromConstraintExpr(S, D, E[I]);
734  if (!Next)
736  NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
737  std::move(*Next), CCK_Conjunction);
738  *Conjunction = std::move(NewConjunction);
739  }
740  return Conjunction;
741 }
742 
744 NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
745  assert(E != nullptr);
746 
747  // C++ [temp.constr.normal]p1.1
748  // [...]
749  // - The normal form of an expression (E) is the normal form of E.
750  // [...]
751  E = E->IgnoreParenImpCasts();
752  if (LogicalBinOp BO = E) {
753  auto LHS = fromConstraintExpr(S, D, BO.getLHS());
754  if (!LHS)
755  return None;
756  auto RHS = fromConstraintExpr(S, D, BO.getRHS());
757  if (!RHS)
758  return None;
759 
760  return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
761  BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
762  } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
763  const NormalizedConstraint *SubNF;
764  {
766  S, CSE->getExprLoc(),
768  CSE->getSourceRange());
769  // C++ [temp.constr.normal]p1.1
770  // [...]
771  // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
772  // where C names a concept, is the normal form of the
773  // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
774  // respective template parameters in the parameter mappings in each atomic
775  // constraint. If any such substitution results in an invalid type or
776  // expression, the program is ill-formed; no diagnostic is required.
777  // [...]
778  ConceptDecl *CD = CSE->getNamedConcept();
780  {CD->getConstraintExpr()});
781  if (!SubNF)
782  return None;
783  }
784 
786  New.emplace(S.Context, *SubNF);
787 
789  S, *New, CSE->getNamedConcept(),
790  CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
791  return None;
792 
793  return New;
794  }
795  return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
796 }
797 
798 using NormalForm =
800 
801 static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
802  if (Normalized.isAtomic())
803  return {{Normalized.getAtomicConstraint()}};
804 
805  NormalForm LCNF = makeCNF(Normalized.getLHS());
806  NormalForm RCNF = makeCNF(Normalized.getRHS());
808  LCNF.reserve(LCNF.size() + RCNF.size());
809  while (!RCNF.empty())
810  LCNF.push_back(RCNF.pop_back_val());
811  return LCNF;
812  }
813 
814  // Disjunction
815  NormalForm Res;
816  Res.reserve(LCNF.size() * RCNF.size());
817  for (auto &LDisjunction : LCNF)
818  for (auto &RDisjunction : RCNF) {
819  NormalForm::value_type Combined;
820  Combined.reserve(LDisjunction.size() + RDisjunction.size());
821  std::copy(LDisjunction.begin(), LDisjunction.end(),
822  std::back_inserter(Combined));
823  std::copy(RDisjunction.begin(), RDisjunction.end(),
824  std::back_inserter(Combined));
825  Res.emplace_back(Combined);
826  }
827  return Res;
828 }
829 
830 static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
831  if (Normalized.isAtomic())
832  return {{Normalized.getAtomicConstraint()}};
833 
834  NormalForm LDNF = makeDNF(Normalized.getLHS());
835  NormalForm RDNF = makeDNF(Normalized.getRHS());
837  LDNF.reserve(LDNF.size() + RDNF.size());
838  while (!RDNF.empty())
839  LDNF.push_back(RDNF.pop_back_val());
840  return LDNF;
841  }
842 
843  // Conjunction
844  NormalForm Res;
845  Res.reserve(LDNF.size() * RDNF.size());
846  for (auto &LConjunction : LDNF) {
847  for (auto &RConjunction : RDNF) {
848  NormalForm::value_type Combined;
849  Combined.reserve(LConjunction.size() + RConjunction.size());
850  std::copy(LConjunction.begin(), LConjunction.end(),
851  std::back_inserter(Combined));
852  std::copy(RConjunction.begin(), RConjunction.end(),
853  std::back_inserter(Combined));
854  Res.emplace_back(Combined);
855  }
856  }
857  return Res;
858 }
859 
860 template<typename AtomicSubsumptionEvaluator>
861 static bool subsumes(NormalForm PDNF, NormalForm QCNF,
862  AtomicSubsumptionEvaluator E) {
863  // C++ [temp.constr.order] p2
864  // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
865  // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
866  // the conjuctive normal form of Q, where [...]
867  for (const auto &Pi : PDNF) {
868  for (const auto &Qj : QCNF) {
869  // C++ [temp.constr.order] p2
870  // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
871  // and only if there exists an atomic constraint Pia in Pi for which
872  // there exists an atomic constraint, Qjb, in Qj such that Pia
873  // subsumes Qjb.
874  bool Found = false;
875  for (const AtomicConstraint *Pia : Pi) {
876  for (const AtomicConstraint *Qjb : Qj) {
877  if (E(*Pia, *Qjb)) {
878  Found = true;
879  break;
880  }
881  }
882  if (Found)
883  break;
884  }
885  if (!Found)
886  return false;
887  }
888  }
889  return true;
890 }
891 
892 template<typename AtomicSubsumptionEvaluator>
894  NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
895  AtomicSubsumptionEvaluator E) {
896  // C++ [temp.constr.order] p2
897  // In order to determine if a constraint P subsumes a constraint Q, P is
898  // transformed into disjunctive normal form, and Q is transformed into
899  // conjunctive normal form. [...]
900  auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
901  if (!PNormalized)
902  return true;
903  const NormalForm PDNF = makeDNF(*PNormalized);
904 
905  auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
906  if (!QNormalized)
907  return true;
908  const NormalForm QCNF = makeCNF(*QNormalized);
909 
910  Subsumes = subsumes(PDNF, QCNF, E);
911  return false;
912 }
913 
916  bool &Result) {
917  if (AC1.empty()) {
918  Result = AC2.empty();
919  return false;
920  }
921  if (AC2.empty()) {
922  // TD1 has associated constraints and TD2 does not.
923  Result = true;
924  return false;
925  }
926 
927  std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
928  auto CacheEntry = SubsumptionCache.find(Key);
929  if (CacheEntry != SubsumptionCache.end()) {
930  Result = CacheEntry->second;
931  return false;
932  }
933 
934  if (subsumes(*this, D1, AC1, D2, AC2, Result,
935  [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
936  return A.subsumes(Context, B);
937  }))
938  return true;
939  SubsumptionCache.try_emplace(Key, Result);
940  return false;
941 }
942 
945  if (isSFINAEContext())
946  // No need to work here because our notes would be discarded.
947  return false;
948 
949  if (AC1.empty() || AC2.empty())
950  return false;
951 
952  auto NormalExprEvaluator =
953  [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
954  return A.subsumes(Context, B);
955  };
956 
957  const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
958  auto IdenticalExprEvaluator =
959  [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
960  if (!A.hasMatchingParameterMapping(Context, B))
961  return false;
962  const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
963  if (EA == EB)
964  return true;
965 
966  // Not the same source level expression - are the expressions
967  // identical?
968  llvm::FoldingSetNodeID IDA, IDB;
969  EA->Profile(IDA, Context, /*Cannonical=*/true);
970  EB->Profile(IDB, Context, /*Cannonical=*/true);
971  if (IDA != IDB)
972  return false;
973 
974  AmbiguousAtomic1 = EA;
975  AmbiguousAtomic2 = EB;
976  return true;
977  };
978 
979  {
980  // The subsumption checks might cause diagnostics
981  SFINAETrap Trap(*this);
982  auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
983  if (!Normalized1)
984  return false;
985  const NormalForm DNF1 = makeDNF(*Normalized1);
986  const NormalForm CNF1 = makeCNF(*Normalized1);
987 
988  auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
989  if (!Normalized2)
990  return false;
991  const NormalForm DNF2 = makeDNF(*Normalized2);
992  const NormalForm CNF2 = makeCNF(*Normalized2);
993 
994  bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
995  bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
996  bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
997  bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
998  if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
999  Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1000  // Same result - no ambiguity was caused by identical atomic expressions.
1001  return false;
1002  }
1003 
1004  // A different result! Some ambiguous atomic constraint(s) caused a difference
1005  assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1006 
1007  Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1008  << AmbiguousAtomic1->getSourceRange();
1009  Diag(AmbiguousAtomic2->getBeginLoc(),
1010  diag::note_ambiguous_atomic_constraints_similar_expression)
1011  << AmbiguousAtomic2->getSourceRange();
1012  return true;
1013 }
1014 
1016  Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1018  ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1019  Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1020  Status == SS_Dependent &&
1021  (E->containsUnexpandedParameterPack() ||
1022  Req.containsUnexpandedParameterPack()),
1023  Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1024  TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1025  Status(Status) {
1026  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1027  "Simple requirement must not have a return type requirement or a "
1028  "noexcept specification");
1029  assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1030  (SubstitutedConstraintExpr != nullptr));
1031 }
1032 
1034  SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1035  SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1036  Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1037  Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1038  Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1039  Status(SS_ExprSubstitutionFailure) {
1040  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1041  "Simple requirement must not have a return type requirement or a "
1042  "noexcept specification");
1043 }
1044 
1047  TypeConstraintInfo(TPL, 0) {
1048  assert(TPL->size() == 1);
1049  const TypeConstraint *TC =
1050  cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1051  assert(TC &&
1052  "TPL must have a template type parameter with a type constraint");
1053  auto *Constraint =
1054  cast_or_null<ConceptSpecializationExpr>(
1055  TC->getImmediatelyDeclaredConstraint());
1056  bool Dependent = false;
1057  if (Constraint->getTemplateArgsAsWritten()) {
1058  for (auto &ArgLoc :
1059  Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)) {
1060  if (ArgLoc.getArgument().isDependent()) {
1061  Dependent = true;
1062  break;
1063  }
1064  }
1065  }
1066  TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1067 }
1068 
1070  Requirement(RK_Type, T->getType()->isDependentType(),
1071  T->getType()->containsUnexpandedParameterPack(),
1072  // We reach this ctor with either dependent types (in which
1073  // IsSatisfied doesn't matter) or with non-dependent type in
1074  // which the existence of the type indicates satisfaction.
1075  /*IsSatisfied=*/true
1076  ), Value(T),
1077  Status(T->getType()->isDependentType() ? SS_Dependent : SS_Satisfied) {}
Represents a function declaration or definition.
Definition: Decl.h:1783
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr *> ConstraintExprs, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
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.
A (possibly-)qualified type.
Definition: Type.h:655
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
A requires-expression requirement which queries the validity and properties of an expression (&#39;simple...
Definition: ExprConcepts.h:254
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs)
Add a new outermost level to the multi-level template argument list.
Definition: Template.h:173
Provides information about an attempted template argument deduction, whose success or failure was des...
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
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition: Sema.h:1517
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:58
StringRef P
The base class of the type hierarchy.
Definition: Type.h:1472
const Expr * ConstraintExpr
Definition: SemaConcept.h:31
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:138
A container of type source information.
Definition: Type.h:6373
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:234
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
Definition: ExprConcepts.h:382
RAII object that enters a new expression evaluation context.
Definition: Sema.h:12557
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const Expr *E, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic *> &Record, bool First=true)
ExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, ReturnTypeRequirement Req, SatisfactionStatus Status, ConceptSpecializationExpr *SubstitutedConstraintExpr=nullptr)
Construct a compound requirement.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const
Produce a unique representation of the given statement.
RAII object used to temporarily allow the C++ &#39;this&#39; expression to be used, with the given qualifiers...
Definition: Sema.h:5871
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Definition: TemplateBase.h:605
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:69
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:633
tok::TokenKind getKind() const
Definition: Token.h:92
The collection of all-type qualifiers we support.
Definition: Type.h:144
ExprResult ExprEmpty()
Definition: Ownership.h:286
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:275
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:418
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
Definition: Type.h:6902
StringRef getOpcodeStr() const
Definition: Expr.h:3709
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:593
PtrTy get() const
Definition: Ownership.h:170
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:37
__device__ int
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:608
A convenient class for passing around template argument information.
Definition: TemplateBase.h:556
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:366
static bool calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, AtomicEvaluator &&Evaluator)
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3644
ConceptDecl * getNamedConcept() const
Definition: ASTConcept.h:154
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&#39;ve been if a pair of atomic constraints involv...
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
Definition: ASTConcept.h:44
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:437
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:186
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
bool IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef< const Expr *> AC1, NamedDecl *D2, ArrayRef< const Expr *> AC2, bool &Result)
Check whether the given declaration&#39;s associated constraints are at least as constrained than another...
DiagnosticsEngine & getDiagnostics() const
Definition: Sema.h:1434
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition: Sema.h:8743
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:340
A requires-expression requirement which queries the existence of a type name or type template special...
Definition: ExprConcepts.h:199
static NormalForm makeCNF(const NormalizedConstraint &Normalized)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:29
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Definition: DeclTemplate.h:421
This represents one expression.
Definition: Expr.h:110
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, ArrayRef< TemplateArgument > TemplateArgs, const ASTTemplateArgumentListInfo *ArgsAsWritten)
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
Definition: ExprConcepts.h:377
static bool subsumes(NormalForm PDNF, NormalForm QCNF, AtomicSubsumptionEvaluator E)
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
Definition: ASTConcept.h:55
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
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 &#39;conjunction&#39;) given...
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
Definition: TemplateBase.h:622
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition: Sema.h:8675
#define bool
Definition: stdbool.h:15
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
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
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:225
Represents a C++ template name within the type system.
Definition: TemplateName.h:192
QualType getType() const
Definition: Expr.h:142
NormalizedConstraint & getRHS() const
Definition: SemaConcept.h:136
Defines and computes precedence levels for binary/ternary operators.
Data structure that captures multiple levels of template argument lists for use in template instantia...
Definition: Template.h:75
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:167
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
Definition: ASTConcept.h:158
CompoundConstraintKind getCompoundKind() const
Definition: SemaConcept.h:124
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
Definition: Decl.h:747
#define false
Definition: stdbool.h:17
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Definition: Ownership.h:153
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on...
Definition: Expr.h:215
A stack object to be created when performing template instantiation.
Definition: Sema.h:8536
Encodes a location in the source.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs. ...
SourceLocation getNoexceptLoc() const
Definition: ExprConcepts.h:364
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load, __atomic_store, and __atomic_compare_exchange_*, for the similarly-named C++11 instructions, and __c11 variants for <stdatomic.h>, and corresponding __opencl_atomic_* for OpenCL 2.0.
Definition: Expr.h:6060
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:314
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr *> AssociatedConstraints)
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: ExprConcepts.h:124
A static requirement that can be used in a requires-expression to check properties of types and expre...
Definition: ExprConcepts.h:145
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
Definition: ASTContext.h:2299
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:226
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:606
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:402
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
Definition: ExprConcepts.h:451
ReturnTypeRequirement()
No return type requirement was specified.
Definition: ExprConcepts.h:274
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:584
NormalizedConstraint & getLHS() const
Definition: SemaConcept.h:131
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:2947
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
Not an overloaded operator.
Definition: OperatorKinds.h:22
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:451
bool containsUnexpandedParameterPack() const
Definition: ExprConcepts.h:192
bool isFunctionType() const
Definition: Type.h:6646
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:77
QualType BuildDecltypeType(Expr *E, SourceLocation Loc, bool AsUnevaluated=true)
If AsUnevaluated is false, E is treated as though it were an evaluated context, such as when building...
Definition: SemaType.cpp:8811
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation())
Check whether the given function decl&#39;s trailing requires clause is satisfied, if any...
ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
ActionResult< Expr * > ExprResult
Definition: Ownership.h:263
Defines Expressions and AST nodes for C++2a concepts.
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
void getAssociatedConstraints(llvm::SmallVectorImpl< const Expr *> &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TypeRequirement(TypeSourceInfo *T)
Construct a type requirement from a type.
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
Definition: ExprConcepts.h:403
Represents the specialization of a concept - evaluates to a prvalue of type bool. ...
Definition: ExprConcepts.h:40
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:263
ExprResult ExprError()
Definition: Ownership.h:279
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2185
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
Definition: Expr.cpp:1983
AtomicConstraint * getAtomicConstraint() const
Definition: SemaConcept.h:141
static NormalForm makeDNF(const NormalizedConstraint &Normalized)
#define true
Definition: stdbool.h:16
A trivial tuple used to represent a source range.
ASTContext & Context
Definition: Sema.h:399
This represents a decl that may have a name.
Definition: Decl.h:223
Optional< MutableArrayRef< TemplateArgumentLoc > > ParameterMapping
Definition: SemaConcept.h:32
CanQualType BoolTy
Definition: ASTContext.h:943
APSInt & getInt()
Definition: APValue.h:380
SourceLocation getBegin() const
SourceLocation getLocation() const
Definition: DeclBase.h:430
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint...
Definition: SemaConcept.h:82
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Definition: Sema.h:8774
const ReturnTypeRequirement & getReturnTypeRequirement() const
Definition: ExprConcepts.h:372