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 TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) {
275 bool shouldVisitTemplateInstantiations()
const {
return true; }
278 HashParameterMapping(Sema &SemaRef,
279 const MultiLevelTemplateArgumentList &TemplateArgs,
280 llvm::FoldingSetNodeID &ID,
281 UnsignedOrNone OuterPackSubstIndex)
282 : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
ID(
ID),
283 OuterPackSubstIndex(OuterPackSubstIndex) {}
285 bool VisitTemplateTypeParmType(TemplateTypeParmType *
T) {
291 TemplateArgument Arg = TemplateArgs(
T->getDepth(),
T->getIndex());
295 "Missing argument pack");
297 Arg = getPackSubstitutedTemplateArgument(Arg);
300 UsedTemplateArgs.push_back(
305 bool VisitDeclRefExpr(DeclRefExpr *E) {
307 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
309 return TraverseDecl(D);
314 "Missing argument pack");
315 Arg = getPackSubstitutedTemplateArgument(Arg);
318 UsedTemplateArgs.push_back(
323 bool VisitTypedefType(TypedefType *TT) {
324 return inherited::TraverseType(TT->
desugar());
327 bool TraverseDecl(Decl *D) {
328 if (
auto *VD = dyn_cast<ValueDecl>(D))
329 return TraverseType(VD->getType());
331 return inherited::TraverseDecl(D);
334 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
336 return TraverseType(TL.
getType(), TraverseQualifier);
339 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
348 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
349 bool TraverseQualifier) {
350 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
353 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
356 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
357 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
359 return inherited::TraverseTemplateArgument(Arg);
362 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
363 return inherited::TraverseTemplateArgument(Arg);
366 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
368 for (
const auto &List : TemplateArgs)
369 for (
const TemplateArgument &Arg : List.Args)
375 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
377 for (
auto &ArgLoc : Mapping) {
378 TemplateArgument Canonical =
381 UsedTemplateArgs.push_back(Canonical);
382 TraverseTemplateArgument(Canonical);
385 for (
auto &
Used : UsedTemplateArgs) {
386 llvm::FoldingSetNodeID R;
393class ConstraintSatisfactionChecker {
396 SourceLocation TemplateNameLoc;
397 UnsignedOrNone PackSubstitutionIndex;
399 ConstraintSatisfaction &Satisfaction;
403 EvaluateAtomicConstraint(
const Expr *AtomicExpr,
404 const MultiLevelTemplateArgumentList &MLTAL);
406 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
407 const FoldExpandedConstraint &FE,
408 const MultiLevelTemplateArgumentList &MLTAL);
411 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
412 const NormalizedConstraintWithParamMapping &Constraint,
413 MultiLevelTemplateArgumentList MLTAL,
414 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
416 ExprResult EvaluateSlow(
const AtomicConstraint &Constraint,
417 const MultiLevelTemplateArgumentList &MLTAL);
420 const MultiLevelTemplateArgumentList &MLTAL);
422 ExprResult EvaluateSlow(
const FoldExpandedConstraint &Constraint,
423 const MultiLevelTemplateArgumentList &MLTAL);
426 const MultiLevelTemplateArgumentList &MLTAL);
428 ExprResult EvaluateSlow(
const ConceptIdConstraint &Constraint,
429 const MultiLevelTemplateArgumentList &MLTAL,
433 const MultiLevelTemplateArgumentList &MLTAL);
436 const MultiLevelTemplateArgumentList &MLTAL);
439 ConstraintSatisfactionChecker(Sema &SemaRef,
const NamedDecl *
Template,
440 SourceLocation TemplateNameLoc,
441 UnsignedOrNone PackSubstitutionIndex,
442 ConstraintSatisfaction &Satisfaction)
444 PackSubstitutionIndex(PackSubstitutionIndex),
445 Satisfaction(Satisfaction) {}
448 const MultiLevelTemplateArgumentList &MLTAL);
451StringRef allocateStringFromConceptDiagnostic(
const Sema &S,
461ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
467 llvm::FoldingSetNodeID
ID;
470 Satisfaction.IsSatisfied =
false;
471 Satisfaction.ContainsErrors =
true;
474 SatisfactionStackRAII StackRAII(S,
Template, ID);
485 if (Inst.isInvalid())
490 SubstitutedExpression =
493 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
497 if (!Trap.hasErrorOccurred())
504 Info.takeSFINAEDiagnostic(SubstDiag);
511 Satisfaction.Details.emplace_back(
514 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
515 Satisfaction.IsSatisfied =
false;
536 SubstitutedExpression.
get(),
539 return SubstitutedExpression;
542std::optional<MultiLevelTemplateArgumentList>
543ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
549 return std::move(MLTAL);
557 if (Inst.isInvalid())
566 : PackSubstitutionIndex);
571 Satisfaction.IsSatisfied =
false;
579 TD->getLocation(), SubstArgs,
585 SubstitutedOuterMost =
586 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
588 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
593 if (I < SubstitutedOuterMost.size()) {
594 SubstitutedOuterMost[I] = Arg;
597 SubstitutedOuterMost.push_back(Arg);
598 Offset = SubstitutedOuterMost.size();
601 if (Offset < SubstitutedOuterMost.size())
602 SubstitutedOuterMost.erase(SubstitutedOuterMost.begin() + Offset);
606 SubstitutedOuterMost);
607 return std::move(MLTAL);
610ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
615 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
616 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOuterMost);
617 if (!SubstitutedArgs) {
618 Satisfaction.IsSatisfied =
false;
623 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
629 if (SubstitutedAtomicExpr.
isUnset())
639 Satisfaction.IsSatisfied =
false;
640 Satisfaction.ContainsErrors =
true;
643 Satisfaction.Details.emplace_back(
645 SubstitutedAtomicExpr.get()->getBeginLoc(),
646 allocateStringFromConceptDiagnostic(S, Msg)});
647 return SubstitutedAtomicExpr;
651 Satisfaction.IsSatisfied =
true;
652 Satisfaction.ContainsErrors =
false;
653 return SubstitutedAtomicExpr;
660 EvalResult.
Diag = &EvaluationDiags;
663 !EvaluationDiags.empty()) {
667 diag::err_non_constant_constraint_expression)
670 S.
Diag(PDiag.first, PDiag.second);
675 "evaluating bool expression didn't produce int");
676 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
677 if (!Satisfaction.IsSatisfied)
678 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
680 return SubstitutedAtomicExpr;
683ExprResult ConstraintSatisfactionChecker::Evaluate(
687 unsigned Size = Satisfaction.Details.size();
688 llvm::FoldingSetNodeID
ID;
692 : PackSubstitutionIndex;
696 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
697 .VisitConstraint(Constraint);
702 auto &Cached = Iter->second.Satisfaction;
703 Satisfaction.ContainsErrors = Cached.ContainsErrors;
704 Satisfaction.IsSatisfied = Cached.IsSatisfied;
705 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
706 Cached.Details.begin(), Cached.Details.end());
707 return Iter->second.SubstExpr;
710 ExprResult E = EvaluateSlow(Constraint, MLTAL);
713 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
714 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
715 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
716 std::back_inserter(
Cache.Satisfaction.Details));
724ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
735 assert(!Unexpanded.empty() &&
"Pack expansion without parameter packs?");
737 bool RetainExpansion =
false;
741 false, Expand, RetainExpansion,
743 !Expand || RetainExpansion)
746 if (NumExpansions && S.
getLangOpts().BracketDepth < *NumExpansions) {
748 clang::diag::err_fold_expression_limit_exceeded)
754 return NumExpansions;
757ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
763 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
768 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
769 SubstitutionInTemplateArguments(
771 MLTAL, SubstitutedOuterMost);
772 if (!SubstitutedArgs) {
773 Satisfaction.IsSatisfied =
false;
779 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
783 if (*NumExpansions == 0) {
784 Satisfaction.IsSatisfied = Conjunction;
788 for (
unsigned I = 0; I < *NumExpansions; I++) {
790 Satisfaction.IsSatisfied =
false;
791 Satisfaction.ContainsErrors =
false;
793 ConstraintSatisfactionChecker(S,
Template, TemplateNameLoc,
796 if (
Expr.isUsable()) {
801 Conjunction ? BinaryOperatorKind::BO_LAnd
802 : BinaryOperatorKind::BO_LOr,
807 assert(!Satisfaction.IsSatisfied);
809 if (!Conjunction && Satisfaction.IsSatisfied) {
810 Satisfaction.Details.erase(Satisfaction.Details.begin() +
811 EffectiveDetailEndIndex,
812 Satisfaction.Details.end());
815 if (Satisfaction.IsSatisfied != Conjunction)
822ExprResult ConstraintSatisfactionChecker::Evaluate(
826 llvm::FoldingSetNodeID
ID;
828 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
833 auto &Cached = Iter->second.Satisfaction;
834 Satisfaction.ContainsErrors = Cached.ContainsErrors;
835 Satisfaction.IsSatisfied = Cached.IsSatisfied;
836 Satisfaction.Details.insert(Satisfaction.Details.end(),
837 Cached.Details.begin(), Cached.Details.end());
838 return Iter->second.SubstExpr;
841 unsigned Size = Satisfaction.Details.size();
843 ExprResult E = EvaluateSlow(Constraint, MLTAL);
845 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
846 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
847 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
848 std::back_inserter(
Cache.Satisfaction.Details));
854ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
860 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
861 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOuterMost);
863 if (!SubstitutedArgs) {
864 Satisfaction.IsSatisfied =
false;
873 : PackSubstitutionIndex);
884 Trap.hasErrorOccurred()) {
885 Satisfaction.IsSatisfied =
false;
886 if (!Trap.hasErrorOccurred())
891 Info.takeSFINAEDiagnostic(SubstDiag);
898 Satisfaction.Details.insert(
899 Satisfaction.Details.begin() + Size,
902 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
914 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
917 if (Size != Satisfaction.Details.size()) {
918 Satisfaction.Details.insert(
919 Satisfaction.Details.begin() + Size,
924 return SubstitutedConceptId;
927ExprResult ConstraintSatisfactionChecker::Evaluate(
936 : PackSubstitutionIndex;
944 unsigned Size = Satisfaction.Details.size();
949 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
956 if (Satisfaction.IsSatisfied)
959 llvm::FoldingSetNodeID
ID;
962 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
963 .VisitConstraint(Constraint);
968 auto &Cached = Iter->second.Satisfaction;
969 Satisfaction.ContainsErrors = Cached.ContainsErrors;
970 Satisfaction.IsSatisfied = Cached.IsSatisfied;
971 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
972 Cached.Details.begin(), Cached.Details.end());
973 return Iter->second.SubstExpr;
976 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
980 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
981 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
982 std::copy(Satisfaction.Details.begin() + Size, Satisfaction.Details.end(),
983 std::back_inserter(
Cache.Satisfaction.Details));
984 Cache.SubstExpr = CE;
989ExprResult ConstraintSatisfactionChecker::Evaluate(
993 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1000 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1003 if (!Conjunction && LHS.
isUsable() && Satisfaction.IsSatisfied &&
1004 !Satisfaction.ContainsErrors)
1007 Satisfaction.ContainsErrors =
false;
1008 Satisfaction.IsSatisfied =
false;
1012 if (RHS.
isUsable() && Satisfaction.IsSatisfied &&
1013 !Satisfaction.ContainsErrors)
1014 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1015 EffectiveDetailEndIndex,
1016 Satisfaction.Details.end());
1025 Conjunction ? BinaryOperatorKind::BO_LAnd
1026 : BinaryOperatorKind::BO_LOr,
1031ExprResult ConstraintSatisfactionChecker::Evaluate(
1034 switch (Constraint.
getKind()) {
1059 *ConvertedExpr =
nullptr;
1061 if (AssociatedConstraints.empty()) {
1076 std::optional<Sema::InstantiatingTemplate> SynthesisContext;
1077 if (!TopLevelConceptId) {
1078 SynthesisContext.emplace(S, TemplateIDRange.
getBegin(),
1091 if (TopLevelConceptId)
1100 .Evaluate(*
C, TemplateArgsLists);
1105 if (Res.
isUsable() && ConvertedExpr)
1106 *ConvertedExpr = Res.
get();
1117 if (AssociatedConstraints.empty()) {
1123 return ::CheckConstraintSatisfaction(
1124 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1125 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1139 for (
auto List : TemplateArgsLists)
1141 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1144 if (TopLevelConceptId)
1147 llvm::FoldingSetNodeID ID;
1150 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1151 OutSatisfaction = *Cached;
1156 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1158 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1159 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1160 OutSatisfaction = std::move(*Satisfaction);
1164 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1173 OutSatisfaction = *Cached;
1178 OutSatisfaction = *Satisfaction;
1182 SatisfactionCache.InsertNode(Satisfaction.release());
1191 Constraints.emplace_back(
1204bool Sema::SetupConstraintScope(
1209 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1213 InstantiatingTemplate Inst(
1218 if (Inst.isInvalid())
1229 if (addInstantiatedParametersToScope(
1238 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1248 FunctionDecl *InstantiatedFrom =
1255 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1256 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1258 if (Inst.isInvalid())
1263 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1272std::optional<MultiLevelTemplateArgumentList>
1273Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1276 MultiLevelTemplateArgumentList MLTAL;
1283 false, std::nullopt,
1290 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1291 return std::nullopt;
1299 bool ForOverloadResolution) {
1318 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1321 Satisfaction, UsageLoc,
1335 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1336 SetupConstraintCheckingTemplateArgumentsAndScope(
1344 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1345 ThisQuals =
Method->getMethodQualifiers();
1352 ForOverloadResolution);
1362 const Expr *ConstrExpr) {
1386 std::optional<LocalInstantiationScope> ScopeForParameters;
1389 ScopeForParameters.emplace(S,
true);
1393 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1395 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1397 if (!PVD->isParameterPack()) {
1398 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1417 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1418 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1422 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1431 std::optional<Sema::ContextRAII> ContextScope;
1439 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1451 return SubstConstr.
get();
1455 const Expr *OldConstr,
1457 const Expr *NewConstr) {
1458 if (OldConstr == NewConstr)
1461 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1463 if (
const Expr *SubstConstr =
1466 OldConstr = SubstConstr;
1469 if (
const Expr *SubstConstr =
1472 NewConstr = SubstConstr;
1477 llvm::FoldingSetNodeID ID1, ID2;
1490 "Non-function templates don't need to be checked");
1511 TemplateIDRange, Satisfaction))
1516 TemplateArgString =
" ";
1522 diag::err_template_arg_list_constraints_not_satisfied)
1524 << TemplateArgString << TemplateIDRange;
1536 Template->getAssociatedConstraints(TemplateAC);
1537 if (TemplateAC.empty()) {
1556 SemaRef, PointOfInstantiation,
1558 PointOfInstantiation);
1559 if (Inst.isInvalid())
1569 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1580 return ::CheckFunctionConstraintsWithoutInstantiation(
1581 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1582 TemplateArgs, Satisfaction);
1587 Template->getAssociatedConstraints(TemplateAC);
1588 if (TemplateAC.empty()) {
1598 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1599 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1607 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1608 ThisQuals =
Method->getMethodQualifiers();
1617 PointOfInstantiation, Satisfaction);
1624 "Diagnose() can only be used on an unsatisfied requirement");
1627 llvm_unreachable(
"Diagnosing a dependent requirement");
1631 if (!SubstDiag->DiagMessage.empty())
1632 S.
Diag(SubstDiag->DiagLoc,
1633 diag::note_expr_requirement_expr_substitution_error)
1634 << (
int)
First << SubstDiag->SubstitutedEntity
1635 << SubstDiag->DiagMessage;
1637 S.
Diag(SubstDiag->DiagLoc,
1638 diag::note_expr_requirement_expr_unknown_substitution_error)
1639 << (
int)
First << SubstDiag->SubstitutedEntity;
1649 if (!SubstDiag->DiagMessage.empty())
1650 S.
Diag(SubstDiag->DiagLoc,
1651 diag::note_expr_requirement_type_requirement_substitution_error)
1652 << (
int)
First << SubstDiag->SubstitutedEntity
1653 << SubstDiag->DiagMessage;
1658 note_expr_requirement_type_requirement_unknown_substitution_error)
1659 << (
int)
First << SubstDiag->SubstitutedEntity;
1669 llvm_unreachable(
"We checked this above");
1677 "Diagnose() can only be used on an unsatisfied requirement");
1680 llvm_unreachable(
"Diagnosing a dependent requirement");
1684 if (!SubstDiag->DiagMessage.empty())
1685 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1686 << (
int)
First << SubstDiag->SubstitutedEntity
1687 << SubstDiag->DiagMessage;
1689 S.
Diag(SubstDiag->DiagLoc,
1690 diag::note_type_requirement_unknown_substitution_error)
1691 << (
int)
First << SubstDiag->SubstitutedEntity;
1695 llvm_unreachable(
"Unknown satisfaction status");
1703 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1707 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1709 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1710 <<
Concept->getNamedConcept();
1712 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1742 const Expr *SubstExpr,
1745 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1746 switch (BO->getOpcode()) {
1758 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1769 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1781 if (BO->getLHS()->getType()->isIntegerType() &&
1782 BO->getRHS()->getType()->isIntegerType()) {
1785 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1788 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1791 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1793 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1806 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1809 if (!Req->isDependent() && !Req->isSatisfied()) {
1810 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1812 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
1820 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1824 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1825 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1826 assert(TTE->getNumArgs() == 2);
1828 diag::note_is_deducible_constraint_evaluated_to_false)
1829 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1834 diag::note_atomic_constraint_evaluated_to_false)
1844 .
template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1846 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
1849 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1853 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
1868 "Attempted to diagnose a satisfied constraint");
1879 "Attempted to diagnose a satisfied constraint");
1887class SubstituteParameterMappings {
1895 SubstituteParameterMappings(
Sema &SemaRef,
1899 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
1900 InFoldExpr(InFoldExpr) {}
1909 SubstituteParameterMappings(
Sema &SemaRef,
bool InFoldExpr =
false)
1911 InFoldExpr(InFoldExpr) {}
1913 bool substitute(NormalizedConstraint &N);
1916void SubstituteParameterMappings::buildParameterMapping(
1921 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
1922 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
1928 0, OccurringIndices);
1932 0, OccurringIndicesForSubsumption);
1939 0, OccurringIndices);
1943 ->getTemplateArgsAsWritten();
1946 0, OccurringIndices);
1951 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
1953 ? ArgsAsWritten->arguments()[I].getLocation()
1957 if (OccurringIndices[I]) {
1961 UsedParams.push_back(Param);
1970 unsigned Size = OccurringIndices.count();
1972 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
1976bool SubstituteParameterMappings::substitute(
1979 buildParameterMapping(N);
1984 InstLocBegin = ArgsAsWritten->getLAngleLoc();
1985 InstLocEnd = ArgsAsWritten->getRAngleLoc();
1987 auto SR =
Arguments[0].getSourceRange();
1988 InstLocBegin = SR.getBegin();
1989 InstLocEnd = SR.getEnd();
1992 SemaRef, InstLocBegin,
1995 {InstLocBegin, InstLocEnd});
1996 if (Inst.isInvalid())
2012 TD->getLocation(), SubstArgs,
2023 if (I < SubstArgs.
size())
2024 Loc = SubstArgs.
arguments()[I].getLocation();
2051 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2052 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2054 auto SR =
Arguments[0].getSourceRange();
2055 InstLocBegin = SR.getBegin();
2056 InstLocEnd = SR.getEnd();
2060 SemaRef, InstLocBegin,
2063 {InstLocBegin, InstLocEnd});
2064 if (Inst.isInvalid())
2073 CSE->getTemplateArgsAsWritten();
2080 CSE->getConceptNameInfo().getLoc(), Out,
2085 auto TemplateArgs = *MLTAL;
2088 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2097 assert(!ArgsAsWritten);
2106 assert(!ArgsAsWritten);
2111 return SubstituteParameterMappings(SemaRef,
true)
2117 assert(ArgsAsWritten);
2118 return substitute(CC);
2120 assert(!ArgsAsWritten);
2130 return SubstituteParameterMappings(
2136 if (substitute(Compound.getLHS()))
2138 return substitute(Compound.getRHS());
2147 assert(ACs.size() != 0);
2149 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2152 for (
unsigned I = 1; I < ACs.size(); ++I) {
2153 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2154 ACs[I].ArgPackSubstIndex);
2165 assert(E !=
nullptr);
2173 llvm::FoldingSetNodeID
ID;
2177 SatisfactionStackRAII StackRAII(S, D, ID);
2184 if (LogicalBinOp BO = E) {
2185 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2188 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2194 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2197 Sema::InstantiatingTemplate Inst(
2199 Sema::InstantiatingTemplate::ConstraintNormalization{},
2202 if (Inst.isInvalid())
2217 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2228 }
else if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2230 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2231 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2236 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2240 if (FE->getInit()) {
2241 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2242 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2246 if (FE->isRightFold())
2259 auto *
Sub = fromConstraintExpr(S, D, FE->
getPattern(), SubstIndex);
2271 if (!ConstrainedDeclOrNestedReq) {
2272 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2273 *
this,
nullptr, AssociatedConstraints);
2275 SubstituteParameterMappings(*this).substitute(*Normalized))
2283 ConstrainedDeclOrNestedReq.dyn_cast<
const NamedDecl *>();
2284 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2285 if (CacheEntry == NormalizationCache.end()) {
2286 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2287 *
this, ND, AssociatedConstraints);
2289 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2292 SubstituteParameterMappings(*this).substitute(*Normalized))
2295 return CacheEntry->second;
2318 if (It != BPacks.end())
2330 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2336 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2337 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2338 "use non-instantiated function declaration for constraints partial "
2353 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2354 auto CacheEntry = SubsumptionCache.find(Key);
2355 if (CacheEntry != SubsumptionCache.end()) {
2356 Result = CacheEntry->second;
2363 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2364 if (Depth2 > Depth1) {
2365 AC1[I].ConstraintExpr =
2366 AdjustConstraintDepth(*
this, Depth2 - Depth1)
2367 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2369 }
else if (Depth1 > Depth2) {
2370 AC2[I].ConstraintExpr =
2371 AdjustConstraintDepth(*
this, Depth1 - Depth2)
2372 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2378 std::optional<bool> Subsumes = SC.
Subsumes(D1, AC1, D2, AC2);
2384 SubsumptionCache.try_emplace(Key, *Subsumes);
2395 if (AC1.empty() || AC2.empty())
2398 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2409 llvm::FoldingSetNodeID IDA, IDB;
2411 EB->Profile(IDB,
Context,
true);
2415 AmbiguousAtomic1 = EA;
2416 AmbiguousAtomic2 = EB;
2433 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2434 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2437 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2438 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2440 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2441 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2446 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2448 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2450 Diag(AmbiguousAtomic2->getBeginLoc(),
2451 diag::note_ambiguous_atomic_constraints_similar_expression)
2452 << AmbiguousAtomic2->getSourceRange();
2463 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2465uint16_t SubsumptionChecker::getNewLiteralId() {
2466 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2467 "too many constraints!");
2472 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2487 llvm::FoldingSetNodeID ID;
2488 ID.AddBoolean(Ori->hasParameterMapping());
2489 if (Ori->hasParameterMapping()) {
2490 const auto &Mapping = Ori->getParameterMapping();
2492 Ori->mappingOccurenceListForSubsumption();
2493 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2500 auto It = Elems.find(ID);
2501 if (It == Elems.end()) {
2504 MappedAtomicConstraint{
2505 Ori, {getNewLiteralId(), Literal::Atomic}}})
2507 ReverseMap[It->second.ID.Value] = Ori;
2509 return It->getSecond().ID;
2513 auto &Elems = FoldMap[Ori->getPattern()];
2515 FoldExpendedConstraintKey K;
2516 K.Kind = Ori->getFoldOperator();
2518 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2519 return K.Kind ==
Other.Kind;
2521 if (It == Elems.end()) {
2522 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2523 It = Elems.insert(Elems.end(), std::move(K));
2524 ReverseMap[It->ID.Value] = Ori;
2530 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2533 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2549template <
typename FormulaType>
2553 auto Add = [&,
this](Clause
C) {
2556 C.erase(llvm::unique(
C),
C.end());
2557 AddUniqueClauseToFormula(Res, std::move(
C));
2563 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2566 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2569 return Normalize<FormulaType>(
2570 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2573 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2575 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2576 Left = Normalize<FormulaType>(Compound.getLHS());
2577 Right = Normalize<FormulaType>(Compound.getRHS());
2580 if (Compound.getCompoundKind() == FormulaType::Kind) {
2581 Res = std::move(Left);
2582 Res.reserve(
Left.size() +
Right.size());
2583 std::for_each(std::make_move_iterator(
Right.begin()),
2584 std::make_move_iterator(
Right.end()), Add);
2588 Res.reserve(
Left.size() *
Right.size());
2589 for (
const auto <ransform : Left) {
2590 for (
const auto &RTransform : Right) {
2592 Combined.reserve(LTransform.size() + RTransform.size());
2593 llvm::copy(LTransform, std::back_inserter(Combined));
2594 llvm::copy(RTransform, std::back_inserter(Combined));
2595 Add(std::move(Combined));
2603void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2604 for (
auto &
Other : F) {
2605 if (llvm::equal(
C,
Other))
2615 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2617 return std::nullopt;
2620 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2622 return std::nullopt;
2624 return Subsumes(PNormalized, QNormalized);
2630 DNFFormula DNFP = DNF(*P);
2631 CNFFormula CNFQ = CNF(*Q);
2636 const CNFFormula &QCNF) {
2637 for (
const auto &Pi : PDNF) {
2638 for (
const auto &Qj : QCNF) {
2644 if (!DNFSubsumes(Pi, Qj))
2651bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2653 return llvm::any_of(P, [&](Literal LP) {
2654 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2660 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2663 auto It = FoldSubsumptionCache.find(Key);
2664 if (It == FoldSubsumptionCache.end()) {
2673 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2679 if (A.Kind != B.Kind)
2682 case Literal::Atomic:
2684 return A.Value == B.Value;
2686 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2687 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2688 case Literal::FoldExpanded:
2690 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2691 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2693 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.
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...
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
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.
pack_iterator pack_begin() const
Iterator referencing the first argument of a template argument pack.
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.
TemplateArgument getPackExpansionPattern() const
When the template argument is a pack expansion, returns the pattern of the pack expansion.
unsigned pack_size() const
The number of template arguments in the given template argument 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