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) {
283 TemplateArgument Arg = TemplateArgs(
T->getDepth(),
T->getIndex());
287 "Missing argument pack");
292 UsedTemplateArgs.push_back(
297 bool VisitDeclRefExpr(DeclRefExpr *E) {
299 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
301 return TraverseDecl(D);
306 "Missing argument pack");
310 UsedTemplateArgs.push_back(
315 bool VisitTypedefType(TypedefType *TT) {
316 return inherited::TraverseType(TT->
desugar());
319 bool TraverseDecl(Decl *D) {
320 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
321 if (
auto *Var = dyn_cast<VarDecl>(VD))
322 TraverseStmt(Var->getInit());
323 return TraverseType(VD->getType());
326 return inherited::TraverseDecl(D);
329 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
331 return TraverseType(TL.
getType(), TraverseQualifier);
334 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
343 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
344 bool TraverseQualifier) {
345 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
348 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
351 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
352 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
354 return inherited::TraverseTemplateArgument(Arg);
357 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
358 return inherited::TraverseTemplateArgument(Arg);
361 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
362 return TraverseDecl(SOPE->
getPack());
365 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
369 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
371 for (
const auto &List : TemplateArgs)
372 for (
const TemplateArgument &Arg : List.Args)
378 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
380 for (
auto &ArgLoc : Mapping) {
381 TemplateArgument Canonical =
384 UsedTemplateArgs.push_back(Canonical);
385 TraverseTemplateArgument(Canonical);
388 for (
auto &
Used : UsedTemplateArgs) {
389 llvm::FoldingSetNodeID R;
396class ConstraintSatisfactionChecker {
399 SourceLocation TemplateNameLoc;
400 UnsignedOrNone PackSubstitutionIndex;
402 ConstraintSatisfaction &Satisfaction;
406 EvaluateAtomicConstraint(
const Expr *AtomicExpr,
407 const MultiLevelTemplateArgumentList &MLTAL);
409 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
410 const FoldExpandedConstraint &FE,
411 const MultiLevelTemplateArgumentList &MLTAL);
414 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
415 const NormalizedConstraintWithParamMapping &Constraint,
416 MultiLevelTemplateArgumentList MLTAL,
417 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
419 ExprResult EvaluateSlow(
const AtomicConstraint &Constraint,
420 const MultiLevelTemplateArgumentList &MLTAL);
423 const MultiLevelTemplateArgumentList &MLTAL);
425 ExprResult EvaluateSlow(
const FoldExpandedConstraint &Constraint,
426 const MultiLevelTemplateArgumentList &MLTAL);
429 const MultiLevelTemplateArgumentList &MLTAL);
431 ExprResult EvaluateSlow(
const ConceptIdConstraint &Constraint,
432 const MultiLevelTemplateArgumentList &MLTAL,
436 const MultiLevelTemplateArgumentList &MLTAL);
439 const MultiLevelTemplateArgumentList &MLTAL);
442 ConstraintSatisfactionChecker(Sema &SemaRef,
const NamedDecl *
Template,
443 SourceLocation TemplateNameLoc,
444 UnsignedOrNone PackSubstitutionIndex,
445 ConstraintSatisfaction &Satisfaction)
447 PackSubstitutionIndex(PackSubstitutionIndex),
448 Satisfaction(Satisfaction) {}
451 const MultiLevelTemplateArgumentList &MLTAL);
454StringRef allocateStringFromConceptDiagnostic(
const Sema &S,
464ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
470 llvm::FoldingSetNodeID
ID;
473 Satisfaction.IsSatisfied =
false;
474 Satisfaction.ContainsErrors =
true;
477 SatisfactionStackRAII StackRAII(S,
Template, ID);
488 if (Inst.isInvalid())
493 SubstitutedExpression =
496 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
500 if (!Trap.hasErrorOccurred())
507 Info.takeSFINAEDiagnostic(SubstDiag);
514 Satisfaction.Details.emplace_back(
517 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
518 Satisfaction.IsSatisfied =
false;
539 SubstitutedExpression.
get(),
542 return SubstitutedExpression;
545std::optional<MultiLevelTemplateArgumentList>
546ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
552 return std::move(MLTAL);
560 if (Inst.isInvalid())
569 : PackSubstitutionIndex);
574 Satisfaction.IsSatisfied =
false;
582 TD->getLocation(), SubstArgs,
588 SubstitutedOuterMost =
589 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
591 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
596 if (I < SubstitutedOuterMost.size()) {
597 SubstitutedOuterMost[I] = Arg;
600 SubstitutedOuterMost.push_back(Arg);
601 Offset = SubstitutedOuterMost.size();
604 if (Offset < SubstitutedOuterMost.size())
605 SubstitutedOuterMost.erase(SubstitutedOuterMost.begin() + Offset);
609 SubstitutedOuterMost);
610 return std::move(MLTAL);
613ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
618 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
619 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOuterMost);
620 if (!SubstitutedArgs) {
621 Satisfaction.IsSatisfied =
false;
626 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
632 if (SubstitutedAtomicExpr.
isUnset())
642 Satisfaction.IsSatisfied =
false;
643 Satisfaction.ContainsErrors =
true;
646 Satisfaction.Details.emplace_back(
648 SubstitutedAtomicExpr.get()->getBeginLoc(),
649 allocateStringFromConceptDiagnostic(S, Msg)});
650 return SubstitutedAtomicExpr;
654 Satisfaction.IsSatisfied =
true;
655 Satisfaction.ContainsErrors =
false;
656 return SubstitutedAtomicExpr;
663 EvalResult.
Diag = &EvaluationDiags;
666 !EvaluationDiags.empty()) {
670 diag::err_non_constant_constraint_expression)
673 S.
Diag(PDiag.first, PDiag.second);
678 "evaluating bool expression didn't produce int");
679 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
680 if (!Satisfaction.IsSatisfied)
681 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
683 return SubstitutedAtomicExpr;
686ExprResult ConstraintSatisfactionChecker::Evaluate(
690 unsigned Size = Satisfaction.Details.size();
691 llvm::FoldingSetNodeID
ID;
695 : PackSubstitutionIndex;
699 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
700 .VisitConstraint(Constraint);
705 auto &Cached = Iter->second.Satisfaction;
706 Satisfaction.ContainsErrors = Cached.ContainsErrors;
707 Satisfaction.IsSatisfied = Cached.IsSatisfied;
708 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
709 Cached.Details.begin(), Cached.Details.end());
710 return Iter->second.SubstExpr;
713 ExprResult E = EvaluateSlow(Constraint, MLTAL);
716 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
717 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
718 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
719 std::back_inserter(
Cache.Satisfaction.Details));
727ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
738 assert(!Unexpanded.empty() &&
"Pack expansion without parameter packs?");
740 bool RetainExpansion =
false;
744 false, Expand, RetainExpansion,
746 !Expand || RetainExpansion)
749 if (NumExpansions && S.
getLangOpts().BracketDepth < *NumExpansions) {
751 clang::diag::err_fold_expression_limit_exceeded)
757 return NumExpansions;
760ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
766 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
771 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
772 SubstitutionInTemplateArguments(
774 MLTAL, SubstitutedOuterMost);
775 if (!SubstitutedArgs) {
776 Satisfaction.IsSatisfied =
false;
782 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
786 if (*NumExpansions == 0) {
787 Satisfaction.IsSatisfied = Conjunction;
791 for (
unsigned I = 0; I < *NumExpansions; I++) {
793 Satisfaction.IsSatisfied =
false;
794 Satisfaction.ContainsErrors =
false;
796 ConstraintSatisfactionChecker(S,
Template, TemplateNameLoc,
799 if (
Expr.isUsable()) {
804 Conjunction ? BinaryOperatorKind::BO_LAnd
805 : BinaryOperatorKind::BO_LOr,
810 assert(!Satisfaction.IsSatisfied);
812 if (!Conjunction && Satisfaction.IsSatisfied) {
813 Satisfaction.Details.erase(Satisfaction.Details.begin() +
814 EffectiveDetailEndIndex,
815 Satisfaction.Details.end());
818 if (Satisfaction.IsSatisfied != Conjunction)
825ExprResult ConstraintSatisfactionChecker::Evaluate(
829 llvm::FoldingSetNodeID
ID;
831 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
836 auto &Cached = Iter->second.Satisfaction;
837 Satisfaction.ContainsErrors = Cached.ContainsErrors;
838 Satisfaction.IsSatisfied = Cached.IsSatisfied;
839 Satisfaction.Details.insert(Satisfaction.Details.end(),
840 Cached.Details.begin(), Cached.Details.end());
841 return Iter->second.SubstExpr;
844 unsigned Size = Satisfaction.Details.size();
846 ExprResult E = EvaluateSlow(Constraint, MLTAL);
848 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
849 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
850 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
851 std::back_inserter(
Cache.Satisfaction.Details));
857ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
863 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
864 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOuterMost);
866 if (!SubstitutedArgs) {
867 Satisfaction.IsSatisfied =
false;
876 : PackSubstitutionIndex);
887 Trap.hasErrorOccurred()) {
888 Satisfaction.IsSatisfied =
false;
889 if (!Trap.hasErrorOccurred())
894 Info.takeSFINAEDiagnostic(SubstDiag);
901 Satisfaction.Details.insert(
902 Satisfaction.Details.begin() + Size,
905 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
917 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
920 if (Size != Satisfaction.Details.size()) {
921 Satisfaction.Details.insert(
922 Satisfaction.Details.begin() + Size,
927 return SubstitutedConceptId;
930ExprResult ConstraintSatisfactionChecker::Evaluate(
939 : PackSubstitutionIndex;
947 unsigned Size = Satisfaction.Details.size();
952 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
959 if (Satisfaction.IsSatisfied)
962 llvm::FoldingSetNodeID
ID;
965 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
966 .VisitConstraint(Constraint);
971 auto &Cached = Iter->second.Satisfaction;
972 Satisfaction.ContainsErrors = Cached.ContainsErrors;
973 Satisfaction.IsSatisfied = Cached.IsSatisfied;
974 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
975 Cached.Details.begin(), Cached.Details.end());
976 return Iter->second.SubstExpr;
979 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
983 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
984 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
985 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
986 std::back_inserter(
Cache.Satisfaction.Details));
987 Cache.SubstExpr = CE;
992ExprResult ConstraintSatisfactionChecker::Evaluate(
996 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1003 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1006 if (!Conjunction && LHS.
isUsable() && Satisfaction.IsSatisfied &&
1007 !Satisfaction.ContainsErrors)
1010 Satisfaction.ContainsErrors =
false;
1011 Satisfaction.IsSatisfied =
false;
1015 if (RHS.
isUsable() && Satisfaction.IsSatisfied &&
1016 !Satisfaction.ContainsErrors)
1017 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1018 EffectiveDetailEndIndex,
1019 Satisfaction.Details.end());
1028 Conjunction ? BinaryOperatorKind::BO_LAnd
1029 : BinaryOperatorKind::BO_LOr,
1034ExprResult ConstraintSatisfactionChecker::Evaluate(
1037 switch (Constraint.
getKind()) {
1062 *ConvertedExpr =
nullptr;
1064 if (AssociatedConstraints.empty()) {
1079 std::optional<Sema::InstantiatingTemplate> SynthesisContext;
1080 if (!TopLevelConceptId) {
1081 SynthesisContext.emplace(S, TemplateIDRange.
getBegin(),
1094 if (TopLevelConceptId)
1103 .Evaluate(*
C, TemplateArgsLists);
1108 if (Res.
isUsable() && ConvertedExpr)
1109 *ConvertedExpr = Res.
get();
1120 if (AssociatedConstraints.empty()) {
1126 return ::CheckConstraintSatisfaction(
1127 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1128 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1142 for (
auto List : TemplateArgsLists)
1144 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1147 if (TopLevelConceptId)
1150 llvm::FoldingSetNodeID ID;
1153 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1154 OutSatisfaction = *Cached;
1159 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1161 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1162 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1163 OutSatisfaction = std::move(*Satisfaction);
1167 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1176 OutSatisfaction = *Cached;
1181 OutSatisfaction = *Satisfaction;
1185 SatisfactionCache.InsertNode(Satisfaction.release());
1194 Constraints.emplace_back(
1207bool Sema::SetupConstraintScope(
1212 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1216 InstantiatingTemplate Inst(
1221 if (Inst.isInvalid())
1232 if (addInstantiatedParametersToScope(
1241 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1251 FunctionDecl *InstantiatedFrom =
1258 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1259 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1261 if (Inst.isInvalid())
1266 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1275std::optional<MultiLevelTemplateArgumentList>
1276Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1279 MultiLevelTemplateArgumentList MLTAL;
1286 false, std::nullopt,
1293 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1294 return std::nullopt;
1302 bool ForOverloadResolution) {
1321 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1324 Satisfaction, UsageLoc,
1338 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1339 SetupConstraintCheckingTemplateArgumentsAndScope(
1347 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1348 ThisQuals =
Method->getMethodQualifiers();
1355 ForOverloadResolution);
1365 const Expr *ConstrExpr) {
1389 std::optional<LocalInstantiationScope> ScopeForParameters;
1392 ScopeForParameters.emplace(S,
true);
1396 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1398 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1400 if (!PVD->isParameterPack()) {
1401 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1420 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1421 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1425 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1434 std::optional<Sema::ContextRAII> ContextScope;
1442 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1454 return SubstConstr.
get();
1458 const Expr *OldConstr,
1460 const Expr *NewConstr) {
1461 if (OldConstr == NewConstr)
1464 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1466 if (
const Expr *SubstConstr =
1469 OldConstr = SubstConstr;
1472 if (
const Expr *SubstConstr =
1475 NewConstr = SubstConstr;
1480 llvm::FoldingSetNodeID ID1, ID2;
1493 "Non-function templates don't need to be checked");
1514 TemplateIDRange, Satisfaction))
1519 TemplateArgString =
" ";
1525 diag::err_template_arg_list_constraints_not_satisfied)
1527 << TemplateArgString << TemplateIDRange;
1539 Template->getAssociatedConstraints(TemplateAC);
1540 if (TemplateAC.empty()) {
1559 SemaRef, PointOfInstantiation,
1561 PointOfInstantiation);
1562 if (Inst.isInvalid())
1572 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1583 return ::CheckFunctionConstraintsWithoutInstantiation(
1584 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1585 TemplateArgs, Satisfaction);
1590 Template->getAssociatedConstraints(TemplateAC);
1591 if (TemplateAC.empty()) {
1601 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1602 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1610 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1611 ThisQuals =
Method->getMethodQualifiers();
1620 PointOfInstantiation, Satisfaction);
1627 "Diagnose() can only be used on an unsatisfied requirement");
1630 llvm_unreachable(
"Diagnosing a dependent requirement");
1634 if (!SubstDiag->DiagMessage.empty())
1635 S.
Diag(SubstDiag->DiagLoc,
1636 diag::note_expr_requirement_expr_substitution_error)
1637 << (
int)
First << SubstDiag->SubstitutedEntity
1638 << SubstDiag->DiagMessage;
1640 S.
Diag(SubstDiag->DiagLoc,
1641 diag::note_expr_requirement_expr_unknown_substitution_error)
1642 << (
int)
First << SubstDiag->SubstitutedEntity;
1652 if (!SubstDiag->DiagMessage.empty())
1653 S.
Diag(SubstDiag->DiagLoc,
1654 diag::note_expr_requirement_type_requirement_substitution_error)
1655 << (
int)
First << SubstDiag->SubstitutedEntity
1656 << SubstDiag->DiagMessage;
1661 note_expr_requirement_type_requirement_unknown_substitution_error)
1662 << (
int)
First << SubstDiag->SubstitutedEntity;
1672 llvm_unreachable(
"We checked this above");
1680 "Diagnose() can only be used on an unsatisfied requirement");
1683 llvm_unreachable(
"Diagnosing a dependent requirement");
1687 if (!SubstDiag->DiagMessage.empty())
1688 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1689 << (
int)
First << SubstDiag->SubstitutedEntity
1690 << SubstDiag->DiagMessage;
1692 S.
Diag(SubstDiag->DiagLoc,
1693 diag::note_type_requirement_unknown_substitution_error)
1694 << (
int)
First << SubstDiag->SubstitutedEntity;
1698 llvm_unreachable(
"Unknown satisfaction status");
1706 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1710 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1712 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1713 <<
Concept->getNamedConcept();
1715 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1745 const Expr *SubstExpr,
1748 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1749 switch (BO->getOpcode()) {
1761 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1772 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1784 if (BO->getLHS()->getType()->isIntegerType() &&
1785 BO->getRHS()->getType()->isIntegerType()) {
1788 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1791 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1794 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1796 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1809 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1812 if (!Req->isDependent() && !Req->isSatisfied()) {
1813 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1815 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
1823 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1827 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1828 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1829 assert(TTE->getNumArgs() == 2);
1831 diag::note_is_deducible_constraint_evaluated_to_false)
1832 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1837 diag::note_atomic_constraint_evaluated_to_false)
1847 .
template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1849 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
1852 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1856 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
1871 "Attempted to diagnose a satisfied constraint");
1882 "Attempted to diagnose a satisfied constraint");
1890class SubstituteParameterMappings {
1898 SubstituteParameterMappings(
Sema &SemaRef,
1902 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
1903 InFoldExpr(InFoldExpr) {}
1912 SubstituteParameterMappings(
Sema &SemaRef,
bool InFoldExpr =
false)
1914 InFoldExpr(InFoldExpr) {}
1916 bool substitute(NormalizedConstraint &N);
1919void SubstituteParameterMappings::buildParameterMapping(
1924 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
1925 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
1931 0, OccurringIndices);
1935 0, OccurringIndicesForSubsumption);
1942 0, OccurringIndices);
1946 ->getTemplateArgsAsWritten();
1949 0, OccurringIndices);
1954 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
1956 ? ArgsAsWritten->arguments()[I].getLocation()
1960 if (OccurringIndices[I]) {
1964 UsedParams.push_back(Param);
1973 unsigned Size = OccurringIndices.count();
1975 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
1979bool SubstituteParameterMappings::substitute(
1982 buildParameterMapping(N);
1987 InstLocBegin = ArgsAsWritten->getLAngleLoc();
1988 InstLocEnd = ArgsAsWritten->getRAngleLoc();
1990 auto SR =
Arguments[0].getSourceRange();
1991 InstLocBegin = SR.getBegin();
1992 InstLocEnd = SR.getEnd();
1995 SemaRef, InstLocBegin,
1998 {InstLocBegin, InstLocEnd});
1999 if (Inst.isInvalid())
2015 TD->getLocation(), SubstArgs,
2026 if (I < SubstArgs.
size())
2027 Loc = SubstArgs.
arguments()[I].getLocation();
2054 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2055 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2057 auto SR =
Arguments[0].getSourceRange();
2058 InstLocBegin = SR.getBegin();
2059 InstLocEnd = SR.getEnd();
2063 SemaRef, InstLocBegin,
2066 {InstLocBegin, InstLocEnd});
2067 if (Inst.isInvalid())
2076 CSE->getTemplateArgsAsWritten();
2083 CSE->getConceptNameInfo().getLoc(), Out,
2088 auto TemplateArgs = *MLTAL;
2091 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2100 assert(!ArgsAsWritten);
2109 assert(!ArgsAsWritten);
2114 return SubstituteParameterMappings(SemaRef,
true)
2120 assert(ArgsAsWritten);
2121 return substitute(CC);
2123 assert(!ArgsAsWritten);
2133 return SubstituteParameterMappings(
2139 if (substitute(Compound.getLHS()))
2141 return substitute(Compound.getRHS());
2150 assert(ACs.size() != 0);
2152 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2155 for (
unsigned I = 1; I < ACs.size(); ++I) {
2156 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2157 ACs[I].ArgPackSubstIndex);
2168 assert(E !=
nullptr);
2176 llvm::FoldingSetNodeID
ID;
2180 SatisfactionStackRAII StackRAII(S, D, ID);
2187 if (LogicalBinOp BO = E) {
2188 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2191 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2197 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2200 Sema::InstantiatingTemplate Inst(
2202 Sema::InstantiatingTemplate::ConstraintNormalization{},
2205 if (Inst.isInvalid())
2220 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2231 }
else if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2233 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2234 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2239 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2243 if (FE->getInit()) {
2244 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2245 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2249 if (FE->isRightFold())
2262 auto *
Sub = fromConstraintExpr(S, D, FE->
getPattern(), SubstIndex);
2274 if (!ConstrainedDeclOrNestedReq) {
2275 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2276 *
this,
nullptr, AssociatedConstraints);
2278 SubstituteParameterMappings(*this).substitute(*Normalized))
2286 ConstrainedDeclOrNestedReq.dyn_cast<
const NamedDecl *>();
2287 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2288 if (CacheEntry == NormalizationCache.end()) {
2289 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2290 *
this, ND, AssociatedConstraints);
2292 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2295 SubstituteParameterMappings(*this).substitute(*Normalized))
2298 return CacheEntry->second;
2321 if (It != BPacks.end())
2333 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2339 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2340 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2341 "use non-instantiated function declaration for constraints partial "
2356 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2357 auto CacheEntry = SubsumptionCache.find(Key);
2358 if (CacheEntry != SubsumptionCache.end()) {
2359 Result = CacheEntry->second;
2366 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2367 if (Depth2 > Depth1) {
2368 AC1[I].ConstraintExpr =
2369 AdjustConstraintDepth(*
this, Depth2 - Depth1)
2370 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2372 }
else if (Depth1 > Depth2) {
2373 AC2[I].ConstraintExpr =
2374 AdjustConstraintDepth(*
this, Depth1 - Depth2)
2375 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2381 std::optional<bool> Subsumes = SC.
Subsumes(D1, AC1, D2, AC2);
2387 SubsumptionCache.try_emplace(Key, *Subsumes);
2398 if (AC1.empty() || AC2.empty())
2401 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2412 llvm::FoldingSetNodeID IDA, IDB;
2414 EB->Profile(IDB,
Context,
true);
2418 AmbiguousAtomic1 = EA;
2419 AmbiguousAtomic2 = EB;
2436 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2437 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2440 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2441 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2443 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2444 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2449 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2451 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2453 Diag(AmbiguousAtomic2->getBeginLoc(),
2454 diag::note_ambiguous_atomic_constraints_similar_expression)
2455 << AmbiguousAtomic2->getSourceRange();
2466 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2468uint16_t SubsumptionChecker::getNewLiteralId() {
2469 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2470 "too many constraints!");
2475 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2490 llvm::FoldingSetNodeID ID;
2491 ID.AddBoolean(Ori->hasParameterMapping());
2492 if (Ori->hasParameterMapping()) {
2493 const auto &Mapping = Ori->getParameterMapping();
2495 Ori->mappingOccurenceListForSubsumption();
2496 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2503 auto It = Elems.find(ID);
2504 if (It == Elems.end()) {
2507 MappedAtomicConstraint{
2508 Ori, {getNewLiteralId(), Literal::Atomic}}})
2510 ReverseMap[It->second.ID.Value] = Ori;
2512 return It->getSecond().ID;
2516 auto &Elems = FoldMap[Ori->getPattern()];
2518 FoldExpendedConstraintKey K;
2519 K.Kind = Ori->getFoldOperator();
2521 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2522 return K.Kind ==
Other.Kind;
2524 if (It == Elems.end()) {
2525 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2526 It = Elems.insert(Elems.end(), std::move(K));
2527 ReverseMap[It->ID.Value] = Ori;
2533 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2536 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2552template <
typename FormulaType>
2556 auto Add = [&,
this](Clause
C) {
2559 C.erase(llvm::unique(
C),
C.end());
2560 AddUniqueClauseToFormula(Res, std::move(
C));
2566 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2569 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2572 return Normalize<FormulaType>(
2573 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2576 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2578 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2579 Left = Normalize<FormulaType>(Compound.getLHS());
2580 Right = Normalize<FormulaType>(Compound.getRHS());
2583 if (Compound.getCompoundKind() == FormulaType::Kind) {
2584 Res = std::move(Left);
2585 Res.reserve(
Left.size() +
Right.size());
2586 std::for_each(std::make_move_iterator(
Right.begin()),
2587 std::make_move_iterator(
Right.end()), Add);
2591 Res.reserve(
Left.size() *
Right.size());
2592 for (
const auto <ransform : Left) {
2593 for (
const auto &RTransform : Right) {
2595 Combined.reserve(LTransform.size() + RTransform.size());
2596 llvm::copy(LTransform, std::back_inserter(Combined));
2597 llvm::copy(RTransform, std::back_inserter(Combined));
2598 Add(std::move(Combined));
2606void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2607 for (
auto &
Other : F) {
2608 if (llvm::equal(
C,
Other))
2618 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2620 return std::nullopt;
2623 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2625 return std::nullopt;
2627 return Subsumes(PNormalized, QNormalized);
2633 DNFFormula DNFP = DNF(*P);
2634 CNFFormula CNFQ = CNF(*Q);
2639 const CNFFormula &QCNF) {
2640 for (
const auto &Pi : PDNF) {
2641 for (
const auto &Qj : QCNF) {
2647 if (!DNFSubsumes(Pi, Qj))
2654bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2656 return llvm::any_of(P, [&](Literal LP) {
2657 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2663 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2666 auto It = FoldSubsumptionCache.find(Key);
2667 if (It == FoldSubsumptionCache.end()) {
2676 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2682 if (A.Kind != B.Kind)
2685 case Literal::Atomic:
2687 return A.Value == B.Value;
2689 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2690 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2691 case Literal::FoldExpanded:
2693 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2694 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2696 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 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.
Expr * getConstraintExpr() const
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...
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
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 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.
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.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial 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.
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.
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.
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)
@ 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