29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/PointerUnion.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/Support/SaveAndRestore.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; }
71 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
76 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
77 assert((!LHS.isInvalid() && !RHS.isInvalid()) &&
"not good expressions?");
79 if (!LHS.isUsable() || !RHS.isUsable())
93 Token NextToken,
bool *PossibleNonPrimary,
94 bool IsTrailingRequiresClause) {
100 if (LogicalBinOp BO = ConstraintExpression) {
102 PossibleNonPrimary) &&
105 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
111 auto CheckForNonPrimary = [&] {
112 if (!PossibleNonPrimary)
115 *PossibleNonPrimary =
126 (NextToken.
is(tok::l_paren) &&
127 (IsTrailingRequiresClause ||
145 CheckForNonPrimary();
151 diag::err_non_bool_atomic_constraint)
153 CheckForNonPrimary();
157 if (PossibleNonPrimary)
158 *PossibleNonPrimary =
false;
163struct SatisfactionStackRAII {
165 bool Inserted =
false;
167 const llvm::FoldingSetNodeID &FSNID)
174 ~SatisfactionStackRAII() {
186 for (
const auto &List : *MLTAL)
204 bool SkipForSpecialization =
false) {
210 true, SkipForSpecialization);
215class AdjustConstraintDepth :
public TreeTransform<AdjustConstraintDepth> {
216 unsigned TemplateDepth = 0;
219 using inherited = TreeTransform<AdjustConstraintDepth>;
220 AdjustConstraintDepth(Sema &SemaRef,
unsigned TemplateDepth)
221 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
223 using inherited::TransformTemplateTypeParmType;
224 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
225 TemplateTypeParmTypeLoc TL,
bool) {
228 TemplateTypeParmDecl *NewTTPDecl =
nullptr;
229 if (TemplateTypeParmDecl *OldTTPDecl =
T->getDecl())
230 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
233 QualType
Result = getSema().Context.getTemplateTypeParmType(
234 T->getDepth() + TemplateDepth,
T->getIndex(),
T->isParameterPack(),
236 TemplateTypeParmTypeLoc NewTL = TLB.
push<TemplateTypeParmTypeLoc>(
Result);
241 bool AlreadyTransformed(QualType
T) {
257 using inherited = RecursiveASTVisitor<HashParameterMapping>;
261 const MultiLevelTemplateArgumentList &TemplateArgs;
262 llvm::FoldingSetNodeID &
ID;
263 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
265 UnsignedOrNone OuterPackSubstIndex;
267 bool shouldVisitTemplateInstantiations()
const {
return true; }
270 HashParameterMapping(Sema &SemaRef,
271 const MultiLevelTemplateArgumentList &TemplateArgs,
272 llvm::FoldingSetNodeID &ID,
273 UnsignedOrNone OuterPackSubstIndex)
274 : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
ID(
ID),
275 OuterPackSubstIndex(OuterPackSubstIndex) {}
277 bool VisitTemplateTypeParmType(TemplateTypeParmType *
T) {
288 TemplateArgument Arg = TemplateArgs(
T->getDepth(),
T->getIndex());
292 "Missing argument pack");
297 UsedTemplateArgs.push_back(
302 bool VisitDeclRefExpr(DeclRefExpr *E) {
304 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
306 return TraverseDecl(D);
317 "Missing argument pack");
321 UsedTemplateArgs.push_back(
326 bool VisitTypedefType(TypedefType *TT) {
327 return inherited::TraverseType(TT->
desugar());
330 bool TraverseDecl(Decl *D) {
331 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
332 if (
auto *Var = dyn_cast<VarDecl>(VD))
333 TraverseStmt(Var->getInit());
334 return TraverseType(VD->getType());
337 return inherited::TraverseDecl(D);
340 bool TraverseCallExpr(CallExpr *CE) {
341 inherited::TraverseStmt(CE->
getCallee());
344 inherited::TraverseStmt(Arg);
349 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
354 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
362 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
363 bool TraverseQualifier) {
364 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
367 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
370 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
371 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
373 return inherited::TraverseTemplateArgument(Arg);
376 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
377 return inherited::TraverseTemplateArgument(Arg);
380 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
381 return TraverseDecl(SOPE->
getPack());
384 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
389 if (
auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
396 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
399 "Missing argument pack");
403 "Null template template argument");
404 UsedTemplateArgs.push_back(
407 return inherited::TraverseTemplateName(
Template);
410 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
412 for (
const auto &List : TemplateArgs)
413 for (
const TemplateArgument &Arg : List.Args)
419 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
421 for (
auto &ArgLoc : Mapping) {
422 TemplateArgument Canonical =
425 UsedTemplateArgs.push_back(Canonical);
426 TraverseTemplateArgument(Canonical);
429 for (
auto &
Used : UsedTemplateArgs) {
430 llvm::FoldingSetNodeID R;
437class ConstraintSatisfactionChecker {
440 SourceLocation TemplateNameLoc;
441 UnsignedOrNone PackSubstitutionIndex;
442 ConstraintSatisfaction &Satisfaction;
443 bool BuildExpression;
447 EvaluateAtomicConstraint(
const Expr *AtomicExpr,
448 const MultiLevelTemplateArgumentList &MLTAL);
450 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
451 const FoldExpandedConstraint &FE,
452 const MultiLevelTemplateArgumentList &MLTAL);
455 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
456 const NormalizedConstraintWithParamMapping &Constraint,
457 const MultiLevelTemplateArgumentList &MLTAL,
458 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
460 ExprResult EvaluateSlow(
const AtomicConstraint &Constraint,
461 const MultiLevelTemplateArgumentList &MLTAL);
464 const MultiLevelTemplateArgumentList &MLTAL);
466 ExprResult EvaluateSlow(
const FoldExpandedConstraint &Constraint,
467 const MultiLevelTemplateArgumentList &MLTAL);
470 const MultiLevelTemplateArgumentList &MLTAL);
472 ExprResult EvaluateSlow(
const ConceptIdConstraint &Constraint,
473 const MultiLevelTemplateArgumentList &MLTAL,
477 const MultiLevelTemplateArgumentList &MLTAL);
480 const MultiLevelTemplateArgumentList &MLTAL);
483 ConstraintSatisfactionChecker(Sema &SemaRef,
const NamedDecl *
Template,
484 SourceLocation TemplateNameLoc,
485 UnsignedOrNone PackSubstitutionIndex,
486 ConstraintSatisfaction &Satisfaction,
487 bool BuildExpression)
489 PackSubstitutionIndex(PackSubstitutionIndex),
490 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
493 const MultiLevelTemplateArgumentList &MLTAL);
496StringRef allocateStringFromConceptDiagnostic(
const Sema &S,
506ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
512 llvm::FoldingSetNodeID
ID;
515 Satisfaction.IsSatisfied =
false;
516 Satisfaction.ContainsErrors =
true;
519 SatisfactionStackRAII StackRAII(S,
Template, ID);
530 if (Inst.isInvalid())
535 SubstitutedExpression =
538 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
542 if (!Trap.hasErrorOccurred())
549 Info.takeSFINAEDiagnostic(SubstDiag);
556 Satisfaction.Details.emplace_back(
559 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
560 Satisfaction.IsSatisfied =
false;
581 SubstitutedExpression.
get(),
584 return SubstitutedExpression;
587std::optional<MultiLevelTemplateArgumentList>
588ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
594 return std::move(MLTAL);
607 if (Inst.isInvalid())
616 : PackSubstitutionIndex);
621 Satisfaction.IsSatisfied =
false;
629 TD->getLocation(), SubstArgs,
638 SubstitutedOutermost =
639 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
641 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
646 if (I < SubstitutedOutermost.size()) {
647 SubstitutedOutermost[I] = Arg;
650 SubstitutedOutermost.push_back(Arg);
651 Offset = SubstitutedOutermost.size();
654 if (Offset < SubstitutedOutermost.size())
655 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
660 return std::move(SubstitutedTemplateArgs);
663ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
668 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
669 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
670 if (!SubstitutedArgs) {
671 Satisfaction.IsSatisfied =
false;
676 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
682 if (SubstitutedAtomicExpr.
isUnset())
692 Satisfaction.IsSatisfied =
false;
693 Satisfaction.ContainsErrors =
true;
696 Satisfaction.Details.emplace_back(
698 SubstitutedAtomicExpr.get()->getBeginLoc(),
699 allocateStringFromConceptDiagnostic(S, Msg)});
700 return SubstitutedAtomicExpr;
704 Satisfaction.IsSatisfied =
true;
705 Satisfaction.ContainsErrors =
false;
706 return SubstitutedAtomicExpr;
713 EvalResult.
Diag = &EvaluationDiags;
716 !EvaluationDiags.empty()) {
720 diag::err_non_constant_constraint_expression)
723 S.
Diag(PDiag.first, PDiag.second);
728 "evaluating bool expression didn't produce int");
729 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
730 if (!Satisfaction.IsSatisfied)
731 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
733 return SubstitutedAtomicExpr;
736ExprResult ConstraintSatisfactionChecker::Evaluate(
740 unsigned Size = Satisfaction.Details.size();
741 llvm::FoldingSetNodeID
ID;
745 : PackSubstitutionIndex;
749 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
750 .VisitConstraint(Constraint);
754 auto &Cached = Iter->second.Satisfaction;
755 Satisfaction.ContainsErrors = Cached.ContainsErrors;
756 Satisfaction.IsSatisfied = Cached.IsSatisfied;
757 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
758 Cached.Details.begin(), Cached.Details.end());
759 return Iter->second.SubstExpr;
762 ExprResult E = EvaluateSlow(Constraint, MLTAL);
765 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
766 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
767 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
768 Satisfaction.Details.begin() + Size,
769 Satisfaction.Details.end());
777ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
788 assert(!Unexpanded.empty() &&
"Pack expansion without parameter packs?");
790 bool RetainExpansion =
false;
794 false, Expand, RetainExpansion,
796 !Expand || RetainExpansion)
799 if (NumExpansions && S.
getLangOpts().BracketDepth < *NumExpansions) {
801 clang::diag::err_fold_expression_limit_exceeded)
807 return NumExpansions;
810ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
816 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
821 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
822 SubstitutionInTemplateArguments(
824 MLTAL, SubstitutedOutermost);
825 if (!SubstitutedArgs) {
826 Satisfaction.IsSatisfied =
false;
832 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
836 if (*NumExpansions == 0) {
837 Satisfaction.IsSatisfied = Conjunction;
841 for (
unsigned I = 0; I < *NumExpansions; I++) {
843 Satisfaction.IsSatisfied =
false;
844 Satisfaction.ContainsErrors =
false;
846 ConstraintSatisfactionChecker(S,
Template, TemplateNameLoc,
850 if (BuildExpression &&
Expr.isUsable()) {
855 Conjunction ? BinaryOperatorKind::BO_LAnd
856 : BinaryOperatorKind::BO_LOr,
861 assert(!BuildExpression || !Satisfaction.IsSatisfied);
863 if (!Conjunction && Satisfaction.IsSatisfied) {
864 Satisfaction.Details.erase(Satisfaction.Details.begin() +
865 EffectiveDetailEndIndex,
866 Satisfaction.Details.end());
869 if (Satisfaction.IsSatisfied != Conjunction)
876ExprResult ConstraintSatisfactionChecker::Evaluate(
880 llvm::FoldingSetNodeID
ID;
882 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
887 auto &Cached = Iter->second.Satisfaction;
888 Satisfaction.ContainsErrors = Cached.ContainsErrors;
889 Satisfaction.IsSatisfied = Cached.IsSatisfied;
890 Satisfaction.Details.insert(Satisfaction.Details.end(),
891 Cached.Details.begin(), Cached.Details.end());
892 return Iter->second.SubstExpr;
895 unsigned Size = Satisfaction.Details.size();
897 ExprResult E = EvaluateSlow(Constraint, MLTAL);
899 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
900 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
901 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
902 Satisfaction.Details.begin() + Size,
903 Satisfaction.Details.end());
909ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
915 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
916 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
918 if (!SubstitutedArgs) {
919 Satisfaction.IsSatisfied =
false;
928 : PackSubstitutionIndex);
939 Trap.hasErrorOccurred()) {
940 Satisfaction.IsSatisfied =
false;
941 if (!Trap.hasErrorOccurred())
946 Info.takeSFINAEDiagnostic(SubstDiag);
953 Satisfaction.Details.insert(
954 Satisfaction.Details.begin() + Size,
957 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
969 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
972 if (Size != Satisfaction.Details.size()) {
973 Satisfaction.Details.insert(
974 Satisfaction.Details.begin() + Size,
979 return SubstitutedConceptId;
982ExprResult ConstraintSatisfactionChecker::Evaluate(
991 : PackSubstitutionIndex;
1005 if (InstTemplate.isInvalid())
1008 unsigned Size = Satisfaction.Details.size();
1013 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1020 if (Satisfaction.IsSatisfied)
1023 llvm::FoldingSetNodeID
ID;
1026 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1027 .VisitConstraint(Constraint);
1032 auto &Cached = Iter->second.Satisfaction;
1033 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1034 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1035 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1036 Cached.Details.begin(), Cached.Details.end());
1037 return Iter->second.SubstExpr;
1040 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1044 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1045 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1046 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
1047 Satisfaction.Details.begin() + Size,
1048 Satisfaction.Details.end());
1049 Cache.SubstExpr = CE;
1054ExprResult ConstraintSatisfactionChecker::Evaluate(
1058 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1065 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1068 if (!Conjunction && !LHS.
isInvalid() && Satisfaction.IsSatisfied &&
1069 !Satisfaction.ContainsErrors)
1072 Satisfaction.ContainsErrors =
false;
1073 Satisfaction.IsSatisfied =
false;
1077 if (!Conjunction && !RHS.
isInvalid() && Satisfaction.IsSatisfied &&
1078 !Satisfaction.ContainsErrors)
1079 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1080 EffectiveDetailEndIndex,
1081 Satisfaction.Details.end());
1083 if (!BuildExpression)
1093 Conjunction ? BinaryOperatorKind::BO_LAnd
1094 : BinaryOperatorKind::BO_LOr,
1099ExprResult ConstraintSatisfactionChecker::Evaluate(
1102 switch (Constraint.
getKind()) {
1117 llvm_unreachable(
"Unknown ConstraintKind enum");
1128 *ConvertedExpr =
nullptr;
1130 if (AssociatedConstraints.empty()) {
1145 std::optional<Sema::InstantiatingTemplate> SynthesisContext;
1146 if (!TopLevelConceptId) {
1147 SynthesisContext.emplace(S, TemplateIDRange.
getBegin(),
1160 if (TopLevelConceptId)
1166 ExprResult Res = ConstraintSatisfactionChecker(
1169 ConvertedExpr !=
nullptr)
1170 .Evaluate(*
C, TemplateArgsLists);
1175 if (Res.
isUsable() && ConvertedExpr)
1176 *ConvertedExpr = Res.
get();
1187 if (AssociatedConstraints.empty()) {
1193 return ::CheckConstraintSatisfaction(
1194 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1195 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1209 for (
auto List : TemplateArgsLists)
1211 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1214 if (TopLevelConceptId)
1217 llvm::FoldingSetNodeID ID;
1220 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1221 OutSatisfaction = *Cached;
1226 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1228 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1229 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1230 OutSatisfaction = std::move(*Satisfaction);
1234 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1243 OutSatisfaction = *Cached;
1248 OutSatisfaction = *Satisfaction;
1252 SatisfactionCache.InsertNode(Satisfaction.release());
1274 return !ArgLoc.getArgument().isDependent() &&
1275 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1277 return Concept->getConstraintExpr();
1300 Constraints.emplace_back(Res.
get());
1312bool Sema::SetupConstraintScope(
1317 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1321 InstantiatingTemplate Inst(
1326 if (Inst.isInvalid())
1337 if (addInstantiatedParametersToScope(
1346 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1356 FunctionDecl *InstantiatedFrom =
1363 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1364 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1366 if (Inst.isInvalid())
1371 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1380std::optional<MultiLevelTemplateArgumentList>
1381Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1384 MultiLevelTemplateArgumentList MLTAL;
1391 false, std::nullopt,
1398 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1399 return std::nullopt;
1407 bool ForOverloadResolution) {
1426 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1429 Satisfaction, UsageLoc,
1443 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1444 SetupConstraintCheckingTemplateArgumentsAndScope(
1452 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1453 ThisQuals =
Method->getMethodQualifiers();
1460 ForOverloadResolution);
1470 const Expr *ConstrExpr) {
1494 std::optional<LocalInstantiationScope> ScopeForParameters;
1497 ScopeForParameters.emplace(S,
true);
1501 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1503 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1505 if (!PVD->isParameterPack()) {
1506 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1525 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1526 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1530 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1539 std::optional<Sema::ContextRAII> ContextScope;
1547 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1559 return SubstConstr.
get();
1563 const Expr *OldConstr,
1565 const Expr *NewConstr) {
1566 if (OldConstr == NewConstr)
1569 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1571 if (
const Expr *SubstConstr =
1574 OldConstr = SubstConstr;
1577 if (
const Expr *SubstConstr =
1580 NewConstr = SubstConstr;
1585 llvm::FoldingSetNodeID ID1, ID2;
1598 "Non-function templates don't need to be checked");
1619 TemplateIDRange, Satisfaction))
1624 TemplateArgString =
" ";
1630 diag::err_template_arg_list_constraints_not_satisfied)
1632 << TemplateArgString << TemplateIDRange;
1644 Template->getAssociatedConstraints(TemplateAC);
1645 if (TemplateAC.empty()) {
1664 SemaRef, PointOfInstantiation,
1666 PointOfInstantiation);
1667 if (Inst.isInvalid())
1677 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1688 return ::CheckFunctionConstraintsWithoutInstantiation(
1689 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1690 TemplateArgs, Satisfaction);
1695 Template->getAssociatedConstraints(TemplateAC);
1696 if (TemplateAC.empty()) {
1706 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1707 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1715 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1716 ThisQuals =
Method->getMethodQualifiers();
1725 PointOfInstantiation, Satisfaction);
1732 "Diagnose() can only be used on an unsatisfied requirement");
1735 llvm_unreachable(
"Diagnosing a dependent requirement");
1739 if (!SubstDiag->DiagMessage.empty())
1740 S.
Diag(SubstDiag->DiagLoc,
1741 diag::note_expr_requirement_expr_substitution_error)
1742 << (
int)
First << SubstDiag->SubstitutedEntity
1743 << SubstDiag->DiagMessage;
1745 S.
Diag(SubstDiag->DiagLoc,
1746 diag::note_expr_requirement_expr_unknown_substitution_error)
1747 << (
int)
First << SubstDiag->SubstitutedEntity;
1757 if (!SubstDiag->DiagMessage.empty())
1758 S.
Diag(SubstDiag->DiagLoc,
1759 diag::note_expr_requirement_type_requirement_substitution_error)
1760 << (
int)
First << SubstDiag->SubstitutedEntity
1761 << SubstDiag->DiagMessage;
1766 note_expr_requirement_type_requirement_unknown_substitution_error)
1767 << (
int)
First << SubstDiag->SubstitutedEntity;
1777 llvm_unreachable(
"We checked this above");
1785 "Diagnose() can only be used on an unsatisfied requirement");
1788 llvm_unreachable(
"Diagnosing a dependent requirement");
1792 if (!SubstDiag->DiagMessage.empty())
1793 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1794 << (
int)
First << SubstDiag->SubstitutedEntity
1795 << SubstDiag->DiagMessage;
1797 S.
Diag(SubstDiag->DiagLoc,
1798 diag::note_type_requirement_unknown_substitution_error)
1799 << (
int)
First << SubstDiag->SubstitutedEntity;
1803 llvm_unreachable(
"Unknown satisfaction status");
1811 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1815 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1817 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1818 <<
Concept->getNamedConcept();
1820 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1850 const Expr *SubstExpr,
1853 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1854 switch (BO->getOpcode()) {
1866 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1877 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1889 if (BO->getLHS()->getType()->isIntegerType() &&
1890 BO->getRHS()->getType()->isIntegerType()) {
1893 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1896 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1899 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1901 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1914 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1917 if (!Req->isDependent() && !Req->isSatisfied()) {
1918 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1920 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
1928 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1932 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1933 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1934 assert(TTE->getNumArgs() == 2);
1936 diag::note_is_deducible_constraint_evaluated_to_false)
1937 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1942 diag::note_atomic_constraint_evaluated_to_false)
1952 .
template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1954 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
1957 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1961 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
1976 "Attempted to diagnose a satisfied constraint");
1987 "Attempted to diagnose a satisfied constraint");
1995class SubstituteParameterMappings {
2003 SubstituteParameterMappings(
Sema &SemaRef,
2007 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2008 InFoldExpr(InFoldExpr) {}
2017 SubstituteParameterMappings(
Sema &SemaRef,
bool InFoldExpr =
false)
2019 InFoldExpr(InFoldExpr) {}
2021 bool substitute(NormalizedConstraint &N);
2024void SubstituteParameterMappings::buildParameterMapping(
2029 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2030 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2036 0, OccurringIndices);
2040 0, OccurringIndicesForSubsumption);
2047 0, OccurringIndices);
2051 ->getTemplateArgsAsWritten();
2054 0, OccurringIndices);
2056 unsigned Size = OccurringIndices.count();
2064 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2066 ? ArgsAsWritten->arguments()[I].getLocation()
2070 if (OccurringIndices[I]) {
2074 UsedParams.push_back(Param);
2084 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2088bool SubstituteParameterMappings::substitute(
2091 buildParameterMapping(N);
2100 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2101 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2103 auto SR =
Arguments[0].getSourceRange();
2104 InstLocBegin = SR.getBegin();
2105 InstLocEnd = SR.getEnd();
2108 SemaRef, InstLocBegin,
2111 {InstLocBegin, InstLocEnd});
2112 if (Inst.isInvalid())
2128 TD->getLocation(), SubstArgs,
2139 if (I < SubstArgs.
size())
2140 Loc = SubstArgs.
arguments()[I].getLocation();
2167 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2168 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2170 auto SR =
Arguments[0].getSourceRange();
2171 InstLocBegin = SR.getBegin();
2172 InstLocEnd = SR.getEnd();
2176 SemaRef, InstLocBegin,
2179 {InstLocBegin, InstLocEnd});
2180 if (Inst.isInvalid())
2189 CSE->getTemplateArgsAsWritten();
2196 CSE->getConceptNameInfo().getLoc(), Out,
2201 auto TemplateArgs = *MLTAL;
2204 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2213 assert(!ArgsAsWritten);
2222 assert(!ArgsAsWritten);
2227 return SubstituteParameterMappings(SemaRef,
true)
2233 assert(ArgsAsWritten);
2234 return substitute(CC);
2236 assert(!ArgsAsWritten);
2246 return SubstituteParameterMappings(
2252 if (substitute(Compound.getLHS()))
2254 return substitute(Compound.getRHS());
2257 llvm_unreachable(
"Unknown ConstraintKind enum");
2264 assert(ACs.size() != 0);
2266 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2269 for (
unsigned I = 1; I < ACs.size(); ++I) {
2270 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2271 ACs[I].ArgPackSubstIndex);
2282 assert(E !=
nullptr);
2290 llvm::FoldingSetNodeID
ID;
2294 SatisfactionStackRAII StackRAII(S, D, ID);
2301 if (LogicalBinOp BO = E) {
2302 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2305 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2311 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2314 Sema::InstantiatingTemplate Inst(
2316 Sema::InstantiatingTemplate::ConstraintNormalization{},
2319 if (Inst.isInvalid())
2340 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2341 S, CD, AssociatedConstraint(Res.
get(), SubstIndex));
2351 }
else if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2353 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2354 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2359 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2363 if (FE->getInit()) {
2364 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2365 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2369 if (FE->isRightFold())
2382 auto *
Sub = fromConstraintExpr(S, D, FE->
getPattern(), SubstIndex);
2394 if (!ConstrainedDeclOrNestedReq) {
2395 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2396 *
this,
nullptr, AssociatedConstraints);
2398 SubstituteParameterMappings(*this).substitute(*Normalized))
2406 ConstrainedDeclOrNestedReq.dyn_cast<
const NamedDecl *>();
2407 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2408 if (CacheEntry == NormalizationCache.end()) {
2409 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2410 *
this, ND, AssociatedConstraints);
2412 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq,
nullptr);
2416 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2418 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2423 return CacheEntry->second;
2446 if (It != BPacks.end())
2458 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2464 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2465 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2466 "use non-instantiated function declaration for constraints partial "
2481 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2482 auto CacheEntry = SubsumptionCache.find(Key);
2483 if (CacheEntry != SubsumptionCache.end()) {
2484 Result = CacheEntry->second;
2491 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2492 if (Depth2 > Depth1) {
2493 AC1[I].ConstraintExpr =
2494 AdjustConstraintDepth(*
this, Depth2 - Depth1)
2495 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2497 }
else if (Depth1 > Depth2) {
2498 AC2[I].ConstraintExpr =
2499 AdjustConstraintDepth(*
this, Depth1 - Depth2)
2500 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2506 std::optional<bool> Subsumes = SC.
Subsumes(D1, AC1, D2, AC2);
2512 SubsumptionCache.try_emplace(Key, *Subsumes);
2523 if (AC1.empty() || AC2.empty())
2526 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2537 llvm::FoldingSetNodeID IDA, IDB;
2539 EB->Profile(IDB,
Context,
true);
2543 AmbiguousAtomic1 = EA;
2544 AmbiguousAtomic2 = EB;
2561 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2562 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2565 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2566 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2568 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2569 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2574 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2576 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2578 Diag(AmbiguousAtomic2->getBeginLoc(),
2579 diag::note_ambiguous_atomic_constraints_similar_expression)
2580 << AmbiguousAtomic2->getSourceRange();
2591 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2593uint16_t SubsumptionChecker::getNewLiteralId() {
2594 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2595 "too many constraints!");
2600 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2615 llvm::FoldingSetNodeID ID;
2616 ID.AddBoolean(Ori->hasParameterMapping());
2617 if (Ori->hasParameterMapping()) {
2618 const auto &Mapping = Ori->getParameterMapping();
2620 Ori->mappingOccurenceListForSubsumption();
2621 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2628 auto It = Elems.find(ID);
2629 if (It == Elems.end()) {
2632 MappedAtomicConstraint{
2633 Ori, {getNewLiteralId(), Literal::Atomic}}})
2635 ReverseMap[It->second.ID.Value] = Ori;
2637 return It->getSecond().ID;
2641 auto &Elems = FoldMap[Ori->getPattern()];
2643 FoldExpendedConstraintKey K;
2644 K.Kind = Ori->getFoldOperator();
2646 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2647 return K.Kind ==
Other.Kind;
2649 if (It == Elems.end()) {
2650 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2651 It = Elems.insert(Elems.end(), std::move(K));
2652 ReverseMap[It->ID.Value] = Ori;
2658 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2661 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2677template <
typename FormulaType>
2681 auto Add = [&,
this](Clause
C) {
2684 C.erase(llvm::unique(
C),
C.end());
2685 AddUniqueClauseToFormula(Res, std::move(
C));
2690 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2693 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2696 return Normalize<FormulaType>(
2697 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2700 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2702 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2703 Left = Normalize<FormulaType>(Compound.getLHS());
2704 Right = Normalize<FormulaType>(Compound.getRHS());
2707 if (Compound.getCompoundKind() == FormulaType::Kind) {
2708 unsigned SizeLeft =
Left.size();
2709 Res = std::move(Left);
2710 Res.reserve(SizeLeft +
Right.size());
2711 std::for_each(std::make_move_iterator(
Right.begin()),
2712 std::make_move_iterator(
Right.end()), Add);
2716 Res.reserve(
Left.size() *
Right.size());
2717 for (
const auto <ransform : Left) {
2718 for (
const auto &RTransform : Right) {
2720 Combined.reserve(LTransform.size() + RTransform.size());
2721 llvm::copy(LTransform, std::back_inserter(Combined));
2722 llvm::copy(RTransform, std::back_inserter(Combined));
2723 Add(std::move(Combined));
2729 llvm_unreachable(
"Unknown ConstraintKind enum");
2732void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2733 for (
auto &
Other : F) {
2734 if (llvm::equal(
C,
Other))
2744 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2746 return std::nullopt;
2749 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2751 return std::nullopt;
2753 return Subsumes(PNormalized, QNormalized);
2759 DNFFormula DNFP = DNF(*P);
2760 CNFFormula CNFQ = CNF(*Q);
2765 const CNFFormula &QCNF) {
2766 for (
const auto &Pi : PDNF) {
2767 for (
const auto &Qj : QCNF) {
2773 if (!DNFSubsumes(Pi, Qj))
2780bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2782 return llvm::any_of(P, [&](Literal LP) {
2783 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2789 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2792 auto It = FoldSubsumptionCache.find(Key);
2793 if (It == FoldSubsumptionCache.end()) {
2802 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2808 if (A.Kind != B.Kind)
2811 case Literal::Atomic:
2813 return A.Value == B.Value;
2815 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2816 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2817 case Literal::FoldExpanded:
2819 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2820 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2822 llvm_unreachable(
"unknown literal kind");
This file provides AST data structures related to concepts.
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 bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E)
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.
llvm::MachO::Records Records
llvm::MachO::Record Record
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 void diagnoseUnsatisfiedConstraintExpr(Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc, bool First, concepts::NestedRequirement *Req=nullptr)
static ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)
static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)
static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, const Expr *SubstExpr, bool First)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList *MLTAL=nullptr)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId=nullptr)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)
static bool CheckFunctionConstraintsWithoutInstantiation(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
llvm::StringRef backupStr(llvm::StringRef S) const
const Expr * getConstraintExpr() const
static AtomicConstraint * Create(ASTContext &Ctx, const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)
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.
Represents a C++ nested-name-specifier or a global scope specifier.
void Adopt(NestedNameSpecifierLoc Other)
Adopt an existing nested-name-specifier (with source-range information).
const NormalizedConstraint & getLHS() const
static CompoundConstraint * CreateConjunction(ASTContext &Ctx, NormalizedConstraint *LHS, NormalizedConstraint *RHS)
CompoundConstraintKind getCompoundKind() const
const NormalizedConstraint & getRHS() const
static CompoundConstraint * Create(ASTContext &Ctx, NormalizedConstraint *LHS, CompoundConstraintKind CCK, NormalizedConstraint *RHS)
Declaration of a C++20 concept.
ConceptDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
const NormalizedConstraint & getNormalizedConstraint() const
const ConceptSpecializationExpr * getConceptSpecializationExpr() const
static ConceptIdConstraint * Create(ASTContext &Ctx, const ConceptReference *ConceptId, NormalizedConstraint *SubConstraint, const NamedDecl *ConstraintDecl, const ConceptSpecializationExpr *CSE, UnsignedOrNone PackIndex)
const ConceptReference * getConceptId() const
A reference to a concept and its template args, as it appears in the code.
const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const
NamedDecl * getFoundDecl() const
const DeclarationNameInfo & getConceptNameInfo() const
SourceLocation getBeginLoc() const LLVM_READONLY
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
TemplateDecl * getNamedConcept() const
SourceLocation getTemplateKWLoc() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getExprLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptReference * getConceptReference() 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...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
llvm::SmallVector< UnsatisfiedConstraintRecord, 4 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
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 isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
const AssociatedConstraint & getTrailingRequiresClause() const
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 isValueDependent() const
Determines whether the value of this expression depends on.
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.
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.
static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)
FoldOperatorKind getFoldOperator() const
const Expr * getPattern() const
static FoldExpandedConstraint * Create(ASTContext &Ctx, const Expr *Pattern, const NamedDecl *ConstraintDecl, FoldOperatorKind OpKind, NormalizedConstraint *Constraint)
const NormalizedConstraint & getNormalizedPattern() const
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...
ArrayRef< ParmVarDecl * > parameters() const
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
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...
bool hasTemplateArgument(unsigned Depth, unsigned Index) const
Determine whether there is a non-NULL template argument at the given depth and index.
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level 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.
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
bool isAnyArgInstantiationDependent() const
This represents a decl that may have a name.
unsigned getPosition() const
Get the position of the template parameter within its parameter list.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getIndex() const
Get the index of the template parameter within its parameter list.
unsigned getDepth() const
Get the nesting depth of the template parameter.
UnsignedOrNone getPackSubstitutionIndex() const
const NamedDecl * getConstraintDecl() const
bool hasMatchingParameterMapping(ASTContext &C, const NormalizedConstraint &Other) const
const OccurenceList & mappingOccurenceList() const
const OccurenceList & mappingOccurenceListForSubsumption() const
TemplateParameterList * getUsedTemplateParamList() const
llvm::MutableArrayRef< TemplateArgumentLoc > getParameterMapping() const
bool hasParameterMapping() const
void updateParameterMapping(OccurenceList Indexes, OccurenceList IndexesForSubsumption, llvm::MutableArrayRef< TemplateArgumentLoc > Args, TemplateParameterList *ParamList)
A (possibly-)qualified type.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
Scope - A scope is a transient data structure that is used while parsing the program.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
RAII object used to change the argument pack substitution index within a Sema object.
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.
SourceLocation getLocation() const
const DeclContext * getDeclContext() const
const NamedDecl * getDecl() const
const DeclContext * getLexicalDeclContext() const
Sema - This implements semantic analysis and AST building for C.
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, NamedDecl *TemplateParam=nullptr)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
ExprResult SubstConceptTemplateArguments(const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, const MultiLevelTemplateArgumentList &MLTAL)
Substitute concept template arguments in the constraint expression of a concept-id.
llvm::DenseMap< llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult > UnsubstitutedConstraintSatisfactionCache
Cache the satisfaction of an atomic constraint.
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
void MarkUsedTemplateParametersForSubsumptionParameterMapping(const Expr *E, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are named in a given expression.
DiagnosticsEngine & getDiagnostics() const
void DiagnoseTypeTraitDetails(const Expr *E)
If E represents a built-in type trait, or a known standard type trait, try to print more information ...
ExprResult SubstConstraintExprWithoutSatisfaction(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
bool CheckConstraintExpression(const Expr *CE, Token NextToken=Token(), bool *PossibleNonPrimary=nullptr, bool IsTrailingRequiresClause=false)
Check whether the given expression is a valid constraint expression.
ASTContext & getASTContext() const
ExprResult CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs, bool DoCheckConstraintSatisfaction=true)
llvm::PointerUnion< const NamedDecl *, const concepts::NestedRequirement * > ConstrainedDeclOrNestedRequirement
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
bool CheckConstraintSatisfaction(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, const ConceptReference *TopLevelConceptId=nullptr, Expr **ConvertedExpr=nullptr)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
const NormalizedConstraint * getNormalizedAssociatedConstraints(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints)
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
void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)
Collect the set of unexpanded parameter packs within the given template argument.
TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const
Determines whether we are currently in a context where template argument substitution failures are no...
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, const DeclContext *DC=nullptr, bool Final=false, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false, bool ForDefaultArgumentSubstitution=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
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)
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
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...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
bool IsAtLeastAsConstrained(const NamedDecl *D1, MutableArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, MutableArrayRef< AssociatedConstraint > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes)
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(const NamedDecl *D1, ArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, ArrayRef< AssociatedConstraint > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions=true, bool *ConstraintsNotSatisfied=nullptr)
Check that the given template arguments can be provided to the given template, converting the argumen...
NamedDecl * getPack() const
Retrieve the parameter pack.
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
Expr * getReplacement() const
SubsumptionChecker establishes subsumption between two set of constraints.
std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)
SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})
llvm::function_ref< bool( const AtomicConstraint &, const AtomicConstraint &)> SubsumptionCallable
A convenient class for passing around template argument information.
ArrayRef< TemplateArgumentLoc > arguments() const
Location wrapper for a TemplateArgument.
Represents a template argument.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
bool containsUnexpandedParameterPack() const
Whether this template argument contains an unexpanded parameter pack.
@ Pack
The template argument is actually a parameter pack.
ArgKind getKind() const
Return the kind of stored template argument.
bool isPackExpansion() const
Determine whether this template argument is a pack expansion.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< AssociatedConstraint > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
bool isNull() const
Determine whether this template name is NULL.
Stores a list of template parameters for a TemplateDecl and its derived classes.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() 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
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
QualType getType() const
Get the type for which this source info wrapper provides information.
SourceLocation getNameLoc() const
void setNameLoc(SourceLocation Loc)
The base class of the type hierarchy.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
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 containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isFunctionType() 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
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
bool hasInvalidConstraint() const
Expr * getConstraintExpr() const
StringRef getInvalidConstraintEntity()
A static requirement that can be used in a requires-expression to check properties of types and expre...
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
Provides information about an attempted template argument deduction, whose success or failure was des...
__inline void unsigned int _2
uint32_t Literal
Literals are represented as positive integers.
bool Sub(InterpState &S, CodePtr OpPC)
bool Add(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
llvm::PointerUnion< const Expr *, const ConceptReference *, const ConstraintSubstitutionDiagnostic * > UnsatisfiedConstraintRecord
std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl *, const TemplateSpecializationType *, const SubstBuiltinTemplatePackType * >, SourceLocation > UnexpandedParameterPack
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
const FunctionProtoType * T
@ Template
We are parsing a template declaration.
@ Concept
The name was classified as a concept name.
std::pair< SourceLocation, StringRef > ConstraintSubstitutionDiagnostic
Unsatisfied constraint expressions if the template arguments could be substituted into them,...
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
@ Other
Other implicit parameter.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
ArrayRef< UnsatisfiedConstraintRecord > records() const
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
SourceLocation RAngleLoc
The source location of the right angle bracket ('>').
SourceLocation LAngleLoc
The source location of the left angle bracket ('<').
ArrayRef< TemplateArgumentLoc > arguments() const
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,...
NormalizedConstraint(const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)
SourceRange getSourceRange() const
ConstraintKind getKind() const
SourceLocation getBeginLoc() const
llvm::SmallBitVector OccurenceList
SmallVector< TemplateArgument, 4 > SugaredConverted
The checked, converted argument will be added to the end of these vectors.
A stack object to be created when performing template instantiation.
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
constexpr unsigned toInternalRepresentation() const