30#include "llvm/ADT/DenseMap.h"
31#include "llvm/ADT/PointerUnion.h"
32#include "llvm/ADT/StringExtras.h"
33#include "llvm/Support/SaveAndRestore.h"
34#include "llvm/Support/ScopedPrinter.h"
35#include "llvm/Support/TimeProfiler.h"
44 const Expr *LHS =
nullptr;
45 const Expr *RHS =
nullptr;
48 LogicalBinOp(
const Expr *E) {
49 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
53 Loc = BO->getExprLoc();
54 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
56 if (OO->getNumArgs() == 2) {
57 Op = OO->getOperator();
60 Loc = OO->getOperatorLoc();
65 bool isAnd()
const {
return Op == OO_AmpAmp; }
66 bool isOr()
const {
return Op == OO_PipePipe; }
67 explicit operator bool()
const {
return isAnd() || isOr(); }
69 const Expr *getLHS()
const {
return LHS; }
70 const Expr *getRHS()
const {
return RHS; }
74 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
79 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
80 assert((!LHS.isInvalid() && !RHS.isInvalid()) &&
"not good expressions?");
82 if (!LHS.isUsable() || !RHS.isUsable())
96 Token NextToken,
bool *PossibleNonPrimary,
97 bool IsTrailingRequiresClause) {
103 if (LogicalBinOp BO = ConstraintExpression) {
105 PossibleNonPrimary) &&
108 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
114 auto CheckForNonPrimary = [&] {
115 if (!PossibleNonPrimary)
118 *PossibleNonPrimary =
129 (NextToken.
is(tok::l_paren) &&
130 (IsTrailingRequiresClause ||
148 CheckForNonPrimary();
154 diag::err_non_bool_atomic_constraint)
156 CheckForNonPrimary();
160 if (PossibleNonPrimary)
161 *PossibleNonPrimary =
false;
166struct SatisfactionStackRAII {
168 bool Inserted =
false;
170 const llvm::FoldingSetNodeID &FSNID)
177 ~SatisfactionStackRAII() {
189 for (
const auto &List : *MLTAL)
207 bool SkipForSpecialization =
false) {
213 true, SkipForSpecialization);
218class AdjustConstraints :
public TreeTransform<AdjustConstraints> {
219 unsigned TemplateDepth = 0;
221 bool RemoveNonPackExpansionPacks =
false;
224 using inherited = TreeTransform<AdjustConstraints>;
225 AdjustConstraints(Sema &SemaRef,
unsigned TemplateDepth,
226 bool RemoveNonPackExpansionPacks =
false)
227 : inherited(SemaRef), TemplateDepth(TemplateDepth),
228 RemoveNonPackExpansionPacks(RemoveNonPackExpansionPacks) {}
230 ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
232 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc, NumExpansions);
235 TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
236 SourceLocation EllipsisLoc,
238 if (!RemoveNonPackExpansionPacks)
239 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc,
245 TemplateArgumentLoc &Out, UnexpandedInfo &Info) {
246 if (!RemoveNonPackExpansionPacks)
247 return inherited::PreparePackForExpansion(In, Uneval, Out, Info);
248 assert(
In.getArgument().isPackExpansion());
254 using inherited::TransformTemplateTypeParmType;
255 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
256 TemplateTypeParmTypeLoc TL,
bool) {
259 TemplateTypeParmDecl *NewTTPDecl =
nullptr;
260 if (TemplateTypeParmDecl *OldTTPDecl =
T->getDecl())
261 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
264 QualType
Result = getSema().Context.getTemplateTypeParmType(
265 T->getDepth() + TemplateDepth,
T->getIndex(),
266 RemoveNonPackExpansionPacks ?
false :
T->isParameterPack(), NewTTPDecl);
267 TemplateTypeParmTypeLoc NewTL = TLB.
push<TemplateTypeParmTypeLoc>(
Result);
272 QualType TransformPackIndexingType(TypeLocBuilder &TLB,
273 PackIndexingTypeLoc TL) {
274 llvm::SaveAndRestore _1(RemoveNonPackExpansionPacks,
false);
275 return inherited::TransformPackIndexingType(TLB, TL);
278 bool AlreadyTransformed(QualType
T) {
288 ExprResult TransformDeclRefExpr(DeclRefExpr *E) {
289 NonTypeTemplateParmDecl *NTTP =
290 dyn_cast<NonTypeTemplateParmDecl>(E->
getDecl());
292 return inherited::TransformDeclRefExpr(E);
295 "Template arguments for NTTP decl?");
311 RemoveNonPackExpansionPacks ? NTTP : D,
321 using inherited = RecursiveASTVisitor<HashParameterMapping>;
325 const MultiLevelTemplateArgumentList &TemplateArgs;
326 llvm::FoldingSetNodeID &
ID;
327 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
331 bool shouldVisitTemplateInstantiations()
const {
return true; }
334 HashParameterMapping(Sema &SemaRef,
335 const MultiLevelTemplateArgumentList &TemplateArgs,
336 llvm::FoldingSetNodeID &ID,
338 : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
ID(
ID),
339 OuterPackSubstIndex(OuterPackSubstIndex) {}
341 bool VisitTemplateTypeParmType(TemplateTypeParmType *
T) {
352 TemplateArgument Arg = TemplateArgs(
T->getDepth(),
T->getIndex());
358 if ((
T->isParameterPack() ||
359 (
T->getDecl() &&
T->getDecl()->isTemplateParameterPack())) &&
362 "Missing argument pack");
367 UsedTemplateArgs.push_back(
372 bool VisitDeclRefExpr(DeclRefExpr *E) {
374 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
376 return TraverseDecl(D);
394 "Missing argument pack");
398 UsedTemplateArgs.push_back(
403 bool VisitTypedefType(TypedefType *TT) {
404 return inherited::TraverseType(TT->
desugar());
407 bool TraversePackIndexingType(PackIndexingType *
T,
bool TraverseQualifier) {
409 Sema::ArgPackSubstIndexRAII _(SemaRef, std::nullopt);
410 if (!TraverseType(
T->getPattern()))
413 return TraverseStmt(
T->getIndexExpr());
416 bool TraverseDecl(Decl *D) {
417 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
418 if (
auto *Var = dyn_cast<VarDecl>(VD))
419 TraverseStmt(Var->getInit());
420 return TraverseType(VD->getType());
423 return inherited::TraverseDecl(D);
426 bool TraverseCallExpr(CallExpr *CE) {
427 inherited::TraverseStmt(CE->
getCallee());
430 inherited::TraverseStmt(Arg);
435 bool TraverseCXXThisExpr(CXXThisExpr *E) {
436 return inherited::TraverseType(E->
getType());
439 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
444 bool TraverseDependentNameType(
const DependentNameType *
T,
446 return TraverseNestedNameSpecifier(
T->getQualifier());
449 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
457 bool TraverseUnresolvedUsingType(UnresolvedUsingType *
T,
458 bool TraverseQualifier) {
461 if (NestedNameSpecifier NNS =
T->getDecl()->getQualifier();
462 TraverseQualifier && NNS)
463 return inherited::TraverseNestedNameSpecifier(NNS);
464 return inherited::TraverseUnresolvedUsingType(
T, TraverseQualifier);
467 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
468 bool TraverseQualifier) {
469 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
472 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
475 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
476 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
478 return inherited::TraverseTemplateArgument(Arg);
481 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
482 return inherited::TraverseTemplateArgument(Arg);
485 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
486 return TraverseDecl(SOPE->
getPack());
489 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
494 bool TraverseQualifier =
true) {
495 if (
auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
502 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
505 "Missing argument pack");
509 "Null template template argument");
510 UsedTemplateArgs.push_back(
513 return inherited::TraverseTemplateName(
Template, TraverseQualifier);
516 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
517 switch (Constraint.
getKind()) {
518 case NormalizedConstraint::ConstraintKind::Atomic:
519 ID.AddPointer(
static_cast<const AtomicConstraint &
>(Constraint)
520 .getConstraintExpr());
523 case NormalizedConstraint::ConstraintKind::ConceptId:
525 static_cast<const ConceptIdConstraint &
>(Constraint).getConceptId());
528 case NormalizedConstraint::ConstraintKind::FoldExpanded:
530 static_cast<const FoldExpandedConstraint &
>(Constraint).getPattern());
532 case NormalizedConstraint::ConstraintKind::Compound:
533 llvm_unreachable(
"Cannot hash a compound constraint");
537 for (
const auto &List : TemplateArgs)
538 for (
const TemplateArgument &Arg : List.Args)
544 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
546 for (
auto &ArgLoc : Mapping) {
547 TemplateArgument Canonical =
550 UsedTemplateArgs.push_back(Canonical);
551 TraverseTemplateArgument(Canonical);
554 for (
auto &
Used : UsedTemplateArgs) {
555 llvm::FoldingSetNodeID
R;
571 bool BuildExpression;
578 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
582 struct ParameterMappingInstantiationCache {
583 llvm::FoldingSetNodeID ID;
585 HashParameterMapping H;
586 unsigned PreviousDetailsSize;
588 ParameterMappingInstantiationCache(
593 : Checker(Checker), H(Checker.S, MLTAL, ID,
PackIndex),
594 PreviousDetailsSize(PreviousDetailsSize
595 ? *PreviousDetailsSize
596 : Checker.Satisfaction.
Details.size()) {
597 H.VisitConstraint(Constraint);
601 auto &
Cache = Checker.S.UnsubstitutedConstraintSatisfactionCache;
602 auto Iter =
Cache.find(ID);
603 if (Iter ==
Cache.end())
605 auto &Satisfaction = Checker.Satisfaction;
606 auto &Cached = Iter->second.Satisfaction;
608 Satisfaction.IsSatisfied = Cached.IsSatisfied;
609 Satisfaction.Details.insert(Satisfaction.Details.begin() +
611 Cached.Details.begin(), Cached.Details.end());
612 return &Iter->second;
617 auto &Satisfaction = Checker.Satisfaction;
618 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
619 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
620 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
621 Satisfaction.Details.begin() +
623 Satisfaction.Details.end());
625 Checker.S.UnsubstitutedConstraintSatisfactionCache.insert(
626 {ID, std::move(
Cache)});
632 template <
class Constra
int>
634 return C.getPackSubstitutionIndex() ?
C.getPackSubstitutionIndex()
635 : PackSubstitutionIndex;
641 Diag.EmitToString(S.getDiagnostics(), DiagString);
642 return S.getASTContext().backupStr(DiagString);
656 Satisfaction.Details.emplace_back(
659 allocateStringFromConceptDiagnostic(SubstDiag.second)});
667 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
700 bool BuildExpression)
701 : S(SemaRef), Template(Template), TopLevelConceptId(TopLevelConceptId),
702 TemplateNameLoc(TemplateNameLoc),
703 PackSubstitutionIndex(PackSubstitutionIndex),
704 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
712ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
714 llvm::FoldingSetNodeID
ID;
717 Satisfaction.IsSatisfied =
false;
718 Satisfaction.ContainsErrors =
true;
721 SatisfactionStackRAII StackRAII(S, Template, ID);
724 ExprResult SubstitutedExpression =
const_cast<Expr *
>(AtomicExpr);
726 TemplateDeductionInfo Info(TemplateNameLoc);
727 Sema::InstantiatingTemplate Inst(
729 Sema::InstantiatingTemplate::ConstraintSubstitution{},
732 if (Inst.isInvalid())
736 Sema::SFINAETrap Trap(S, Info);
737 SubstitutedExpression =
738 S.SubstConstraintExpr(
const_cast<Expr *
>(AtomicExpr), MLTAL);
740 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
744 if (!Trap.hasErrorOccurred())
748 consumeSFINAEFailure(Info, Satisfaction);
753 if (!S.CheckConstraintExpression(SubstitutedExpression.
get()))
768 S.Context, SubstitutedExpression.
get()->
getType(), CK_LValueToRValue,
769 SubstitutedExpression.
get(),
772 return SubstitutedExpression;
775std::optional<MultiLevelTemplateArgumentList>
776ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
790 return MultiLevelTemplateArgumentList();
792 TemplateDeductionInfo Info(Constraint.
getBeginLoc());
793 Sema::SFINAETrap Trap(S, Info);
794 Sema::InstantiatingTemplate Inst(
796 Sema::InstantiatingTemplate::ConstraintSubstitution{},
799 if (Inst.isInvalid())
802 TemplateArgumentListInfo SubstArgs;
803 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
805 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
806 &CachedTemplateArgs);
810 if (S.SubstTemplateArgumentsInParameterMapping(
813 Satisfaction.IsSatisfied =
false;
814 if (Trap.hasErrorOccurred())
815 consumeSFINAEFailure(Info, Satisfaction);
819 Sema::CheckTemplateArgumentInfo CTAI;
820 auto *TD =
const_cast<TemplateDecl *
>(
823 TD->getLocation(), SubstArgs,
832 SubstitutedOutermost =
833 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
835 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
836 TemplateArgument Arg;
838 Arg = S.Context.getCanonicalTemplateArgument(
840 if (I < SubstitutedOutermost.size()) {
841 SubstitutedOutermost[I] = Arg;
844 SubstitutedOutermost.push_back(Arg);
845 Offset = SubstitutedOutermost.size();
848 if (Offset < SubstitutedOutermost.size())
849 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
851 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
854 return std::move(SubstitutedTemplateArgs);
857ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
860 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
864 EvaluationContext.emplace(
867 EvaluationContext.emplace(
871 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
872 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
873 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
874 if (!SubstitutedArgs) {
875 Satisfaction.IsSatisfied =
false;
882 std::optional<Sema::ContextRAII> ConceptContext;
884 ConceptContext.emplace(S, ParentConcept->getDeclContext());
886 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
887 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
893 if (SubstitutedAtomicExpr.
isUnset())
903 Satisfaction.IsSatisfied =
false;
904 Satisfaction.ContainsErrors =
true;
906 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
907 Satisfaction.Details.emplace_back(
909 SubstitutedAtomicExpr.get()->getBeginLoc(),
910 allocateStringFromConceptDiagnostic(Msg)});
911 return SubstitutedAtomicExpr;
915 Satisfaction.IsSatisfied =
true;
916 Satisfaction.ContainsErrors =
false;
917 return SubstitutedAtomicExpr;
920 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
921 Expr::EvalResult EvalResult;
922 EvalResult.
Diag = &EvaluationDiags;
925 !EvaluationDiags.empty()) {
929 diag::err_non_constant_constraint_expression)
932 S.Diag(PDiag.first, PDiag.second);
937 "evaluating bool expression didn't produce int");
938 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
939 if (!Satisfaction.IsSatisfied)
940 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
942 return SubstitutedAtomicExpr;
945ExprResult ConstraintSatisfactionChecker::Evaluate(
949 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
950 getOuterPackIndex(Constraint));
952 if (
auto *
V = PMCache.available())
955 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
958ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
964 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
966 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
968 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
969 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
970 SubstitutionInTemplateArguments(
971 static_cast<const NormalizedConstraintWithParamMapping &
>(Constraint),
972 MLTAL, SubstitutedOutermost);
973 if (!SubstitutedArgs) {
974 Satisfaction.IsSatisfied =
false;
980 Sema::InstantiatingTemplate InstTemplate(
982 Sema::InstantiatingTemplate::ConstraintSubstitution{},
984 NumExpansions = S.EvaluateFoldExpandedConstraintSize(
990 if (*NumExpansions == 0) {
991 Satisfaction.IsSatisfied = Conjunction;
996 for (
unsigned I = 0; I < *NumExpansions; I++) {
997 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
998 Satisfaction.IsSatisfied =
false;
999 Satisfaction.ContainsErrors =
false;
1006 if (BuildExpression) {
1011 Conjunction ? BinaryOperatorKind::BO_LAnd
1012 : BinaryOperatorKind::BO_LOr,
1015 FPOptionsOverride{});
1017 if (!Conjunction && Satisfaction.IsSatisfied) {
1018 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1019 EffectiveDetailEndIndex,
1020 Satisfaction.Details.end());
1023 if (Satisfaction.IsSatisfied != Conjunction)
1030ExprResult ConstraintSatisfactionChecker::Evaluate(
1034 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
1037 if (
auto *
V = PMCache.available())
1038 return V->SubstExpr;
1040 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
1043ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1046 const ConceptReference *ConceptId = Constraint.
getConceptId();
1048 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
1049 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1050 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1052 if (!SubstitutedArgs) {
1053 Satisfaction.IsSatisfied =
false;
1057 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
1059 const ASTTemplateArgumentListInfo *Ori =
1061 TemplateDeductionInfo Info(TemplateNameLoc);
1062 Sema::SFINAETrap Trap(S, Info);
1063 Sema::InstantiatingTemplate
_2(
1064 S, TemplateNameLoc, Sema::InstantiatingTemplate::ConstraintSubstitution{},
1071 if (TopLevelConceptId &&
1073 TopLevelConceptId->getNamedConcept().getAsTemplateDecl()) {
1075 OutArgs.addArgument(A);
1076 }
else if (S.SubstTemplateArguments(Ori->
arguments(), *SubstitutedArgs,
1078 Trap.hasErrorOccurred()) {
1079 Satisfaction.IsSatisfied =
false;
1080 if (Trap.hasErrorOccurred())
1081 consumeSFINAEFailure(Info, Satisfaction);
1088 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1094 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
1097 if (Size != Satisfaction.Details.size()) {
1098 Satisfaction.Details.insert(
1099 Satisfaction.Details.begin() + Size,
1101 SubstitutedConceptId.
getAs<ConceptSpecializationExpr>()
1102 ->getConceptReference()));
1104 return SubstitutedConceptId;
1107ExprResult ConstraintSatisfactionChecker::Evaluate(
1111 const ConceptReference *ConceptId = Constraint.
getConceptId();
1112 Sema::InstantiatingTemplate InstTemplate(
1114 Sema::InstantiatingTemplate::ConstraintsCheck{},
1122 : ArrayRef<TemplateArgument>{},
1124 if (InstTemplate.isInvalid())
1127 unsigned Size = Satisfaction.Details.size();
1129 llvm::SaveAndRestore PushConceptDecl(
1136 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1143 if (Satisfaction.IsSatisfied)
1146 ParameterMappingInstantiationCache PMCache(
1147 *
this, Constraint, MLTAL, getOuterPackIndex(Constraint), Size);
1149 if (
auto *
V = PMCache.available())
1150 return V->SubstExpr;
1152 return PMCache.cache(EvaluateSlow(Constraint, MLTAL, Size));
1155ExprResult ConstraintSatisfactionChecker::Evaluate(
1159 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1166 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1169 if (!Conjunction && !LHS.
isInvalid() && Satisfaction.IsSatisfied &&
1170 !Satisfaction.ContainsErrors)
1173 Satisfaction.ContainsErrors =
false;
1174 Satisfaction.IsSatisfied =
false;
1178 if (!Conjunction && !RHS.
isInvalid() && Satisfaction.IsSatisfied &&
1179 !Satisfaction.ContainsErrors)
1180 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1181 EffectiveDetailEndIndex,
1182 Satisfaction.Details.end());
1184 if (!BuildExpression)
1194 Conjunction ? BinaryOperatorKind::BO_LAnd
1195 : BinaryOperatorKind::BO_LOr,
1203 switch (Constraint.
getKind()) {
1218 llvm_unreachable(
"Unknown ConstraintKind enum");
1229 *ConvertedExpr =
nullptr;
1231 if (AssociatedConstraints.empty()) {
1251 struct SynthesisContextPair {
1257 : Inst(S, InstantiationRange.
getBegin(),
1259 TemplateArgs, InstantiationRange),
1262 std::optional<SynthesisContextPair> SynthesisContext;
1263 if (!TopLevelConceptId)
1274 if (TopLevelConceptId)
1284 ConvertedExpr !=
nullptr)
1285 .Evaluate(*
C, TemplateArgsLists);
1287 if (Res.
isUsable() && ConvertedExpr)
1288 *ConvertedExpr = Res.
get();
1299 llvm::TimeTraceScope TimeScope(
1300 "CheckConstraintSatisfaction", [TemplateIDRange,
this] {
1303 if (AssociatedConstraints.empty()) {
1307 const auto *
Template = dyn_cast_if_present<const NamedDecl *>(Entity);
1309 return ::CheckConstraintSatisfaction(
1310 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1311 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1325 for (
auto List : TemplateArgsLists)
1327 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1330 if (TopLevelConceptId)
1333 llvm::FoldingSetNodeID ID;
1335 llvm::FoldingSetInsertToken
Token;
1336 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1337 OutSatisfaction = *Cached;
1342 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1344 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1345 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1346 OutSatisfaction = std::move(*Satisfaction);
1350 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1359 OutSatisfaction = *Cached;
1364 OutSatisfaction = *Satisfaction;
1366 SatisfactionCache.insert(Satisfaction.release());
1388 return !ArgLoc.getArgument().isDependent() &&
1389 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1391 return Concept->getConstraintExpr();
1404bool Sema::SetupConstraintScope(
1409 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1415 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1416 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1418 if (Inst.isInvalid())
1427 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1429 if (addInstantiatedParametersToScope(
1436 if (FunctionTemplateDecl *FromMemTempl =
1438 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1448 FunctionDecl *InstantiatedFrom =
1455 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1456 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1458 if (Inst.isInvalid())
1463 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1472std::optional<MultiLevelTemplateArgumentList>
1473Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1476 MultiLevelTemplateArgumentList MLTAL;
1483 false, std::nullopt,
1490 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1491 return std::nullopt;
1499 bool ForOverloadResolution) {
1518 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1521 Satisfaction, UsageLoc,
1535 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1536 SetupConstraintCheckingTemplateArgumentsAndScope(
1544 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1545 ThisQuals =
Method->getMethodQualifiers();
1552 ForOverloadResolution);
1562 const Expr *ConstrExpr) {
1577 std::optional<LocalInstantiationScope> ScopeForParameters;
1580 ScopeForParameters.emplace(S,
true);
1584 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1586 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1588 if (!PVD->isParameterPack()) {
1589 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1608 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1609 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1613 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1622 std::optional<Sema::ContextRAII> ContextScope;
1630 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1642 return SubstConstr.
get();
1646 const Expr *OldConstr,
1648 const Expr *NewConstr) {
1649 if (OldConstr == NewConstr)
1652 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1655 if (
const Expr *SubstConstr =
1658 OldConstr = SubstConstr;
1661 if (
const Expr *SubstConstr =
1664 NewConstr = SubstConstr;
1669 llvm::FoldingSetNodeID ID1, ID2;
1682 "Non-function templates don't need to be checked");
1703 TemplateIDRange, Satisfaction) ||
1706 TemplateArgString =
" ";
1712 diag::err_template_arg_list_constraints_not_satisfied)
1714 << TemplateArgString << TemplateIDRange;
1726 Template->getAssociatedConstraints(TemplateAC);
1727 if (TemplateAC.empty()) {
1746 SemaRef, PointOfInstantiation,
1748 PointOfInstantiation);
1749 if (Inst.isInvalid())
1759 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1770 return ::CheckFunctionConstraintsWithoutInstantiation(
1771 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1772 TemplateArgs, Satisfaction);
1777 Template->getAssociatedConstraints(TemplateAC);
1778 if (TemplateAC.empty()) {
1788 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1789 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1797 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1798 ThisQuals =
Method->getMethodQualifiers();
1807 PointOfInstantiation, Satisfaction);
1814 "Diagnose() can only be used on an unsatisfied requirement");
1817 llvm_unreachable(
"Diagnosing a dependent requirement");
1821 if (!SubstDiag->DiagMessage.empty())
1822 S.
Diag(SubstDiag->DiagLoc,
1823 diag::note_expr_requirement_expr_substitution_error)
1824 << (
int)
First << SubstDiag->SubstitutedEntity
1825 << SubstDiag->DiagMessage;
1827 S.
Diag(SubstDiag->DiagLoc,
1828 diag::note_expr_requirement_expr_unknown_substitution_error)
1829 << (
int)
First << SubstDiag->SubstitutedEntity;
1839 if (!SubstDiag->DiagMessage.empty())
1840 S.
Diag(SubstDiag->DiagLoc,
1841 diag::note_expr_requirement_type_requirement_substitution_error)
1842 << (
int)
First << SubstDiag->SubstitutedEntity
1843 << SubstDiag->DiagMessage;
1848 note_expr_requirement_type_requirement_unknown_substitution_error)
1849 << (
int)
First << SubstDiag->SubstitutedEntity;
1859 llvm_unreachable(
"We checked this above");
1867 "Diagnose() can only be used on an unsatisfied requirement");
1870 llvm_unreachable(
"Diagnosing a dependent requirement");
1874 if (!SubstDiag->DiagMessage.empty())
1875 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1876 << (
int)
First << SubstDiag->SubstitutedEntity
1877 << SubstDiag->DiagMessage;
1879 S.
Diag(SubstDiag->DiagLoc,
1880 diag::note_type_requirement_unknown_substitution_error)
1881 << (
int)
First << SubstDiag->SubstitutedEntity;
1885 llvm_unreachable(
"Unknown satisfaction status");
1893 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1897 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1899 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1900 <<
Concept->getNamedConcept().getAsTemplateDecl();
1902 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1932 const Expr *SubstExpr,
1935 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1936 switch (BO->getOpcode()) {
1948 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1959 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1971 if (BO->getLHS()->getType()->isIntegerType() &&
1972 BO->getRHS()->getType()->isIntegerType()) {
1975 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1978 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1981 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1983 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1996 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1999 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
2003 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
2004 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
2005 assert(TTE->getNumArgs() == 2);
2007 diag::note_is_deducible_constraint_evaluated_to_false)
2008 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2013 diag::note_atomic_constraint_evaluated_to_false)
2021 if (
auto *
Diag = dyn_cast<const ConstraintSubstitutionDiagnostic *>(
Record)) {
2023 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
2026 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2030 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
2043 if (!Req->isDependent() && !Req->isSatisfied()) {
2044 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2046 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
2060 "Attempted to diagnose a satisfied constraint");
2071 "Attempted to diagnose a satisfied constraint");
2079class SubstituteParameterMappings {
2091 bool RemovePacksForFoldExpr;
2093 SubstituteParameterMappings(
Sema &SemaRef,
2096 bool RemovePacksForFoldExpr)
2097 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2098 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2108 bool RemovePacksForFoldExpr =
false)
2110 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2117void SubstituteParameterMappings::buildParameterMapping(
2119 TemplateParameterList *TemplateParams =
2122 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2123 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2126 SemaRef.MarkUsedTemplateParameters(
2127 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2129 0, OccurringIndices);
2131 SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(
2132 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2133 0, OccurringIndicesForSubsumption);
2137 SemaRef.MarkUsedTemplateParameters(
2138 static_cast<FoldExpandedConstraint &
>(N).getPattern(),
2140 0, OccurringIndices);
2142 auto *Args =
static_cast<ConceptIdConstraint &
>(N)
2144 ->getTemplateArgsAsWritten();
2146 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2147 0, OccurringIndices);
2153 llvm::SmallVector<TemplateArgument> DefaultArgs;
2155 I < TemplateParams->size(); ++I) {
2156 const NamedDecl *Param = TemplateParams->
getParam(I);
2159 const TemplateArgument *Arg =
2160 SemaRef.getASTContext().getDefaultTemplateArgumentOrNone(Param);
2161 assert(Arg &&
"expected a default argument");
2162 DefaultArgs.emplace_back(std::move(*Arg));
2164 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2165 0, OccurringIndices);
2166 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2168 OccurringIndicesForSubsumption);
2171 unsigned Size = OccurringIndices.count();
2176 TemplateArgumentLoc *TempArgs =
2177 new (SemaRef.Context) TemplateArgumentLoc[Size];
2178 llvm::SmallVector<NamedDecl *> UsedParams;
2179 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2180 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2181 ? ArgsAsWritten->arguments()[I].getLocation()
2185 if (OccurringIndices[I]) {
2186 NamedDecl *Param = TemplateParams->
begin()[I];
2187 new (&(TempArgs)[J]) TemplateArgumentLoc(
2188 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2189 UsedParams.push_back(Param);
2199 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2200 MutableArrayRef<TemplateArgumentLoc>{TempArgs,
Size}, UsedList);
2203bool SubstituteParameterMappings::substitute(
2206 buildParameterMapping(N);
2212 SourceLocation InstLocBegin, InstLocEnd;
2213 llvm::ArrayRef
Arguments = ArgsAsWritten->arguments();
2215 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2216 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2218 auto SR =
Arguments[0].getSourceRange();
2219 InstLocBegin = SR.getBegin();
2220 InstLocEnd = SR.getEnd();
2222 Sema::NonSFINAEContext _(SemaRef);
2223 Sema::InstantiatingTemplate Inst(
2224 SemaRef, InstLocBegin,
2225 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2227 {InstLocBegin, InstLocEnd});
2228 if (Inst.isInvalid())
2235 TemplateArgumentListInfo SubstArgs;
2236 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2237 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2238 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2241 Sema::CheckTemplateArgumentInfo CTAI;
2245 TD->getLocation(), SubstArgs,
2250 TemplateArgumentLoc *TempArgs =
2256 if (I < SubstArgs.
size())
2257 Loc = SubstArgs.
arguments()[I].getLocation();
2259 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2263 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2274 if (substitute(
static_cast<NormalizedConstraintWithParamMapping &
>(CC)))
2281 SourceLocation InstLocBegin, InstLocEnd;
2282 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2284 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2285 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2287 auto SR =
Arguments[0].getSourceRange();
2288 InstLocBegin = SR.getBegin();
2289 InstLocEnd = SR.getEnd();
2291 Sema::NonSFINAEContext _(SemaRef);
2293 Sema::InstantiatingTemplate Inst(
2294 SemaRef, InstLocBegin,
2295 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2297 {InstLocBegin, InstLocEnd});
2298 if (Inst.isInvalid())
2301 TemplateArgumentListInfo
Out;
2306 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2307 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2308 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2309 CSE->getTemplateArgsAsWritten();
2310 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2311 ArgsAsWritten->arguments(), CC.
getBeginLoc(), *MLTAL, Out))
2313 Sema::CheckTemplateArgumentInfo CTAI;
2314 if (SemaRef.CheckTemplateArgumentList(CSE->getConceptDecl(),
2315 CSE->getConceptNameInfo().getLoc(), Out,
2320 auto TemplateArgs = *MLTAL;
2321 TemplateArgs.replaceOutermostTemplateArguments(CSE->getConceptDecl(),
2323 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2324 RemovePacksForFoldExpr)
2332 assert(!ArgsAsWritten);
2341 assert(!ArgsAsWritten);
2342 return substitute(FE.getNormalizedPattern());
2346 return SubstituteParameterMappings(SemaRef,
true)
2347 .substitute(FE.getNormalizedPattern());
2352 assert(ArgsAsWritten);
2353 return substitute(CC);
2355 assert(!ArgsAsWritten);
2367 if (RemovePacksForFoldExpr) {
2371 if (AdjustConstraints(SemaRef, 0,
2373 .TransformTemplateArguments(InputArgLoc.begin(),
2374 InputArgLoc.end(), OutArgs))
2378 if (SemaRef.CheckTemplateArgumentList(
2395 return SubstituteParameterMappings(SemaRef, &MLTAL,
2397 RemovePacksForFoldExpr)
2402 if (substitute(Compound.getLHS()))
2404 return substitute(Compound.getRHS());
2407 llvm_unreachable(
"Unknown ConstraintKind enum");
2412 assert(ACs.size() != 0);
2414 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2417 for (
unsigned I = 1; I < ACs.size(); ++I) {
2418 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2419 ACs[I].ArgPackSubstIndex);
2430 assert(E !=
nullptr);
2438 llvm::FoldingSetNodeID
ID;
2442 SatisfactionStackRAII StackRAII(S, D, ID);
2449 if (LogicalBinOp BO = E) {
2450 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2453 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2460 if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2476 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2477 S, CSE->getConceptDecl()->getCanonicalDecl(),
2478 AssociatedConstraint(Res.get(), SubstIndex));
2482 CSE->getConceptReference(), SubNF, D,
2485 if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2487 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2488 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2493 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2497 if (FE->getInit()) {
2498 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2499 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2503 if (FE->isRightFold())
2505 FE->getPattern(), D, Kind, LHS);
2508 FE->getPattern(), D, Kind, RHS);
2516 auto *
Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2528 if (!ConstrainedDeclOrNestedReq) {
2529 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2530 *
this,
nullptr, AssociatedConstraints);
2539 const NamedDecl *ND = dyn_cast<const NamedDecl *>(ConstrainedDeclOrNestedReq);
2547 std::pair<const Expr *, unsigned> Key(
2548 AC.ConstraintExpr, AC.ArgPackSubstIndex.toInternalRepresentation());
2550 if (
auto It = NormalizedConstraintExprCache.find(Key);
2551 It != NormalizedConstraintExprCache.end()) {
2554 Next = NormalizedConstraint::fromAssociatedConstraints(*
this, ND, AC);
2558 NormalizedConstraintExprCache.try_emplace(Key,
Next);
2590 if (It != BPacks.end())
2602 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2608 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2609 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2610 "use non-instantiated function declaration for constraints partial "
2625 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2626 auto CacheEntry = SubsumptionCache.find(Key);
2627 if (CacheEntry != SubsumptionCache.end()) {
2628 Result = CacheEntry->second;
2635 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2636 if (Depth2 > Depth1) {
2637 AC1[I].ConstraintExpr =
2638 AdjustConstraints(*
this, Depth2 - Depth1)
2639 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2641 }
else if (Depth1 > Depth2) {
2642 AC2[I].ConstraintExpr =
2643 AdjustConstraints(*
this, Depth1 - Depth2)
2644 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2653 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2654 if (Depth2 > Depth1)
2656 else if (Depth1 > Depth2)
2658 std::optional<bool> Subsumes = SC.
Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2664 SubsumptionCache.try_emplace(Key, *Subsumes);
2675 if (AC1.empty() || AC2.empty())
2678 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2689 llvm::FoldingSetNodeID IDA, IDB;
2691 EB->Profile(IDB,
Context,
true);
2695 AmbiguousAtomic1 = EA;
2696 AmbiguousAtomic2 = EB;
2711 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2712 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2715 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2716 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2718 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2719 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2724 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2726 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2728 Diag(AmbiguousAtomic2->getBeginLoc(),
2729 diag::note_ambiguous_atomic_constraints_similar_expression)
2730 << AmbiguousAtomic2->getSourceRange();
2741 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2743uint16_t SubsumptionChecker::getNewLiteralId() {
2744 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2745 "too many constraints!");
2750 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2765 llvm::FoldingSetNodeID ID;
2766 ID.AddBoolean(Ori->hasParameterMapping());
2767 if (Ori->hasParameterMapping()) {
2768 const auto &Mapping = Ori->getParameterMapping();
2770 Ori->mappingOccurenceListForSubsumption();
2771 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2778 auto It = Elems.find(ID);
2779 if (It == Elems.end()) {
2782 MappedAtomicConstraint{
2783 Ori, {getNewLiteralId(), Literal::Atomic}}})
2785 ReverseMap[It->second.ID.Value] = Ori;
2787 return It->getSecond().ID;
2791 auto &Elems = FoldMap[Ori->getPattern()];
2793 FoldExpendedConstraintKey K;
2794 K.Kind = Ori->getFoldOperator();
2796 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2797 return K.Kind ==
Other.Kind;
2799 if (It == Elems.end()) {
2800 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2801 It = Elems.insert(Elems.end(), std::move(K));
2802 ReverseMap[It->ID.Value] = Ori;
2808 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2811 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2827template <
typename FormulaType>
2831 auto Add = [&,
this](Clause
C) {
2834 C.erase(llvm::unique(
C),
C.end());
2835 AddUniqueClauseToFormula(Res, std::move(
C));
2840 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2843 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2846 return Normalize<FormulaType>(
2847 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2850 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2852 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2853 Left = Normalize<FormulaType>(Compound.getLHS());
2854 Right = Normalize<FormulaType>(Compound.getRHS());
2857 if (Compound.getCompoundKind() == FormulaType::Kind) {
2858 unsigned SizeLeft =
Left.size();
2859 Res = std::move(Left);
2860 Res.reserve(SizeLeft +
Right.size());
2861 std::for_each(std::make_move_iterator(
Right.begin()),
2862 std::make_move_iterator(
Right.end()), Add);
2866 Res.reserve(
Left.size() *
Right.size());
2867 for (
const auto <ransform : Left) {
2868 for (
const auto &RTransform : Right) {
2870 Combined.reserve(LTransform.size() + RTransform.size());
2871 llvm::copy(LTransform, std::back_inserter(Combined));
2872 llvm::copy(RTransform, std::back_inserter(Combined));
2873 Add(std::move(Combined));
2879 llvm_unreachable(
"Unknown ConstraintKind enum");
2882void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2883 for (
auto &
Other : F) {
2884 if (llvm::equal(
C,
Other))
2894 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2896 return std::nullopt;
2899 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2901 return std::nullopt;
2903 return Subsumes(PNormalized, QNormalized);
2909 DNFFormula DNFP = DNF(*P);
2910 CNFFormula CNFQ = CNF(*Q);
2915 const CNFFormula &QCNF) {
2916 for (
const auto &Pi : PDNF) {
2917 for (
const auto &Qj : QCNF) {
2923 if (!DNFSubsumes(Pi, Qj))
2930bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2932 return llvm::any_of(P, [&](Literal LP) {
2933 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2939 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2942 auto It = FoldSubsumptionCache.find(Key);
2943 if (It == FoldSubsumptionCache.end()) {
2952 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2958 if (A.Kind != B.Kind)
2961 case Literal::Atomic:
2963 return A.Value == B.Value;
2965 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2966 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2967 case Literal::FoldExpanded:
2969 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2970 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2972 llvm_unreachable(
"unknown literal kind");
2977class DumpNormalizedConstraint {
2979 const PrintingPolicy &PP;
2983 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2984 :
OS(
OS), PP(Context.getPrintingPolicy()),
2987 void dump(
const NormalizedConstraint &N) {
2992 void Traverse(
const NormalizedConstraint &N) {
2994 case NormalizedConstraint::ConstraintKind::Compound:
2995 VisitCompound(
static_cast<const CompoundConstraint &
>(N));
2997 case NormalizedConstraint::ConstraintKind::Atomic:
2998 VisitAtomic(
static_cast<const AtomicConstraint &
>(N));
3000 case NormalizedConstraint::ConstraintKind::ConceptId:
3001 VisitConceptId(
static_cast<const ConceptIdConstraint &
>(N));
3003 case NormalizedConstraint::ConstraintKind::FoldExpanded:
3004 VisitFoldExpanded(
static_cast<const FoldExpandedConstraint &
>(N));
3009 void WriteNodeHeader(
const NormalizedConstraint &N, StringRef Kind) {
3015 void WritePackIndex(
const NormalizedConstraintWithParamMapping &N) {
3017 OS <<
" SubstIndex=" << *Idx;
3020 void VisitCompound(
const CompoundConstraint &
C) {
3021 WriteNodeHeader(
C,
"CompoundConstraint");
3026 TD.
AddChild([&] { Traverse(
C.getLHS()); });
3027 TD.
AddChild([&] { Traverse(
C.getRHS()); });
3030 void VisitAtomic(
const AtomicConstraint &A) {
3031 WriteNodeHeader(A,
"AtomicConstraint");
3035 WriteParameterMapping(A);
3038 void VisitConceptId(
const ConceptIdConstraint &
C) {
3039 WriteNodeHeader(
C,
"ConceptIdConstraint");
3042 if (
auto *CSE =
C.getConceptSpecializationExpr()) {
3043 CSE->printPretty(OS,
nullptr, PP);
3045 C.getConceptId()->print(OS, PP);
3047 WriteParameterMapping(
C);
3048 TD.
AddChild([&] { Traverse(
C.getNormalizedConstraint()); });
3051 void VisitFoldExpanded(
const FoldExpandedConstraint &F) {
3052 WriteNodeHeader(F,
"FoldExpandedConstraint");
3054 << (F.
getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3060 WriteParameterMapping(F);
3064 void WriteParameterMapping(
const NormalizedConstraintWithParamMapping &N) {
3071 OS <<
"ParameterMapping";
3072 WriteOccurenceList(
"Indexes", Indexes);
3073 WriteOccurenceList(
"IndexesForSubsumption", IndexesForSub);
3075 for (unsigned ParamIndex : Indexes.set_bits()) {
3076 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3077 assert(TPL && Slot < TPL->size());
3078 const NamedDecl *Param = TPL->getParam(Slot);
3079 OS <<
"#" << ParamIndex <<
": <";
3080 Param->print(OS, PP);
3082 Mapping[Slot].getArgument().print(PP, OS,
3084 TD.AddChild([this, Slot, Mapping] {
3085 const TemplateArgument &TA = Mapping[Slot].getArgument();
3086 OS <<
"TemplateArgument " << TA.getKindName();
3087 TD.dumpPointer(&TA);
3095 void WriteOccurenceList(StringRef Label,
3099 OS <<
" " << Label <<
"={"
3102 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3103 [](
unsigned I) { return llvm::to_string(I); }),
3112 dump(llvm::errs(), Context);
3117 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.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool containsErrors() const
Whether this expression contains subexpressions which had errors.
bool EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, ConstantExprKind Kind=ConstantExprKind::Normal) const
Evaluate an expression that is required to be a constant expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
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.