29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/PointerUnion.h"
31#include "llvm/ADT/StringExtras.h"
41 const Expr *LHS =
nullptr;
42 const Expr *RHS =
nullptr;
45 LogicalBinOp(
const Expr *E) {
46 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
50 Loc = BO->getExprLoc();
51 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
53 if (OO->getNumArgs() == 2) {
54 Op = OO->getOperator();
57 Loc = OO->getOperatorLoc();
62 bool isAnd()
const {
return Op == OO_AmpAmp; }
63 bool isOr()
const {
return Op == OO_PipePipe; }
64 explicit operator bool()
const {
return isAnd() || isOr(); }
66 const Expr *getLHS()
const {
return LHS; }
67 const Expr *getRHS()
const {
return RHS; }
70 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
75 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
92 Token NextToken,
bool *PossibleNonPrimary,
93 bool IsTrailingRequiresClause) {
99 if (LogicalBinOp BO = ConstraintExpression) {
101 PossibleNonPrimary) &&
104 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
110 auto CheckForNonPrimary = [&] {
111 if (!PossibleNonPrimary)
114 *PossibleNonPrimary =
125 (NextToken.
is(tok::l_paren) &&
126 (IsTrailingRequiresClause ||
128 isa<UnresolvedLookupExpr>(ConstraintExpression) &&
144 CheckForNonPrimary();
150 diag::err_non_bool_atomic_constraint) <<
Type
152 CheckForNonPrimary();
156 if (PossibleNonPrimary)
157 *PossibleNonPrimary =
false;
162struct SatisfactionStackRAII {
164 bool Inserted =
false;
166 const llvm::FoldingSetNodeID &FSNID)
173 ~SatisfactionStackRAII() {
180template <
typename AtomicEvaluator>
184 AtomicEvaluator &&Evaluator) {
187 if (LogicalBinOp BO = ConstraintExpr) {
188 size_t EffectiveDetailEndIndex = Satisfaction.
Details.size();
190 S, BO.getLHS(), Satisfaction, Evaluator);
197 if (BO.isOr() && IsLHSSatisfied)
207 if (BO.isAnd() && !IsLHSSatisfied)
218 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
231 if (BO.isOr() && IsRHSSatisfied) {
232 auto EffectiveDetailEnd = Satisfaction.
Details.begin();
233 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex);
234 Satisfaction.
Details.erase(EffectiveDetailEnd,
238 return BO.recreateBinOp(S, LHSRes, RHSRes);
241 if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
245 S,
C->getSubExpr(), Satisfaction,
246 std::forward<AtomicEvaluator>(Evaluator));
250 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
255 if (!SubstitutedAtomicExpr.
isUsable())
272 unsigned MessageSize = DiagString.size();
273 char *Mem =
new (S.
Context)
char[MessageSize];
274 memcpy(Mem, DiagString.c_str(), MessageSize);
275 Satisfaction.
Details.emplace_back(
278 SubstitutedAtomicExpr.get()->getBeginLoc(),
279 StringRef(Mem, MessageSize)});
280 return SubstitutedAtomicExpr;
287 EvalResult.
Diag = &EvaluationDiags;
290 !EvaluationDiags.empty()) {
294 diag::err_non_constant_constraint_expression)
297 S.
Diag(PDiag.first, PDiag.second);
302 "evaluating bool expression didn't produce int");
305 Satisfaction.
Details.emplace_back(ConstraintExpr,
306 SubstitutedAtomicExpr.
get());
308 return SubstitutedAtomicExpr;
316 for (
const auto &List : MLTAL)
356 llvm::FoldingSetNodeID ID;
364 SatisfactionStackRAII StackRAII(S, Template, ID);
368 SubstitutedExpression =
392 unsigned MessageSize = DiagString.size();
393 char *Mem =
new (S.
Context)
char[MessageSize];
394 memcpy(Mem, DiagString.c_str(), MessageSize);
395 Satisfaction.
Details.emplace_back(
398 SubstDiag.first, StringRef(Mem, MessageSize)});
420 CK_LValueToRValue, SubstitutedExpression.
get(),
423 return SubstitutedExpression;
432 if (ConstraintExprs.empty()) {
449 const_cast<NamedDecl *
>(Template), TemplateArgs, TemplateIDRange);
453 for (
const Expr *ConstraintExpr : ConstraintExprs) {
455 S, Template, TemplateIDRange.
getBegin(), TemplateArgsLists,
456 ConstraintExpr, Satisfaction);
460 Converted.push_back(Res.
get());
464 Converted.append(ConstraintExprs.size() - Converted.size(),
nullptr);
480 if (ConstraintExprs.empty()) {
485 return ::CheckConstraintSatisfaction(
486 *
this,
nullptr, ConstraintExprs, ConvertedConstraints,
487 TemplateArgsLists, TemplateIDRange, OutSatisfaction);
495 for (
auto List : TemplateArgsLists)
496 FlattenedArgs.insert(FlattenedArgs.end(), List.Args.begin(),
499 llvm::FoldingSetNodeID ID;
502 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
503 OutSatisfaction = *Cached;
508 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs);
510 ConvertedConstraints, TemplateArgsLists,
511 TemplateIDRange, *Satisfaction)) {
512 OutSatisfaction = *Satisfaction;
516 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
525 OutSatisfaction = *Cached;
530 OutSatisfaction = *Satisfaction;
534 SatisfactionCache.InsertNode(Satisfaction.release());
541 *
this, ConstraintExpr, Satisfaction,
550bool Sema::addInstantiatedCapturesToScope(
554 const auto *LambdaClass = cast<CXXMethodDecl>(Function)->getParent();
555 const auto *LambdaPattern = cast<CXXMethodDecl>(PatternDecl)->getParent();
557 unsigned Instantiated = 0;
559 auto AddSingleCapture = [&](
const ValueDecl *CapturedPattern,
561 ValueDecl *CapturedVar = LambdaClass->getCapture(Index)->getCapturedVar();
563 Scope.InstantiatedLocal(CapturedPattern, CapturedVar);
566 for (
const LambdaCapture &CapturePattern : LambdaPattern->captures()) {
567 if (!CapturePattern.capturesVariable()) {
571 const ValueDecl *CapturedPattern = CapturePattern.getCapturedVar();
573 AddSingleCapture(CapturedPattern, Instantiated++);
575 Scope.MakeInstantiatedLocalArgPack(CapturedPattern);
576 std::optional<unsigned> NumArgumentsInExpansion =
578 if (!NumArgumentsInExpansion)
580 for (
unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg)
581 AddSingleCapture(CapturedPattern, Instantiated++);
587bool Sema::SetupConstraintScope(
592 InstantiatingTemplate Inst(
597 if (Inst.isInvalid())
608 if (addInstantiatedParametersToScope(
615 if (
const auto *FromMemTempl =
617 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
632 InstantiatingTemplate Inst(
637 if (Inst.isInvalid())
642 if (addInstantiatedParametersToScope(FD, InstantiatedFrom,
Scope, MLTAL))
651std::optional<MultiLevelTemplateArgumentList>
652Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
665 if (SetupConstraintScope(FD, TemplateArgs, MLTAL,
Scope))
674 bool ForOverloadResolution) {
689 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
692 Satisfaction, UsageLoc,
693 ForOverloadResolution);
707 std::optional<MultiLevelTemplateArgumentList> MLTAL =
708 SetupConstraintCheckingTemplateArgumentsAndScope(
716 if (
auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
717 ThisQuals = Method->getMethodQualifiers();
737 bool SkipForSpecialization =
false) {
739 ND,
false,
nullptr,
true,
741 true, SkipForSpecialization);
746 class AdjustConstraintDepth :
public TreeTransform<AdjustConstraintDepth> {
747 unsigned TemplateDepth = 0;
750 AdjustConstraintDepth(
Sema &SemaRef,
unsigned TemplateDepth)
751 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
753 using inherited::TransformTemplateTypeParmType;
760 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
763 QualType Result = getSema().Context.getTemplateTypeParmType(
774 const Expr *ConstrExpr) {
793 std::optional<Sema::CXXThisScopeRAII> ThisScope;
800 return SubstConstr.
get();
804 const Expr *OldConstr,
806 const Expr *NewConstr) {
807 if (OldConstr == NewConstr)
810 if (Old && New && Old != New &&
812 if (
const Expr *SubstConstr =
814 OldConstr = SubstConstr;
817 if (
const Expr *SubstConstr =
819 NewConstr = SubstConstr;
824 llvm::FoldingSetNodeID ID1, ID2;
837 "Non-function templates don't need to be checked");
843 for (
const Expr *Constraint : ACs)
858 TemplateIDRange, Satisfaction))
863 TemplateArgString =
" ";
869 diag::err_template_arg_list_constraints_not_satisfied)
871 << TemplateArgString << TemplateIDRange;
888 if (TemplateAC.empty()) {
898 std::optional<MultiLevelTemplateArgumentList> MLTAL =
899 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
907 if (
auto *Method = dyn_cast<CXXMethodDecl>(
Decl)) {
908 ThisQuals = Method->getMethodQualifiers();
909 Record = Method->getParent();
918 PointOfInstantiation, Satisfaction);
925 &&
"Diagnose() can only be used on an unsatisfied requirement");
928 llvm_unreachable(
"Diagnosing a dependent requirement");
932 if (!SubstDiag->DiagMessage.empty())
933 S.
Diag(SubstDiag->DiagLoc,
934 diag::note_expr_requirement_expr_substitution_error)
935 << (
int)
First << SubstDiag->SubstitutedEntity
936 << SubstDiag->DiagMessage;
938 S.
Diag(SubstDiag->DiagLoc,
939 diag::note_expr_requirement_expr_unknown_substitution_error)
940 << (
int)
First << SubstDiag->SubstitutedEntity;
945 diag::note_expr_requirement_noexcept_not_met)
951 if (!SubstDiag->DiagMessage.empty())
952 S.
Diag(SubstDiag->DiagLoc,
953 diag::note_expr_requirement_type_requirement_substitution_error)
954 << (
int)
First << SubstDiag->SubstitutedEntity
955 << SubstDiag->DiagMessage;
957 S.
Diag(SubstDiag->DiagLoc,
958 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
959 << (
int)
First << SubstDiag->SubstitutedEntity;
970 diag::note_expr_requirement_constraints_not_satisfied_simple)
975 diag::note_expr_requirement_constraints_not_satisfied)
976 << (
int)
First << ConstraintExpr;
982 llvm_unreachable(
"We checked this above");
990 &&
"Diagnose() can only be used on an unsatisfied requirement");
993 llvm_unreachable(
"Diagnosing a dependent requirement");
997 if (!SubstDiag->DiagMessage.empty())
998 S.
Diag(SubstDiag->DiagLoc,
999 diag::note_type_requirement_substitution_error) << (
int)
First
1000 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
1002 S.
Diag(SubstDiag->DiagLoc,
1003 diag::note_type_requirement_unknown_substitution_error)
1004 << (
int)
First << SubstDiag->SubstitutedEntity;
1008 llvm_unreachable(
"Unknown satisfaction status");
1019 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
1021 if (
auto *SubstDiag = Pair.second.dyn_cast<SubstitutionDiagnostic *>())
1022 S.
Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error)
1026 S, Pair.second.dyn_cast<
Expr *>(),
First);
1036 switch (BO->getOpcode()) {
1048 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1059 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1071 if (BO->getLHS()->getType()->isIntegerType() &&
1072 BO->getRHS()->getType()->isIntegerType()) {
1075 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1078 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1081 if (!SimplifiedLHS.
Diag && ! SimplifiedRHS.
Diag) {
1083 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1096 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1097 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1099 CSE->getSourceRange().getBegin(),
1101 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1103 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1104 << CSE->getNamedConcept();
1107 diag::note_concept_specialization_constraint_evaluated_to_false)
1108 << (
int)
First << CSE;
1112 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1115 if (!Req->isDependent() && !Req->isSatisfied()) {
1116 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1118 else if (
auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1122 S, cast<concepts::NestedRequirement>(Req),
First);
1129 diag::note_atomic_constraint_evaluated_to_false)
1133template<
typename SubstitutionDiagnostic>
1136 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
1137 bool First =
true) {
1138 if (
auto *
Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
1139 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1145 Record.template get<Expr *>(),
First);
1152 "Attempted to diagnose a satisfied constraint");
1153 for (
auto &Pair : Satisfaction.
Details) {
1163 "Attempted to diagnose a satisfied constraint");
1164 for (
auto &Pair : Satisfaction) {
1178 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
1179 if (CacheEntry == NormalizationCache.end()) {
1181 NormalizedConstraint::fromConstraintExprs(*
this, ConstrainedDecl,
1182 AssociatedConstraints);
1185 .try_emplace(ConstrainedDecl,
1188 std::move(*Normalized))
1192 return CacheEntry->second;
1212 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
1214 0, OccurringIndices);
1217 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I)
1218 if (OccurringIndices[I])
1219 new (&(TempArgs)[J++])
1221 TemplateParams->
begin()[I],
1231 ? ArgsAsWritten->
arguments()[I].getLocation()
1236 S, ArgsAsWritten->
arguments().front().getSourceRange().getBegin(),
1238 ArgsAsWritten->
arguments().front().getSourceRange());
1264std::optional<NormalizedConstraint>
1265NormalizedConstraint::fromConstraintExprs(
Sema &S,
NamedDecl *D,
1267 assert(E.size() != 0);
1268 auto Conjunction = fromConstraintExpr(S, D, E[0]);
1270 return std::nullopt;
1271 for (
unsigned I = 1; I < E.size(); ++I) {
1272 auto Next = fromConstraintExpr(S, D, E[I]);
1274 return std::nullopt;
1281std::optional<NormalizedConstraint>
1283 assert(E !=
nullptr);
1296 if (LogicalBinOp BO = E) {
1297 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
1299 return std::nullopt;
1300 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
1302 return std::nullopt;
1306 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
1310 S, CSE->getExprLoc(),
1312 CSE->getSourceRange());
1326 return std::nullopt;
1329 std::optional<NormalizedConstraint> New;
1330 New.emplace(S.
Context, *SubNF);
1333 return std::nullopt;
1350 LCNF.reserve(LCNF.size() + RCNF.size());
1351 while (!RCNF.empty())
1352 LCNF.push_back(RCNF.pop_back_val());
1358 Res.reserve(LCNF.size() * RCNF.size());
1359 for (
auto &LDisjunction : LCNF)
1360 for (
auto &RDisjunction : RCNF) {
1361 NormalForm::value_type Combined;
1362 Combined.reserve(LDisjunction.size() + RDisjunction.size());
1363 std::copy(LDisjunction.begin(), LDisjunction.end(),
1364 std::back_inserter(Combined));
1365 std::copy(RDisjunction.begin(), RDisjunction.end(),
1366 std::back_inserter(Combined));
1367 Res.emplace_back(Combined);
1379 LDNF.reserve(LDNF.size() + RDNF.size());
1380 while (!RDNF.empty())
1381 LDNF.push_back(RDNF.pop_back_val());
1387 Res.reserve(LDNF.size() * RDNF.size());
1388 for (
auto &LConjunction : LDNF) {
1389 for (
auto &RConjunction : RDNF) {
1390 NormalForm::value_type Combined;
1391 Combined.reserve(LConjunction.size() + RConjunction.size());
1392 std::copy(LConjunction.begin(), LConjunction.end(),
1393 std::back_inserter(Combined));
1394 std::copy(RConjunction.begin(), RConjunction.end(),
1395 std::back_inserter(Combined));
1396 Res.emplace_back(Combined);
1402template<
typename AtomicSubsumptionEvaluator>
1404 AtomicSubsumptionEvaluator E) {
1409 for (
const auto &Pi : PDNF) {
1410 for (
const auto &Qj : QCNF) {
1419 if (E(*Pia, *Qjb)) {
1434template<
typename AtomicSubsumptionEvaluator>
1437 AtomicSubsumptionEvaluator E) {
1452 Subsumes =
subsumes(PDNF, QCNF, E);
1461 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
1467 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
1468 (void)IsExpectedEntity;
1471 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
1472 "use non-instantiated function declaration for constraints partial "
1486 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
1487 auto CacheEntry = SubsumptionCache.find(Key);
1488 if (CacheEntry != SubsumptionCache.end()) {
1489 Result = CacheEntry->second;
1496 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
1497 if (Depth2 > Depth1) {
1498 AC1[I] = AdjustConstraintDepth(*
this, Depth2 - Depth1)
1499 .TransformExpr(
const_cast<Expr *
>(AC1[I]))
1501 }
else if (Depth1 > Depth2) {
1502 AC2[I] = AdjustConstraintDepth(*
this, Depth1 - Depth2)
1503 .TransformExpr(
const_cast<Expr *
>(AC2[I]))
1513 SubsumptionCache.try_emplace(Key,
Result);
1523 if (AC1.empty() || AC2.empty())
1526 auto NormalExprEvaluator =
1531 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
1532 auto IdenticalExprEvaluator =
1542 llvm::FoldingSetNodeID IDA, IDB;
1544 EB->Profile(IDB,
Context,
true);
1548 AmbiguousAtomic1 = EA;
1549 AmbiguousAtomic2 = EB;
1568 bool Is1AtLeastAs2Normally =
subsumes(DNF1, CNF2, NormalExprEvaluator);
1569 bool Is2AtLeastAs1Normally =
subsumes(DNF2, CNF1, NormalExprEvaluator);
1570 bool Is1AtLeastAs2 =
subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1571 bool Is2AtLeastAs1 =
subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1572 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1573 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1579 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
1581 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1583 Diag(AmbiguousAtomic2->getBeginLoc(),
1584 diag::note_ambiguous_atomic_constraints_similar_expression)
1585 << AmbiguousAtomic2->getSourceRange();
1593 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1594 Status == SS_Dependent &&
1595 (E->containsUnexpandedParameterPack() ||
1596 Req.containsUnexpandedParameterPack()),
1597 Status == SS_Satisfied),
Value(E), NoexceptLoc(NoexceptLoc),
1598 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1601 "Simple requirement must not have a return type requirement or a "
1602 "noexcept specification");
1604 (SubstitutedConstraintExpr !=
nullptr));
1610 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1611 Req.containsUnexpandedParameterPack(),
false),
1612 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1613 Status(SS_ExprSubstitutionFailure) {
1615 "Simple requirement must not have a return type requirement or a "
1616 "noexcept specification");
1621 TypeConstraintInfo(TPL,
false) {
1622 assert(TPL->
size() == 1);
1624 cast<TemplateTypeParmDecl>(TPL->
getParam(0))->getTypeConstraint();
1626 "TPL must have a template type parameter with a type constraint");
1630 Constraint->getTemplateArgsAsWritten() &&
1632 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1633 TypeConstraintInfo.setInt(Dependent ?
true :
false);
1644 Status(T->getType()->isInstantiationDependentType() ?
SS_Dependent
This file provides some common utility functions for processing Lambda related AST Constructs.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
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.
Defines and computes precedence levels for binary/ternary operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static NormalForm makeCNF(const NormalizedConstraint &Normalized)
static bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF, AtomicSubsumptionEvaluator E)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, llvm::SmallVectorImpl< Expr * > &Converted, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
static NormalForm makeDNF(const NormalizedConstraint &Normalized)
static ExprResult calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction, AtomicEvaluator &&Evaluator)
static const Expr * SubstituteConstraintExpression(Sema &S, const NamedDecl *ND, const Expr *ConstrExpr)
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const Expr *E, const llvm::PointerUnion< Expr *, SubstitutionDiagnostic * > &Record, bool First=true)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList &MLTAL)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First=true)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, ConceptDecl *Concept, const MultiLevelTemplateArgumentList &MLTAL, const ASTTemplateArgumentListInfo *ArgsAsWritten)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
static bool isInvalid(LocType Loc, bool *Invalid)
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
QualType getReferenceQualifiedType(const Expr *e) const
getReferenceQualifiedType - Given an expr, will return the type for that expression,...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...
SourceLocation getBeginLoc() const LLVM_READONLY
A builtin binary operation expression such as "x + y" or "x <= y".
static OverloadedOperatorKind getOverloadedOperator(Opcode Opc)
Retrieve the overloaded operator kind that corresponds to the given binary opcode.
StringRef getOpcodeStr() const
static BinaryOperator * Create(const ASTContext &C, Expr *lhs, Expr *rhs, Opcode opc, QualType ResTy, ExprValueKind VK, ExprObjectKind OK, SourceLocation opLoc, FPOptionsOverride FPFeatures)
static Opcode getOverloadedOpcode(OverloadedOperatorKind OO)
Retrieve the binary opcode that corresponds to the given overloaded operator.
Represents a C++ conversion function within a class.
Represents a C++ struct/union/class.
Declaration of a C++20 concept.
Expr * getConstraintExpr() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
llvm::SmallVector< std::pair< const Expr *, Detail >, 4 > Details
Pairs of unsatisfied atomic constraint expressions along with the substituted constraint expr,...
std::pair< SourceLocation, StringRef > SubstitutionDiagnostic
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getNonTransparentContext()
Decl - This represents one declaration (or definition), e.g.
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
bool isParameterPack() const
Whether this declaration is a parameter pack.
SourceLocation getLocation() const
DeclContext * getDeclContext()
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Expr * getTrailingRequiresClause()
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
RAII object that enters a new expression evaluation context.
This represents one expression.
@ SE_NoSideEffects
Strictly evaluate the expression.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required to be a constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Represents difference between two FPOptions values.
Represents a function declaration or definition.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
TemplatedKind
The kind of templated function a FunctionDecl can be.
@ TK_MemberSpecialization
@ TK_DependentNonTemplate
@ TK_FunctionTemplateSpecialization
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
FunctionDecl * getInstantiatedFromDecl() const
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
FunctionTemplateDecl * getInstantiatedFromMemberTemplate() const
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
const TypeClass * getTypePtr() const
Describes the capture of a variable or of this, or of a C++1y init-capture.
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Data structure that captures multiple levels of template argument lists for use in template instantia...
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
bool isAnyArgInstantiationDependent() const
This represents a decl that may have a name.
void EmitToString(DiagnosticsEngine &Diags, SmallVectorImpl< char > &Buf) const
A (possibly-)qualified type.
The collection of all-type qualifiers we support.
Scope - A scope is a transient data structure that is used while parsing the program.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
Sema - This implements semantic analysis and AST building for C.
bool CheckInstantiatedFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, bool Final=false, const TemplateArgumentList *Innermost=nullptr, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
DiagnosticsEngine & getDiagnostics() const
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
const LangOptions & getLangOpts() const
bool CheckConstraintSatisfaction(const NamedDecl *Template, ArrayRef< const Expr * > ConstraintExprs, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
sema::FunctionScopeInfo * getCurFunction() const
std::optional< unsigned > getNumArgumentsInExpansion(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs)
Determine the number of arguments in the given pack expansion type.
std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const
Determines whether we are currently in a context where template argument substitution failures are no...
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...
ExprResult PerformContextuallyConvertToBool(Expr *From)
PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)
Check whether the given function decl's trailing requires clause is satisfied, if any.
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
bool IsAtLeastAsConstrained(NamedDecl *D1, MutableArrayRef< const Expr * > AC1, NamedDecl *D2, MutableArrayRef< const Expr * > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
void PopSatisfactionStackEntry()
ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const NamedDecl *New, const Expr *NewConstr)
const NormalizedConstraint * getNormalizedAssociatedConstraints(NamedDecl *ConstrainedDecl, ArrayRef< const Expr * > AssociatedConstraints)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
A convenient class for passing around template argument information.
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
A template argument list.
Location wrapper for a TemplateArgument.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< const Expr * > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Represents a C++ template name within the type system.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
static bool anyInstantiationDependentTemplateArguments(ArrayRef< TemplateArgumentLoc > Args)
Declaration of a template type parameter.
Wrapper for template type parameters.
TemplateTypeParmDecl * getDecl() const
bool isParameterPack() const
unsigned getIndex() const
unsigned getDepth() const
Token - This structure provides full information about a lexed token.
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)) {....
tok::TokenKind getKind() const
Models the abbreviated syntax to constrain a template type parameter: template <convertible_to<string...
Expr * getImmediatelyDeclaredConstraint() const
Get the immediately-declared constraint expression introduced by this type-constraint,...
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
A container of type source information.
SourceLocation getNameLoc() const
void setNameLoc(SourceLocation Loc)
The base class of the type hierarchy.
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isFunctionType() const
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
ReturnTypeRequirement()
No return type requirement was specified.
bool isTypeConstraint() const
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
A requires-expression requirement which queries the validity and properties of an expression ('simple...
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
@ SS_ConstraintsNotSatisfied
@ SS_TypeRequirementSubstitutionFailure
@ SS_ExprSubstitutionFailure
const ReturnTypeRequirement & getReturnTypeRequirement() const
SatisfactionStatus getSatisfactionStatus() const
SourceLocation getNoexceptLoc() const
ExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, ReturnTypeRequirement Req, SatisfactionStatus Status, ConceptSpecializationExpr *SubstitutedConstraintExpr=nullptr)
Construct a compound requirement.
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
StringRef getInvalidConstraintEntity()
A static requirement that can be used in a requires-expression to check properties of types and expre...
bool containsUnexpandedParameterPack() const
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
TypeRequirement(TypeSourceInfo *T)
Construct a type requirement from a type.
Provides information about an attempted template argument deduction, whose success or failure was des...
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ OK_Ordinary
An ordinary object is located at an address in memory.
@ C
Languages that the frontend can parse and compile.
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
llvm::ArrayRef< TemplateArgumentLoc > arguments() const
unsigned NumTemplateArgs
The number of template arguments in TemplateArgs.
bool subsumes(ASTContext &C, const AtomicConstraint &Other) const
std::optional< ArrayRef< TemplateArgumentLoc > > ParameterMapping
bool hasMatchingParameterMapping(ASTContext &C, const AtomicConstraint &Other) const
const Expr * ConstraintExpr
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
AtomicConstraint * getAtomicConstraint() const
CompoundConstraintKind getCompoundKind() const
NormalizedConstraint & getRHS() const
NormalizedConstraint & getLHS() const
A stack object to be created when performing template instantiation.
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.