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 TraverseDecl(Decl *D) {
408 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
409 if (
auto *Var = dyn_cast<VarDecl>(VD))
410 TraverseStmt(Var->getInit());
411 return TraverseType(VD->getType());
414 return inherited::TraverseDecl(D);
417 bool TraverseCallExpr(CallExpr *CE) {
418 inherited::TraverseStmt(CE->
getCallee());
421 inherited::TraverseStmt(Arg);
426 bool TraverseCXXThisExpr(CXXThisExpr *E) {
427 return inherited::TraverseType(E->
getType());
430 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
435 bool TraverseDependentNameType(
const DependentNameType *
T,
437 return TraverseNestedNameSpecifier(
T->getQualifier());
440 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
448 bool TraverseUnresolvedUsingType(UnresolvedUsingType *
T,
449 bool TraverseQualifier) {
452 if (NestedNameSpecifier NNS =
T->getDecl()->getQualifier();
453 TraverseQualifier && NNS)
454 return inherited::TraverseNestedNameSpecifier(NNS);
455 return inherited::TraverseUnresolvedUsingType(
T, TraverseQualifier);
458 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
459 bool TraverseQualifier) {
460 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
463 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
466 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
467 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
469 return inherited::TraverseTemplateArgument(Arg);
472 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
473 return inherited::TraverseTemplateArgument(Arg);
476 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
477 return TraverseDecl(SOPE->
getPack());
480 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
485 bool TraverseQualifier =
true) {
486 if (
auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
493 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
496 "Missing argument pack");
500 "Null template template argument");
501 UsedTemplateArgs.push_back(
504 return inherited::TraverseTemplateName(
Template, TraverseQualifier);
507 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
508 switch (Constraint.
getKind()) {
509 case NormalizedConstraint::ConstraintKind::Atomic:
510 ID.AddPointer(
static_cast<const AtomicConstraint &
>(Constraint)
511 .getConstraintExpr());
514 case NormalizedConstraint::ConstraintKind::ConceptId:
516 static_cast<const ConceptIdConstraint &
>(Constraint).getConceptId());
519 case NormalizedConstraint::ConstraintKind::FoldExpanded:
521 static_cast<const FoldExpandedConstraint &
>(Constraint).getPattern());
523 case NormalizedConstraint::ConstraintKind::Compound:
524 llvm_unreachable(
"Cannot hash a compound constraint");
528 for (
const auto &List : TemplateArgs)
529 for (
const TemplateArgument &Arg : List.Args)
535 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
537 for (
auto &ArgLoc : Mapping) {
538 TemplateArgument Canonical =
541 UsedTemplateArgs.push_back(Canonical);
542 TraverseTemplateArgument(Canonical);
545 for (
auto &
Used : UsedTemplateArgs) {
546 llvm::FoldingSetNodeID
R;
562 bool BuildExpression;
569 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
573 struct ParameterMappingInstantiationCache {
574 llvm::FoldingSetNodeID ID;
576 HashParameterMapping H;
577 unsigned PreviousDetailsSize;
579 ParameterMappingInstantiationCache(
584 : Checker(Checker), H(Checker.S, MLTAL, ID,
PackIndex),
585 PreviousDetailsSize(PreviousDetailsSize
586 ? *PreviousDetailsSize
587 : Checker.Satisfaction.
Details.size()) {
588 H.VisitConstraint(Constraint);
592 auto &
Cache = Checker.S.UnsubstitutedConstraintSatisfactionCache;
593 auto Iter =
Cache.find(ID);
594 if (Iter ==
Cache.end())
596 auto &Satisfaction = Checker.Satisfaction;
597 auto &Cached = Iter->second.Satisfaction;
599 Satisfaction.IsSatisfied = Cached.IsSatisfied;
600 Satisfaction.Details.insert(Satisfaction.Details.begin() +
602 Cached.Details.begin(), Cached.Details.end());
603 return &Iter->second;
608 auto &Satisfaction = Checker.Satisfaction;
609 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
610 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
611 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
612 Satisfaction.Details.begin() +
614 Satisfaction.Details.end());
616 Checker.S.UnsubstitutedConstraintSatisfactionCache.insert(
617 {ID, std::move(
Cache)});
623 template <
class Constra
int>
625 return C.getPackSubstitutionIndex() ?
C.getPackSubstitutionIndex()
626 : PackSubstitutionIndex;
632 Diag.EmitToString(S.getDiagnostics(), DiagString);
633 return S.getASTContext().backupStr(DiagString);
647 Satisfaction.Details.emplace_back(
650 allocateStringFromConceptDiagnostic(SubstDiag.second)});
658 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
691 bool BuildExpression)
692 : S(SemaRef), Template(Template), TopLevelConceptId(TopLevelConceptId),
693 TemplateNameLoc(TemplateNameLoc),
694 PackSubstitutionIndex(PackSubstitutionIndex),
695 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
703ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
705 llvm::FoldingSetNodeID
ID;
708 Satisfaction.IsSatisfied =
false;
709 Satisfaction.ContainsErrors =
true;
712 SatisfactionStackRAII StackRAII(S, Template, ID);
715 ExprResult SubstitutedExpression =
const_cast<Expr *
>(AtomicExpr);
717 TemplateDeductionInfo Info(TemplateNameLoc);
718 Sema::InstantiatingTemplate Inst(
720 Sema::InstantiatingTemplate::ConstraintSubstitution{},
723 if (Inst.isInvalid())
727 Sema::SFINAETrap Trap(S, Info);
728 SubstitutedExpression =
729 S.SubstConstraintExpr(
const_cast<Expr *
>(AtomicExpr), MLTAL);
731 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
735 if (!Trap.hasErrorOccurred())
739 consumeSFINAEFailure(Info, Satisfaction);
744 if (!S.CheckConstraintExpression(SubstitutedExpression.
get()))
759 S.Context, SubstitutedExpression.
get()->
getType(), CK_LValueToRValue,
760 SubstitutedExpression.
get(),
763 return SubstitutedExpression;
766std::optional<MultiLevelTemplateArgumentList>
767ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
781 return MultiLevelTemplateArgumentList();
783 TemplateDeductionInfo Info(Constraint.
getBeginLoc());
784 Sema::SFINAETrap Trap(S, Info);
785 Sema::InstantiatingTemplate Inst(
787 Sema::InstantiatingTemplate::ConstraintSubstitution{},
790 if (Inst.isInvalid())
793 TemplateArgumentListInfo SubstArgs;
794 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
796 llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs,
797 &CachedTemplateArgs);
801 if (S.SubstTemplateArgumentsInParameterMapping(
804 Satisfaction.IsSatisfied =
false;
805 if (Trap.hasErrorOccurred())
806 consumeSFINAEFailure(Info, Satisfaction);
810 Sema::CheckTemplateArgumentInfo CTAI;
811 auto *TD =
const_cast<TemplateDecl *
>(
814 TD->getLocation(), SubstArgs,
823 SubstitutedOutermost =
824 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
826 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
827 TemplateArgument Arg;
829 Arg = S.Context.getCanonicalTemplateArgument(
831 if (I < SubstitutedOutermost.size()) {
832 SubstitutedOutermost[I] = Arg;
835 SubstitutedOutermost.push_back(Arg);
836 Offset = SubstitutedOutermost.size();
839 if (Offset < SubstitutedOutermost.size())
840 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
842 MultiLevelTemplateArgumentList SubstitutedTemplateArgs;
845 return std::move(SubstitutedTemplateArgs);
848ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
851 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
855 EvaluationContext.emplace(
858 EvaluationContext.emplace(
862 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
863 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
864 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
865 if (!SubstitutedArgs) {
866 Satisfaction.IsSatisfied =
false;
873 std::optional<Sema::ContextRAII> ConceptContext;
875 ConceptContext.emplace(S, ParentConcept->getDeclContext());
877 Sema::ArgPackSubstIndexRAII SubstIndex(S, PackSubstitutionIndex);
878 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
884 if (SubstitutedAtomicExpr.
isUnset())
894 Satisfaction.IsSatisfied =
false;
895 Satisfaction.ContainsErrors =
true;
897 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error);
898 Satisfaction.Details.emplace_back(
900 SubstitutedAtomicExpr.get()->getBeginLoc(),
901 allocateStringFromConceptDiagnostic(Msg)});
902 return SubstitutedAtomicExpr;
906 Satisfaction.IsSatisfied =
true;
907 Satisfaction.ContainsErrors =
false;
908 return SubstitutedAtomicExpr;
911 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
912 Expr::EvalResult EvalResult;
913 EvalResult.
Diag = &EvaluationDiags;
916 !EvaluationDiags.empty()) {
920 diag::err_non_constant_constraint_expression)
923 S.Diag(PDiag.first, PDiag.second);
928 "evaluating bool expression didn't produce int");
929 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
930 if (!Satisfaction.IsSatisfied)
931 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
933 return SubstitutedAtomicExpr;
936ExprResult ConstraintSatisfactionChecker::Evaluate(
940 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
941 getOuterPackIndex(Constraint));
943 if (
auto *
V = PMCache.available())
946 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
949ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
955 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
957 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
959 llvm::SaveAndRestore _(PackSubstitutionIndex, S.ArgPackSubstIndex);
960 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
961 SubstitutionInTemplateArguments(
962 static_cast<const NormalizedConstraintWithParamMapping &
>(Constraint),
963 MLTAL, SubstitutedOutermost);
964 if (!SubstitutedArgs) {
965 Satisfaction.IsSatisfied =
false;
971 Sema::InstantiatingTemplate InstTemplate(
973 Sema::InstantiatingTemplate::ConstraintSubstitution{},
975 NumExpansions = S.EvaluateFoldExpandedConstraintSize(
981 if (*NumExpansions == 0) {
982 Satisfaction.IsSatisfied = Conjunction;
987 for (
unsigned I = 0; I < *NumExpansions; I++) {
988 Sema::ArgPackSubstIndexRAII SubstIndex(S, I);
989 Satisfaction.IsSatisfied =
false;
990 Satisfaction.ContainsErrors =
false;
997 if (BuildExpression) {
1002 Conjunction ? BinaryOperatorKind::BO_LAnd
1003 : BinaryOperatorKind::BO_LOr,
1006 FPOptionsOverride{});
1008 if (!Conjunction && Satisfaction.IsSatisfied) {
1009 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1010 EffectiveDetailEndIndex,
1011 Satisfaction.Details.end());
1014 if (Satisfaction.IsSatisfied != Conjunction)
1021ExprResult ConstraintSatisfactionChecker::Evaluate(
1025 ParameterMappingInstantiationCache PMCache(*
this, Constraint, MLTAL,
1028 if (
auto *
V = PMCache.available())
1029 return V->SubstExpr;
1031 return PMCache.cache(EvaluateSlow(Constraint, MLTAL));
1034ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
1037 const ConceptReference *ConceptId = Constraint.
getConceptId();
1039 llvm::SmallVector<TemplateArgument> SubstitutedOutermost;
1040 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
1041 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
1043 if (!SubstitutedArgs) {
1044 Satisfaction.IsSatisfied =
false;
1048 Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint));
1050 const ASTTemplateArgumentListInfo *Ori =
1052 TemplateDeductionInfo Info(TemplateNameLoc);
1053 Sema::SFINAETrap Trap(S, Info);
1054 Sema::InstantiatingTemplate
_2(
1055 S, TemplateNameLoc, Sema::InstantiatingTemplate::ConstraintSubstitution{},
1062 if (TopLevelConceptId &&
1064 TopLevelConceptId->getNamedConcept().getAsTemplateDecl()) {
1066 OutArgs.addArgument(A);
1067 }
else if (S.SubstTemplateArguments(Ori->
arguments(), *SubstitutedArgs,
1069 Trap.hasErrorOccurred()) {
1070 Satisfaction.IsSatisfied =
false;
1071 if (Trap.hasErrorOccurred())
1072 consumeSFINAEFailure(Info, Satisfaction);
1079 ExprResult SubstitutedConceptId = S.CheckConceptTemplateId(
1085 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
1088 if (Size != Satisfaction.Details.size()) {
1089 Satisfaction.Details.insert(
1090 Satisfaction.Details.begin() + Size,
1092 SubstitutedConceptId.
getAs<ConceptSpecializationExpr>()
1093 ->getConceptReference()));
1095 return SubstitutedConceptId;
1098ExprResult ConstraintSatisfactionChecker::Evaluate(
1102 const ConceptReference *ConceptId = Constraint.
getConceptId();
1103 Sema::InstantiatingTemplate InstTemplate(
1105 Sema::InstantiatingTemplate::ConstraintsCheck{},
1113 : ArrayRef<TemplateArgument>{},
1115 if (InstTemplate.isInvalid())
1118 unsigned Size = Satisfaction.Details.size();
1120 llvm::SaveAndRestore PushConceptDecl(
1127 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
1134 if (Satisfaction.IsSatisfied)
1137 ParameterMappingInstantiationCache PMCache(
1138 *
this, Constraint, MLTAL, getOuterPackIndex(Constraint), Size);
1140 if (
auto *
V = PMCache.available())
1141 return V->SubstExpr;
1143 return PMCache.cache(EvaluateSlow(Constraint, MLTAL, Size));
1146ExprResult ConstraintSatisfactionChecker::Evaluate(
1150 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1157 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1160 if (!Conjunction && !LHS.
isInvalid() && Satisfaction.IsSatisfied &&
1161 !Satisfaction.ContainsErrors)
1164 Satisfaction.ContainsErrors =
false;
1165 Satisfaction.IsSatisfied =
false;
1169 if (!Conjunction && !RHS.
isInvalid() && Satisfaction.IsSatisfied &&
1170 !Satisfaction.ContainsErrors)
1171 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1172 EffectiveDetailEndIndex,
1173 Satisfaction.Details.end());
1175 if (!BuildExpression)
1185 Conjunction ? BinaryOperatorKind::BO_LAnd
1186 : BinaryOperatorKind::BO_LOr,
1194 switch (Constraint.
getKind()) {
1209 llvm_unreachable(
"Unknown ConstraintKind enum");
1220 *ConvertedExpr =
nullptr;
1222 if (AssociatedConstraints.empty()) {
1242 struct SynthesisContextPair {
1248 : Inst(S, InstantiationRange.
getBegin(),
1250 TemplateArgs, InstantiationRange),
1253 std::optional<SynthesisContextPair> SynthesisContext;
1254 if (!TopLevelConceptId)
1265 if (TopLevelConceptId)
1275 ConvertedExpr !=
nullptr)
1276 .Evaluate(*
C, TemplateArgsLists);
1278 if (Res.
isUsable() && ConvertedExpr)
1279 *ConvertedExpr = Res.
get();
1290 llvm::TimeTraceScope TimeScope(
1291 "CheckConstraintSatisfaction", [TemplateIDRange,
this] {
1294 if (AssociatedConstraints.empty()) {
1298 const auto *
Template = dyn_cast_if_present<const NamedDecl *>(Entity);
1300 return ::CheckConstraintSatisfaction(
1301 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1302 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1316 for (
auto List : TemplateArgsLists)
1318 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1321 if (TopLevelConceptId)
1324 llvm::FoldingSetNodeID ID;
1326 llvm::FoldingSetInsertToken
Token;
1327 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1328 OutSatisfaction = *Cached;
1333 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1335 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1336 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1337 OutSatisfaction = std::move(*Satisfaction);
1341 if (
auto *Cached = SatisfactionCache.lookup(ID,
Token)) {
1350 OutSatisfaction = *Cached;
1355 OutSatisfaction = *Satisfaction;
1357 SatisfactionCache.insert(Satisfaction.release());
1379 return !ArgLoc.getArgument().isDependent() &&
1380 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1382 return Concept->getConstraintExpr();
1395bool Sema::SetupConstraintScope(
1400 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1406 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1407 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1409 if (Inst.isInvalid())
1418 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1420 if (addInstantiatedParametersToScope(
1427 if (FunctionTemplateDecl *FromMemTempl =
1429 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1439 FunctionDecl *InstantiatedFrom =
1446 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1447 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1449 if (Inst.isInvalid())
1454 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1463std::optional<MultiLevelTemplateArgumentList>
1464Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1467 MultiLevelTemplateArgumentList MLTAL;
1474 false, std::nullopt,
1481 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1482 return std::nullopt;
1490 bool ForOverloadResolution) {
1509 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1512 Satisfaction, UsageLoc,
1526 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1527 SetupConstraintCheckingTemplateArgumentsAndScope(
1535 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1536 ThisQuals =
Method->getMethodQualifiers();
1543 ForOverloadResolution);
1553 const Expr *ConstrExpr) {
1568 std::optional<LocalInstantiationScope> ScopeForParameters;
1571 ScopeForParameters.emplace(S,
true);
1575 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1577 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1579 if (!PVD->isParameterPack()) {
1580 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1599 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1600 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1604 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1613 std::optional<Sema::ContextRAII> ContextScope;
1621 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1633 return SubstConstr.
get();
1637 const Expr *OldConstr,
1639 const Expr *NewConstr) {
1640 if (OldConstr == NewConstr)
1643 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1646 if (
const Expr *SubstConstr =
1649 OldConstr = SubstConstr;
1652 if (
const Expr *SubstConstr =
1655 NewConstr = SubstConstr;
1660 llvm::FoldingSetNodeID ID1, ID2;
1673 "Non-function templates don't need to be checked");
1694 TemplateIDRange, Satisfaction) ||
1697 TemplateArgString =
" ";
1703 diag::err_template_arg_list_constraints_not_satisfied)
1705 << TemplateArgString << TemplateIDRange;
1717 Template->getAssociatedConstraints(TemplateAC);
1718 if (TemplateAC.empty()) {
1737 SemaRef, PointOfInstantiation,
1739 PointOfInstantiation);
1740 if (Inst.isInvalid())
1750 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1761 return ::CheckFunctionConstraintsWithoutInstantiation(
1762 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1763 TemplateArgs, Satisfaction);
1768 Template->getAssociatedConstraints(TemplateAC);
1769 if (TemplateAC.empty()) {
1779 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1780 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1788 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1789 ThisQuals =
Method->getMethodQualifiers();
1798 PointOfInstantiation, Satisfaction);
1805 "Diagnose() can only be used on an unsatisfied requirement");
1808 llvm_unreachable(
"Diagnosing a dependent requirement");
1812 if (!SubstDiag->DiagMessage.empty())
1813 S.
Diag(SubstDiag->DiagLoc,
1814 diag::note_expr_requirement_expr_substitution_error)
1815 << (
int)
First << SubstDiag->SubstitutedEntity
1816 << SubstDiag->DiagMessage;
1818 S.
Diag(SubstDiag->DiagLoc,
1819 diag::note_expr_requirement_expr_unknown_substitution_error)
1820 << (
int)
First << SubstDiag->SubstitutedEntity;
1830 if (!SubstDiag->DiagMessage.empty())
1831 S.
Diag(SubstDiag->DiagLoc,
1832 diag::note_expr_requirement_type_requirement_substitution_error)
1833 << (
int)
First << SubstDiag->SubstitutedEntity
1834 << SubstDiag->DiagMessage;
1839 note_expr_requirement_type_requirement_unknown_substitution_error)
1840 << (
int)
First << SubstDiag->SubstitutedEntity;
1850 llvm_unreachable(
"We checked this above");
1858 "Diagnose() can only be used on an unsatisfied requirement");
1861 llvm_unreachable(
"Diagnosing a dependent requirement");
1865 if (!SubstDiag->DiagMessage.empty())
1866 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1867 << (
int)
First << SubstDiag->SubstitutedEntity
1868 << SubstDiag->DiagMessage;
1870 S.
Diag(SubstDiag->DiagLoc,
1871 diag::note_type_requirement_unknown_substitution_error)
1872 << (
int)
First << SubstDiag->SubstitutedEntity;
1876 llvm_unreachable(
"Unknown satisfaction status");
1884 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1888 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1890 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1891 <<
Concept->getNamedConcept().getAsTemplateDecl();
1893 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1923 const Expr *SubstExpr,
1926 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1927 switch (BO->getOpcode()) {
1939 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1950 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1962 if (BO->getLHS()->getType()->isIntegerType() &&
1963 BO->getRHS()->getType()->isIntegerType()) {
1966 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1969 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1972 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1974 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1987 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1990 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1994 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1995 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1996 assert(TTE->getNumArgs() == 2);
1998 diag::note_is_deducible_constraint_evaluated_to_false)
1999 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
2004 diag::note_atomic_constraint_evaluated_to_false)
2014 .
template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
2016 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
2019 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
2023 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
2036 if (!Req->isDependent() && !Req->isSatisfied()) {
2037 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
2039 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
2053 "Attempted to diagnose a satisfied constraint");
2064 "Attempted to diagnose a satisfied constraint");
2072class SubstituteParameterMappings {
2084 bool RemovePacksForFoldExpr;
2086 SubstituteParameterMappings(
Sema &SemaRef,
2089 bool RemovePacksForFoldExpr)
2090 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2091 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2101 bool RemovePacksForFoldExpr =
false)
2103 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2110void SubstituteParameterMappings::buildParameterMapping(
2112 TemplateParameterList *TemplateParams =
2115 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2116 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2119 SemaRef.MarkUsedTemplateParameters(
2120 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2122 0, OccurringIndices);
2124 SemaRef.MarkUsedTemplateParametersForSubsumptionParameterMapping(
2125 static_cast<AtomicConstraint &
>(N).getConstraintExpr(),
2126 0, OccurringIndicesForSubsumption);
2130 SemaRef.MarkUsedTemplateParameters(
2131 static_cast<FoldExpandedConstraint &
>(N).getPattern(),
2133 0, OccurringIndices);
2135 auto *Args =
static_cast<ConceptIdConstraint &
>(N)
2137 ->getTemplateArgsAsWritten();
2139 SemaRef.MarkUsedTemplateParameters(Args->arguments(),
2140 0, OccurringIndices);
2146 llvm::SmallVector<TemplateArgument> DefaultArgs;
2148 I < TemplateParams->size(); ++I) {
2149 const NamedDecl *Param = TemplateParams->
getParam(I);
2152 const TemplateArgument *Arg =
2153 SemaRef.getASTContext().getDefaultTemplateArgumentOrNone(Param);
2154 assert(Arg &&
"expected a default argument");
2155 DefaultArgs.emplace_back(std::move(*Arg));
2157 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2158 0, OccurringIndices);
2159 SemaRef.MarkUsedTemplateParameters(DefaultArgs,
false,
2161 OccurringIndicesForSubsumption);
2164 unsigned Size = OccurringIndices.count();
2169 TemplateArgumentLoc *TempArgs =
2170 new (SemaRef.Context) TemplateArgumentLoc[Size];
2171 llvm::SmallVector<NamedDecl *> UsedParams;
2172 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2173 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
2174 ? ArgsAsWritten->arguments()[I].getLocation()
2178 if (OccurringIndices[I]) {
2179 NamedDecl *Param = TemplateParams->
begin()[I];
2180 new (&(TempArgs)[J]) TemplateArgumentLoc(
2181 SemaRef.getIdentityTemplateArgumentLoc(Param, Loc));
2182 UsedParams.push_back(Param);
2192 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2193 MutableArrayRef<TemplateArgumentLoc>{TempArgs,
Size}, UsedList);
2196bool SubstituteParameterMappings::substitute(
2199 buildParameterMapping(N);
2205 SourceLocation InstLocBegin, InstLocEnd;
2206 llvm::ArrayRef
Arguments = ArgsAsWritten->arguments();
2208 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2209 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2211 auto SR =
Arguments[0].getSourceRange();
2212 InstLocBegin = SR.getBegin();
2213 InstLocEnd = SR.getEnd();
2215 Sema::NonSFINAEContext _(SemaRef);
2216 Sema::InstantiatingTemplate Inst(
2217 SemaRef, InstLocBegin,
2218 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2220 {InstLocBegin, InstLocEnd});
2221 if (Inst.isInvalid())
2228 TemplateArgumentListInfo SubstArgs;
2229 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2230 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2231 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2234 Sema::CheckTemplateArgumentInfo CTAI;
2238 TD->getLocation(), SubstArgs,
2243 TemplateArgumentLoc *TempArgs =
2249 if (I < SubstArgs.
size())
2250 Loc = SubstArgs.
arguments()[I].getLocation();
2252 TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc(
2256 MutableArrayRef<TemplateArgumentLoc> Mapping(TempArgs,
2267 if (substitute(
static_cast<NormalizedConstraintWithParamMapping &
>(CC)))
2274 SourceLocation InstLocBegin, InstLocEnd;
2275 if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments();
2277 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2278 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2280 auto SR =
Arguments[0].getSourceRange();
2281 InstLocBegin = SR.getBegin();
2282 InstLocEnd = SR.getEnd();
2284 Sema::NonSFINAEContext _(SemaRef);
2286 Sema::InstantiatingTemplate Inst(
2287 SemaRef, InstLocBegin,
2288 Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
2290 {InstLocBegin, InstLocEnd});
2291 if (Inst.isInvalid())
2294 TemplateArgumentListInfo
Out;
2299 llvm::SaveAndRestore<
decltype(SemaRef.CurrentCachedTemplateArgs)>
2300 DoNotCacheDependentArgs(SemaRef.CurrentCachedTemplateArgs,
nullptr);
2301 const ASTTemplateArgumentListInfo *ArgsAsWritten =
2302 CSE->getTemplateArgsAsWritten();
2303 if (SemaRef.SubstTemplateArgumentsInParameterMapping(
2304 ArgsAsWritten->arguments(), CC.
getBeginLoc(), *MLTAL, Out))
2306 Sema::CheckTemplateArgumentInfo CTAI;
2307 if (SemaRef.CheckTemplateArgumentList(CSE->getConceptDecl(),
2308 CSE->getConceptNameInfo().getLoc(), Out,
2313 auto TemplateArgs = *MLTAL;
2314 TemplateArgs.replaceOutermostTemplateArguments(CSE->getConceptDecl(),
2316 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2317 RemovePacksForFoldExpr)
2325 assert(!ArgsAsWritten);
2334 assert(!ArgsAsWritten);
2335 return substitute(FE.getNormalizedPattern());
2339 return SubstituteParameterMappings(SemaRef,
true)
2340 .substitute(FE.getNormalizedPattern());
2345 assert(ArgsAsWritten);
2346 return substitute(CC);
2348 assert(!ArgsAsWritten);
2360 if (RemovePacksForFoldExpr) {
2364 if (AdjustConstraints(SemaRef, 0,
2366 .TransformTemplateArguments(InputArgLoc.begin(),
2367 InputArgLoc.end(), OutArgs))
2371 if (SemaRef.CheckTemplateArgumentList(
2388 return SubstituteParameterMappings(SemaRef, &MLTAL,
2390 RemovePacksForFoldExpr)
2395 if (substitute(Compound.getLHS()))
2397 return substitute(Compound.getRHS());
2400 llvm_unreachable(
"Unknown ConstraintKind enum");
2405 assert(ACs.size() != 0);
2407 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2410 for (
unsigned I = 1; I < ACs.size(); ++I) {
2411 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2412 ACs[I].ArgPackSubstIndex);
2423 assert(E !=
nullptr);
2431 llvm::FoldingSetNodeID
ID;
2435 SatisfactionStackRAII StackRAII(S, D, ID);
2442 if (LogicalBinOp BO = E) {
2443 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2446 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2453 if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2469 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2470 S, CSE->getConceptDecl()->getCanonicalDecl(),
2471 AssociatedConstraint(Res.get(), SubstIndex));
2475 CSE->getConceptReference(), SubNF, D,
2478 if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2480 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2481 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2486 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2490 if (FE->getInit()) {
2491 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2492 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2496 if (FE->isRightFold())
2498 FE->getPattern(), D, Kind, LHS);
2501 FE->getPattern(), D, Kind, RHS);
2509 auto *
Sub = fromConstraintExpr(S, D, FE->getPattern(), SubstIndex);
2521 if (!ConstrainedDeclOrNestedReq) {
2522 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2523 *
this,
nullptr, AssociatedConstraints);
2532 const NamedDecl *ND = dyn_cast<const NamedDecl *>(ConstrainedDeclOrNestedReq);
2533 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2534 if (CacheEntry == NormalizationCache.end()) {
2535 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2536 *
this, ND, AssociatedConstraints);
2538 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq,
nullptr);
2544 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2549 return CacheEntry->second;
2572 if (It != BPacks.end())
2584 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2590 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2591 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2592 "use non-instantiated function declaration for constraints partial "
2607 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2608 auto CacheEntry = SubsumptionCache.find(Key);
2609 if (CacheEntry != SubsumptionCache.end()) {
2610 Result = CacheEntry->second;
2617 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2618 if (Depth2 > Depth1) {
2619 AC1[I].ConstraintExpr =
2620 AdjustConstraints(*
this, Depth2 - Depth1)
2621 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2623 }
else if (Depth1 > Depth2) {
2624 AC2[I].ConstraintExpr =
2625 AdjustConstraints(*
this, Depth1 - Depth2)
2626 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2635 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2636 if (Depth2 > Depth1)
2638 else if (Depth1 > Depth2)
2640 std::optional<bool> Subsumes = SC.
Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2646 SubsumptionCache.try_emplace(Key, *Subsumes);
2657 if (AC1.empty() || AC2.empty())
2660 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2671 llvm::FoldingSetNodeID IDA, IDB;
2673 EB->Profile(IDB,
Context,
true);
2677 AmbiguousAtomic1 = EA;
2678 AmbiguousAtomic2 = EB;
2693 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2694 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2697 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2698 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2700 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2701 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2706 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2708 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2710 Diag(AmbiguousAtomic2->getBeginLoc(),
2711 diag::note_ambiguous_atomic_constraints_similar_expression)
2712 << AmbiguousAtomic2->getSourceRange();
2723 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2725uint16_t SubsumptionChecker::getNewLiteralId() {
2726 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2727 "too many constraints!");
2732 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2747 llvm::FoldingSetNodeID ID;
2748 ID.AddBoolean(Ori->hasParameterMapping());
2749 if (Ori->hasParameterMapping()) {
2750 const auto &Mapping = Ori->getParameterMapping();
2752 Ori->mappingOccurenceListForSubsumption();
2753 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2760 auto It = Elems.find(ID);
2761 if (It == Elems.end()) {
2764 MappedAtomicConstraint{
2765 Ori, {getNewLiteralId(), Literal::Atomic}}})
2767 ReverseMap[It->second.ID.Value] = Ori;
2769 return It->getSecond().ID;
2773 auto &Elems = FoldMap[Ori->getPattern()];
2775 FoldExpendedConstraintKey K;
2776 K.Kind = Ori->getFoldOperator();
2778 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2779 return K.Kind ==
Other.Kind;
2781 if (It == Elems.end()) {
2782 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2783 It = Elems.insert(Elems.end(), std::move(K));
2784 ReverseMap[It->ID.Value] = Ori;
2790 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2793 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2809template <
typename FormulaType>
2813 auto Add = [&,
this](Clause
C) {
2816 C.erase(llvm::unique(
C),
C.end());
2817 AddUniqueClauseToFormula(Res, std::move(
C));
2822 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2825 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2828 return Normalize<FormulaType>(
2829 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2832 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2834 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2835 Left = Normalize<FormulaType>(Compound.getLHS());
2836 Right = Normalize<FormulaType>(Compound.getRHS());
2839 if (Compound.getCompoundKind() == FormulaType::Kind) {
2840 unsigned SizeLeft =
Left.size();
2841 Res = std::move(Left);
2842 Res.reserve(SizeLeft +
Right.size());
2843 std::for_each(std::make_move_iterator(
Right.begin()),
2844 std::make_move_iterator(
Right.end()), Add);
2848 Res.reserve(
Left.size() *
Right.size());
2849 for (
const auto <ransform : Left) {
2850 for (
const auto &RTransform : Right) {
2852 Combined.reserve(LTransform.size() + RTransform.size());
2853 llvm::copy(LTransform, std::back_inserter(Combined));
2854 llvm::copy(RTransform, std::back_inserter(Combined));
2855 Add(std::move(Combined));
2861 llvm_unreachable(
"Unknown ConstraintKind enum");
2864void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2865 for (
auto &
Other : F) {
2866 if (llvm::equal(
C,
Other))
2876 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2878 return std::nullopt;
2881 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2883 return std::nullopt;
2885 return Subsumes(PNormalized, QNormalized);
2891 DNFFormula DNFP = DNF(*P);
2892 CNFFormula CNFQ = CNF(*Q);
2897 const CNFFormula &QCNF) {
2898 for (
const auto &Pi : PDNF) {
2899 for (
const auto &Qj : QCNF) {
2905 if (!DNFSubsumes(Pi, Qj))
2912bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2914 return llvm::any_of(P, [&](Literal LP) {
2915 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2921 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2924 auto It = FoldSubsumptionCache.find(Key);
2925 if (It == FoldSubsumptionCache.end()) {
2934 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2940 if (A.Kind != B.Kind)
2943 case Literal::Atomic:
2945 return A.Value == B.Value;
2947 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2948 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2949 case Literal::FoldExpanded:
2951 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2952 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2954 llvm_unreachable(
"unknown literal kind");
2959class DumpNormalizedConstraint {
2961 const PrintingPolicy &PP;
2965 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2966 :
OS(
OS), PP(Context.getPrintingPolicy()),
2969 void dump(
const NormalizedConstraint &N) {
2974 void Traverse(
const NormalizedConstraint &N) {
2976 case NormalizedConstraint::ConstraintKind::Compound:
2977 VisitCompound(
static_cast<const CompoundConstraint &
>(N));
2979 case NormalizedConstraint::ConstraintKind::Atomic:
2980 VisitAtomic(
static_cast<const AtomicConstraint &
>(N));
2982 case NormalizedConstraint::ConstraintKind::ConceptId:
2983 VisitConceptId(
static_cast<const ConceptIdConstraint &
>(N));
2985 case NormalizedConstraint::ConstraintKind::FoldExpanded:
2986 VisitFoldExpanded(
static_cast<const FoldExpandedConstraint &
>(N));
2991 void WriteNodeHeader(
const NormalizedConstraint &N, StringRef Kind) {
2997 void WritePackIndex(
const NormalizedConstraintWithParamMapping &N) {
2999 OS <<
" SubstIndex=" << *Idx;
3002 void VisitCompound(
const CompoundConstraint &
C) {
3003 WriteNodeHeader(
C,
"CompoundConstraint");
3008 TD.
AddChild([&] { Traverse(
C.getLHS()); });
3009 TD.
AddChild([&] { Traverse(
C.getRHS()); });
3012 void VisitAtomic(
const AtomicConstraint &A) {
3013 WriteNodeHeader(A,
"AtomicConstraint");
3017 WriteParameterMapping(A);
3020 void VisitConceptId(
const ConceptIdConstraint &
C) {
3021 WriteNodeHeader(
C,
"ConceptIdConstraint");
3024 if (
auto *CSE =
C.getConceptSpecializationExpr()) {
3025 CSE->printPretty(OS,
nullptr, PP);
3027 C.getConceptId()->print(OS, PP);
3029 WriteParameterMapping(
C);
3030 TD.
AddChild([&] { Traverse(
C.getNormalizedConstraint()); });
3033 void VisitFoldExpanded(
const FoldExpandedConstraint &F) {
3034 WriteNodeHeader(F,
"FoldExpandedConstraint");
3036 << (F.
getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3042 WriteParameterMapping(F);
3046 void WriteParameterMapping(
const NormalizedConstraintWithParamMapping &N) {
3053 OS <<
"ParameterMapping";
3054 WriteOccurenceList(
"Indexes", Indexes);
3055 WriteOccurenceList(
"IndexesForSubsumption", IndexesForSub);
3057 for (unsigned ParamIndex : Indexes.set_bits()) {
3058 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3059 assert(TPL && Slot < TPL->size());
3060 const NamedDecl *Param = TPL->getParam(Slot);
3061 OS <<
"#" << ParamIndex <<
": <";
3062 Param->print(OS, PP);
3064 Mapping[Slot].getArgument().print(PP, OS,
3066 TD.AddChild([this, Slot, Mapping] {
3067 const TemplateArgument &TA = Mapping[Slot].getArgument();
3068 OS <<
"TemplateArgument " << TA.getKindName();
3069 TD.dumpPointer(&TA);
3077 void WriteOccurenceList(StringRef Label,
3081 OS <<
" " << Label <<
"={"
3084 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3085 [](
unsigned I) { return llvm::to_string(I); }),
3094 dump(llvm::errs(), Context);
3099 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.