30#include "llvm/ADT/DenseMap.h"
31#include "llvm/ADT/PointerUnion.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/Support/SaveAndRestore.h"
34#include "llvm/Support/ScopedPrinter.h"
35#include "llvm/Support/TimeProfiler.h"
44 const Expr *LHS =
nullptr;
45 const Expr *RHS =
nullptr;
48 LogicalBinOp(
const Expr *E) {
49 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
53 Loc = BO->getExprLoc();
54 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
56 if (OO->getNumArgs() == 2) {
57 Op = OO->getOperator();
60 Loc = OO->getOperatorLoc();
65 bool isAnd()
const {
return Op == OO_AmpAmp; }
66 bool isOr()
const {
return Op == OO_PipePipe; }
67 explicit operator bool()
const {
return isAnd() || isOr(); }
69 const Expr *getLHS()
const {
return LHS; }
70 const Expr *getRHS()
const {
return RHS; }
74 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
79 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
80 assert((!LHS.isInvalid() && !RHS.isInvalid()) &&
"not good expressions?");
82 if (!LHS.isUsable() || !RHS.isUsable())
96 Token NextToken,
bool *PossibleNonPrimary,
97 bool IsTrailingRequiresClause) {
103 if (LogicalBinOp BO = ConstraintExpression) {
105 PossibleNonPrimary) &&
108 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
114 auto CheckForNonPrimary = [&] {
115 if (!PossibleNonPrimary)
118 *PossibleNonPrimary =
129 (NextToken.
is(tok::l_paren) &&
130 (IsTrailingRequiresClause ||
148 CheckForNonPrimary();
154 diag::err_non_bool_atomic_constraint)
156 CheckForNonPrimary();
160 if (PossibleNonPrimary)
161 *PossibleNonPrimary =
false;
166struct SatisfactionStackRAII {
168 bool Inserted =
false;
170 const llvm::FoldingSetNodeID &FSNID)
177 ~SatisfactionStackRAII() {
189 for (
const auto &List : *MLTAL)
207 bool SkipForSpecialization =
false) {
213 true, SkipForSpecialization);
218class AdjustConstraints :
public TreeTransform<AdjustConstraints> {
219 unsigned TemplateDepth = 0;
221 bool RemoveNonPackExpansionPacks =
false;
224 using inherited = TreeTransform<AdjustConstraints>;
225 AdjustConstraints(Sema &SemaRef,
unsigned TemplateDepth,
226 bool RemoveNonPackExpansionPacks =
false)
227 : inherited(SemaRef), TemplateDepth(TemplateDepth),
228 RemoveNonPackExpansionPacks(RemoveNonPackExpansionPacks) {}
230 ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
232 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc, NumExpansions);
235 TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
236 SourceLocation EllipsisLoc,
238 if (!RemoveNonPackExpansionPacks)
239 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc,
245 TemplateArgumentLoc &Out, UnexpandedInfo &Info) {
246 if (!RemoveNonPackExpansionPacks)
247 return inherited::PreparePackForExpansion(In, Uneval, Out, Info);
248 assert(
In.getArgument().isPackExpansion());
254 using inherited::TransformTemplateTypeParmType;
255 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
256 TemplateTypeParmTypeLoc TL,
bool) {
259 TemplateTypeParmDecl *NewTTPDecl =
nullptr;
260 if (TemplateTypeParmDecl *OldTTPDecl =
T->getDecl())
261 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
264 QualType
Result = getSema().Context.getTemplateTypeParmType(
265 T->getDepth() + TemplateDepth,
T->getIndex(),
266 RemoveNonPackExpansionPacks ?
false :
T->isParameterPack(), NewTTPDecl);
267 TemplateTypeParmTypeLoc NewTL = TLB.
push<TemplateTypeParmTypeLoc>(
Result);
272 QualType TransformPackIndexingType(TypeLocBuilder &TLB,
273 PackIndexingTypeLoc TL) {
274 llvm::SaveAndRestore _1(RemoveNonPackExpansionPacks,
false);
275 return inherited::TransformPackIndexingType(TLB, TL);
278 bool AlreadyTransformed(QualType
T) {
288 ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
289 NonTypeTemplateParmDecl *NTTP =
290 dyn_cast<NonTypeTemplateParmDecl>(E->
getDecl());
292 return inherited::TransformDeclRefExpr(E);
295 "Template arguments for NTTP decl?");
311 RemoveNonPackExpansionPacks ? NTTP : D,
321 using inherited = RecursiveASTVisitor<HashParameterMapping>;
325 const MultiLevelTemplateArgumentList &TemplateArgs;
326 llvm::FoldingSetNodeID &
ID;
327 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
331 bool shouldVisitTemplateInstantiations()
const {
return true; }
334 HashParameterMapping(Sema &SemaRef,
335 const MultiLevelTemplateArgumentList &TemplateArgs,
336 llvm::FoldingSetNodeID &ID,
338 : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
ID(
ID),
339 OuterPackSubstIndex(OuterPackSubstIndex) {}
341 bool VisitTemplateTypeParmType(TemplateTypeParmType *
T) {
352 TemplateArgument Arg = TemplateArgs(
T->getDepth(),
T->getIndex());
358 if ((
T->isParameterPack() ||
359 (
T->getDecl() &&
T->getDecl()->isTemplateParameterPack())) &&
362 "Missing argument pack");
367 UsedTemplateArgs.push_back(
372 bool VisitDeclRefExpr(DeclRefExpr *E) {
374 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
376 return TraverseDecl(D);
394 "Missing argument pack");
398 UsedTemplateArgs.push_back(
403 bool VisitTypedefType(TypedefType *TT) {
404 return inherited::TraverseType(TT->
desugar());
407 bool TraverseDecl(Decl *D) {
408 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
409 if (
auto *Var = dyn_cast<VarDecl>(VD))
410 TraverseStmt(Var->getInit());
411 return TraverseType(VD->getType());
414 return inherited::TraverseDecl(D);
417 bool TraverseCallExpr(CallExpr *CE) {
418 inherited::TraverseStmt(CE->
getCallee());
421 inherited::TraverseStmt(Arg);
426 bool TraverseCXXThisExpr(CXXThisExpr *E) {
427 return inherited::TraverseType(E->
getType());
430 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
435 bool TraverseDependentNameType(
const DependentNameType *
T,
437 return TraverseNestedNameSpecifier(
T->getQualifier());
440 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
448 bool TraverseUnresolvedUsingType(UnresolvedUsingType *
T,
449 bool TraverseQualifier) {
452 if (NestedNameSpecifier NNS =
T->getDecl()->getQualifier();
453 TraverseQualifier && NNS)
454 return inherited::TraverseNestedNameSpecifier(NNS);
455 return inherited::TraverseUnresolvedUsingType(
T, TraverseQualifier);
458 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
459 bool TraverseQualifier) {
460 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
463 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
466 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
467 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
469 return inherited::TraverseTemplateArgument(Arg);
472 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
473 return inherited::TraverseTemplateArgument(Arg);
476 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
477 return TraverseDecl(SOPE->
getPack());
480 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
485 bool TraverseQualifier =
true) {
486 if (
auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
493 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
496 "Missing argument pack");
500 "Null template template argument");
501 UsedTemplateArgs.push_back(
504 return inherited::TraverseTemplateName(
Template, TraverseQualifier);
507 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
508 switch (Constraint.
getKind()) {
509 case NormalizedConstraint::ConstraintKind::Atomic:
510 ID.AddPointer(
static_cast<const AtomicConstraint &
>(Constraint)
511 .getConstraintExpr());
514 case NormalizedConstraint::ConstraintKind::ConceptId:
516 static_cast<const ConceptIdConstraint &
>(Constraint).getConceptId());
519 case NormalizedConstraint::ConstraintKind::FoldExpanded:
521 static_cast<const FoldExpandedConstraint &
>(Constraint).getPattern());
523 case NormalizedConstraint::ConstraintKind::Compound:
524 llvm_unreachable(
"Cannot hash a compound constraint");
528 for (
const auto &List : TemplateArgs)
529 for (
const TemplateArgument &Arg : List.Args)
535 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
537 for (
auto &ArgLoc : Mapping) {
538 TemplateArgument Canonical =
541 UsedTemplateArgs.push_back(Canonical);
542 TraverseTemplateArgument(Canonical);
545 for (
auto &
Used : UsedTemplateArgs) {
546 llvm::FoldingSetNodeID
R;
553class ConstraintSatisfactionChecker {
556 const ConceptReference *TopLevelConceptId;
557 SourceLocation TemplateNameLoc;
559 ConstraintSatisfaction &Satisfaction;
560 bool BuildExpression;
563 ConceptDecl *ParentConcept =
nullptr;
567 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
571 struct ParameterMappingInstantiationCache {
572 llvm::FoldingSetNodeID
ID;
573 ConstraintSatisfactionChecker &Checker;
574 HashParameterMapping H;
575 unsigned PreviousDetailsSize;
577 ParameterMappingInstantiationCache(
578 ConstraintSatisfactionChecker &Checker,
579 const NormalizedConstraintWithParamMapping &Constraint,
582 : Checker(Checker), H(Checker.S, MLTAL,
ID,
PackIndex),
583 PreviousDetailsSize(PreviousDetailsSize
584 ? *PreviousDetailsSize
585 : Checker.Satisfaction.Details.size()) {
586 H.VisitConstraint(Constraint);
589 const UnsubstitutedConstraintSatisfactionCacheResult *available() {
591 auto Iter =
Cache.find(ID);
592 if (Iter ==
Cache.end())
594 auto &Satisfaction = Checker.Satisfaction;
595 auto &Cached = Iter->second.Satisfaction;
600 Cached.Details.begin(), Cached.Details.end());
601 return &Iter->second;
605 UnsubstitutedConstraintSatisfactionCacheResult
Cache;
606 auto &Satisfaction = Checker.Satisfaction;
609 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
621 template <
class Constra
int>
623 return C.getPackSubstitutionIndex() ?
C.getPackSubstitutionIndex()
624 : PackSubstitutionIndex;
627 StringRef allocateStringFromConceptDiagnostic(
const PartialDiagnostic &
Diag) {
628 SmallString<128> DiagString;
634 void consumeSFINAEFailure(TemplateDeductionInfo &Info,
635 ConstraintSatisfaction &Satisfaction) {
637 PartialDiagnostic::NullDiagnostic()};
645 Satisfaction.
Details.emplace_back(
648 allocateStringFromConceptDiagnostic(SubstDiag.second)});
652 EvaluateAtomicConstraint(
const Expr *AtomicExpr,
653 const MultiLevelTemplateArgumentList &MLTAL);
656 const FoldExpandedConstraint &FE,
657 const MultiLevelTemplateArgumentList &MLTAL);
660 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
661 const NormalizedConstraintWithParamMapping &Constraint,
662 const MultiLevelTemplateArgumentList &MLTAL,
663 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
665 ExprResult EvaluateSlow(
const AtomicConstraint &Constraint,
666 const MultiLevelTemplateArgumentList &MLTAL);
669 const MultiLevelTemplateArgumentList &MLTAL);
671 ExprResult EvaluateSlow(
const FoldExpandedConstraint &Constraint,
672 const MultiLevelTemplateArgumentList &MLTAL);
675 const MultiLevelTemplateArgumentList &MLTAL);
677 ExprResult EvaluateSlow(
const ConceptIdConstraint &Constraint,
678 const MultiLevelTemplateArgumentList &MLTAL,
682 const MultiLevelTemplateArgumentList &MLTAL);
685 const MultiLevelTemplateArgumentList &MLTAL);
688 ConstraintSatisfactionChecker(Sema &SemaRef,
const NamedDecl *
Template,
689 const ConceptReference *TopLevelConceptId,
690 SourceLocation TemplateNameLoc,
692 ConstraintSatisfaction &Satisfaction,
693 bool BuildExpression)
695 TemplateNameLoc(TemplateNameLoc),
696 PackSubstitutionIndex(PackSubstitutionIndex),
697 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
700 const MultiLevelTemplateArgumentList &MLTAL);
705ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
707 llvm::FoldingSetNodeID
ID;
714 SatisfactionStackRAII StackRAII(S,
Template, ID);
725 if (Inst.isInvalid())
730 SubstitutedExpression =
733 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
737 if (!Trap.hasErrorOccurred())
741 consumeSFINAEFailure(Info, Satisfaction);
762 SubstitutedExpression.
get(),
765 return SubstitutedExpression;
768std::optional<MultiLevelTemplateArgumentList>
769ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
792 if (Inst.isInvalid())
799 &CachedTemplateArgs);
807 if (Trap.hasErrorOccurred())
808 consumeSFINAEFailure(Info, Satisfaction);
816 TD->getLocation(), SubstArgs,
825 SubstitutedOutermost =
826 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
828 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
833 if (I < SubstitutedOutermost.size()) {
834 SubstitutedOutermost[I] = Arg;
837 SubstitutedOutermost.push_back(Arg);
838 Offset = SubstitutedOutermost.size();
841 if (Offset < SubstitutedOutermost.size())
842 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
847 return std::move(SubstitutedTemplateArgs);
850ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
853 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
857 EvaluationContext.emplace(
860 EvaluationContext.emplace(
865 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
866 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
867 if (!SubstitutedArgs) {
875 std::optional<Sema::ContextRAII> ConceptContext;
880 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
886 if (SubstitutedAtomicExpr.
isUnset())
900 Satisfaction.
Details.emplace_back(
902 SubstitutedAtomicExpr.get()->getBeginLoc(),
903 allocateStringFromConceptDiagnostic(Msg)});
904 return SubstitutedAtomicExpr;
910 return SubstitutedAtomicExpr;
915 EvalResult.
Diag = &EvaluationDiags;
918 !EvaluationDiags.empty()) {
922 diag::err_non_constant_constraint_expression)
925 S.
Diag(PDiag.first, PDiag.second);
930 "evaluating bool expression didn't produce int");
933 Satisfaction.
Details.emplace_back(SubstitutedAtomicExpr.
get());
935 return SubstitutedAtomicExpr;
938ExprResult ConstraintSatisfactionChecker::Evaluate(
942 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
943 getOuterPackIndex(Constraint));
945 if (
auto *
V = PMCache.available())
948 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
952ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
960 assert(!Unexpanded.empty() &&
"Pack expansion without parameter packs?");
962 bool RetainExpansion =
false;
966 false, Expand, RetainExpansion,
967 NumExpansions,
false) ||
968 !Expand || RetainExpansion)
971 if (NumExpansions && S.
getLangOpts().BracketDepth < *NumExpansions)
973 return NumExpansions;
976ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
982 unsigned EffectiveDetailEndIndex = Satisfaction.
Details.size();
987 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
988 SubstitutionInTemplateArguments(
990 MLTAL, SubstitutedOutermost);
991 if (!SubstitutedArgs) {
998 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
1002 if (*NumExpansions == 0) {
1007 for (
unsigned I = 0; I < *NumExpansions; I++) {
1012 ConstraintSatisfactionChecker(S,
Template, TopLevelConceptId,
1017 if (BuildExpression) {
1018 if (
Out.isUnset() || !
Expr.isUsable())
1022 Conjunction ? BinaryOperatorKind::BO_LAnd
1023 : BinaryOperatorKind::BO_LOr,
1030 EffectiveDetailEndIndex,
1041ExprResult ConstraintSatisfactionChecker::Evaluate(
1045 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
1048 if (
auto *
V = PMCache.available())
1049 return V->SubstExpr;
1051 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
1054ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1060 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1061 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1063 if (!SubstitutedArgs) {
1082 if (TopLevelConceptId &&
1086 OutArgs.addArgument(A);
1089 Trap.hasErrorOccurred()) {
1091 if (Trap.hasErrorOccurred())
1092 consumeSFINAEFailure(Info, Satisfaction);
1105 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
1108 if (Size != Satisfaction.
Details.size()) {
1110 Satisfaction.
Details.begin() + Size,
1115 return SubstitutedConceptId;
1118ExprResult ConstraintSatisfactionChecker::Evaluate(
1135 if (InstTemplate.isInvalid())
1147 Satisfaction.
Details.insert(Satisfaction.
Details.begin() + Size, ConceptId);
1157 ParameterMappingInstantiationCache PMCache(
1158 *
this, Constraint, MLTAL, getOuterPackIndex(Constraint), Size);
1160 if (
auto *
V = PMCache.available())
1161 return V->SubstExpr;
1163 return PMCache.cache(EvaluateSlow(Constraint, MLTAL, Size));
1166ExprResult ConstraintSatisfactionChecker::Evaluate(
1170 unsigned EffectiveDetailEndIndex = Satisfaction.
Details.size();
1192 EffectiveDetailEndIndex,
1195 if (!BuildExpression)
1205 Conjunction ? BinaryOperatorKind::BO_LAnd
1206 : BinaryOperatorKind::BO_LOr,
1211ExprResult ConstraintSatisfactionChecker::Evaluate(
1214 switch (Constraint.
getKind()) {
1229 llvm_unreachable(
"Unknown ConstraintKind enum");
1240 *ConvertedExpr =
nullptr;
1242 if (AssociatedConstraints.empty()) {
1262 struct SynthesisContextPair {
1268 : Inst(S, InstantiationRange.
getBegin(),
1270 TemplateArgs, InstantiationRange),
1273 std::optional<SynthesisContextPair> SynthesisContext;
1274 if (!TopLevelConceptId)
1285 if (TopLevelConceptId)
1292 ConstraintSatisfactionChecker(
1295 ConvertedExpr !=
nullptr)
1296 .Evaluate(*
C, TemplateArgsLists);
1298 if (Res.
isUsable() && ConvertedExpr)
1299 *ConvertedExpr = Res.
get();
1310 llvm::TimeTraceScope TimeScope(
1311 "CheckConstraintSatisfaction", [TemplateIDRange,
this] {
1314 if (AssociatedConstraints.empty()) {
1320 return ::CheckConstraintSatisfaction(
1321 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1322 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1336 for (
auto List : TemplateArgsLists)
1338 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1341 if (TopLevelConceptId)
1344 llvm::FoldingSetNodeID ID;
1346 llvm::FoldingSetInsertToken
Token;
1347 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1348 OutSatisfaction = *Cached;
1353 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1355 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1356 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1357 OutSatisfaction = std::move(*Satisfaction);
1361 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1370 OutSatisfaction = *Cached;
1375 OutSatisfaction = *Satisfaction;
1377 SatisfactionCache.insert(Satisfaction.release());
1399 return !ArgLoc.getArgument().isDependent() &&
1400 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1402 return Concept->getConstraintExpr();
1415bool Sema::SetupConstraintScope(
1420 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1426 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1427 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1429 if (Inst.isInvalid())
1438 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1440 if (addInstantiatedParametersToScope(
1447 if (FunctionTemplateDecl *FromMemTempl =
1449 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1459 FunctionDecl *InstantiatedFrom =
1466 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1467 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1469 if (Inst.isInvalid())
1474 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1483std::optional<MultiLevelTemplateArgumentList>
1484Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1487 MultiLevelTemplateArgumentList MLTAL;
1494 false, std::nullopt,
1501 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1502 return std::nullopt;
1510 bool ForOverloadResolution) {
1529 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1532 Satisfaction, UsageLoc,
1546 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1547 SetupConstraintCheckingTemplateArgumentsAndScope(
1555 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1556 ThisQuals =
Method->getMethodQualifiers();
1563 ForOverloadResolution);
1573 const Expr *ConstrExpr) {
1588 std::optional<LocalInstantiationScope> ScopeForParameters;
1591 ScopeForParameters.emplace(S,
true);
1595 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1597 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1599 if (!PVD->isParameterPack()) {
1600 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1619 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1620 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1624 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1633 std::optional<Sema::ContextRAII> ContextScope;
1641 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1653 return SubstConstr.
get();
1657 const Expr *OldConstr,
1659 const Expr *NewConstr) {
1660 if (OldConstr == NewConstr)
1663 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1666 if (
const Expr *SubstConstr =
1669 OldConstr = SubstConstr;
1672 if (
const Expr *SubstConstr =
1675 NewConstr = SubstConstr;
1680 llvm::FoldingSetNodeID ID1, ID2;
1693 "Non-function templates don't need to be checked");
1714 TemplateIDRange, Satisfaction) ||
1717 TemplateArgString =
" ";
1723 diag::err_template_arg_list_constraints_not_satisfied)
1725 << TemplateArgString << TemplateIDRange;
1737 Template->getAssociatedConstraints(TemplateAC);
1738 if (TemplateAC.empty()) {
1757 SemaRef, PointOfInstantiation,
1759 PointOfInstantiation);
1760 if (Inst.isInvalid())
1770 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1781 return ::CheckFunctionConstraintsWithoutInstantiation(
1782 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1783 TemplateArgs, Satisfaction);
1788 Template->getAssociatedConstraints(TemplateAC);
1789 if (TemplateAC.empty()) {
1799 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1800 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1808 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1809 ThisQuals =
Method->getMethodQualifiers();
1818 PointOfInstantiation, Satisfaction);
1825 "Diagnose() can only be used on an unsatisfied requirement");
1828 llvm_unreachable(
"Diagnosing a dependent requirement");
1832 if (!SubstDiag->DiagMessage.empty())
1833 S.
Diag(SubstDiag->DiagLoc,
1834 diag::note_expr_requirement_expr_substitution_error)
1835 << (
int)
First << SubstDiag->SubstitutedEntity
1836 << SubstDiag->DiagMessage;
1838 S.
Diag(SubstDiag->DiagLoc,
1839 diag::note_expr_requirement_expr_unknown_substitution_error)
1840 << (
int)
First << SubstDiag->SubstitutedEntity;
1850 if (!SubstDiag->DiagMessage.empty())
1851 S.
Diag(SubstDiag->DiagLoc,
1852 diag::note_expr_requirement_type_requirement_substitution_error)
1853 << (
int)
First << SubstDiag->SubstitutedEntity
1854 << SubstDiag->DiagMessage;
1859 note_expr_requirement_type_requirement_unknown_substitution_error)
1860 << (
int)
First << SubstDiag->SubstitutedEntity;
1870 llvm_unreachable(
"We checked this above");
1878 "Diagnose() can only be used on an unsatisfied requirement");
1881 llvm_unreachable(
"Diagnosing a dependent requirement");
1885 if (!SubstDiag->DiagMessage.empty())
1886 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1887 << (
int)
First << SubstDiag->SubstitutedEntity
1888 << SubstDiag->DiagMessage;
1890 S.
Diag(SubstDiag->DiagLoc,
1891 diag::note_type_requirement_unknown_substitution_error)
1892 << (
int)
First << SubstDiag->SubstitutedEntity;
1896 llvm_unreachable(
"Unknown satisfaction status");
1904 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1908 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1910 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1911 <<
Concept->getNamedConcept().getAsTemplateDecl();
1913 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1943 const Expr *SubstExpr,
1946 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1947 switch (BO->getOpcode()) {
1959 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1970 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1982 if (BO->getLHS()->getType()->isIntegerType() &&
1983 BO->getRHS()->getType()->isIntegerType()) {
1986 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1989 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1992 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1994 diag::note_atomic_constraint_evaluated_to_false_elaborated)
2007 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
2010 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
2014 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
2015 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
2016 assert(TTE->getNumArgs() == 2);
2018 diag::note_is_deducible_constraint_evaluated_to_false)
2019 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2024 diag::note_atomic_constraint_evaluated_to_false)
2034 .
template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
2036 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
2039 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2043 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
2056 if (!Req->isDependent() && !Req->isSatisfied()) {
2057 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2059 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
2073 "Attempted to diagnose a satisfied constraint");
2084 "Attempted to diagnose a satisfied constraint");
2092class SubstituteParameterMappings {
2104 bool RemovePacksForFoldExpr;
2106 SubstituteParameterMappings(
Sema &SemaRef,
2109 bool RemovePacksForFoldExpr)
2110 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2111 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2120 SubstituteParameterMappings(
Sema &SemaRef,
2121 bool RemovePacksForFoldExpr =
false)
2123 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2125 bool substitute(NormalizedConstraint &N);
2128void SubstituteParameterMappings::buildParameterMapping(
2133 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2134 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2140 0, OccurringIndices);
2144 0, OccurringIndicesForSubsumption);
2151 0, OccurringIndices);
2155 ->getTemplateArgsAsWritten();
2158 0, OccurringIndices);
2166 I < TemplateParams->size(); ++I) {
2172 assert(Arg &&
"expected a default argument");
2173 DefaultArgs.emplace_back(std::move(*Arg));
2176 0, OccurringIndices);
2179 OccurringIndicesForSubsumption);
2182 unsigned Size = OccurringIndices.count();
2190 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2192 ? ArgsAsWritten->arguments()[I].getLocation()
2196 if (OccurringIndices[I]) {
2200 UsedParams.push_back(Param);
2210 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2214bool SubstituteParameterMappings::substitute(
2217 buildParameterMapping(N);
2226 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2227 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2229 auto SR =
Arguments[0].getSourceRange();
2230 InstLocBegin = SR.getBegin();
2231 InstLocEnd = SR.getEnd();
2235 SemaRef, InstLocBegin,
2238 {InstLocBegin, InstLocEnd});
2239 if (Inst.isInvalid())
2256 TD->getLocation(), SubstArgs,
2267 if (I < SubstArgs.
size())
2268 Loc = SubstArgs.
arguments()[I].getLocation();
2295 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2296 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2298 auto SR =
Arguments[0].getSourceRange();
2299 InstLocBegin = SR.getBegin();
2300 InstLocEnd = SR.getEnd();
2305 SemaRef, InstLocBegin,
2308 {InstLocBegin, InstLocEnd});
2309 if (Inst.isInvalid())
2320 CSE->getTemplateArgsAsWritten();
2326 CSE->getConceptNameInfo().getLoc(), Out,
2331 auto TemplateArgs = *MLTAL;
2334 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2335 RemovePacksForFoldExpr)
2343 assert(!ArgsAsWritten);
2352 assert(!ArgsAsWritten);
2357 return SubstituteParameterMappings(SemaRef,
true)
2363 assert(ArgsAsWritten);
2364 return substitute(CC);
2366 assert(!ArgsAsWritten);
2378 if (RemovePacksForFoldExpr) {
2382 if (AdjustConstraints(SemaRef, 0,
2384 .TransformTemplateArguments(InputArgLoc.begin(),
2385 InputArgLoc.end(), OutArgs))
2406 return SubstituteParameterMappings(SemaRef, &MLTAL,
2408 RemovePacksForFoldExpr)
2413 if (substitute(Compound.getLHS()))
2415 return substitute(Compound.getRHS());
2418 llvm_unreachable(
"Unknown ConstraintKind enum");
2425 assert(ACs.size() != 0);
2427 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2430 for (
unsigned I = 1; I < ACs.size(); ++I) {
2431 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2432 ACs[I].ArgPackSubstIndex);
2443 assert(E !=
nullptr);
2451 llvm::FoldingSetNodeID
ID;
2455 SatisfactionStackRAII StackRAII(S, D, ID);
2462 if (LogicalBinOp BO = E) {
2463 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2466 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2473 if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2489 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2491 AssociatedConstraint(Res.get(), SubstIndex));
2498 if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2500 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2501 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2506 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2510 if (FE->getInit()) {
2511 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2512 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2516 if (FE->isRightFold())
2529 auto *
Sub = fromConstraintExpr(S, D, FE->
getPattern(), SubstIndex);
2541 if (!ConstrainedDeclOrNestedReq) {
2542 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2543 *
this,
nullptr, AssociatedConstraints);
2545 SubstituteParameterMappings(*this).substitute(*Normalized))
2553 ConstrainedDeclOrNestedReq.dyn_cast<
const NamedDecl *>();
2554 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2555 if (CacheEntry == NormalizationCache.end()) {
2556 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2557 *
this, ND, AssociatedConstraints);
2559 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq,
nullptr);
2563 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2565 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2570 return CacheEntry->second;
2593 if (It != BPacks.end())
2605 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2611 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2612 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2613 "use non-instantiated function declaration for constraints partial "
2628 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2629 auto CacheEntry = SubsumptionCache.find(Key);
2630 if (CacheEntry != SubsumptionCache.end()) {
2631 Result = CacheEntry->second;
2638 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2639 if (Depth2 > Depth1) {
2640 AC1[I].ConstraintExpr =
2641 AdjustConstraints(*
this, Depth2 - Depth1)
2642 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2644 }
else if (Depth1 > Depth2) {
2645 AC2[I].ConstraintExpr =
2646 AdjustConstraints(*
this, Depth1 - Depth2)
2647 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2656 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2657 if (Depth2 > Depth1)
2659 else if (Depth1 > Depth2)
2661 std::optional<bool> Subsumes = SC.
Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2667 SubsumptionCache.try_emplace(Key, *Subsumes);
2678 if (AC1.empty() || AC2.empty())
2681 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2692 llvm::FoldingSetNodeID IDA, IDB;
2694 EB->Profile(IDB,
Context,
true);
2698 AmbiguousAtomic1 = EA;
2699 AmbiguousAtomic2 = EB;
2714 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2715 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2718 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2719 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2721 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2722 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2727 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2729 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2731 Diag(AmbiguousAtomic2->getBeginLoc(),
2732 diag::note_ambiguous_atomic_constraints_similar_expression)
2733 << AmbiguousAtomic2->getSourceRange();
2744 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2746uint16_t SubsumptionChecker::getNewLiteralId() {
2747 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2748 "too many constraints!");
2753 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2768 llvm::FoldingSetNodeID ID;
2769 ID.AddBoolean(Ori->hasParameterMapping());
2770 if (Ori->hasParameterMapping()) {
2771 const auto &Mapping = Ori->getParameterMapping();
2773 Ori->mappingOccurenceListForSubsumption();
2774 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2781 auto It = Elems.find(ID);
2782 if (It == Elems.end()) {
2785 MappedAtomicConstraint{
2786 Ori, {getNewLiteralId(), Literal::Atomic}}})
2788 ReverseMap[It->second.ID.Value] = Ori;
2790 return It->getSecond().ID;
2794 auto &Elems = FoldMap[Ori->getPattern()];
2796 FoldExpendedConstraintKey K;
2797 K.Kind = Ori->getFoldOperator();
2799 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2800 return K.Kind ==
Other.Kind;
2802 if (It == Elems.end()) {
2803 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2804 It = Elems.insert(Elems.end(), std::move(K));
2805 ReverseMap[It->ID.Value] = Ori;
2811 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2814 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2830template <
typename FormulaType>
2834 auto Add = [&,
this](Clause
C) {
2837 C.erase(llvm::unique(
C),
C.end());
2838 AddUniqueClauseToFormula(Res, std::move(
C));
2843 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2846 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2849 return Normalize<FormulaType>(
2850 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2853 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2855 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2856 Left = Normalize<FormulaType>(Compound.getLHS());
2857 Right = Normalize<FormulaType>(Compound.getRHS());
2860 if (Compound.getCompoundKind() == FormulaType::Kind) {
2861 unsigned SizeLeft =
Left.size();
2862 Res = std::move(Left);
2863 Res.reserve(SizeLeft +
Right.size());
2864 std::for_each(std::make_move_iterator(
Right.begin()),
2865 std::make_move_iterator(
Right.end()), Add);
2869 Res.reserve(
Left.size() *
Right.size());
2870 for (
const auto <ransform : Left) {
2871 for (
const auto &RTransform : Right) {
2873 Combined.reserve(LTransform.size() + RTransform.size());
2874 llvm::copy(LTransform, std::back_inserter(Combined));
2875 llvm::copy(RTransform, std::back_inserter(Combined));
2876 Add(std::move(Combined));
2882 llvm_unreachable(
"Unknown ConstraintKind enum");
2885void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2886 for (
auto &
Other : F) {
2887 if (llvm::equal(
C,
Other))
2897 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2899 return std::nullopt;
2902 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2904 return std::nullopt;
2906 return Subsumes(PNormalized, QNormalized);
2912 DNFFormula DNFP = DNF(*P);
2913 CNFFormula CNFQ = CNF(*Q);
2918 const CNFFormula &QCNF) {
2919 for (
const auto &Pi : PDNF) {
2920 for (
const auto &Qj : QCNF) {
2926 if (!DNFSubsumes(Pi, Qj))
2933bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2935 return llvm::any_of(P, [&](Literal LP) {
2936 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2942 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2945 auto It = FoldSubsumptionCache.find(Key);
2946 if (It == FoldSubsumptionCache.end()) {
2955 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2961 if (A.Kind != B.Kind)
2964 case Literal::Atomic:
2966 return A.Value == B.Value;
2968 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2969 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2970 case Literal::FoldExpanded:
2972 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2973 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2975 llvm_unreachable(
"unknown literal kind");
2980class DumpNormalizedConstraint {
2982 const PrintingPolicy &PP;
2986 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2987 :
OS(
OS), PP(Context.getPrintingPolicy()),
2990 void dump(
const NormalizedConstraint &N) {
2995 void Traverse(
const NormalizedConstraint &N) {
2997 case NormalizedConstraint::ConstraintKind::Compound:
2998 VisitCompound(
static_cast<const CompoundConstraint &
>(N));
3000 case NormalizedConstraint::ConstraintKind::Atomic:
3001 VisitAtomic(
static_cast<const AtomicConstraint &
>(N));
3003 case NormalizedConstraint::ConstraintKind::ConceptId:
3004 VisitConceptId(
static_cast<const ConceptIdConstraint &
>(N));
3006 case NormalizedConstraint::ConstraintKind::FoldExpanded:
3007 VisitFoldExpanded(
static_cast<const FoldExpandedConstraint &
>(N));
3012 void WriteNodeHeader(
const NormalizedConstraint &N, StringRef Kind) {
3018 void WritePackIndex(
const NormalizedConstraintWithParamMapping &N) {
3020 OS <<
" SubstIndex=" << *Idx;
3023 void VisitCompound(
const CompoundConstraint &
C) {
3024 WriteNodeHeader(
C,
"CompoundConstraint");
3029 TD.
AddChild([&] { Traverse(
C.getLHS()); });
3030 TD.
AddChild([&] { Traverse(
C.getRHS()); });
3033 void VisitAtomic(
const AtomicConstraint &A) {
3034 WriteNodeHeader(A,
"AtomicConstraint");
3038 WriteParameterMapping(A);
3041 void VisitConceptId(
const ConceptIdConstraint &
C) {
3042 WriteNodeHeader(
C,
"ConceptIdConstraint");
3045 if (
auto *CSE =
C.getConceptSpecializationExpr()) {
3048 C.getConceptId()->print(OS, PP);
3050 WriteParameterMapping(
C);
3051 TD.
AddChild([&] { Traverse(
C.getNormalizedConstraint()); });
3054 void VisitFoldExpanded(
const FoldExpandedConstraint &F) {
3055 WriteNodeHeader(F,
"FoldExpandedConstraint");
3057 << (F.
getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3063 WriteParameterMapping(F);
3067 void WriteParameterMapping(
const NormalizedConstraintWithParamMapping &N) {
3074 OS <<
"ParameterMapping";
3075 WriteOccurenceList(
"Indexes", Indexes);
3076 WriteOccurenceList(
"IndexesForSubsumption", IndexesForSub);
3078 for (unsigned ParamIndex : Indexes.set_bits()) {
3079 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3080 assert(TPL && Slot < TPL->size());
3081 const NamedDecl *Param = TPL->getParam(Slot);
3082 OS <<
"#" << ParamIndex <<
": <";
3083 Param->print(OS, PP);
3085 Mapping[Slot].getArgument().print(PP, OS,
3087 TD.AddChild([this, Slot, Mapping] {
3088 const TemplateArgument &TA = Mapping[Slot].getArgument();
3089 OS <<
"TemplateArgument " << TA.getKindName();
3090 TD.dumpPointer(&TA);
3098 void WriteOccurenceList(StringRef Label,
3102 OS <<
" " << Label <<
"={"
3105 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3106 [](
unsigned I) { return llvm::to_string(I); }),
3115 dump(llvm::errs(), Context);
3120 return DumpNormalizedConstraint(OS, Context).dump(*
this);
This file provides AST data structures related to concepts.
This file provides some common utility functions for processing Lambda related AST Constructs.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
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)
Result
Implement __builtin_bit_cast and related operations.
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)
static bool PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base, const MultiLevelTemplateArgumentList &TemplateArgs, TypeSourceInfo *&Out, UnexpandedInfo &Info)
TypePropertyCache< Private > Cache
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
const TemplateArgument * getDefaultTemplateArgumentOrNone(const NamedDecl *P) const
Return the default argument of a template parameter, if one exists.
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
TemplateName getNamedConcept() const
SourceLocation getTemplateKWLoc() 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
ConceptDecl * getConceptDecl() const
ConceptReference * getConceptReference() const
const ImplicitConceptSpecializationDecl * getSpecializationDecl() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
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()
NamedDecl * getFoundDecl()
Get the NamedDecl through which this reference occurred.
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
DeclarationNameInfo getNameInfo() const
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
const TemplateArgumentLoc * getTemplateArgs() const
Retrieve the template arguments provided as part of this template-id.
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
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.
bool isParameterPack() const
Whether this declaration is a parameter pack.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
DeclContext * getDeclContext()
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
SourceLocation getInnerLocStart() const
Return start of source range ignoring outer template declarations.
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
TypeSourceInfo * getTypeSourceInfo() const
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.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
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
void setRetainInnerDepths()
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo)
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...
C++2a [expr.prim.req]: A requires-expression provides a concise way to express requirements on templa...
ArrayRef< concepts::Requirement * > getRequirements() const
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...
const DeclContext * getDeclContext() const
const NamedDecl * getDecl() const
const DeclContext * getLexicalDeclContext() const
Sema - This implements semantic analysis and AST building for C.
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 ...
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions, bool Diagnose=true)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
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)
void DiagnoseUnsatisfiedRequiresExpr(const RequiresExpr *RequiresExpr, bool First=true)
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.
bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out)
TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
llvm::DenseMap< llvm::FoldingSetNodeID, TemplateArgumentLoc > * CurrentCachedTemplateArgs
Cache the instantiation results of template parameter mappings within concepts.
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
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)
SourceManager & getSourceManager() const
bool isSFINAEContext() const
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 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)
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
std::string printToString(const SourceManager &SM) const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) 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.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
bool isNull() const
Determine whether this template name is NULL.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
unsigned getMinRequiredArguments() const
Returns the minimum number of arguments needed to form a template specialization.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() const
void dumpPointer(const void *Ptr)
void dumpSourceRange(SourceRange R)
void AddChild(Fn DoAddChild)
Add a child of the current node. Calls DoAddChild without arguments.
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...
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
__inline void unsigned int _2
uint32_t Literal
Literals are represented as positive integers.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool Sub(InterpState &S, CodePtr OpPC)
bool Add(InterpState &S, CodePtr OpPC)
Top level wrappers for InstallAPI frontend operations.
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.
OptionalUnsigned< unsigned > UnsignedOrNone
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)
@ PackIndex
Index of a pack indexing expression or specifier.
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
void dump(ASTContext &Context) const
SourceLocation getBeginLoc() const
llvm::SmallBitVector OccurenceList
constexpr underlying_type toInternalRepresentation() const
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.