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