clang  10.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 bool
32 Sema::CheckConstraintExpression(Expr *ConstraintExpression, Token NextToken,
33  bool *PossibleNonPrimary,
34  bool IsTrailingRequiresClause) {
35  // C++2a [temp.constr.atomic]p1
36  // ..E shall be a constant expression of type bool.
37 
38  ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
39 
40  if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
41  if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)
42  return CheckConstraintExpression(BinOp->getLHS(), NextToken,
43  PossibleNonPrimary) &&
44  CheckConstraintExpression(BinOp->getRHS(), NextToken,
45  PossibleNonPrimary);
46  } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
47  return CheckConstraintExpression(C->getSubExpr(), NextToken,
48  PossibleNonPrimary);
49 
50  QualType Type = ConstraintExpression->getType();
51 
52  auto CheckForNonPrimary = [&] {
53  if (PossibleNonPrimary)
54  *PossibleNonPrimary =
55  // We have the following case:
56  // template<typename> requires func(0) struct S { };
57  // The user probably isn't aware of the parentheses required around
58  // the function call, and we're only going to parse 'func' as the
59  // primary-expression, and complain that it is of non-bool type.
60  (NextToken.is(tok::l_paren) &&
61  (IsTrailingRequiresClause ||
62  (Type->isDependentType() &&
63  IsDependentFunctionNameExpr(ConstraintExpression)) ||
64  Type->isFunctionType() ||
65  Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
66  // We have the following case:
67  // template<typename T> requires size_<T> == 0 struct S { };
68  // The user probably isn't aware of the parentheses required around
69  // the binary operator, and we're only going to parse 'func' as the
70  // first operand, and complain that it is of non-bool type.
71  getBinOpPrecedence(NextToken.getKind(),
72  /*GreaterThanIsOperator=*/true,
73  getLangOpts().CPlusPlus11) > prec::LogicalAnd;
74  };
75 
76  // An atomic constraint!
77  if (ConstraintExpression->isTypeDependent()) {
78  CheckForNonPrimary();
79  return true;
80  }
81 
82  if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
83  Diag(ConstraintExpression->getExprLoc(),
84  diag::err_non_bool_atomic_constraint) << Type
85  << ConstraintExpression->getSourceRange();
86  CheckForNonPrimary();
87  return false;
88  }
89 
90  if (PossibleNonPrimary)
91  *PossibleNonPrimary = false;
92  return true;
93 }
94 
95 template <typename AtomicEvaluator>
96 static bool
97 calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
98  ConstraintSatisfaction &Satisfaction,
99  AtomicEvaluator &&Evaluator) {
100  ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
101 
102  if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
103  if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
104  if (calculateConstraintSatisfaction(S, BO->getLHS(), Satisfaction,
105  Evaluator))
106  return true;
107 
108  bool IsLHSSatisfied = Satisfaction.IsSatisfied;
109 
110  if (BO->getOpcode() == BO_LOr && IsLHSSatisfied)
111  // [temp.constr.op] p3
112  // A disjunction is a constraint taking two operands. To determine if
113  // a disjunction is satisfied, the satisfaction of the first operand
114  // is checked. If that is satisfied, the disjunction is satisfied.
115  // Otherwise, the disjunction is satisfied if and only if the second
116  // operand is satisfied.
117  return false;
118 
119  if (BO->getOpcode() == BO_LAnd && !IsLHSSatisfied)
120  // [temp.constr.op] p2
121  // A conjunction is a constraint taking two operands. To determine if
122  // a conjunction is satisfied, the satisfaction of the first operand
123  // is checked. If that is not satisfied, the conjunction is not
124  // satisfied. Otherwise, the conjunction is satisfied if and only if
125  // the second operand is satisfied.
126  return false;
127 
128  return calculateConstraintSatisfaction(S, BO->getRHS(), Satisfaction,
129  std::forward<AtomicEvaluator>(Evaluator));
130  }
131  }
132  else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
133  return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
134  std::forward<AtomicEvaluator>(Evaluator));
135 
136  // An atomic constraint expression
137  ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
138 
139  if (SubstitutedAtomicExpr.isInvalid())
140  return true;
141 
142  if (!SubstitutedAtomicExpr.isUsable())
143  // Evaluator has decided satisfaction without yielding an expression.
144  return false;
145 
146  EnterExpressionEvaluationContext ConstantEvaluated(
148  SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
149  Expr::EvalResult EvalResult;
150  EvalResult.Diag = &EvaluationDiags;
151  if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
152  // C++2a [temp.constr.atomic]p1
153  // ...E shall be a constant expression of type bool.
154  S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
155  diag::err_non_constant_constraint_expression)
156  << SubstitutedAtomicExpr.get()->getSourceRange();
157  for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
158  S.Diag(PDiag.first, PDiag.second);
159  return true;
160  }
161 
162  Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
163  if (!Satisfaction.IsSatisfied)
164  Satisfaction.Details.emplace_back(ConstraintExpr,
165  SubstitutedAtomicExpr.get());
166 
167  return false;
168 }
169 
171  Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
172  SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
173  const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
175  S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
176  EnterExpressionEvaluationContext ConstantEvaluated(
178 
179  // Atomic constraint - substitute arguments and check satisfaction.
180  ExprResult SubstitutedExpression;
181  {
182  TemplateDeductionInfo Info(TemplateNameLoc);
183  Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
185  const_cast<NamedDecl *>(Template), Info,
186  AtomicExpr->getSourceRange());
187  if (Inst.isInvalid())
188  return ExprError();
189  // We do not want error diagnostics escaping here.
190  Sema::SFINAETrap Trap(S);
191  SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
192  MLTAL);
193  if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
194  // C++2a [temp.constr.atomic]p1
195  // ...If substitution results in an invalid type or expression, the
196  // constraint is not satisfied.
197  if (!Trap.hasErrorOccurred())
198  // A non-SFINAE error has occured as a result of this
199  // substitution.
200  return ExprError();
201 
204  Info.takeSFINAEDiagnostic(SubstDiag);
205  // FIXME: Concepts: This is an unfortunate consequence of there
206  // being no serialization code for PartialDiagnostics and the fact
207  // that serializing them would likely take a lot more storage than
208  // just storing them as strings. We would still like, in the
209  // future, to serialize the proper PartialDiagnostic as serializing
210  // it as a string defeats the purpose of the diagnostic mechanism.
211  SmallString<128> DiagString;
212  DiagString = ": ";
213  SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
214  unsigned MessageSize = DiagString.size();
215  char *Mem = new (S.Context) char[MessageSize];
216  memcpy(Mem, DiagString.c_str(), MessageSize);
217  Satisfaction.Details.emplace_back(
218  AtomicExpr,
220  SubstDiag.first, StringRef(Mem, MessageSize)});
221  Satisfaction.IsSatisfied = false;
222  return ExprEmpty();
223  }
224  }
225 
226  if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
227  return ExprError();
228 
229  return SubstitutedExpression;
230  });
231 }
232 
233 static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
234  ArrayRef<const Expr *> ConstraintExprs,
235  ArrayRef<TemplateArgument> TemplateArgs,
236  SourceRange TemplateIDRange,
237  ConstraintSatisfaction &Satisfaction) {
238  if (ConstraintExprs.empty()) {
239  Satisfaction.IsSatisfied = true;
240  return false;
241  }
242 
243  for (auto& Arg : TemplateArgs)
244  if (Arg.isInstantiationDependent()) {
245  // No need to check satisfaction for dependent constraint expressions.
246  Satisfaction.IsSatisfied = true;
247  return false;
248  }
249 
250  Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
252  const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
253  if (Inst.isInvalid())
254  return true;
255 
257  MLTAL.addOuterTemplateArguments(TemplateArgs);
258 
259  for (const Expr *ConstraintExpr : ConstraintExprs) {
260  if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
261  TemplateIDRange.getBegin(), MLTAL,
262  ConstraintExpr, Satisfaction))
263  return true;
264  if (!Satisfaction.IsSatisfied)
265  // [temp.constr.op] p2
266  // [...] To determine if a conjunction is satisfied, the satisfaction
267  // of the first operand is checked. If that is not satisfied, the
268  // conjunction is not satisfied. [...]
269  return false;
270  }
271  return false;
272 }
273 
275  const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
276  ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
277  ConstraintSatisfaction &OutSatisfaction) {
278  if (ConstraintExprs.empty()) {
279  OutSatisfaction.IsSatisfied = true;
280  return false;
281  }
282 
283  llvm::FoldingSetNodeID ID;
284  void *InsertPos;
285  ConstraintSatisfaction *Satisfaction = nullptr;
286  bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
287  if (ShouldCache) {
288  ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
289  Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
290  if (Satisfaction) {
291  OutSatisfaction = *Satisfaction;
292  return false;
293  }
294  Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs);
295  } else {
296  Satisfaction = &OutSatisfaction;
297  }
298  if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
299  TemplateArgs, TemplateIDRange,
300  *Satisfaction)) {
301  if (ShouldCache)
302  delete Satisfaction;
303  return true;
304  }
305 
306  if (ShouldCache) {
307  // We cannot use InsertNode here because CheckConstraintSatisfaction might
308  // have invalidated it.
309  SatisfactionCache.InsertNode(Satisfaction);
310  OutSatisfaction = *Satisfaction;
311  }
312  return false;
313 }
314 
315 bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
316  ConstraintSatisfaction &Satisfaction) {
318  *this, ConstraintExpr, Satisfaction,
319  [](const Expr *AtomicExpr) -> ExprResult {
320  return ExprResult(const_cast<Expr *>(AtomicExpr));
321  });
322 }
323 
325  ConstraintSatisfaction &Satisfaction,
326  SourceLocation UsageLoc) {
327  const Expr *RC = FD->getTrailingRequiresClause();
328  if (RC->isInstantiationDependent()) {
329  Satisfaction.IsSatisfied = true;
330  return false;
331  }
332  Qualifiers ThisQuals;
333  CXXRecordDecl *Record = nullptr;
334  if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
335  ThisQuals = Method->getMethodQualifiers();
336  Record = const_cast<CXXRecordDecl *>(Method->getParent());
337  }
338  CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
339  // We substitute with empty arguments in order to rebuild the atomic
340  // constraint in a constant-evaluated context.
341  // FIXME: Should this be a dedicated TreeTransform?
343  FD, {RC}, /*TemplateArgs=*/{},
344  SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
345  Satisfaction);
346 }
347 
349  TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
350  SourceRange TemplateIDRange) {
351  ConstraintSatisfaction Satisfaction;
352  llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
353  TD->getAssociatedConstraints(AssociatedConstraints);
354  if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
355  TemplateIDRange, Satisfaction))
356  return true;
357 
358  if (!Satisfaction.IsSatisfied) {
359  SmallString<128> TemplateArgString;
360  TemplateArgString = " ";
361  TemplateArgString += getTemplateArgumentBindingsText(
362  TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
363 
364  Diag(TemplateIDRange.getBegin(),
365  diag::err_template_arg_list_constraints_not_satisfied)
366  << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
367  << TemplateArgString << TemplateIDRange;
368  DiagnoseUnsatisfiedConstraint(Satisfaction);
369  return true;
370  }
371  return false;
372 }
373 
376  bool First) {
377  assert(!Req->isSatisfied()
378  && "Diagnose() can only be used on an unsatisfied requirement");
379  switch (Req->getSatisfactionStatus()) {
381  llvm_unreachable("Diagnosing a dependent requirement");
382  break;
384  auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
385  if (!SubstDiag->DiagMessage.empty())
386  S.Diag(SubstDiag->DiagLoc,
387  diag::note_expr_requirement_expr_substitution_error)
388  << (int)First << SubstDiag->SubstitutedEntity
389  << SubstDiag->DiagMessage;
390  else
391  S.Diag(SubstDiag->DiagLoc,
392  diag::note_expr_requirement_expr_unknown_substitution_error)
393  << (int)First << SubstDiag->SubstitutedEntity;
394  break;
395  }
397  S.Diag(Req->getNoexceptLoc(),
398  diag::note_expr_requirement_noexcept_not_met)
399  << (int)First << Req->getExpr();
400  break;
402  auto *SubstDiag =
404  if (!SubstDiag->DiagMessage.empty())
405  S.Diag(SubstDiag->DiagLoc,
406  diag::note_expr_requirement_type_requirement_substitution_error)
407  << (int)First << SubstDiag->SubstitutedEntity
408  << SubstDiag->DiagMessage;
409  else
410  S.Diag(SubstDiag->DiagLoc,
411  diag::note_expr_requirement_type_requirement_unknown_substitution_error)
412  << (int)First << SubstDiag->SubstitutedEntity;
413  break;
414  }
416  ConceptSpecializationExpr *ConstraintExpr =
418  if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1)
419  // A simple case - expr type is the type being constrained and the concept
420  // was not provided arguments.
421  S.Diag(ConstraintExpr->getBeginLoc(),
422  diag::note_expr_requirement_constraints_not_satisfied_simple)
423  << (int)First << S.BuildDecltypeType(Req->getExpr(),
424  Req->getExpr()->getBeginLoc())
425  << ConstraintExpr->getNamedConcept();
426  else
427  S.Diag(ConstraintExpr->getBeginLoc(),
428  diag::note_expr_requirement_constraints_not_satisfied)
429  << (int)First << ConstraintExpr;
430  S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
431  break;
432  }
434  llvm_unreachable("We checked this above");
435  }
436 }
437 
440  bool First) {
441  assert(!Req->isSatisfied()
442  && "Diagnose() can only be used on an unsatisfied requirement");
443  switch (Req->getSatisfactionStatus()) {
445  llvm_unreachable("Diagnosing a dependent requirement");
446  return;
448  auto *SubstDiag = Req->getSubstitutionDiagnostic();
449  if (!SubstDiag->DiagMessage.empty())
450  S.Diag(SubstDiag->DiagLoc,
451  diag::note_type_requirement_substitution_error) << (int)First
452  << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
453  else
454  S.Diag(SubstDiag->DiagLoc,
455  diag::note_type_requirement_unknown_substitution_error)
456  << (int)First << SubstDiag->SubstitutedEntity;
457  return;
458  }
459  default:
460  llvm_unreachable("Unknown satisfaction status");
461  return;
462  }
463 }
464 
467  bool First) {
468  if (Req->isSubstitutionFailure()) {
471  if (!SubstDiag->DiagMessage.empty())
472  S.Diag(SubstDiag->DiagLoc,
473  diag::note_nested_requirement_substitution_error)
474  << (int)First << SubstDiag->SubstitutedEntity
475  << SubstDiag->DiagMessage;
476  else
477  S.Diag(SubstDiag->DiagLoc,
478  diag::note_nested_requirement_unknown_substitution_error)
479  << (int)First << SubstDiag->SubstitutedEntity;
480  return;
481  }
483 }
484 
485 
487  Expr *SubstExpr,
488  bool First = true) {
489  SubstExpr = SubstExpr->IgnoreParenImpCasts();
490  if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
491  switch (BO->getOpcode()) {
492  // These two cases will in practice only be reached when using fold
493  // expressions with || and &&, since otherwise the || and && will have been
494  // broken down into atomic constraints during satisfaction checking.
495  case BO_LOr:
496  // Or evaluated to false - meaning both RHS and LHS evaluated to false.
499  /*First=*/false);
500  return;
501  case BO_LAnd:
502  bool LHSSatisfied;
503  BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
504  if (LHSSatisfied) {
505  // LHS is true, so RHS must be false.
507  return;
508  }
509  // LHS is false
511 
512  // RHS might also be false
513  bool RHSSatisfied;
514  BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
515  if (!RHSSatisfied)
517  /*First=*/false);
518  return;
519  case BO_GE:
520  case BO_LE:
521  case BO_GT:
522  case BO_LT:
523  case BO_EQ:
524  case BO_NE:
525  if (BO->getLHS()->getType()->isIntegerType() &&
526  BO->getRHS()->getType()->isIntegerType()) {
527  Expr::EvalResult SimplifiedLHS;
528  Expr::EvalResult SimplifiedRHS;
529  BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
530  BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
531  if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
532  S.Diag(SubstExpr->getBeginLoc(),
533  diag::note_atomic_constraint_evaluated_to_false_elaborated)
534  << (int)First << SubstExpr
535  << SimplifiedLHS.Val.getInt().toString(10)
536  << BinaryOperator::getOpcodeStr(BO->getOpcode())
537  << SimplifiedRHS.Val.getInt().toString(10);
538  return;
539  }
540  }
541  break;
542 
543  default:
544  break;
545  }
546  } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
547  if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
548  S.Diag(
549  CSE->getSourceRange().getBegin(),
550  diag::
551  note_single_arg_concept_specialization_constraint_evaluated_to_false)
552  << (int)First
553  << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
554  << CSE->getNamedConcept();
555  } else {
556  S.Diag(SubstExpr->getSourceRange().getBegin(),
557  diag::note_concept_specialization_constraint_evaluated_to_false)
558  << (int)First << CSE;
559  }
560  S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
561  return;
562  } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
563  for (concepts::Requirement *Req : RE->getRequirements())
564  if (!Req->isDependent() && !Req->isSatisfied()) {
565  if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
567  else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
569  else
571  S, cast<concepts::NestedRequirement>(Req), First);
572  break;
573  }
574  return;
575  }
576 
577  S.Diag(SubstExpr->getSourceRange().getBegin(),
578  diag::note_atomic_constraint_evaluated_to_false)
579  << (int)First << SubstExpr;
580 }
581 
582 template<typename SubstitutionDiagnostic>
584  Sema &S, const Expr *E,
585  const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
586  bool First = true) {
587  if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
588  S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
589  << Diag->second;
590  return;
591  }
592 
594  Record.template get<Expr *>(), First);
595 }
596 
597 void
599  bool First) {
600  assert(!Satisfaction.IsSatisfied &&
601  "Attempted to diagnose a satisfied constraint");
602  for (auto &Pair : Satisfaction.Details) {
603  diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
604  First = false;
605  }
606 }
607 
609  const ASTConstraintSatisfaction &Satisfaction,
610  bool First) {
611  assert(!Satisfaction.IsSatisfied &&
612  "Attempted to diagnose a satisfied constraint");
613  for (auto &Pair : Satisfaction) {
614  diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
615  First = false;
616  }
617 }
618 
619 const NormalizedConstraint *
621  NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
622  auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
623  if (CacheEntry == NormalizationCache.end()) {
624  auto Normalized =
625  NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
626  AssociatedConstraints);
627  CacheEntry =
628  NormalizationCache
629  .try_emplace(ConstrainedDecl,
630  Normalized
631  ? new (Context) NormalizedConstraint(
632  std::move(*Normalized))
633  : nullptr)
634  .first;
635  }
636  return CacheEntry->second;
637 }
638 
640  ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
641  const ASTTemplateArgumentListInfo *ArgsAsWritten) {
642  if (!N.isAtomic()) {
643  if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
644  ArgsAsWritten))
645  return true;
646  return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
647  ArgsAsWritten);
648  }
649  TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
650 
651  AtomicConstraint &Atomic = *N.getAtomicConstraint();
652  TemplateArgumentListInfo SubstArgs;
654  MLTAL.addOuterTemplateArguments(TemplateArgs);
655  if (!Atomic.ParameterMapping) {
656  llvm::SmallBitVector OccurringIndices(TemplateParams->size());
657  S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
658  /*Depth=*/0, OccurringIndices);
659  Atomic.ParameterMapping.emplace(
661  new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
662  OccurringIndices.count()));
663  for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
664  if (OccurringIndices[I])
665  new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
666  S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
667  // Here we assume we do not support things like
668  // template<typename A, typename B>
669  // concept C = ...;
670  //
671  // template<typename... Ts> requires C<Ts...>
672  // struct S { };
673  // The above currently yields a diagnostic.
674  // We still might have default arguments for concept parameters.
675  ArgsAsWritten->NumTemplateArgs > I ?
676  ArgsAsWritten->arguments()[I].getLocation() :
677  SourceLocation()));
678  }
680  S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
682  SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
683  ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
684  if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
685  return true;
686  Atomic.ParameterMapping.emplace(
688  new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
689  SubstArgs.size()));
690  std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
691  N.getAtomicConstraint()->ParameterMapping->begin());
692  return false;
693 }
694 
696 NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
698  assert(E.size() != 0);
699  auto First = fromConstraintExpr(S, D, E[0]);
700  if (E.size() == 1)
701  return First;
702  auto Second = fromConstraintExpr(S, D, E[1]);
703  if (!Second)
704  return None;
706  Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
707  CCK_Conjunction);
708  for (unsigned I = 2; I < E.size(); ++I) {
709  auto Next = fromConstraintExpr(S, D, E[I]);
710  if (!Next)
712  NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
713  std::move(*Next), CCK_Conjunction);
714  *Conjunction = std::move(NewConjunction);
715  }
716  return Conjunction;
717 }
718 
720 NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
721  assert(E != nullptr);
722 
723  // C++ [temp.constr.normal]p1.1
724  // [...]
725  // - The normal form of an expression (E) is the normal form of E.
726  // [...]
727  E = E->IgnoreParenImpCasts();
728  if (auto *BO = dyn_cast<const BinaryOperator>(E)) {
729  if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
730  auto LHS = fromConstraintExpr(S, D, BO->getLHS());
731  if (!LHS)
732  return None;
733  auto RHS = fromConstraintExpr(S, D, BO->getRHS());
734  if (!RHS)
735  return None;
736 
737  return NormalizedConstraint(
738  S.Context, std::move(*LHS), std::move(*RHS),
739  BO->getOpcode() == BO_LAnd ? CCK_Conjunction : CCK_Disjunction);
740  }
741  } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
742  const NormalizedConstraint *SubNF;
743  {
745  S, CSE->getExprLoc(),
747  CSE->getSourceRange());
748  // C++ [temp.constr.normal]p1.1
749  // [...]
750  // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
751  // where C names a concept, is the normal form of the
752  // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
753  // respective template parameters in the parameter mappings in each atomic
754  // constraint. If any such substitution results in an invalid type or
755  // expression, the program is ill-formed; no diagnostic is required.
756  // [...]
757  ConceptDecl *CD = CSE->getNamedConcept();
759  {CD->getConstraintExpr()});
760  if (!SubNF)
761  return None;
762  }
763 
765  New.emplace(S.Context, *SubNF);
766 
768  S, *New, CSE->getNamedConcept(),
769  CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
770  return None;
771 
772  return New;
773  }
774  return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
775 }
776 
777 using NormalForm =
779 
780 static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
781  if (Normalized.isAtomic())
782  return {{Normalized.getAtomicConstraint()}};
783 
784  NormalForm LCNF = makeCNF(Normalized.getLHS());
785  NormalForm RCNF = makeCNF(Normalized.getRHS());
787  LCNF.reserve(LCNF.size() + RCNF.size());
788  while (!RCNF.empty())
789  LCNF.push_back(RCNF.pop_back_val());
790  return LCNF;
791  }
792 
793  // Disjunction
794  NormalForm Res;
795  Res.reserve(LCNF.size() * RCNF.size());
796  for (auto &LDisjunction : LCNF)
797  for (auto &RDisjunction : RCNF) {
798  NormalForm::value_type Combined;
799  Combined.reserve(LDisjunction.size() + RDisjunction.size());
800  std::copy(LDisjunction.begin(), LDisjunction.end(),
801  std::back_inserter(Combined));
802  std::copy(RDisjunction.begin(), RDisjunction.end(),
803  std::back_inserter(Combined));
804  Res.emplace_back(Combined);
805  }
806  return Res;
807 }
808 
809 static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
810  if (Normalized.isAtomic())
811  return {{Normalized.getAtomicConstraint()}};
812 
813  NormalForm LDNF = makeDNF(Normalized.getLHS());
814  NormalForm RDNF = makeDNF(Normalized.getRHS());
816  LDNF.reserve(LDNF.size() + RDNF.size());
817  while (!RDNF.empty())
818  LDNF.push_back(RDNF.pop_back_val());
819  return LDNF;
820  }
821 
822  // Conjunction
823  NormalForm Res;
824  Res.reserve(LDNF.size() * RDNF.size());
825  for (auto &LConjunction : LDNF) {
826  for (auto &RConjunction : RDNF) {
827  NormalForm::value_type Combined;
828  Combined.reserve(LConjunction.size() + RConjunction.size());
829  std::copy(LConjunction.begin(), LConjunction.end(),
830  std::back_inserter(Combined));
831  std::copy(RConjunction.begin(), RConjunction.end(),
832  std::back_inserter(Combined));
833  Res.emplace_back(Combined);
834  }
835  }
836  return Res;
837 }
838 
839 template<typename AtomicSubsumptionEvaluator>
840 static bool subsumes(NormalForm PDNF, NormalForm QCNF,
841  AtomicSubsumptionEvaluator E) {
842  // C++ [temp.constr.order] p2
843  // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
844  // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
845  // the conjuctive normal form of Q, where [...]
846  for (const auto &Pi : PDNF) {
847  for (const auto &Qj : QCNF) {
848  // C++ [temp.constr.order] p2
849  // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
850  // and only if there exists an atomic constraint Pia in Pi for which
851  // there exists an atomic constraint, Qjb, in Qj such that Pia
852  // subsumes Qjb.
853  bool Found = false;
854  for (const AtomicConstraint *Pia : Pi) {
855  for (const AtomicConstraint *Qjb : Qj) {
856  if (E(*Pia, *Qjb)) {
857  Found = true;
858  break;
859  }
860  }
861  if (Found)
862  break;
863  }
864  if (!Found)
865  return false;
866  }
867  }
868  return true;
869 }
870 
871 template<typename AtomicSubsumptionEvaluator>
873  NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
874  AtomicSubsumptionEvaluator E) {
875  // C++ [temp.constr.order] p2
876  // In order to determine if a constraint P subsumes a constraint Q, P is
877  // transformed into disjunctive normal form, and Q is transformed into
878  // conjunctive normal form. [...]
879  auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
880  if (!PNormalized)
881  return true;
882  const NormalForm PDNF = makeDNF(*PNormalized);
883 
884  auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
885  if (!QNormalized)
886  return true;
887  const NormalForm QCNF = makeCNF(*QNormalized);
888 
889  Subsumes = subsumes(PDNF, QCNF, E);
890  return false;
891 }
892 
895  bool &Result) {
896  if (AC1.empty()) {
897  Result = AC2.empty();
898  return false;
899  }
900  if (AC2.empty()) {
901  // TD1 has associated constraints and TD2 does not.
902  Result = true;
903  return false;
904  }
905 
906  std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
907  auto CacheEntry = SubsumptionCache.find(Key);
908  if (CacheEntry != SubsumptionCache.end()) {
909  Result = CacheEntry->second;
910  return false;
911  }
912 
913  if (subsumes(*this, D1, AC1, D2, AC2, Result,
914  [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
915  return A.subsumes(Context, B);
916  }))
917  return true;
918  SubsumptionCache.try_emplace(Key, Result);
919  return false;
920 }
921 
924  if (isSFINAEContext())
925  // No need to work here because our notes would be discarded.
926  return false;
927 
928  if (AC1.empty() || AC2.empty())
929  return false;
930 
931  auto NormalExprEvaluator =
932  [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
933  return A.subsumes(Context, B);
934  };
935 
936  const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
937  auto IdenticalExprEvaluator =
938  [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
939  if (!A.hasMatchingParameterMapping(Context, B))
940  return false;
941  const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
942  if (EA == EB)
943  return true;
944 
945  // Not the same source level expression - are the expressions
946  // identical?
947  llvm::FoldingSetNodeID IDA, IDB;
948  EA->Profile(IDA, Context, /*Cannonical=*/true);
949  EB->Profile(IDB, Context, /*Cannonical=*/true);
950  if (IDA != IDB)
951  return false;
952 
953  AmbiguousAtomic1 = EA;
954  AmbiguousAtomic2 = EB;
955  return true;
956  };
957 
958  {
959  // The subsumption checks might cause diagnostics
960  SFINAETrap Trap(*this);
961  auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
962  if (!Normalized1)
963  return false;
964  const NormalForm DNF1 = makeDNF(*Normalized1);
965  const NormalForm CNF1 = makeCNF(*Normalized1);
966 
967  auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
968  if (!Normalized2)
969  return false;
970  const NormalForm DNF2 = makeDNF(*Normalized2);
971  const NormalForm CNF2 = makeCNF(*Normalized2);
972 
973  bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
974  bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
975  bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
976  bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
977  if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
978  Is2AtLeastAs1 == Is2AtLeastAs1Normally)
979  // Same result - no ambiguity was caused by identical atomic expressions.
980  return false;
981  }
982 
983  // A different result! Some ambiguous atomic constraint(s) caused a difference
984  assert(AmbiguousAtomic1 && AmbiguousAtomic2);
985 
986  Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
987  << AmbiguousAtomic1->getSourceRange();
988  Diag(AmbiguousAtomic2->getBeginLoc(),
989  diag::note_ambiguous_atomic_constraints_similar_expression)
990  << AmbiguousAtomic2->getSourceRange();
991  return true;
992 }
993 
995  Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
997  ConceptSpecializationExpr *SubstitutedConstraintExpr) :
998  Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
999  Status == SS_Dependent &&
1000  (E->containsUnexpandedParameterPack() ||
1001  Req.containsUnexpandedParameterPack()),
1002  Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1003  TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1004  Status(Status) {
1005  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1006  "Simple requirement must not have a return type requirement or a "
1007  "noexcept specification");
1008  assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
1009  (SubstitutedConstraintExpr != nullptr));
1010 }
1011 
1013  SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1014  SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1015  Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1016  Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1017  Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1018  Status(SS_ExprSubstitutionFailure) {
1019  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1020  "Simple requirement must not have a return type requirement or a "
1021  "noexcept specification");
1022 }
1023 
1026  TypeConstraintInfo(TPL, 0) {
1027  assert(TPL->size() == 1);
1028  const TypeConstraint *TC =
1029  cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1030  assert(TC &&
1031  "TPL must have a template type parameter with a type constraint");
1032  auto *Constraint =
1033  cast_or_null<ConceptSpecializationExpr>(
1034  TC->getImmediatelyDeclaredConstraint());
1035  bool Dependent = false;
1036  if (Constraint->getTemplateArgsAsWritten()) {
1037  for (auto &ArgLoc :
1038  Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)) {
1039  if (ArgLoc.getArgument().isDependent()) {
1040  Dependent = true;
1041  break;
1042  }
1043  }
1044  }
1045  TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1046 }
1047 
1049  Requirement(RK_Type, T->getType()->isDependentType(),
1050  T->getType()->containsUnexpandedParameterPack(),
1051  // We reach this ctor with either dependent types (in which
1052  // IsSatisfied doesn't matter) or with non-dependent type in
1053  // which the existence of the type indicates satisfaction.
1054  /*IsSatisfied=*/true
1055  ), Value(T),
1056  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:654
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:253
void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs)
Add a new outermost level to the multi-level template argument list.
Definition: Template.h:133
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:1411
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:58
StringRef P
The base class of the type hierarchy.
Definition: Type.h:1450
const Expr * ConstraintExpr
Definition: SemaConcept.h:31
NamedDecl * getParam(unsigned Idx)
Definition: DeclTemplate.h:138
A container of type source information.
Definition: Type.h:6227
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:233
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
Definition: ExprConcepts.h:381
RAII object that enters a new expression evaluation context.
Definition: Sema.h:12029
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:5616
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Definition: TemplateBase.h:603
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:631
tok::TokenKind getKind() const
Definition: Token.h:92
The collection of all-type qualifiers we support.
Definition: Type.h:143
ExprResult ExprEmpty()
Definition: Ownership.h:285
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:275
virtual SourceRange getSourceRange() const LLVM_READONLY
Source range that this declaration covers.
Definition: DeclBase.h:417
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:6744
StringRef getOpcodeStr() const
Definition: Expr.h:3490
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:573
PtrTy get() const
Definition: Ownership.h:170
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
Definition: SemaConcept.h:37
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:588
A convenient class for passing around template argument information.
Definition: TemplateBase.h:554
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:365
static bool calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, AtomicEvaluator &&Evaluator)
Definition: SemaConcept.cpp:97
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3434
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:436
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
Definition: Expr.h:176
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:1328
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
Definition: Sema.h:8450
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:336
A requires-expression requirement which queries the existence of a type name or type template special...
Definition: ExprConcepts.h:198
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:108
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, ArrayRef< TemplateArgument > TemplateArgs, const ASTTemplateArgumentListInfo *ArgsAsWritten)
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
Definition: ExprConcepts.h:376
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:620
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
Definition: Sema.h:8382
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
SatisfactionStatus getSatisfactionStatus() const
Definition: ExprConcepts.h:224
Represents a C++ template name within the type system.
Definition: TemplateName.h:191
QualType getType() const
Definition: Expr.h:137
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:64
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 a template...
Definition: Expr.h:200
A stack object to be created when performing template instantiation.
Definition: Sema.h:8243
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:363
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:5849
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
Definition: ExprConcepts.h:313
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:2345
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:224
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:586
The base class of all kinds of template declarations (e.g., class, function, etc.).
Definition: DeclTemplate.h:402
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
Definition: ExprConcepts.h:450
ReturnTypeRequirement()
No return type requirement was specified.
Definition: ExprConcepts.h:273
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
Definition: TemplateBase.h:582
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:2995
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
Location wrapper for a TemplateArgument.
Definition: TemplateBase.h:449
bool CheckConstraintExpression(Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
Definition: SemaConcept.cpp:32
bool containsUnexpandedParameterPack() const
Definition: ExprConcepts.h:191
bool isFunctionType() const
Definition: Type.h:6500
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:8471
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:253
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:402
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:2150
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.
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:385
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:1017
APSInt & getInt()
Definition: APValue.h:380
SourceLocation getBegin() const
SourceLocation getLocation() const
Definition: DeclBase.h:429
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:8481
const ReturnTypeRequirement & getReturnTypeRequirement() const
Definition: ExprConcepts.h:371