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()) {
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);
2533 ConstrainedDeclOrNestedReq.dyn_cast<
const NamedDecl *>();
2534 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2535 if (CacheEntry == NormalizationCache.end()) {
2536 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2537 *
this, ND, AssociatedConstraints);
2539 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq,
nullptr);
2545 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2550 return CacheEntry->second;
2573 if (It != BPacks.end())
2585 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2591 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2592 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2593 "use non-instantiated function declaration for constraints partial "
2608 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2609 auto CacheEntry = SubsumptionCache.find(Key);
2610 if (CacheEntry != SubsumptionCache.end()) {
2611 Result = CacheEntry->second;
2618 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2619 if (Depth2 > Depth1) {
2620 AC1[I].ConstraintExpr =
2621 AdjustConstraints(*
this, Depth2 - Depth1)
2622 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2624 }
else if (Depth1 > Depth2) {
2625 AC2[I].ConstraintExpr =
2626 AdjustConstraints(*
this, Depth1 - Depth2)
2627 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2636 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2637 if (Depth2 > Depth1)
2639 else if (Depth1 > Depth2)
2641 std::optional<bool> Subsumes = SC.
Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2647 SubsumptionCache.try_emplace(Key, *Subsumes);
2658 if (AC1.empty() || AC2.empty())
2661 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2672 llvm::FoldingSetNodeID IDA, IDB;
2674 EB->Profile(IDB,
Context,
true);
2678 AmbiguousAtomic1 = EA;
2679 AmbiguousAtomic2 = EB;
2694 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2695 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2698 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2699 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2701 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2702 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2707 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2709 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2711 Diag(AmbiguousAtomic2->getBeginLoc(),
2712 diag::note_ambiguous_atomic_constraints_similar_expression)
2713 << AmbiguousAtomic2->getSourceRange();
2724 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2726uint16_t SubsumptionChecker::getNewLiteralId() {
2727 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2728 "too many constraints!");
2733 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2748 llvm::FoldingSetNodeID ID;
2749 ID.AddBoolean(Ori->hasParameterMapping());
2750 if (Ori->hasParameterMapping()) {
2751 const auto &Mapping = Ori->getParameterMapping();
2753 Ori->mappingOccurenceListForSubsumption();
2754 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2761 auto It = Elems.find(ID);
2762 if (It == Elems.end()) {
2765 MappedAtomicConstraint{
2766 Ori, {getNewLiteralId(), Literal::Atomic}}})
2768 ReverseMap[It->second.ID.Value] = Ori;
2770 return It->getSecond().ID;
2774 auto &Elems = FoldMap[Ori->getPattern()];
2776 FoldExpendedConstraintKey K;
2777 K.Kind = Ori->getFoldOperator();
2779 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2780 return K.Kind ==
Other.Kind;
2782 if (It == Elems.end()) {
2783 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2784 It = Elems.insert(Elems.end(), std::move(K));
2785 ReverseMap[It->ID.Value] = Ori;
2791 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2794 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2810template <
typename FormulaType>
2814 auto Add = [&,
this](Clause
C) {
2817 C.erase(llvm::unique(
C),
C.end());
2818 AddUniqueClauseToFormula(Res, std::move(
C));
2823 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2826 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2829 return Normalize<FormulaType>(
2830 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2833 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2835 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2836 Left = Normalize<FormulaType>(Compound.getLHS());
2837 Right = Normalize<FormulaType>(Compound.getRHS());
2840 if (Compound.getCompoundKind() == FormulaType::Kind) {
2841 unsigned SizeLeft =
Left.size();
2842 Res = std::move(Left);
2843 Res.reserve(SizeLeft +
Right.size());
2844 std::for_each(std::make_move_iterator(
Right.begin()),
2845 std::make_move_iterator(
Right.end()), Add);
2849 Res.reserve(
Left.size() *
Right.size());
2850 for (
const auto <ransform : Left) {
2851 for (
const auto &RTransform : Right) {
2853 Combined.reserve(LTransform.size() + RTransform.size());
2854 llvm::copy(LTransform, std::back_inserter(Combined));
2855 llvm::copy(RTransform, std::back_inserter(Combined));
2856 Add(std::move(Combined));
2862 llvm_unreachable(
"Unknown ConstraintKind enum");
2865void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2866 for (
auto &
Other : F) {
2867 if (llvm::equal(
C,
Other))
2877 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2879 return std::nullopt;
2882 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2884 return std::nullopt;
2886 return Subsumes(PNormalized, QNormalized);
2892 DNFFormula DNFP = DNF(*P);
2893 CNFFormula CNFQ = CNF(*Q);
2898 const CNFFormula &QCNF) {
2899 for (
const auto &Pi : PDNF) {
2900 for (
const auto &Qj : QCNF) {
2906 if (!DNFSubsumes(Pi, Qj))
2913bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2915 return llvm::any_of(P, [&](Literal LP) {
2916 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2922 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2925 auto It = FoldSubsumptionCache.find(Key);
2926 if (It == FoldSubsumptionCache.end()) {
2935 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2941 if (A.Kind != B.Kind)
2944 case Literal::Atomic:
2946 return A.Value == B.Value;
2948 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2949 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2950 case Literal::FoldExpanded:
2952 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2953 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2955 llvm_unreachable(
"unknown literal kind");
2960class DumpNormalizedConstraint {
2962 const PrintingPolicy &PP;
2966 DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context)
2967 :
OS(
OS), PP(Context.getPrintingPolicy()),
2970 void dump(
const NormalizedConstraint &N) {
2975 void Traverse(
const NormalizedConstraint &N) {
2977 case NormalizedConstraint::ConstraintKind::Compound:
2978 VisitCompound(
static_cast<const CompoundConstraint &
>(N));
2980 case NormalizedConstraint::ConstraintKind::Atomic:
2981 VisitAtomic(
static_cast<const AtomicConstraint &
>(N));
2983 case NormalizedConstraint::ConstraintKind::ConceptId:
2984 VisitConceptId(
static_cast<const ConceptIdConstraint &
>(N));
2986 case NormalizedConstraint::ConstraintKind::FoldExpanded:
2987 VisitFoldExpanded(
static_cast<const FoldExpandedConstraint &
>(N));
2992 void WriteNodeHeader(
const NormalizedConstraint &N, StringRef Kind) {
2998 void WritePackIndex(
const NormalizedConstraintWithParamMapping &N) {
3000 OS <<
" SubstIndex=" << *Idx;
3003 void VisitCompound(
const CompoundConstraint &
C) {
3004 WriteNodeHeader(
C,
"CompoundConstraint");
3009 TD.
AddChild([&] { Traverse(
C.getLHS()); });
3010 TD.
AddChild([&] { Traverse(
C.getRHS()); });
3013 void VisitAtomic(
const AtomicConstraint &A) {
3014 WriteNodeHeader(A,
"AtomicConstraint");
3018 WriteParameterMapping(A);
3021 void VisitConceptId(
const ConceptIdConstraint &
C) {
3022 WriteNodeHeader(
C,
"ConceptIdConstraint");
3025 if (
auto *CSE =
C.getConceptSpecializationExpr()) {
3026 CSE->printPretty(OS,
nullptr, PP);
3028 C.getConceptId()->print(OS, PP);
3030 WriteParameterMapping(
C);
3031 TD.
AddChild([&] { Traverse(
C.getNormalizedConstraint()); });
3034 void VisitFoldExpanded(
const FoldExpandedConstraint &F) {
3035 WriteNodeHeader(F,
"FoldExpandedConstraint");
3037 << (F.
getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And
3043 WriteParameterMapping(F);
3047 void WriteParameterMapping(
const NormalizedConstraintWithParamMapping &N) {
3054 OS <<
"ParameterMapping";
3055 WriteOccurenceList(
"Indexes", Indexes);
3056 WriteOccurenceList(
"IndexesForSubsumption", IndexesForSub);
3058 for (unsigned ParamIndex : Indexes.set_bits()) {
3059 TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] {
3060 assert(TPL && Slot < TPL->size());
3061 const NamedDecl *Param = TPL->getParam(Slot);
3062 OS <<
"#" << ParamIndex <<
": <";
3063 Param->print(OS, PP);
3065 Mapping[Slot].getArgument().print(PP, OS,
3067 TD.AddChild([this, Slot, Mapping] {
3068 const TemplateArgument &TA = Mapping[Slot].getArgument();
3069 OS <<
"TemplateArgument " << TA.getKindName();
3070 TD.dumpPointer(&TA);
3078 void WriteOccurenceList(StringRef Label,
3082 OS <<
" " << Label <<
"={"
3085 llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()),
3086 [](
unsigned I) { return llvm::to_string(I); }),
3095 dump(llvm::errs(), Context);
3100 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.