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::FoldingSetNodeIDRef, 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;
611 Satisfaction.Details.begin(),
612 Satisfaction.Details.begin() + PreviousDetailsSize);
613 Details.append(Cached.Details.begin(), Cached.Details.end());
614 std::swap(Details, Satisfaction.Details);
615 return &Iter->second;
620 auto &Satisfaction = Checker.Satisfaction;
621 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
622 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
623 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
624 Satisfaction.Details.begin() +
626 Satisfaction.Details.end());
628 Checker.S.UnsubstitutedConstraintSatisfactionCache.try_emplace(
635 template <
class Constra
int>
637 return C.getPackSubstitutionIndex() ?
C.getPackSubstitutionIndex()
638 : PackSubstitutionIndex;
644 Diag.EmitToString(S.getDiagnostics(), DiagString);
645 return S.getASTContext().backupStr(DiagString);
659 Satisfaction.Details.emplace_back(
662 allocateStringFromConceptDiagnostic(SubstDiag.second)});
670 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
703 bool BuildExpression)
704 : S(SemaRef), Template(Template), TopLevelConceptId(TopLevelConceptId),
705 TemplateNameLoc(TemplateNameLoc),
706 PackSubstitutionIndex(PackSubstitutionIndex),
707 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
715ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
717 llvm::FoldingSetNodeID
ID;
720 Satisfaction.IsSatisfied =
false;
721 Satisfaction.ContainsErrors =
true;
724 SatisfactionStackRAII StackRAII(S, Template, ID);
727 ExprResult SubstitutedExpression =
const_cast<Expr *
>(AtomicExpr);
729 TemplateDeductionInfo Info(TemplateNameLoc);
730 Sema::InstantiatingTemplate Inst(
732 Sema::InstantiatingTemplate::ConstraintSubstitution{},
735 if (Inst.isInvalid())
739 Sema::SFINAETrap Trap(S, Info);
740 SubstitutedExpression =
741 S.SubstConstraintExpr(
const_cast<Expr *
>(AtomicExpr), MLTAL);
743 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
747 if (!Trap.hasErrorOccurred())
751 consumeSFINAEFailure(Info, Satisfaction);
756 if (!S.CheckConstraintExpression(SubstitutedExpression.
get()))
771 S.Context, SubstitutedExpression.
get()->
getType(), CK_LValueToRValue,
772 SubstitutedExpression.
get(),
775 return SubstitutedExpression;
778std::optional<MultiLevelTemplateArgumentList>
779ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
793 return MultiLevelTemplateArgumentList();
795 TemplateDeductionInfo Info(Constraint.
getBeginLoc());
796 Sema::SFINAETrap Trap(S, Info);
797 Sema::InstantiatingTemplate Inst(
799 Sema::InstantiatingTemplate::ConstraintSubstitution{},
802 if (Inst.isInvalid())
805 TemplateArgumentListInfo SubstArgs;
806 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
808 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
809 &CachedTemplateArgs);
813 if (S.SubstTemplateArgumentsInParameterMapping(
816 Satisfaction.IsSatisfied =
false;
817 if (Trap.hasErrorOccurred())
818 consumeSFINAEFailure(Info, Satisfaction);
822 Sema::CheckTemplateArgumentInfo CTAI;
823 auto *TD =
const_cast<TemplateDecl *
>(
826 TD->getLocation(), SubstArgs,
835 SubstitutedOutermost =
836 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
838 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
839 TemplateArgument Arg;
841 Arg = S.Context.getCanonicalTemplateArgument(
843 if (I < SubstitutedOutermost.size()) {
844 SubstitutedOutermost[I] = Arg;
847 SubstitutedOutermost.push_back(Arg);
848 Offset = SubstitutedOutermost.size();
851 if (Offset < SubstitutedOutermost.size())
852 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
854 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
857 return std::move(SubstitutedTemplateArgs);
860ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
863 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
867 EvaluationContext.emplace(
870 EvaluationContext.emplace(
874 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
875 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
876 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
877 if (!SubstitutedArgs) {
878 Satisfaction.IsSatisfied =
false;
885 std::optional<Sema::ContextRAII> ConceptContext;
887 ConceptContext.emplace(S, ParentConcept->getDeclContext());
889 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
890 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
896 if (SubstitutedAtomicExpr.
isUnset())
906 Satisfaction.IsSatisfied =
false;
907 Satisfaction.ContainsErrors =
true;
909 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
910 Satisfaction.Details.emplace_back(
912 SubstitutedAtomicExpr.get()->getBeginLoc(),
913 allocateStringFromConceptDiagnostic(Msg)});
914 return SubstitutedAtomicExpr;
918 Satisfaction.IsSatisfied =
true;
919 Satisfaction.ContainsErrors =
false;
920 return SubstitutedAtomicExpr;
923 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
924 Expr::EvalResult EvalResult;
925 EvalResult.
Diag = &EvaluationDiags;
928 EvalResult, S.Context, SProxy) ||
929 !EvaluationDiags.empty()) {
933 diag::err_non_constant_constraint_expression)
936 S.Diag(PDiag.first, PDiag.second);
941 "evaluating bool expression didn't produce int");
942 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
943 if (!Satisfaction.IsSatisfied)
944 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
946 return SubstitutedAtomicExpr;
949ExprResult ConstraintSatisfactionChecker::Evaluate(
953 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
954 getOuterPackIndex(Constraint));
956 if (
auto *
V = PMCache.available())
959 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
962ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
968 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
970 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
972 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
973 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
974 SubstitutionInTemplateArguments(
975 static_cast<const NormalizedConstraintWithParamMapping &
>(Constraint),
976 MLTAL, SubstitutedOutermost);
977 if (!SubstitutedArgs) {
978 Satisfaction.IsSatisfied =
false;
984 Sema::InstantiatingTemplate InstTemplate(
986 Sema::InstantiatingTemplate::ConstraintSubstitution{},
988 NumExpansions = S.EvaluateFoldExpandedConstraintSize(
994 if (*NumExpansions == 0) {
995 Satisfaction.IsSatisfied = Conjunction;
1000 for (
unsigned I = 0; I < *NumExpansions; I++) {
1001 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
1002 Satisfaction.IsSatisfied =
false;
1003 Satisfaction.ContainsErrors =
false;
1010 if (BuildExpression) {
1015 Conjunction ? BinaryOperatorKind::BO_LAnd
1016 : BinaryOperatorKind::BO_LOr,
1019 FPOptionsOverride{});
1021 if (!Conjunction && Satisfaction.IsSatisfied) {
1022 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1023 EffectiveDetailEndIndex,
1024 Satisfaction.Details.end());
1027 if (Satisfaction.IsSatisfied != Conjunction)
1034ExprResult ConstraintSatisfactionChecker::Evaluate(
1038 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
1041 if (
auto *
V = PMCache.available())
1042 return V->SubstExpr;
1044 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
1047ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1050 const ConceptReference *ConceptId = Constraint.
getConceptId();
1052 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
1053 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1054 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1056 if (!SubstitutedArgs) {
1057 Satisfaction.IsSatisfied =
false;
1061 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
1063 const ASTTemplateArgumentListInfo *Ori =
1065 TemplateDeductionInfo Info(TemplateNameLoc);
1066 Sema::SFINAETrap Trap(S, Info);
1067 Sema::InstantiatingTemplate
_2(
1068 S, TemplateNameLoc, Sema::InstantiatingTemplate::ConstraintSubstitution{},
1075 if (TopLevelConceptId &&
1077 TopLevelConceptId->getNamedConcept().getAsTemplateDecl()) {
1079 OutArgs.addArgument(A);
1080 }
else if (S.SubstTemplateArguments(Ori->
arguments(), *SubstitutedArgs,
1082 Trap.hasErrorOccurred()) {
1083 Satisfaction.IsSatisfied =
false;
1084 if (Trap.hasErrorOccurred())
1085 consumeSFINAEFailure(Info, Satisfaction);
1092 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1098 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
1101 if (Size != Satisfaction.Details.size()) {
1102 Satisfaction.Details.insert(
1103 Satisfaction.Details.begin() + Size,
1105 SubstitutedConceptId.
getAs<ConceptSpecializationExpr>()
1106 ->getConceptReference()));
1108 return SubstitutedConceptId;
1111ExprResult ConstraintSatisfactionChecker::Evaluate(
1115 const ConceptReference *ConceptId = Constraint.
getConceptId();
1116 Sema::InstantiatingTemplate InstTemplate(
1118 Sema::InstantiatingTemplate::ConstraintsCheck{},
1126 : ArrayRef<TemplateArgument>{},
1128 if (InstTemplate.isInvalid())
1131 unsigned Size = Satisfaction.Details.size();
1133 llvm::SaveAndRestore PushConceptDecl(
1140 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1147 if (Satisfaction.IsSatisfied)
1150 ParameterMappingInstantiationCache PMCache(
1151 *
this, Constraint, MLTAL, getOuterPackIndex(Constraint), Size);
1153 if (
auto *
V = PMCache.available())
1154 return V->SubstExpr;
1156 return PMCache.cache(EvaluateSlow(Constraint, MLTAL, Size));
1159ExprResult ConstraintSatisfactionChecker::Evaluate(
1163 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1170 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1173 if (!Conjunction && !LHS.
isInvalid() && Satisfaction.IsSatisfied &&
1174 !Satisfaction.ContainsErrors)
1177 Satisfaction.ContainsErrors =
false;
1178 Satisfaction.IsSatisfied =
false;
1182 if (!Conjunction && !RHS.
isInvalid() && Satisfaction.IsSatisfied &&
1183 !Satisfaction.ContainsErrors)
1184 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1185 EffectiveDetailEndIndex,
1186 Satisfaction.Details.end());
1188 if (!BuildExpression)
1198 Conjunction ? BinaryOperatorKind::BO_LAnd
1199 : BinaryOperatorKind::BO_LOr,
1207 switch (Constraint.
getKind()) {
1222 llvm_unreachable(
"Unknown ConstraintKind enum");
1233 *ConvertedExpr =
nullptr;
1235 if (AssociatedConstraints.empty()) {
1255 struct SynthesisContextPair {
1261 : Inst(S, InstantiationRange.
getBegin(),
1263 TemplateArgs, InstantiationRange),
1266 std::optional<SynthesisContextPair> SynthesisContext;
1267 if (!TopLevelConceptId)
1278 if (TopLevelConceptId)
1288 ConvertedExpr !=
nullptr)
1289 .Evaluate(*
C, TemplateArgsLists);
1291 if (Res.
isUsable() && ConvertedExpr)
1292 *ConvertedExpr = Res.
get();
1303 llvm::TimeTraceScope TimeScope(
1304 "CheckConstraintSatisfaction", [TemplateIDRange,
this] {
1307 if (AssociatedConstraints.empty()) {
1311 const auto *
Template = dyn_cast_if_present<const NamedDecl *>(Entity);
1313 return ::CheckConstraintSatisfaction(
1314 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1315 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1329 for (
auto List : TemplateArgsLists)
1331 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1334 if (TopLevelConceptId)
1337 llvm::FoldingSetNodeID ID;
1339 if (
auto *Cached = SatisfactionCache.lookup(ID)) {
1340 OutSatisfaction = *Cached;
1344 auto Satisfaction = std::make_unique<ConstraintSatisfaction>();
1346 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1347 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1348 OutSatisfaction = std::move(*Satisfaction);
1353 OutSatisfaction = *Satisfaction;
1355 auto [Iter, Inserted] =
1356 SatisfactionCache.try_emplace(ID.Intern(
BumpAlloc),
nullptr);
1358 Iter->second = Satisfaction.release();
1380 return !ArgLoc.getArgument().isDependent() &&
1381 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1383 return Concept->getConstraintExpr();
1396bool Sema::SetupConstraintScope(
1401 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1407 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1408 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1410 if (Inst.isInvalid())
1419 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1421 if (addInstantiatedParametersToScope(
1428 if (FunctionTemplateDecl *FromMemTempl =
1430 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1440 FunctionDecl *InstantiatedFrom =
1447 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1448 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1450 if (Inst.isInvalid())
1455 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1464std::optional<MultiLevelTemplateArgumentList>
1465Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1468 MultiLevelTemplateArgumentList MLTAL;
1475 false, std::nullopt,
1482 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1483 return std::nullopt;
1491 bool ForOverloadResolution) {
1510 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1513 Satisfaction, UsageLoc,
1527 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1528 SetupConstraintCheckingTemplateArgumentsAndScope(
1536 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1537 ThisQuals =
Method->getMethodQualifiers();
1544 ForOverloadResolution);
1554 const Expr *ConstrExpr) {
1569 std::optional<LocalInstantiationScope> ScopeForParameters;
1572 ScopeForParameters.emplace(S,
true);
1576 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1578 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1580 if (!PVD->isParameterPack()) {
1581 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1600 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1601 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1605 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1614 std::optional<Sema::ContextRAII> ContextScope;
1622 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1634 return SubstConstr.
get();
1638 const Expr *OldConstr,
1640 const Expr *NewConstr) {
1641 if (OldConstr == NewConstr)
1644 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1647 if (
const Expr *SubstConstr =
1650 OldConstr = SubstConstr;
1653 if (
const Expr *SubstConstr =
1656 NewConstr = SubstConstr;
1661 llvm::FoldingSetNodeID ID1, ID2;
1674 "Non-function templates don't need to be checked");
1695 TemplateIDRange, Satisfaction) ||
1698 TemplateArgString =
" ";
1704 diag::err_template_arg_list_constraints_not_satisfied)
1706 << TemplateArgString << TemplateIDRange;
1718 Template->getAssociatedConstraints(TemplateAC);
1719 if (TemplateAC.empty()) {
1738 SemaRef, PointOfInstantiation,
1740 PointOfInstantiation);
1741 if (Inst.isInvalid())
1751 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1762 return ::CheckFunctionConstraintsWithoutInstantiation(
1763 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1764 TemplateArgs, Satisfaction);
1769 Template->getAssociatedConstraints(TemplateAC);
1770 if (TemplateAC.empty()) {
1780 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1781 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1789 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1790 ThisQuals =
Method->getMethodQualifiers();
1799 PointOfInstantiation, Satisfaction);
1806 "Diagnose() can only be used on an unsatisfied requirement");
1809 llvm_unreachable(
"Diagnosing a dependent requirement");
1813 if (!SubstDiag->DiagMessage.empty())
1814 S.
Diag(SubstDiag->DiagLoc,
1815 diag::note_expr_requirement_expr_substitution_error)
1816 << (
int)
First << SubstDiag->SubstitutedEntity
1817 << SubstDiag->DiagMessage;
1819 S.
Diag(SubstDiag->DiagLoc,
1820 diag::note_expr_requirement_expr_unknown_substitution_error)
1821 << (
int)
First << SubstDiag->SubstitutedEntity;
1831 if (!SubstDiag->DiagMessage.empty())
1832 S.
Diag(SubstDiag->DiagLoc,
1833 diag::note_expr_requirement_type_requirement_substitution_error)
1834 << (
int)
First << SubstDiag->SubstitutedEntity
1835 << SubstDiag->DiagMessage;
1840 note_expr_requirement_type_requirement_unknown_substitution_error)
1841 << (
int)
First << SubstDiag->SubstitutedEntity;
1851 llvm_unreachable(
"We checked this above");
1859 "Diagnose() can only be used on an unsatisfied requirement");
1862 llvm_unreachable(
"Diagnosing a dependent requirement");
1866 if (!SubstDiag->DiagMessage.empty())
1867 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1868 << (
int)
First << SubstDiag->SubstitutedEntity
1869 << SubstDiag->DiagMessage;
1871 S.
Diag(SubstDiag->DiagLoc,
1872 diag::note_type_requirement_unknown_substitution_error)
1873 << (
int)
First << SubstDiag->SubstitutedEntity;
1877 llvm_unreachable(
"Unknown satisfaction status");
1885 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1889 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1891 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1892 <<
Concept->getNamedConcept().getAsTemplateDecl();
1894 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1924 const Expr *SubstExpr,
1927 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1928 switch (BO->getOpcode()) {
1940 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1951 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1963 if (BO->getLHS()->getType()->isIntegerType() &&
1964 BO->getRHS()->getType()->isIntegerType()) {
1967 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1970 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1973 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1975 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1988 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1991 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1995 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1996 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1997 assert(TTE->getNumArgs() == 2);
1999 diag::note_is_deducible_constraint_evaluated_to_false)
2000 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2005 diag::note_atomic_constraint_evaluated_to_false)
2013 if (
auto *
Diag = dyn_cast<const ConstraintSubstitutionDiagnostic *>(
Record)) {
2015 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
2018 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2022 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
2035 if (!Req->isDependent() && !Req->isSatisfied()) {
2036 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2038 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
2052 "Attempted to diagnose a satisfied constraint");
2063 "Attempted to diagnose a satisfied constraint");
2071class SubstituteParameterMappings {
2083 bool RemovePacksForFoldExpr;
2085 SubstituteParameterMappings(
Sema &SemaRef,
2088 bool RemovePacksForFoldExpr)
2089 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2090 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2100 bool RemovePacksForFoldExpr =
false)
2102 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2109void SubstituteParameterMappings::buildParameterMapping(
2111 TemplateParameterList *TemplateParams =
2114 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2115 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2118 SemaRef.MarkUsedTemplateParameters(
2119 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2121 0, OccurringIndices);
2123 SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(
2124 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2125 0, OccurringIndicesForSubsumption);
2129 SemaRef.MarkUsedTemplateParameters(
2130 static_cast<FoldExpandedConstraint &
>(N).getPattern(),
2132 0, OccurringIndices);
2134 auto *Args =
static_cast<ConceptIdConstraint &
>(N)
2136 ->getTemplateArgsAsWritten();
2138 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2139 0, OccurringIndices);
2145 llvm::SmallVector<TemplateArgument> DefaultArgs;
2147 I < TemplateParams->size(); ++I) {
2148 const NamedDecl *Param = TemplateParams->
getParam(I);
2151 const TemplateArgument *Arg =
2152 SemaRef.getASTContext().getDefaultTemplateArgumentOrNone(Param);
2153 assert(Arg &&
"expected a default argument");
2154 DefaultArgs.emplace_back(std::move(*Arg));
2156 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2157 0, OccurringIndices);
2158 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2160 OccurringIndicesForSubsumption);
2163 unsigned Size = OccurringIndices.count();
2168 TemplateArgumentLoc *TempArgs =
2169 new (SemaRef.Context) TemplateArgumentLoc[Size];
2170 llvm::SmallVector<NamedDecl *> UsedParams;
2171 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2172 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2173 ? ArgsAsWritten->arguments()[I].getLocation()
2177 if (OccurringIndices[I]) {
2178 NamedDecl *Param = TemplateParams->
begin()[I];
2179 new (&(TempArgs)[J]) TemplateArgumentLoc(
2180 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2181 UsedParams.push_back(Param);
2191 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2192 MutableArrayRef<TemplateArgumentLoc>{TempArgs,
Size}, UsedList);
2195bool SubstituteParameterMappings::substitute(
2198 buildParameterMapping(N);
2204 SourceLocation InstLocBegin, InstLocEnd;
2205 llvm::ArrayRef
Arguments = ArgsAsWritten->arguments();
2207 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2208 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2210 auto SR =
Arguments[0].getSourceRange();
2211 InstLocBegin = SR.getBegin();
2212 InstLocEnd = SR.getEnd();
2214 Sema::NonSFINAEContext _(SemaRef);
2215 Sema::InstantiatingTemplate Inst(
2216 SemaRef, InstLocBegin,
2217 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2219 {InstLocBegin, InstLocEnd});
2220 if (Inst.isInvalid())
2227 TemplateArgumentListInfo SubstArgs;
2228 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2229 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2230 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2233 Sema::CheckTemplateArgumentInfo CTAI;
2237 TD->getLocation(), SubstArgs,
2242 TemplateArgumentLoc *TempArgs =
2248 if (I < SubstArgs.
size())
2249 Loc = SubstArgs.
arguments()[I].getLocation();
2251 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2255 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2266 if (substitute(
static_cast<NormalizedConstraintWithParamMapping &
>(CC)))
2273 SourceLocation InstLocBegin, InstLocEnd;
2274 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2276 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2277 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2279 auto SR =
Arguments[0].getSourceRange();
2280 InstLocBegin = SR.getBegin();
2281 InstLocEnd = SR.getEnd();
2283 Sema::NonSFINAEContext _(SemaRef);
2285 Sema::InstantiatingTemplate Inst(
2286 SemaRef, InstLocBegin,
2287 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2289 {InstLocBegin, InstLocEnd});
2290 if (Inst.isInvalid())
2293 TemplateArgumentListInfo
Out;
2298 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2299 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2300 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2301 CSE->getTemplateArgsAsWritten();
2302 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2303 ArgsAsWritten->arguments(), CC.
getBeginLoc(), *MLTAL, Out))
2305 Sema::CheckTemplateArgumentInfo CTAI;
2306 if (SemaRef.CheckTemplateArgumentList(CSE->getConceptDecl(),
2307 CSE->getConceptNameInfo().getLoc(), Out,
2312 auto TemplateArgs = *MLTAL;
2313 TemplateArgs.replaceOutermostTemplateArguments(CSE->getConceptDecl(),
2315 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2316 RemovePacksForFoldExpr)
2324 assert(!ArgsAsWritten);
2333 assert(!ArgsAsWritten);
2334 return substitute(FE.getNormalizedPattern());
2338 return SubstituteParameterMappings(SemaRef,
true)
2339 .substitute(FE.getNormalizedPattern());
2344 assert(ArgsAsWritten);
2345 return substitute(CC);
2347 assert(!ArgsAsWritten);
2359 if (RemovePacksForFoldExpr) {
2363 if (AdjustConstraints(SemaRef, 0,
2365 .TransformTemplateArguments(InputArgLoc.begin(),
2366 InputArgLoc.end(), OutArgs))
2370 if (SemaRef.CheckTemplateArgumentList(
2387 return SubstituteParameterMappings(SemaRef, &MLTAL,
2389 RemovePacksForFoldExpr)
2394 if (substitute(Compound.getLHS()))
2396 return substitute(Compound.getRHS());
2399 llvm_unreachable(
"Unknown ConstraintKind enum");
2404 assert(ACs.size() != 0);
2406 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2409 for (
unsigned I = 1; I < ACs.size(); ++I) {
2410 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2411 ACs[I].ArgPackSubstIndex);
2422 assert(E !=
nullptr);
2430 llvm::FoldingSetNodeID
ID;
2434 SatisfactionStackRAII StackRAII(S, D, ID);
2441 if (LogicalBinOp BO = E) {
2442 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2445 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2452 if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2468 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2469 S, CSE->getConceptDecl()->getCanonicalDecl(),
2470 AssociatedConstraint(Res.get(), SubstIndex));
2474 CSE->getConceptReference(), SubNF, D,
2477 if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2479 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2480 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2485 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2489 if (FE->getInit()) {
2490 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2491 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2495 if (FE->isRightFold())
2497 FE->getPattern(), D, Kind, LHS);
2500 FE->getPattern(), D, Kind, RHS);
2508 auto *
Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2520 if (!ConstrainedDeclOrNestedReq) {
2521 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2522 *
this,
nullptr, AssociatedConstraints);
2531 const NamedDecl *ND = dyn_cast<const NamedDecl *>(ConstrainedDeclOrNestedReq);
2539 std::pair<const Expr *, unsigned> Key(
2540 AC.ConstraintExpr, AC.ArgPackSubstIndex.toInternalRepresentation());
2542 if (
auto It = NormalizedConstraintExprCache.find(Key);
2543 It != NormalizedConstraintExprCache.end()) {
2546 Next = NormalizedConstraint::fromAssociatedConstraints(*
this, ND, AC);
2550 NormalizedConstraintExprCache.try_emplace(Key,
Next);
2582 if (It != BPacks.end())
2594 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2601 ->getOverloadedOperator() == OO_Spaceship);
2603 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2604 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2605 "use non-instantiated function declaration for constraints partial "
2620 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2621 auto CacheEntry = SubsumptionCache.find(Key);
2622 if (CacheEntry != SubsumptionCache.end()) {
2623 Result = CacheEntry->second;
2630 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2631 if (Depth2 > Depth1) {
2632 AC1[I].ConstraintExpr =
2633 AdjustConstraints(*
this, Depth2 - Depth1)
2634 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2636 }
else if (Depth1 > Depth2) {
2637 AC2[I].ConstraintExpr =
2638 AdjustConstraints(*
this, Depth1 - Depth2)
2639 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2648 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2649 if (Depth2 > Depth1)
2651 else if (Depth1 > Depth2)
2653 std::optional<bool> Subsumes = SC.
Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2659 SubsumptionCache.try_emplace(Key, *Subsumes);
2670 if (AC1.empty() || AC2.empty())
2673 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2684 llvm::FoldingSetNodeID IDA, IDB;
2686 EB->Profile(IDB,
Context,
true);
2690 AmbiguousAtomic1 = EA;
2691 AmbiguousAtomic2 = EB;
2706 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2707 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2710 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2711 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2713 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2714 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2719 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2721 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2723 Diag(AmbiguousAtomic2->getBeginLoc(),
2724 diag::note_ambiguous_atomic_constraints_similar_expression)
2725 << AmbiguousAtomic2->getSourceRange();
2736 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2738uint16_t SubsumptionChecker::getNewLiteralId() {
2739 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2740 "too many constraints!");
2745 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2760 llvm::FoldingSetNodeID ID;
2761 ID.AddBoolean(Ori->hasParameterMapping());
2762 if (Ori->hasParameterMapping()) {
2763 const auto &Mapping = Ori->getParameterMapping();
2765 Ori->mappingOccurenceListForSubsumption();
2766 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2773 auto It = Elems.find(ID);
2774 if (It == Elems.end()) {
2777 MappedAtomicConstraint{
2778 Ori, {getNewLiteralId(), Literal::Atomic}}})
2780 ReverseMap[It->second.ID.Value] = Ori;
2782 return It->getSecond().ID;
2786 auto &Elems = FoldMap[Ori->getPattern()];
2788 FoldExpendedConstraintKey K;
2789 K.Kind = Ori->getFoldOperator();
2791 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2792 return K.Kind ==
Other.Kind;
2794 if (It == Elems.end()) {
2795 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2796 It = Elems.insert(Elems.end(), std::move(K));
2797 ReverseMap[It->ID.Value] = Ori;
2803 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2806 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2822template <
typename FormulaType>
2826 auto Add = [&,
this](Clause
C) {
2829 C.erase(llvm::unique(
C),
C.end());
2830 AddUniqueClauseToFormula(Res, std::move(
C));
2835 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2838 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2841 return Normalize<FormulaType>(
2842 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2845 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2847 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2848 Left = Normalize<FormulaType>(Compound.getLHS());
2849 Right = Normalize<FormulaType>(Compound.getRHS());
2852 if (Compound.getCompoundKind() == FormulaType::Kind) {
2853 unsigned SizeLeft =
Left.size();
2854 Res = std::move(Left);
2855 Res.reserve(SizeLeft +
Right.size());
2856 std::for_each(std::make_move_iterator(
Right.begin()),
2857 std::make_move_iterator(
Right.end()), Add);
2861 Res.reserve(
Left.size() *
Right.size());
2862 for (
const auto <ransform : Left) {
2863 for (
const auto &RTransform : Right) {
2865 Combined.reserve(LTransform.size() + RTransform.size());
2866 llvm::copy(LTransform, std::back_inserter(Combined));
2867 llvm::copy(RTransform, std::back_inserter(Combined));
2868 Add(std::move(Combined));
2874 llvm_unreachable(
"Unknown ConstraintKind enum");
2877void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2878 for (
auto &
Other : F) {
2879 if (llvm::equal(
C,
Other))
2889 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2891 return std::nullopt;
2894 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2896 return std::nullopt;
2898 return Subsumes(PNormalized, QNormalized);
2904 DNFFormula DNFP = DNF(*P);
2905 CNFFormula CNFQ = CNF(*Q);
2910 const CNFFormula &QCNF) {
2911 for (
const auto &Pi : PDNF) {
2912 for (
const auto &Qj : QCNF) {
2918 if (!DNFSubsumes(Pi, Qj))
2925bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2927 return llvm::any_of(P, [&](Literal LP) {
2928 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2934 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2937 auto It = FoldSubsumptionCache.find(Key);
2938 if (It == FoldSubsumptionCache.end()) {
2947 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2953 if (A.Kind != B.Kind)
2956 case Literal::Atomic:
2958 return A.Value == B.Value;
2960 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2961 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2962 case Literal::FoldExpanded:
2964 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2965 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2967 llvm_unreachable(
"unknown literal kind");
2972class DumpNormalizedConstraint {
2974 const PrintingPolicy &PP;
2978 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2979 :
OS(
OS), PP(Context.getPrintingPolicy()),
2982 void dump(
const NormalizedConstraint &N) {
2987 void Traverse(
const NormalizedConstraint &N) {
2989 case NormalizedConstraint::ConstraintKind::Compound:
2990 VisitCompound(
static_cast<const CompoundConstraint &
>(N));
2992 case NormalizedConstraint::ConstraintKind::Atomic:
2993 VisitAtomic(
static_cast<const AtomicConstraint &
>(N));
2995 case NormalizedConstraint::ConstraintKind::ConceptId:
2996 VisitConceptId(
static_cast<const ConceptIdConstraint &
>(N));
2998 case NormalizedConstraint::ConstraintKind::FoldExpanded:
2999 VisitFoldExpanded(
static_cast<const FoldExpandedConstraint &
>(N));
3004 void WriteNodeHeader(
const NormalizedConstraint &N, StringRef Kind) {
3010 void WritePackIndex(
const NormalizedConstraintWithParamMapping &N) {
3012 OS <<
" SubstIndex=" << *Idx;
3015 void VisitCompound(
const CompoundConstraint &
C) {
3016 WriteNodeHeader(
C,
"CompoundConstraint");
3021 TD.
AddChild([&] { Traverse(
C.getLHS()); });
3022 TD.
AddChild([&] { Traverse(
C.getRHS()); });
3025 void VisitAtomic(
const AtomicConstraint &A) {
3026 WriteNodeHeader(A,
"AtomicConstraint");
3030 WriteParameterMapping(A);
3033 void VisitConceptId(
const ConceptIdConstraint &
C) {
3034 WriteNodeHeader(
C,
"ConceptIdConstraint");
3037 if (
auto *CSE =
C.getConceptSpecializationExpr()) {
3038 CSE->printPretty(OS,
nullptr, PP);
3040 C.getConceptId()->print(OS, PP);
3042 WriteParameterMapping(
C);
3043 TD.
AddChild([&] { Traverse(
C.getNormalizedConstraint()); });
3046 void VisitFoldExpanded(
const FoldExpandedConstraint &F) {
3047 WriteNodeHeader(F,
"FoldExpandedConstraint");
3049 << (F.
getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3055 WriteParameterMapping(F);
3059 void WriteParameterMapping(
const NormalizedConstraintWithParamMapping &N) {
3066 OS <<
"ParameterMapping";
3067 WriteOccurenceList(
"Indexes", Indexes);
3068 WriteOccurenceList(
"IndexesForSubsumption", IndexesForSub);
3070 for (unsigned ParamIndex : Indexes.set_bits()) {
3071 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3072 assert(TPL && Slot < TPL->size());
3073 const NamedDecl *Param = TPL->getParam(Slot);
3074 OS <<
"#" << ParamIndex <<
": <";
3075 Param->print(OS, PP);
3077 Mapping[Slot].getArgument().print(PP, OS,
3079 TD.AddChild([this, Slot, Mapping] {
3080 const TemplateArgument &TA = Mapping[Slot].getArgument();
3081 OS <<
"TemplateArgument " << TA.getKindName();
3082 TD.dumpPointer(&TA);
3090 void WriteOccurenceList(StringRef Label,
3094 OS <<
" " << Label <<
"={"
3097 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3098 [](
unsigned I) { return llvm::to_string(I); }),
3107 dump(llvm::errs(), Context);
3112 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)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
ArrayRef< UnsatisfiedConstraintRecord > records() const
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...
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C, const NamedDecl *ConstraintOwner, ArrayRef< TemplateArgument > TemplateArgs)
llvm::SmallVector< UnsatisfiedConstraintRecord, 1 > 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...
llvm::BumpPtrAllocator BumpAlloc
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.
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.