31#include "llvm/ADT/DenseMap.h"
32#include "llvm/ADT/PointerUnion.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/Support/SaveAndRestore.h"
35#include "llvm/Support/ScopedPrinter.h"
36#include "llvm/Support/TimeProfiler.h"
45 const Expr *LHS =
nullptr;
46 const Expr *RHS =
nullptr;
49 LogicalBinOp(
const Expr *E) {
50 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
54 Loc = BO->getExprLoc();
55 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
57 if (OO->getNumArgs() == 2) {
58 Op = OO->getOperator();
61 Loc = OO->getOperatorLoc();
66 bool isAnd()
const {
return Op == OO_AmpAmp; }
67 bool isOr()
const {
return Op == OO_PipePipe; }
68 explicit operator bool()
const {
return isAnd() || isOr(); }
70 const Expr *getLHS()
const {
return LHS; }
71 const Expr *getRHS()
const {
return RHS; }
75 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
80 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
81 assert((!LHS.isInvalid() && !RHS.isInvalid()) &&
"not good expressions?");
83 if (!LHS.isUsable() || !RHS.isUsable())
97 Token NextToken,
bool *PossibleNonPrimary,
98 bool IsTrailingRequiresClause) {
104 if (LogicalBinOp BO = ConstraintExpression) {
106 PossibleNonPrimary) &&
109 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
115 auto CheckForNonPrimary = [&] {
116 if (!PossibleNonPrimary)
119 *PossibleNonPrimary =
130 (NextToken.
is(tok::l_paren) &&
131 (IsTrailingRequiresClause ||
149 CheckForNonPrimary();
155 diag::err_non_bool_atomic_constraint)
157 CheckForNonPrimary();
161 if (PossibleNonPrimary)
162 *PossibleNonPrimary =
false;
167struct SatisfactionStackRAII {
169 bool Inserted =
false;
171 const llvm::FoldingSetNodeID &FSNID)
178 ~SatisfactionStackRAII() {
190 for (
const auto &List : *MLTAL)
208 bool SkipForSpecialization =
false) {
214 true, SkipForSpecialization);
219class AdjustConstraints :
public TreeTransform<AdjustConstraints> {
220 unsigned TemplateDepth = 0;
222 bool RemoveNonPackExpansionPacks =
false;
225 using inherited = TreeTransform<AdjustConstraints>;
226 AdjustConstraints(Sema &SemaRef,
unsigned TemplateDepth,
227 bool RemoveNonPackExpansionPacks =
false)
228 : inherited(SemaRef), TemplateDepth(TemplateDepth),
229 RemoveNonPackExpansionPacks(RemoveNonPackExpansionPacks) {}
231 ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
233 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc, NumExpansions);
236 TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
237 SourceLocation EllipsisLoc,
239 if (!RemoveNonPackExpansionPacks)
240 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc,
246 TemplateArgumentLoc &Out, UnexpandedInfo &Info) {
247 if (!RemoveNonPackExpansionPacks)
248 return inherited::PreparePackForExpansion(In, Uneval, Out, Info);
249 assert(
In.getArgument().isPackExpansion());
255 using inherited::TransformTemplateTypeParmType;
256 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
257 TemplateTypeParmTypeLoc TL,
bool) {
260 TemplateTypeParmDecl *NewTTPDecl =
nullptr;
261 if (TemplateTypeParmDecl *OldTTPDecl =
T->getDecl())
262 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
265 QualType
Result = getSema().Context.getTemplateTypeParmType(
266 T->getDepth() + TemplateDepth,
T->getIndex(),
267 RemoveNonPackExpansionPacks ?
false :
T->isParameterPack(), NewTTPDecl);
268 TemplateTypeParmTypeLoc NewTL = TLB.
push<TemplateTypeParmTypeLoc>(
Result);
273 QualType TransformPackIndexingType(TypeLocBuilder &TLB,
274 PackIndexingTypeLoc TL) {
275 llvm::SaveAndRestore _1(RemoveNonPackExpansionPacks,
false);
276 return inherited::TransformPackIndexingType(TLB, TL);
279 bool AlreadyTransformed(QualType
T) {
289 ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
290 NonTypeTemplateParmDecl *NTTP =
291 dyn_cast<NonTypeTemplateParmDecl>(E->
getDecl());
293 return inherited::TransformDeclRefExpr(E);
296 "Template arguments for NTTP decl?");
312 RemoveNonPackExpansionPacks ? NTTP : D,
322 using inherited = RecursiveASTVisitor<HashParameterMapping>;
326 const MultiLevelTemplateArgumentList &TemplateArgs;
327 llvm::FoldingSetNodeID &
ID;
328 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
332 bool shouldVisitTemplateInstantiations()
const {
return true; }
335 HashParameterMapping(Sema &SemaRef,
336 const MultiLevelTemplateArgumentList &TemplateArgs,
337 llvm::FoldingSetNodeID &ID,
339 : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
ID(
ID),
340 OuterPackSubstIndex(OuterPackSubstIndex) {}
342 bool VisitTemplateTypeParmType(TemplateTypeParmType *
T) {
353 TemplateArgument Arg = TemplateArgs(
T->getDepth(),
T->getIndex());
359 if ((
T->isParameterPack() ||
360 (
T->getDecl() &&
T->getDecl()->isTemplateParameterPack())) &&
363 "Missing argument pack");
368 UsedTemplateArgs.push_back(
373 bool VisitDeclRefExpr(DeclRefExpr *E) {
375 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
377 return TraverseDecl(D);
395 "Missing argument pack");
399 UsedTemplateArgs.push_back(
404 bool VisitTypedefType(TypedefType *TT) {
405 return inherited::TraverseType(TT->
desugar());
408 bool TraversePackIndexingType(PackIndexingType *
T,
bool TraverseQualifier) {
410 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
411 if (!TraverseType(
T->getPattern()))
414 return TraverseStmt(
T->getIndexExpr());
417 bool TraverseDecl(Decl *D) {
418 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
419 if (
auto *Var = dyn_cast<VarDecl>(VD))
420 TraverseStmt(Var->getInit());
421 return TraverseType(VD->getType());
424 return inherited::TraverseDecl(D);
427 bool TraverseCallExpr(CallExpr *CE) {
428 inherited::TraverseStmt(CE->
getCallee());
431 inherited::TraverseStmt(Arg);
436 bool TraverseCXXThisExpr(CXXThisExpr *E) {
437 return inherited::TraverseType(E->
getType());
440 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
445 bool TraverseDependentNameType(
const DependentNameType *
T,
447 return TraverseNestedNameSpecifier(
T->getQualifier());
450 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
458 bool TraverseUnresolvedUsingType(UnresolvedUsingType *
T,
459 bool TraverseQualifier) {
462 if (NestedNameSpecifier NNS =
T->getDecl()->getQualifier();
463 TraverseQualifier && NNS)
464 return inherited::TraverseNestedNameSpecifier(NNS);
465 return inherited::TraverseUnresolvedUsingType(
T, TraverseQualifier);
468 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
469 bool TraverseQualifier) {
470 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
473 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
476 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
477 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
479 return inherited::TraverseTemplateArgument(Arg);
482 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
483 return inherited::TraverseTemplateArgument(Arg);
486 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
487 return TraverseDecl(SOPE->
getPack());
490 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
495 bool TraverseQualifier =
true) {
496 if (
auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
503 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
506 "Missing argument pack");
510 "Null template template argument");
511 UsedTemplateArgs.push_back(
514 return inherited::TraverseTemplateName(
Template, TraverseQualifier);
517 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
518 switch (Constraint.
getKind()) {
519 case NormalizedConstraint::ConstraintKind::Atomic:
520 ID.AddPointer(
static_cast<const AtomicConstraint &
>(Constraint)
521 .getConstraintExpr());
524 case NormalizedConstraint::ConstraintKind::ConceptId:
526 static_cast<const ConceptIdConstraint &
>(Constraint).getConceptId());
529 case NormalizedConstraint::ConstraintKind::FoldExpanded:
531 static_cast<const FoldExpandedConstraint &
>(Constraint).getPattern());
533 case NormalizedConstraint::ConstraintKind::Compound:
534 llvm_unreachable(
"Cannot hash a compound constraint");
538 for (
const auto &List : TemplateArgs)
539 for (
const TemplateArgument &Arg : List.Args)
545 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
547 for (
auto &ArgLoc : Mapping) {
548 TemplateArgument Canonical =
551 UsedTemplateArgs.push_back(Canonical);
552 TraverseTemplateArgument(Canonical);
555 for (
auto &
Used : UsedTemplateArgs) {
556 llvm::FoldingSetNodeID
R;
572 bool BuildExpression;
579 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
583 struct ParameterMappingInstantiationCache {
584 llvm::FoldingSetNodeID ID;
586 HashParameterMapping H;
587 unsigned PreviousDetailsSize;
589 ParameterMappingInstantiationCache(
594 : Checker(Checker), H(Checker.S, MLTAL, ID,
PackIndex),
595 PreviousDetailsSize(PreviousDetailsSize
596 ? *PreviousDetailsSize
597 : Checker.Satisfaction.
Details.size()) {
598 H.VisitConstraint(Constraint);
602 auto &
Cache = Checker.S.UnsubstitutedConstraintSatisfactionCache;
603 auto Iter =
Cache.find(ID);
604 if (Iter ==
Cache.end())
606 auto &Satisfaction = Checker.Satisfaction;
607 auto &Cached = Iter->second.Satisfaction;
609 Satisfaction.IsSatisfied = Cached.IsSatisfied;
610 Satisfaction.Details.insert(Satisfaction.Details.begin() +
612 Cached.Details.begin(), Cached.Details.end());
613 return &Iter->second;
618 auto &Satisfaction = Checker.Satisfaction;
619 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
620 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
621 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
622 Satisfaction.Details.begin() +
624 Satisfaction.Details.end());
626 Checker.S.UnsubstitutedConstraintSatisfactionCache.insert(
627 {ID, std::move(
Cache)});
633 template <
class Constra
int>
635 return C.getPackSubstitutionIndex() ?
C.getPackSubstitutionIndex()
636 : PackSubstitutionIndex;
642 Diag.EmitToString(S.getDiagnostics(), DiagString);
643 return S.getASTContext().backupStr(DiagString);
657 Satisfaction.Details.emplace_back(
660 allocateStringFromConceptDiagnostic(SubstDiag.second)});
668 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
701 bool BuildExpression)
702 : S(SemaRef), Template(Template), TopLevelConceptId(TopLevelConceptId),
703 TemplateNameLoc(TemplateNameLoc),
704 PackSubstitutionIndex(PackSubstitutionIndex),
705 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
713ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
715 llvm::FoldingSetNodeID
ID;
718 Satisfaction.IsSatisfied =
false;
719 Satisfaction.ContainsErrors =
true;
722 SatisfactionStackRAII StackRAII(S, Template, ID);
725 ExprResult SubstitutedExpression =
const_cast<Expr *
>(AtomicExpr);
727 TemplateDeductionInfo Info(TemplateNameLoc);
728 Sema::InstantiatingTemplate Inst(
730 Sema::InstantiatingTemplate::ConstraintSubstitution{},
733 if (Inst.isInvalid())
737 Sema::SFINAETrap Trap(S, Info);
738 SubstitutedExpression =
739 S.SubstConstraintExpr(
const_cast<Expr *
>(AtomicExpr), MLTAL);
741 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
745 if (!Trap.hasErrorOccurred())
749 consumeSFINAEFailure(Info, Satisfaction);
754 if (!S.CheckConstraintExpression(SubstitutedExpression.
get()))
769 S.Context, SubstitutedExpression.
get()->
getType(), CK_LValueToRValue,
770 SubstitutedExpression.
get(),
773 return SubstitutedExpression;
776std::optional<MultiLevelTemplateArgumentList>
777ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
791 return MultiLevelTemplateArgumentList();
793 TemplateDeductionInfo Info(Constraint.
getBeginLoc());
794 Sema::SFINAETrap Trap(S, Info);
795 Sema::InstantiatingTemplate Inst(
797 Sema::InstantiatingTemplate::ConstraintSubstitution{},
800 if (Inst.isInvalid())
803 TemplateArgumentListInfo SubstArgs;
804 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
806 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
807 &CachedTemplateArgs);
811 if (S.SubstTemplateArgumentsInParameterMapping(
814 Satisfaction.IsSatisfied =
false;
815 if (Trap.hasErrorOccurred())
816 consumeSFINAEFailure(Info, Satisfaction);
820 Sema::CheckTemplateArgumentInfo CTAI;
821 auto *TD =
const_cast<TemplateDecl *
>(
824 TD->getLocation(), SubstArgs,
833 SubstitutedOutermost =
834 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
836 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
837 TemplateArgument Arg;
839 Arg = S.Context.getCanonicalTemplateArgument(
841 if (I < SubstitutedOutermost.size()) {
842 SubstitutedOutermost[I] = Arg;
845 SubstitutedOutermost.push_back(Arg);
846 Offset = SubstitutedOutermost.size();
849 if (Offset < SubstitutedOutermost.size())
850 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
852 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
855 return std::move(SubstitutedTemplateArgs);
858ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
861 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
865 EvaluationContext.emplace(
868 EvaluationContext.emplace(
872 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
873 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
874 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
875 if (!SubstitutedArgs) {
876 Satisfaction.IsSatisfied =
false;
883 std::optional<Sema::ContextRAII> ConceptContext;
885 ConceptContext.emplace(S, ParentConcept->getDeclContext());
887 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
888 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
894 if (SubstitutedAtomicExpr.
isUnset())
904 Satisfaction.IsSatisfied =
false;
905 Satisfaction.ContainsErrors =
true;
907 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
908 Satisfaction.Details.emplace_back(
910 SubstitutedAtomicExpr.get()->getBeginLoc(),
911 allocateStringFromConceptDiagnostic(Msg)});
912 return SubstitutedAtomicExpr;
916 Satisfaction.IsSatisfied =
true;
917 Satisfaction.ContainsErrors =
false;
918 return SubstitutedAtomicExpr;
921 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
922 Expr::EvalResult EvalResult;
923 EvalResult.
Diag = &EvaluationDiags;
926 EvalResult, S.Context, SProxy) ||
927 !EvaluationDiags.empty()) {
931 diag::err_non_constant_constraint_expression)
934 S.Diag(PDiag.first, PDiag.second);
939 "evaluating bool expression didn't produce int");
940 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
941 if (!Satisfaction.IsSatisfied)
942 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
944 return SubstitutedAtomicExpr;
947ExprResult ConstraintSatisfactionChecker::Evaluate(
951 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
952 getOuterPackIndex(Constraint));
954 if (
auto *
V = PMCache.available())
957 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
960ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
966 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
968 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
970 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
971 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
972 SubstitutionInTemplateArguments(
973 static_cast<const NormalizedConstraintWithParamMapping &
>(Constraint),
974 MLTAL, SubstitutedOutermost);
975 if (!SubstitutedArgs) {
976 Satisfaction.IsSatisfied =
false;
982 Sema::InstantiatingTemplate InstTemplate(
984 Sema::InstantiatingTemplate::ConstraintSubstitution{},
986 NumExpansions = S.EvaluateFoldExpandedConstraintSize(
992 if (*NumExpansions == 0) {
993 Satisfaction.IsSatisfied = Conjunction;
998 for (
unsigned I = 0; I < *NumExpansions; I++) {
999 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
1000 Satisfaction.IsSatisfied =
false;
1001 Satisfaction.ContainsErrors =
false;
1008 if (BuildExpression) {
1013 Conjunction ? BinaryOperatorKind::BO_LAnd
1014 : BinaryOperatorKind::BO_LOr,
1017 FPOptionsOverride{});
1019 if (!Conjunction && Satisfaction.IsSatisfied) {
1020 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1021 EffectiveDetailEndIndex,
1022 Satisfaction.Details.end());
1025 if (Satisfaction.IsSatisfied != Conjunction)
1032ExprResult ConstraintSatisfactionChecker::Evaluate(
1036 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
1039 if (
auto *
V = PMCache.available())
1040 return V->SubstExpr;
1042 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
1045ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1048 const ConceptReference *ConceptId = Constraint.
getConceptId();
1050 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
1051 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1052 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1054 if (!SubstitutedArgs) {
1055 Satisfaction.IsSatisfied =
false;
1059 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
1061 const ASTTemplateArgumentListInfo *Ori =
1063 TemplateDeductionInfo Info(TemplateNameLoc);
1064 Sema::SFINAETrap Trap(S, Info);
1065 Sema::InstantiatingTemplate
_2(
1066 S, TemplateNameLoc, Sema::InstantiatingTemplate::ConstraintSubstitution{},
1073 if (TopLevelConceptId &&
1075 TopLevelConceptId->getNamedConcept().getAsTemplateDecl()) {
1077 OutArgs.addArgument(A);
1078 }
else if (S.SubstTemplateArguments(Ori->
arguments(), *SubstitutedArgs,
1080 Trap.hasErrorOccurred()) {
1081 Satisfaction.IsSatisfied =
false;
1082 if (Trap.hasErrorOccurred())
1083 consumeSFINAEFailure(Info, Satisfaction);
1090 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1096 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
1099 if (Size != Satisfaction.Details.size()) {
1100 Satisfaction.Details.insert(
1101 Satisfaction.Details.begin() + Size,
1103 SubstitutedConceptId.
getAs<ConceptSpecializationExpr>()
1104 ->getConceptReference()));
1106 return SubstitutedConceptId;
1109ExprResult ConstraintSatisfactionChecker::Evaluate(
1113 const ConceptReference *ConceptId = Constraint.
getConceptId();
1114 Sema::InstantiatingTemplate InstTemplate(
1116 Sema::InstantiatingTemplate::ConstraintsCheck{},
1124 : ArrayRef<TemplateArgument>{},
1126 if (InstTemplate.isInvalid())
1129 unsigned Size = Satisfaction.Details.size();
1131 llvm::SaveAndRestore PushConceptDecl(
1138 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1145 if (Satisfaction.IsSatisfied)
1148 ParameterMappingInstantiationCache PMCache(
1149 *
this, Constraint, MLTAL, getOuterPackIndex(Constraint), Size);
1151 if (
auto *
V = PMCache.available())
1152 return V->SubstExpr;
1154 return PMCache.cache(EvaluateSlow(Constraint, MLTAL, Size));
1157ExprResult ConstraintSatisfactionChecker::Evaluate(
1161 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1168 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1171 if (!Conjunction && !LHS.
isInvalid() && Satisfaction.IsSatisfied &&
1172 !Satisfaction.ContainsErrors)
1175 Satisfaction.ContainsErrors =
false;
1176 Satisfaction.IsSatisfied =
false;
1180 if (!Conjunction && !RHS.
isInvalid() && Satisfaction.IsSatisfied &&
1181 !Satisfaction.ContainsErrors)
1182 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1183 EffectiveDetailEndIndex,
1184 Satisfaction.Details.end());
1186 if (!BuildExpression)
1196 Conjunction ? BinaryOperatorKind::BO_LAnd
1197 : BinaryOperatorKind::BO_LOr,
1205 switch (Constraint.
getKind()) {
1220 llvm_unreachable(
"Unknown ConstraintKind enum");
1231 *ConvertedExpr =
nullptr;
1233 if (AssociatedConstraints.empty()) {
1253 struct SynthesisContextPair {
1259 : Inst(S, InstantiationRange.
getBegin(),
1261 TemplateArgs, InstantiationRange),
1264 std::optional<SynthesisContextPair> SynthesisContext;
1265 if (!TopLevelConceptId)
1276 if (TopLevelConceptId)
1286 ConvertedExpr !=
nullptr)
1287 .Evaluate(*
C, TemplateArgsLists);
1289 if (Res.
isUsable() && ConvertedExpr)
1290 *ConvertedExpr = Res.
get();
1301 llvm::TimeTraceScope TimeScope(
1302 "CheckConstraintSatisfaction", [TemplateIDRange,
this] {
1305 if (AssociatedConstraints.empty()) {
1309 const auto *
Template = dyn_cast_if_present<const NamedDecl *>(Entity);
1311 return ::CheckConstraintSatisfaction(
1312 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1313 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1327 for (
auto List : TemplateArgsLists)
1329 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1332 if (TopLevelConceptId)
1335 llvm::FoldingSetNodeID ID;
1337 llvm::FoldingSetInsertToken
Token;
1338 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1339 OutSatisfaction = *Cached;
1344 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1346 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1347 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1348 OutSatisfaction = std::move(*Satisfaction);
1352 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1361 OutSatisfaction = *Cached;
1366 OutSatisfaction = *Satisfaction;
1368 SatisfactionCache.insert(Satisfaction.release());
1390 return !ArgLoc.getArgument().isDependent() &&
1391 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1393 return Concept->getConstraintExpr();
1406bool Sema::SetupConstraintScope(
1411 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1417 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1418 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1420 if (Inst.isInvalid())
1429 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1431 if (addInstantiatedParametersToScope(
1438 if (FunctionTemplateDecl *FromMemTempl =
1440 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1450 FunctionDecl *InstantiatedFrom =
1457 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1458 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1460 if (Inst.isInvalid())
1465 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1474std::optional<MultiLevelTemplateArgumentList>
1475Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1478 MultiLevelTemplateArgumentList MLTAL;
1485 false, std::nullopt,
1492 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1493 return std::nullopt;
1501 bool ForOverloadResolution) {
1520 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1523 Satisfaction, UsageLoc,
1537 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1538 SetupConstraintCheckingTemplateArgumentsAndScope(
1546 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1547 ThisQuals =
Method->getMethodQualifiers();
1554 ForOverloadResolution);
1564 const Expr *ConstrExpr) {
1579 std::optional<LocalInstantiationScope> ScopeForParameters;
1582 ScopeForParameters.emplace(S,
true);
1586 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1588 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1590 if (!PVD->isParameterPack()) {
1591 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1610 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1611 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1615 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1624 std::optional<Sema::ContextRAII> ContextScope;
1632 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1644 return SubstConstr.
get();
1648 const Expr *OldConstr,
1650 const Expr *NewConstr) {
1651 if (OldConstr == NewConstr)
1654 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1657 if (
const Expr *SubstConstr =
1660 OldConstr = SubstConstr;
1663 if (
const Expr *SubstConstr =
1666 NewConstr = SubstConstr;
1671 llvm::FoldingSetNodeID ID1, ID2;
1684 "Non-function templates don't need to be checked");
1705 TemplateIDRange, Satisfaction) ||
1708 TemplateArgString =
" ";
1714 diag::err_template_arg_list_constraints_not_satisfied)
1716 << TemplateArgString << TemplateIDRange;
1728 Template->getAssociatedConstraints(TemplateAC);
1729 if (TemplateAC.empty()) {
1748 SemaRef, PointOfInstantiation,
1750 PointOfInstantiation);
1751 if (Inst.isInvalid())
1761 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1772 return ::CheckFunctionConstraintsWithoutInstantiation(
1773 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1774 TemplateArgs, Satisfaction);
1779 Template->getAssociatedConstraints(TemplateAC);
1780 if (TemplateAC.empty()) {
1790 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1791 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1799 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1800 ThisQuals =
Method->getMethodQualifiers();
1809 PointOfInstantiation, Satisfaction);
1816 "Diagnose() can only be used on an unsatisfied requirement");
1819 llvm_unreachable(
"Diagnosing a dependent requirement");
1823 if (!SubstDiag->DiagMessage.empty())
1824 S.
Diag(SubstDiag->DiagLoc,
1825 diag::note_expr_requirement_expr_substitution_error)
1826 << (
int)
First << SubstDiag->SubstitutedEntity
1827 << SubstDiag->DiagMessage;
1829 S.
Diag(SubstDiag->DiagLoc,
1830 diag::note_expr_requirement_expr_unknown_substitution_error)
1831 << (
int)
First << SubstDiag->SubstitutedEntity;
1841 if (!SubstDiag->DiagMessage.empty())
1842 S.
Diag(SubstDiag->DiagLoc,
1843 diag::note_expr_requirement_type_requirement_substitution_error)
1844 << (
int)
First << SubstDiag->SubstitutedEntity
1845 << SubstDiag->DiagMessage;
1850 note_expr_requirement_type_requirement_unknown_substitution_error)
1851 << (
int)
First << SubstDiag->SubstitutedEntity;
1861 llvm_unreachable(
"We checked this above");
1869 "Diagnose() can only be used on an unsatisfied requirement");
1872 llvm_unreachable(
"Diagnosing a dependent requirement");
1876 if (!SubstDiag->DiagMessage.empty())
1877 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1878 << (
int)
First << SubstDiag->SubstitutedEntity
1879 << SubstDiag->DiagMessage;
1881 S.
Diag(SubstDiag->DiagLoc,
1882 diag::note_type_requirement_unknown_substitution_error)
1883 << (
int)
First << SubstDiag->SubstitutedEntity;
1887 llvm_unreachable(
"Unknown satisfaction status");
1895 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1899 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1901 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1902 <<
Concept->getNamedConcept().getAsTemplateDecl();
1904 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1934 const Expr *SubstExpr,
1937 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1938 switch (BO->getOpcode()) {
1950 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1961 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1973 if (BO->getLHS()->getType()->isIntegerType() &&
1974 BO->getRHS()->getType()->isIntegerType()) {
1977 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1980 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1983 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1985 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1998 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
2001 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
2005 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
2006 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
2007 assert(TTE->getNumArgs() == 2);
2009 diag::note_is_deducible_constraint_evaluated_to_false)
2010 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2015 diag::note_atomic_constraint_evaluated_to_false)
2023 if (
auto *
Diag = dyn_cast<const ConstraintSubstitutionDiagnostic *>(
Record)) {
2025 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
2028 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2032 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
2045 if (!Req->isDependent() && !Req->isSatisfied()) {
2046 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2048 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
2062 "Attempted to diagnose a satisfied constraint");
2073 "Attempted to diagnose a satisfied constraint");
2081class SubstituteParameterMappings {
2093 bool RemovePacksForFoldExpr;
2095 SubstituteParameterMappings(
Sema &SemaRef,
2098 bool RemovePacksForFoldExpr)
2099 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2100 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2110 bool RemovePacksForFoldExpr =
false)
2112 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2119void SubstituteParameterMappings::buildParameterMapping(
2121 TemplateParameterList *TemplateParams =
2124 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2125 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2128 SemaRef.MarkUsedTemplateParameters(
2129 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2131 0, OccurringIndices);
2133 SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(
2134 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2135 0, OccurringIndicesForSubsumption);
2139 SemaRef.MarkUsedTemplateParameters(
2140 static_cast<FoldExpandedConstraint &
>(N).getPattern(),
2142 0, OccurringIndices);
2144 auto *Args =
static_cast<ConceptIdConstraint &
>(N)
2146 ->getTemplateArgsAsWritten();
2148 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2149 0, OccurringIndices);
2155 llvm::SmallVector<TemplateArgument> DefaultArgs;
2157 I < TemplateParams->size(); ++I) {
2158 const NamedDecl *Param = TemplateParams->
getParam(I);
2161 const TemplateArgument *Arg =
2162 SemaRef.getASTContext().getDefaultTemplateArgumentOrNone(Param);
2163 assert(Arg &&
"expected a default argument");
2164 DefaultArgs.emplace_back(std::move(*Arg));
2166 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2167 0, OccurringIndices);
2168 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2170 OccurringIndicesForSubsumption);
2173 unsigned Size = OccurringIndices.count();
2178 TemplateArgumentLoc *TempArgs =
2179 new (SemaRef.Context) TemplateArgumentLoc[Size];
2180 llvm::SmallVector<NamedDecl *> UsedParams;
2181 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2182 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2183 ? ArgsAsWritten->arguments()[I].getLocation()
2187 if (OccurringIndices[I]) {
2188 NamedDecl *Param = TemplateParams->
begin()[I];
2189 new (&(TempArgs)[J]) TemplateArgumentLoc(
2190 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2191 UsedParams.push_back(Param);
2201 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2202 MutableArrayRef<TemplateArgumentLoc>{TempArgs,
Size}, UsedList);
2205bool SubstituteParameterMappings::substitute(
2208 buildParameterMapping(N);
2214 SourceLocation InstLocBegin, InstLocEnd;
2215 llvm::ArrayRef
Arguments = ArgsAsWritten->arguments();
2217 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2218 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2220 auto SR =
Arguments[0].getSourceRange();
2221 InstLocBegin = SR.getBegin();
2222 InstLocEnd = SR.getEnd();
2224 Sema::NonSFINAEContext _(SemaRef);
2225 Sema::InstantiatingTemplate Inst(
2226 SemaRef, InstLocBegin,
2227 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2229 {InstLocBegin, InstLocEnd});
2230 if (Inst.isInvalid())
2237 TemplateArgumentListInfo SubstArgs;
2238 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2239 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2240 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2243 Sema::CheckTemplateArgumentInfo CTAI;
2247 TD->getLocation(), SubstArgs,
2252 TemplateArgumentLoc *TempArgs =
2258 if (I < SubstArgs.
size())
2259 Loc = SubstArgs.
arguments()[I].getLocation();
2261 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2265 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2276 if (substitute(
static_cast<NormalizedConstraintWithParamMapping &
>(CC)))
2283 SourceLocation InstLocBegin, InstLocEnd;
2284 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2286 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2287 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2289 auto SR =
Arguments[0].getSourceRange();
2290 InstLocBegin = SR.getBegin();
2291 InstLocEnd = SR.getEnd();
2293 Sema::NonSFINAEContext _(SemaRef);
2295 Sema::InstantiatingTemplate Inst(
2296 SemaRef, InstLocBegin,
2297 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2299 {InstLocBegin, InstLocEnd});
2300 if (Inst.isInvalid())
2303 TemplateArgumentListInfo
Out;
2308 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2309 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2310 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2311 CSE->getTemplateArgsAsWritten();
2312 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2313 ArgsAsWritten->arguments(), CC.
getBeginLoc(), *MLTAL, Out))
2315 Sema::CheckTemplateArgumentInfo CTAI;
2316 if (SemaRef.CheckTemplateArgumentList(CSE->getConceptDecl(),
2317 CSE->getConceptNameInfo().getLoc(), Out,
2322 auto TemplateArgs = *MLTAL;
2323 TemplateArgs.replaceOutermostTemplateArguments(CSE->getConceptDecl(),
2325 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2326 RemovePacksForFoldExpr)
2334 assert(!ArgsAsWritten);
2343 assert(!ArgsAsWritten);
2344 return substitute(FE.getNormalizedPattern());
2348 return SubstituteParameterMappings(SemaRef,
true)
2349 .substitute(FE.getNormalizedPattern());
2354 assert(ArgsAsWritten);
2355 return substitute(CC);
2357 assert(!ArgsAsWritten);
2369 if (RemovePacksForFoldExpr) {
2373 if (AdjustConstraints(SemaRef, 0,
2375 .TransformTemplateArguments(InputArgLoc.begin(),
2376 InputArgLoc.end(), OutArgs))
2380 if (SemaRef.CheckTemplateArgumentList(
2397 return SubstituteParameterMappings(SemaRef, &MLTAL,
2399 RemovePacksForFoldExpr)
2404 if (substitute(Compound.getLHS()))
2406 return substitute(Compound.getRHS());
2409 llvm_unreachable(
"Unknown ConstraintKind enum");
2414 assert(ACs.size() != 0);
2416 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2419 for (
unsigned I = 1; I < ACs.size(); ++I) {
2420 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2421 ACs[I].ArgPackSubstIndex);
2432 assert(E !=
nullptr);
2440 llvm::FoldingSetNodeID
ID;
2444 SatisfactionStackRAII StackRAII(S, D, ID);
2451 if (LogicalBinOp BO = E) {
2452 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2455 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2462 if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2478 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2479 S, CSE->getConceptDecl()->getCanonicalDecl(),
2480 AssociatedConstraint(Res.get(), SubstIndex));
2484 CSE->getConceptReference(), SubNF, D,
2487 if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2489 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2490 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2495 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2499 if (FE->getInit()) {
2500 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2501 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2505 if (FE->isRightFold())
2507 FE->getPattern(), D, Kind, LHS);
2510 FE->getPattern(), D, Kind, RHS);
2518 auto *
Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2530 if (!ConstrainedDeclOrNestedReq) {
2531 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2532 *
this,
nullptr, AssociatedConstraints);
2541 const NamedDecl *ND = dyn_cast<const NamedDecl *>(ConstrainedDeclOrNestedReq);
2549 std::pair<const Expr *, unsigned> Key(
2550 AC.ConstraintExpr, AC.ArgPackSubstIndex.toInternalRepresentation());
2552 if (
auto It = NormalizedConstraintExprCache.find(Key);
2553 It != NormalizedConstraintExprCache.end()) {
2556 Next = NormalizedConstraint::fromAssociatedConstraints(*
this, ND, AC);
2560 NormalizedConstraintExprCache.try_emplace(Key,
Next);
2592 if (It != BPacks.end())
2604 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2611 ->getOverloadedOperator() == OO_Spaceship);
2613 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2614 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2615 "use non-instantiated function declaration for constraints partial "
2630 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2631 auto CacheEntry = SubsumptionCache.find(Key);
2632 if (CacheEntry != SubsumptionCache.end()) {
2633 Result = CacheEntry->second;
2640 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2641 if (Depth2 > Depth1) {
2642 AC1[I].ConstraintExpr =
2643 AdjustConstraints(*
this, Depth2 - Depth1)
2644 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2646 }
else if (Depth1 > Depth2) {
2647 AC2[I].ConstraintExpr =
2648 AdjustConstraints(*
this, Depth1 - Depth2)
2649 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2658 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2659 if (Depth2 > Depth1)
2661 else if (Depth1 > Depth2)
2663 std::optional<bool> Subsumes = SC.
Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2669 SubsumptionCache.try_emplace(Key, *Subsumes);
2680 if (AC1.empty() || AC2.empty())
2683 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2694 llvm::FoldingSetNodeID IDA, IDB;
2696 EB->Profile(IDB,
Context,
true);
2700 AmbiguousAtomic1 = EA;
2701 AmbiguousAtomic2 = EB;
2716 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2717 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2720 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2721 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2723 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2724 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2729 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2731 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2733 Diag(AmbiguousAtomic2->getBeginLoc(),
2734 diag::note_ambiguous_atomic_constraints_similar_expression)
2735 << AmbiguousAtomic2->getSourceRange();
2746 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2748uint16_t SubsumptionChecker::getNewLiteralId() {
2749 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2750 "too many constraints!");
2755 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2770 llvm::FoldingSetNodeID ID;
2771 ID.AddBoolean(Ori->hasParameterMapping());
2772 if (Ori->hasParameterMapping()) {
2773 const auto &Mapping = Ori->getParameterMapping();
2775 Ori->mappingOccurenceListForSubsumption();
2776 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2783 auto It = Elems.find(ID);
2784 if (It == Elems.end()) {
2787 MappedAtomicConstraint{
2788 Ori, {getNewLiteralId(), Literal::Atomic}}})
2790 ReverseMap[It->second.ID.Value] = Ori;
2792 return It->getSecond().ID;
2796 auto &Elems = FoldMap[Ori->getPattern()];
2798 FoldExpendedConstraintKey K;
2799 K.Kind = Ori->getFoldOperator();
2801 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2802 return K.Kind ==
Other.Kind;
2804 if (It == Elems.end()) {
2805 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2806 It = Elems.insert(Elems.end(), std::move(K));
2807 ReverseMap[It->ID.Value] = Ori;
2813 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2816 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2832template <
typename FormulaType>
2836 auto Add = [&,
this](Clause
C) {
2839 C.erase(llvm::unique(
C),
C.end());
2840 AddUniqueClauseToFormula(Res, std::move(
C));
2845 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2848 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2851 return Normalize<FormulaType>(
2852 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2855 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2857 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2858 Left = Normalize<FormulaType>(Compound.getLHS());
2859 Right = Normalize<FormulaType>(Compound.getRHS());
2862 if (Compound.getCompoundKind() == FormulaType::Kind) {
2863 unsigned SizeLeft =
Left.size();
2864 Res = std::move(Left);
2865 Res.reserve(SizeLeft +
Right.size());
2866 std::for_each(std::make_move_iterator(
Right.begin()),
2867 std::make_move_iterator(
Right.end()), Add);
2871 Res.reserve(
Left.size() *
Right.size());
2872 for (
const auto <ransform : Left) {
2873 for (
const auto &RTransform : Right) {
2875 Combined.reserve(LTransform.size() + RTransform.size());
2876 llvm::copy(LTransform, std::back_inserter(Combined));
2877 llvm::copy(RTransform, std::back_inserter(Combined));
2878 Add(std::move(Combined));
2884 llvm_unreachable(
"Unknown ConstraintKind enum");
2887void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2888 for (
auto &
Other : F) {
2889 if (llvm::equal(
C,
Other))
2899 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2901 return std::nullopt;
2904 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2906 return std::nullopt;
2908 return Subsumes(PNormalized, QNormalized);
2914 DNFFormula DNFP = DNF(*P);
2915 CNFFormula CNFQ = CNF(*Q);
2920 const CNFFormula &QCNF) {
2921 for (
const auto &Pi : PDNF) {
2922 for (
const auto &Qj : QCNF) {
2928 if (!DNFSubsumes(Pi, Qj))
2935bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2937 return llvm::any_of(P, [&](Literal LP) {
2938 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2944 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2947 auto It = FoldSubsumptionCache.find(Key);
2948 if (It == FoldSubsumptionCache.end()) {
2957 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2963 if (A.Kind != B.Kind)
2966 case Literal::Atomic:
2968 return A.Value == B.Value;
2970 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2971 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2972 case Literal::FoldExpanded:
2974 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2975 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2977 llvm_unreachable(
"unknown literal kind");
2982class DumpNormalizedConstraint {
2984 const PrintingPolicy &PP;
2988 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2989 :
OS(
OS), PP(Context.getPrintingPolicy()),
2992 void dump(
const NormalizedConstraint &N) {
2997 void Traverse(
const NormalizedConstraint &N) {
2999 case NormalizedConstraint::ConstraintKind::Compound:
3000 VisitCompound(
static_cast<const CompoundConstraint &
>(N));
3002 case NormalizedConstraint::ConstraintKind::Atomic:
3003 VisitAtomic(
static_cast<const AtomicConstraint &
>(N));
3005 case NormalizedConstraint::ConstraintKind::ConceptId:
3006 VisitConceptId(
static_cast<const ConceptIdConstraint &
>(N));
3008 case NormalizedConstraint::ConstraintKind::FoldExpanded:
3009 VisitFoldExpanded(
static_cast<const FoldExpandedConstraint &
>(N));
3014 void WriteNodeHeader(
const NormalizedConstraint &N, StringRef Kind) {
3020 void WritePackIndex(
const NormalizedConstraintWithParamMapping &N) {
3022 OS <<
" SubstIndex=" << *Idx;
3025 void VisitCompound(
const CompoundConstraint &
C) {
3026 WriteNodeHeader(
C,
"CompoundConstraint");
3031 TD.
AddChild([&] { Traverse(
C.getLHS()); });
3032 TD.
AddChild([&] { Traverse(
C.getRHS()); });
3035 void VisitAtomic(
const AtomicConstraint &A) {
3036 WriteNodeHeader(A,
"AtomicConstraint");
3040 WriteParameterMapping(A);
3043 void VisitConceptId(
const ConceptIdConstraint &
C) {
3044 WriteNodeHeader(
C,
"ConceptIdConstraint");
3047 if (
auto *CSE =
C.getConceptSpecializationExpr()) {
3048 CSE->printPretty(OS,
nullptr, PP);
3050 C.getConceptId()->print(OS, PP);
3052 WriteParameterMapping(
C);
3053 TD.
AddChild([&] { Traverse(
C.getNormalizedConstraint()); });
3056 void VisitFoldExpanded(
const FoldExpandedConstraint &F) {
3057 WriteNodeHeader(F,
"FoldExpandedConstraint");
3059 << (F.
getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3065 WriteParameterMapping(F);
3069 void WriteParameterMapping(
const NormalizedConstraintWithParamMapping &N) {
3076 OS <<
"ParameterMapping";
3077 WriteOccurenceList(
"Indexes", Indexes);
3078 WriteOccurenceList(
"IndexesForSubsumption", IndexesForSub);
3080 for (unsigned ParamIndex : Indexes.set_bits()) {
3081 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3082 assert(TPL && Slot < TPL->size());
3083 const NamedDecl *Param = TPL->getParam(Slot);
3084 OS <<
"#" << ParamIndex <<
": <";
3085 Param->print(OS, PP);
3087 Mapping[Slot].getArgument().print(PP, OS,
3089 TD.AddChild([this, Slot, Mapping] {
3090 const TemplateArgument &TA = Mapping[Slot].getArgument();
3091 OS <<
"TemplateArgument " << TA.getKindName();
3092 TD.dumpPointer(&TA);
3100 void WriteOccurenceList(StringRef Label,
3104 OS <<
" " << Label <<
"={"
3107 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3108 [](
unsigned I) { return llvm::to_string(I); }),
3117 dump(llvm::errs(), Context);
3122 return DumpNormalizedConstraint(OS, Context).dump(*
this);
This file provides AST data structures related to concepts.
This file provides some common utility functions for processing Lambda related AST Constructs.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines Expressions and AST nodes for C++2a concepts.
static bool Evaluate(APValue &Result, EvalInfo &Info, const Expr *E)
Result
Implement __builtin_bit_cast and related operations.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
llvm::MachO::Records Records
llvm::MachO::Record Record
Defines and computes precedence levels for binary/ternary operators.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static void diagnoseUnsatisfiedConstraintExpr(Sema &S, const UnsatisfiedConstraintRecord &Record, SourceLocation Loc, bool First, concepts::NestedRequirement *Req=nullptr)
static ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)
static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)
static const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, const Expr *ConstrExpr)
static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, const Expr *SubstExpr, bool First)
static bool DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, const NamedDecl *Templ, const Expr *E, const MultiLevelTemplateArgumentList *MLTAL=nullptr)
static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgsLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId=nullptr)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)
static bool CheckFunctionConstraintsWithoutInstantiation(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
static unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, bool SkipForSpecialization=false)
static bool PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base, const MultiLevelTemplateArgumentList &TemplateArgs, TypeSourceInfo *&Out, UnexpandedInfo &Info)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
const 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,...
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.
void Adopt(NestedNameSpecifierLoc Other)
Adopt an existing nested-name-specifier (with source-range information).
const NormalizedConstraint & getLHS() const
static CompoundConstraint * CreateConjunction(ASTContext &Ctx, NormalizedConstraint *LHS, NormalizedConstraint *RHS)
CompoundConstraintKind getCompoundKind() const
const NormalizedConstraint & getRHS() const
static CompoundConstraint * Create(ASTContext &Ctx, NormalizedConstraint *LHS, CompoundConstraintKind CCK, NormalizedConstraint *RHS)
Declaration of a C++20 concept.
ConceptDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
const NormalizedConstraint & getNormalizedConstraint() const
const ConceptSpecializationExpr * getConceptSpecializationExpr() const
static ConceptIdConstraint * Create(ASTContext &Ctx, const ConceptReference *ConceptId, NormalizedConstraint *SubConstraint, const NamedDecl *ConstraintDecl, const ConceptSpecializationExpr *CSE, UnsignedOrNone PackIndex)
const ConceptReference * getConceptId() const
A reference to a concept and its template args, as it appears in the code.
const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const
NamedDecl * getFoundDecl() const
const DeclarationNameInfo & getConceptNameInfo() const
SourceLocation getBeginLoc() const LLVM_READONLY
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
TemplateName getNamedConcept() const
SourceLocation getTemplateKWLoc() const
Represents the specialization of a concept - evaluates to a prvalue of type bool.
SourceLocation getBeginLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptDecl * getConceptDecl() const
ConceptReference * getConceptReference() const
const ImplicitConceptSpecializationDecl * getSpecializationDecl() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConstraintSatisfactionChecker(Sema &SemaRef, const NamedDecl *Template, const ConceptReference *TopLevelConceptId, SourceLocation TemplateNameLoc, UnsignedOrNone PackSubstitutionIndex, ConstraintSatisfaction &Satisfaction, bool BuildExpression)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C)
llvm::SmallVector< UnsatisfiedConstraintRecord, 4 > Details
The substituted constraint expr, if the template arguments could be substituted into them,...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTransparentContext() const
isTransparentContext - Determines whether this context is a "transparent" context,...
bool isDependentContext() const
Determines whether this context is dependent on a template parameter.
DeclContext * getNonTransparentContext()
NamedDecl * getFoundDecl()
Get the NamedDecl through which this reference occurred.
bool refersToEnclosingVariableOrCapture() const
Does this DeclRefExpr refer to an enclosing local or a captured variable?
DeclarationNameInfo getNameInfo() const
SourceLocation getTemplateKeywordLoc() const
Retrieve the location of the template keyword preceding this name, if any.
static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, QualType T, ExprValueKind VK, NamedDecl *FoundD=nullptr, const TemplateArgumentListInfo *TemplateArgs=nullptr, NonOdrUseReason NOUR=NOUR_None)
NestedNameSpecifierLoc getQualifierLoc() const
If the name was qualified, retrieves the nested-name-specifier that precedes the name,...
const TemplateArgumentLoc * getTemplateArgs() const
Retrieve the template arguments provided as part of this template-id.
NonOdrUseReason isNonOdrUse() const
Is this expression a non-odr-use reference, and if so, why?
Decl - This represents one declaration (or definition), e.g.
FriendObjectKind getFriendObjectKind() const
Determines whether this declaration is the object of a friend declaration and, if so,...
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
bool isParameterPack() const
Whether this declaration is a parameter pack.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
DeclContext * getDeclContext()
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
SourceLocation getInnerLocStart() const
Return start of source range ignoring outer template declarations.
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
TypeSourceInfo * getTypeSourceInfo() const
RAII object that enters a new expression evaluation context.
This represents one expression.
@ SE_NoSideEffects
Strictly evaluate the expression.
bool isValueDependent() const
Determines whether the value of this expression depends on.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
bool EvaluateAsMandatedConstantExpr(EvalResult &Result, const ASTContext &Ctx, SemaProxy &SProxy, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required by the language to be a constant expression.
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.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static bool AreCompatibleForSubsumption(const FoldExpandedConstraint &A, const FoldExpandedConstraint &B)
FoldOperatorKind getFoldOperator() const
const Expr * getPattern() const
static FoldExpandedConstraint * Create(ASTContext &Ctx, const Expr *Pattern, const NamedDecl *ConstraintDecl, FoldOperatorKind OpKind, NormalizedConstraint *Constraint)
const NormalizedConstraint & getNormalizedPattern() const
Represents a function declaration or definition.
FunctionTemplateDecl * getDescribedFunctionTemplate() const
Retrieves the function template that is described by this function declaration.
SourceLocation getPointOfInstantiation() const
Retrieve the (first) point of instantiation of a function template specialization or a member of a cl...
ArrayRef< ParmVarDecl * > parameters() const
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
const TemplateArgumentList * getTemplateSpecializationArgs() const
Retrieve the template arguments used to produce this function template specialization from the primar...
bool isTemplateInstantiation() const
Determines if the given function was instantiated from a function template.
TemplatedKind
The kind of templated function a FunctionDecl can be.
@ TK_MemberSpecialization
@ TK_DependentNonTemplate
@ TK_FunctionTemplateSpecialization
TemplatedKind getTemplatedKind() const
What kind of templated function this is.
FunctionDecl * getInstantiatedFromDecl() const
FunctionDecl * getInstantiatedFromMemberFunction() const
If this function is an instantiation of a member function of a class template specialization,...
Declaration of a template function.
FunctionDecl * getTemplatedDecl() const
Get the underlying function declaration of the template.
FunctionTemplateDecl * getInstantiatedFromMemberTemplate() const
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
const TypeClass * getTypePtr() const
A stack-allocated class that identifies which local variable declaration instantiations are present i...
Data structure that captures multiple levels of template argument lists for use in template instantia...
bool hasTemplateArgument(unsigned Depth, unsigned Index) const
Determine whether there is a non-NULL template argument at the given depth and index.
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
bool isAnyArgInstantiationDependent() const
void setRetainInnerDepths()
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, int D, int P, const IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo)
unsigned getPosition() const
Get the position of the template parameter within its parameter list.
bool isParameterPack() const
Whether this parameter is a non-type template parameter pack.
unsigned getIndex() const
Get the index of the template parameter within its parameter list.
unsigned getDepth() const
Get the nesting depth of the template parameter.
UnsignedOrNone getPackSubstitutionIndex() const
const NamedDecl * getConstraintDecl() const
bool hasMatchingParameterMapping(ASTContext &C, const NormalizedConstraint &Other) const
const OccurenceList & mappingOccurenceList() const
const OccurenceList & mappingOccurenceListForSubsumption() const
TemplateParameterList * getUsedTemplateParamList() const
llvm::MutableArrayRef< TemplateArgumentLoc > getParameterMapping() const
bool hasParameterMapping() const
void updateParameterMapping(OccurenceList Indexes, OccurenceList IndexesForSubsumption, llvm::MutableArrayRef< TemplateArgumentLoc > Args, TemplateParameterList *ParamList)
A (possibly-)qualified type.
QualType getCanonicalType() const
The collection of all-type qualifiers we support.
A class that does preorder or postorder depth-first traversal on the entire Clang AST and visits each...
C++2a [expr.prim.req]: A requires-expression provides a concise way to express requirements on templa...
ArrayRef< concepts::Requirement * > getRequirements() const
Scope - A scope is a transient data structure that is used while parsing the program.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
RAII object used to change the argument pack substitution index within a Sema object.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
RAII class used to determine whether SFINAE has trapped any errors that occur during template argumen...
const DeclContext * getDeclContext() const
const NamedDecl * getDecl() const
const DeclContext * getLexicalDeclContext() const
Sema - This implements semantic analysis and AST building for C.
ExprResult SubstConceptTemplateArguments(const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, const MultiLevelTemplateArgumentList &MLTAL)
Substitute concept template arguments in the constraint expression of a concept-id.
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
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
friend class SubstituteParameterMappings
llvm::PointerUnion< const NamedDecl *, const concepts::NestedRequirement * > ConstrainedDeclOrNestedRequirement
bool CheckConstraintSatisfaction(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgLists, SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, const ConceptReference *TopLevelConceptId=nullptr, Expr **ConvertedExpr=nullptr)
Check whether the given list of constraint expressions are satisfied (as if in a 'conjunction') given...
const NormalizedConstraint * getNormalizedAssociatedConstraints(ConstrainedDeclOrNestedRequirement Entity, ArrayRef< AssociatedConstraint > AssociatedConstraints)
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
void DiagnoseUnsatisfiedRequiresExpr(const RequiresExpr *RequiresExpr, bool First=true)
bool EnsureTemplateArgumentListConstraints(TemplateDecl *Template, const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange)
Ensure that the given template arguments satisfy the constraints associated with the given template,...
const LangOptions & getLangOpts() const
void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl< UnexpandedParameterPack > &Unexpanded)
Collect the set of unexpanded parameter packs within the given template argument.
TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const
bool AreConstraintExpressionsEqual(const NamedDecl *Old, const Expr *OldConstr, const TemplateCompareNewDeclInfo &New, const Expr *NewConstr)
sema::FunctionScopeInfo * getCurFunction() const
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const NamedDecl *D, const DeclContext *DC=nullptr, bool Final=false, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, bool RelativeToPrimary=false, const FunctionDecl *Pattern=nullptr, bool ForConstraintInstantiation=false, bool SkipForSpecialization=false, bool ForDefaultArgumentSubstitution=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
bool CheckFunctionConstraints(const FunctionDecl *FD, ConstraintSatisfaction &Satisfaction, SourceLocation UsageLoc=SourceLocation(), bool ForOverloadResolution=false)
Check whether the given function decl's trailing requires clause is satisfied, if any.
TemplateNameKindForDiagnostics getTemplateNameKindForDiagnostics(TemplateName Name)
SourceManager & getSourceManager() const
bool isSFINAEContext() const
UnsignedOrNone ArgPackSubstIndex
The current index into pack expansion arguments that will be used for substitution of parameter packs...
void PushSatisfactionStackEntry(const NamedDecl *D, const llvm::FoldingSetNodeID &ID)
void PopSatisfactionStackEntry()
@ ConstantEvaluated
The current context is "potentially evaluated" in C++11 terms, but the expression is evaluated at com...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
bool SatisfactionStackContains(const NamedDecl *D, const llvm::FoldingSetNodeID &ID) const
bool IsAtLeastAsConstrained(const NamedDecl *D1, MutableArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, MutableArrayRef< AssociatedConstraint > AC2, bool &Result)
Check whether the given declaration's associated constraints are at least as constrained than another...
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
std::string getTemplateArgumentBindingsText(const TemplateParameterList *Params, const TemplateArgumentList &Args)
Produces a formatted string that describes the binding of template parameters to template arguments.
bool MaybeEmitAmbiguousAtomicConstraintsDiagnostic(const NamedDecl *D1, ArrayRef< AssociatedConstraint > AC1, const NamedDecl *D2, ArrayRef< AssociatedConstraint > AC2)
If D1 was not at least as constrained as D2, but would've been if a pair of atomic constraints involv...
NamedDecl * getPack() const
Retrieve the parameter pack.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
std::string printToString(const SourceManager &SM) const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
SourceLocation getBeginLoc() const LLVM_READONLY
Expr * getReplacement() const
SubstituteParameterMappings(Sema &SemaRef, bool RemovePacksForFoldExpr=false)
SubsumptionChecker establishes subsumption between two set of constraints.
std::optional< bool > Subsumes(const NamedDecl *DP, ArrayRef< AssociatedConstraint > P, const NamedDecl *DQ, ArrayRef< AssociatedConstraint > Q)
SubsumptionChecker(Sema &SemaRef, SubsumptionCallable Callable={})
llvm::function_ref< bool( const AtomicConstraint &, const AtomicConstraint &)> SubsumptionCallable
A convenient class for passing around template argument information.
ArrayRef< TemplateArgumentLoc > arguments() const
Location wrapper for a TemplateArgument.
Represents a template argument.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
TemplateName getAsTemplate() const
Retrieve the template name for a template name argument.
bool containsUnexpandedParameterPack() const
Whether this template argument contains an unexpanded parameter pack.
@ Pack
The template argument is actually a parameter pack.
ArgKind getKind() const
Return the kind of stored template argument.
bool isPackExpansion() const
Determine whether this template argument is a pack expansion.
The base class of all kinds of template declarations (e.g., class, function, etc.).
void getAssociatedConstraints(llvm::SmallVectorImpl< AssociatedConstraint > &AC) const
Get the total constraint-expression associated with this template, including constraint-expressions d...
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
bool isNull() const
Determine whether this template name is NULL.
NamedDecl * getParam(unsigned Idx)
unsigned getMinRequiredArguments() const
Returns the minimum number of arguments needed to form a template specialization.
static TemplateParameterList * Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef< NamedDecl * > Params, SourceLocation RAngleLoc, Expr *RequiresClause)
SourceLocation getLAngleLoc() const
SourceLocation getTemplateLoc() const
void dumpPointer(const void *Ptr)
void dumpSourceRange(SourceRange R)
void AddChild(Fn DoAddChild)
Add a child of the current node. Calls DoAddChild without arguments.
Token - This structure provides full information about a lexed token.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
TyLocType push(QualType T)
Pushes space for a new TypeLoc of the given type.
QualType getType() const
Get the type for which this source info wrapper provides information.
SourceLocation getNameLoc() const
void setNameLoc(SourceLocation Loc)
The base class of the type hierarchy.
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool containsUnexpandedParameterPack() const
Whether this type is or contains an unexpanded parameter pack, used to support C++0x variadic templat...
bool isVariablyModifiedType() const
Whether this type is a variably-modified type (C99 6.7.5).
bool isFunctionType() const
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
A requires-expression requirement which queries the validity and properties of an expression ('simple...
SubstitutionDiagnostic * getExprSubstitutionDiagnostic() const
ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr() const
@ SS_ConstraintsNotSatisfied
@ SS_TypeRequirementSubstitutionFailure
@ SS_ExprSubstitutionFailure
const ReturnTypeRequirement & getReturnTypeRequirement() const
SatisfactionStatus getSatisfactionStatus() const
SourceLocation getNoexceptLoc() const
A requires-expression requirement which is satisfied when a general constraint expression is satisfie...
const ASTConstraintSatisfaction & getConstraintSatisfaction() const
bool hasInvalidConstraint() const
Expr * getConstraintExpr() const
StringRef getInvalidConstraintEntity()
A static requirement that can be used in a requires-expression to check properties of types and expre...
A requires-expression requirement which queries the existence of a type name or type template special...
SubstitutionDiagnostic * getSubstitutionDiagnostic() const
SatisfactionStatus getSatisfactionStatus() const
Provides information about an attempted template argument deduction, whose success or failure was des...
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
__inline void unsigned int _2
uint32_t Literal
Literals are represented as positive integers.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
bool Sub(InterpState &S, CodePtr OpPC)
bool Add(InterpState &S, CodePtr OpPC)
Top level wrappers for InstallAPI frontend operations.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
@ OK_Ordinary
An ordinary object is located at an address in memory.
llvm::PointerUnion< const Expr *, const ConceptReference *, const ConstraintSubstitutionDiagnostic * > UnsatisfiedConstraintRecord
std::pair< llvm::PointerUnion< const TemplateTypeParmType *, NamedDecl *, const TemplateSpecializationType *, const SubstBuiltinTemplatePackType * >, SourceLocation > UnexpandedParameterPack
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
bool isLambdaCallOperator(const CXXMethodDecl *MD)
@ Result
The result type of a method or function.
std::pair< unsigned, unsigned > getDepthAndIndex(const NamedDecl *ND)
Retrieve the depth and index of a template parameter.
OptionalUnsigned< unsigned > UnsignedOrNone
const FunctionProtoType * T
@ Template
We are parsing a template declaration.
@ Concept
The name was classified as a concept name.
std::pair< SourceLocation, StringRef > ConstraintSubstitutionDiagnostic
Unsatisfied constraint expressions if the template arguments could be substituted into them,...
prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11)
Return the precedence of the specified binary operator token.
bool isLambdaConversionOperator(CXXConversionDecl *C)
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
U cast(CodeGen::Address addr)
@ PackIndex
Index of a pack indexing expression or specifier.
ActionResult< Expr * > ExprResult
@ Other
Other implicit parameter.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
ArrayRef< UnsatisfiedConstraintRecord > records() const
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
SourceLocation RAngleLoc
The source location of the right angle bracket ('>').
SourceLocation LAngleLoc
The source location of the left angle bracket ('<').
ArrayRef< TemplateArgumentLoc > arguments() const
EvalResult is a struct with detailed info about an evaluated expression.
APValue Val
Val - This is the value the expression can be folded to.
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
A normalized constraint, as defined in C++ [temp.constr.normal], is either an atomic constraint,...
NormalizedConstraint(const Expr *ConstraintExpr, const NamedDecl *ConstraintDecl, UnsignedOrNone PackIndex)
SourceRange getSourceRange() const
ConstraintKind getKind() const
void dump(ASTContext &Context) const
SourceLocation getBeginLoc() const
llvm::SmallBitVector OccurenceList
constexpr underlying_type toInternalRepresentation() const
SmallVector< TemplateArgument, 4 > SugaredConverted
The checked, converted argument will be added to the end of these vectors.
A stack object to be created when performing template instantiation.