29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/PointerUnion.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/Support/SaveAndRestore.h"
33#include "llvm/Support/TimeProfiler.h"
42 const Expr *LHS =
nullptr;
43 const Expr *RHS =
nullptr;
46 LogicalBinOp(
const Expr *E) {
47 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
51 Loc = BO->getExprLoc();
52 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
54 if (OO->getNumArgs() == 2) {
55 Op = OO->getOperator();
58 Loc = OO->getOperatorLoc();
63 bool isAnd()
const {
return Op == OO_AmpAmp; }
64 bool isOr()
const {
return Op == OO_PipePipe; }
65 explicit operator bool()
const {
return isAnd() || isOr(); }
67 const Expr *getLHS()
const {
return LHS; }
68 const Expr *getRHS()
const {
return RHS; }
72 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
77 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
78 assert((!LHS.isInvalid() && !RHS.isInvalid()) &&
"not good expressions?");
80 if (!LHS.isUsable() || !RHS.isUsable())
94 Token NextToken,
bool *PossibleNonPrimary,
95 bool IsTrailingRequiresClause) {
101 if (LogicalBinOp BO = ConstraintExpression) {
103 PossibleNonPrimary) &&
106 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
112 auto CheckForNonPrimary = [&] {
113 if (!PossibleNonPrimary)
116 *PossibleNonPrimary =
127 (NextToken.
is(tok::l_paren) &&
128 (IsTrailingRequiresClause ||
146 CheckForNonPrimary();
152 diag::err_non_bool_atomic_constraint)
154 CheckForNonPrimary();
158 if (PossibleNonPrimary)
159 *PossibleNonPrimary =
false;
164struct SatisfactionStackRAII {
166 bool Inserted =
false;
168 const llvm::FoldingSetNodeID &FSNID)
175 ~SatisfactionStackRAII() {
187 for (
const auto &List : *MLTAL)
211class AdjustConstraints :
public TreeTransform<AdjustConstraints> {
212 unsigned TemplateDepth = 0;
214 bool RemoveNonPackExpansionPacks =
false;
217 using inherited = TreeTransform<AdjustConstraints>;
218 AdjustConstraints(Sema &SemaRef,
unsigned TemplateDepth,
219 bool RemoveNonPackExpansionPacks =
false)
220 : inherited(SemaRef), TemplateDepth(TemplateDepth),
221 RemoveNonPackExpansionPacks(RemoveNonPackExpansionPacks) {}
223 ExprResult RebuildPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc,
225 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc, NumExpansions);
228 TemplateArgumentLoc RebuildPackExpansion(TemplateArgumentLoc Pattern,
229 SourceLocation EllipsisLoc,
231 if (!RemoveNonPackExpansionPacks)
232 return inherited::RebuildPackExpansion(Pattern, EllipsisLoc,
238 TemplateArgumentLoc &Out, UnexpandedInfo &Info) {
239 if (!RemoveNonPackExpansionPacks)
240 return inherited::PreparePackForExpansion(In, Uneval, Out, Info);
241 assert(
In.getArgument().isPackExpansion());
247 using inherited::TransformTemplateTypeParmType;
248 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
249 TemplateTypeParmTypeLoc TL,
bool) {
250 const TemplateTypeParmType *T = TL.
getTypePtr();
252 TemplateTypeParmDecl *NewTTPDecl =
nullptr;
253 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl())
254 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
257 QualType
Result = getSema().Context.getTemplateTypeParmType(
258 T->getDepth() + TemplateDepth, T->getIndex(),
259 RemoveNonPackExpansionPacks ?
false : T->isParameterPack(), NewTTPDecl);
260 TemplateTypeParmTypeLoc NewTL = TLB.
push<TemplateTypeParmTypeLoc>(
Result);
265 bool AlreadyTransformed(QualType T) {
281 using inherited = RecursiveASTVisitor<HashParameterMapping>;
285 const MultiLevelTemplateArgumentList &TemplateArgs;
286 llvm::FoldingSetNodeID &
ID;
287 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
291 bool shouldVisitTemplateInstantiations()
const {
return true; }
294 HashParameterMapping(Sema &SemaRef,
295 const MultiLevelTemplateArgumentList &TemplateArgs,
296 llvm::FoldingSetNodeID &ID,
298 : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
ID(
ID),
299 OuterPackSubstIndex(OuterPackSubstIndex) {}
301 bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
312 TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
318 if ((T->isParameterPack() ||
319 (T->getDecl() && T->getDecl()->isTemplateParameterPack())) &&
322 "Missing argument pack");
327 UsedTemplateArgs.push_back(
332 bool VisitDeclRefExpr(DeclRefExpr *E) {
334 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
336 return TraverseDecl(D);
347 "Missing argument pack");
351 UsedTemplateArgs.push_back(
356 bool VisitTypedefType(TypedefType *TT) {
357 return inherited::TraverseType(TT->
desugar());
360 bool TraverseDecl(Decl *D) {
361 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
362 if (
auto *Var = dyn_cast<VarDecl>(VD))
363 TraverseStmt(Var->getInit());
364 return TraverseType(VD->getType());
367 return inherited::TraverseDecl(D);
370 bool TraverseCallExpr(CallExpr *CE) {
371 inherited::TraverseStmt(CE->
getCallee());
374 inherited::TraverseStmt(Arg);
379 bool TraverseCXXThisExpr(CXXThisExpr *E) {
380 return inherited::TraverseType(E->
getType());
383 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
388 bool TraverseDependentNameType(
const DependentNameType *T,
390 return TraverseNestedNameSpecifier(T->getQualifier());
393 bool TraverseTagType(
const TagType *T,
bool TraverseQualifier) {
401 bool TraverseUnresolvedUsingType(UnresolvedUsingType *T,
402 bool TraverseQualifier) {
406 TraverseQualifier && NNS)
407 return inherited::TraverseNestedNameSpecifier(NNS);
408 return inherited::TraverseUnresolvedUsingType(T, TraverseQualifier);
411 bool TraverseInjectedClassNameType(InjectedClassNameType *T,
412 bool TraverseQualifier) {
413 return TraverseTemplateArguments(T->getTemplateArgs(SemaRef.
Context));
416 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
419 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
420 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
422 return inherited::TraverseTemplateArgument(Arg);
425 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
426 return inherited::TraverseTemplateArgument(Arg);
429 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
430 return TraverseDecl(SOPE->
getPack());
433 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
438 if (
auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
445 TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
448 "Missing argument pack");
452 "Null template template argument");
453 UsedTemplateArgs.push_back(
456 return inherited::TraverseTemplateName(
Template);
459 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
461 for (
const auto &List : TemplateArgs)
462 for (
const TemplateArgument &Arg : List.Args)
468 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
470 for (
auto &ArgLoc : Mapping) {
471 TemplateArgument Canonical =
474 UsedTemplateArgs.push_back(Canonical);
475 TraverseTemplateArgument(Canonical);
478 for (
auto &
Used : UsedTemplateArgs) {
479 llvm::FoldingSetNodeID
R;
486class ConstraintSatisfactionChecker {
489 SourceLocation TemplateNameLoc;
491 ConstraintSatisfaction &Satisfaction;
492 bool BuildExpression;
495 ConceptDecl *ParentConcept =
nullptr;
499 llvm::DenseMap<llvm::FoldingSetNodeID, TemplateArgumentLoc>
503 template <
class Constra
int>
505 return C.getPackSubstitutionIndex() ?
C.getPackSubstitutionIndex()
506 : PackSubstitutionIndex;
510 EvaluateAtomicConstraint(
const Expr *AtomicExpr,
511 const MultiLevelTemplateArgumentList &MLTAL);
514 const FoldExpandedConstraint &FE,
515 const MultiLevelTemplateArgumentList &MLTAL);
518 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
519 const NormalizedConstraintWithParamMapping &Constraint,
520 const MultiLevelTemplateArgumentList &MLTAL,
521 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
523 ExprResult EvaluateSlow(
const AtomicConstraint &Constraint,
524 const MultiLevelTemplateArgumentList &MLTAL);
527 const MultiLevelTemplateArgumentList &MLTAL);
529 ExprResult EvaluateSlow(
const FoldExpandedConstraint &Constraint,
530 const MultiLevelTemplateArgumentList &MLTAL);
533 const MultiLevelTemplateArgumentList &MLTAL);
535 ExprResult EvaluateSlow(
const ConceptIdConstraint &Constraint,
536 const MultiLevelTemplateArgumentList &MLTAL,
540 const MultiLevelTemplateArgumentList &MLTAL);
543 const MultiLevelTemplateArgumentList &MLTAL);
546 ConstraintSatisfactionChecker(Sema &SemaRef,
const NamedDecl *
Template,
547 SourceLocation TemplateNameLoc,
549 ConstraintSatisfaction &Satisfaction,
550 bool BuildExpression)
552 PackSubstitutionIndex(PackSubstitutionIndex),
553 Satisfaction(Satisfaction), BuildExpression(BuildExpression) {}
556 const MultiLevelTemplateArgumentList &MLTAL);
559StringRef allocateStringFromConceptDiagnostic(
const Sema &S,
569ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
571 llvm::FoldingSetNodeID
ID;
578 SatisfactionStackRAII StackRAII(S,
Template, ID);
589 if (Inst.isInvalid())
594 SubstitutedExpression =
597 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
601 if (!Trap.hasErrorOccurred())
608 Info.takeSFINAEDiagnostic(SubstDiag);
615 Satisfaction.
Details.emplace_back(
618 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
640 SubstitutedExpression.
get(),
643 return SubstitutedExpression;
646std::optional<MultiLevelTemplateArgumentList>
647ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
670 if (Inst.isInvalid())
677 &CachedTemplateArgs);
690 TD->getLocation(), SubstArgs,
699 SubstitutedOutermost =
700 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
702 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
707 if (I < SubstitutedOutermost.size()) {
708 SubstitutedOutermost[I] = Arg;
711 SubstitutedOutermost.push_back(Arg);
712 Offset = SubstitutedOutermost.size();
715 if (Offset < SubstitutedOutermost.size())
716 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
721 return std::move(SubstitutedTemplateArgs);
724ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
727 std::optional<EnterExpressionEvaluationContext> EvaluationContext;
728 EvaluationContext.emplace(
733 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
734 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
735 if (!SubstitutedArgs) {
743 std::optional<Sema::ContextRAII> ConceptContext;
748 EvaluationContext.emplace(
753 ParentConcept->
getBeginLoc(), SubstitutedOutermost));
757 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
763 if (SubstitutedAtomicExpr.
isUnset())
777 Satisfaction.
Details.emplace_back(
779 SubstitutedAtomicExpr.get()->getBeginLoc(),
780 allocateStringFromConceptDiagnostic(S, Msg)});
781 return SubstitutedAtomicExpr;
787 return SubstitutedAtomicExpr;
792 EvalResult.
Diag = &EvaluationDiags;
795 !EvaluationDiags.empty()) {
799 diag::err_non_constant_constraint_expression)
802 S.
Diag(PDiag.first, PDiag.second);
807 "evaluating bool expression didn't produce int");
810 Satisfaction.
Details.emplace_back(SubstitutedAtomicExpr.
get());
812 return SubstitutedAtomicExpr;
815ExprResult ConstraintSatisfactionChecker::Evaluate(
820 llvm::FoldingSetNodeID
ID;
821 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
825 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
826 .VisitConstraint(Constraint);
830 auto &Cached = Iter->second.Satisfaction;
834 Cached.Details.begin(), Cached.Details.end());
835 return Iter->second.SubstExpr;
838 ExprResult E = EvaluateSlow(Constraint, MLTAL);
843 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
844 Satisfaction.
Details.begin() + Size,
853ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
861 assert(!Unexpanded.empty() &&
"Pack expansion without parameter packs?");
863 bool RetainExpansion =
false;
867 false, Expand, RetainExpansion,
868 NumExpansions,
false) ||
869 !Expand || RetainExpansion)
872 if (NumExpansions && S.
getLangOpts().BracketDepth < *NumExpansions)
874 return NumExpansions;
877ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
883 unsigned EffectiveDetailEndIndex = Satisfaction.
Details.size();
888 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
889 SubstitutionInTemplateArguments(
891 MLTAL, SubstitutedOutermost);
892 if (!SubstitutedArgs) {
899 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
903 if (*NumExpansions == 0) {
908 for (
unsigned I = 0; I < *NumExpansions; I++) {
913 ConstraintSatisfactionChecker(S,
Template, TemplateNameLoc,
917 if (BuildExpression) {
918 if (
Out.isUnset() || !
Expr.isUsable())
922 Conjunction ? BinaryOperatorKind::BO_LAnd
923 : BinaryOperatorKind::BO_LOr,
930 EffectiveDetailEndIndex,
941ExprResult ConstraintSatisfactionChecker::Evaluate(
945 llvm::FoldingSetNodeID
ID;
947 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
952 auto &Cached = Iter->second.Satisfaction;
956 Cached.Details.begin(), Cached.Details.end());
957 return Iter->second.SubstExpr;
962 ExprResult E = EvaluateSlow(Constraint, MLTAL);
966 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
967 Satisfaction.
Details.begin() + Size,
974ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
980 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
981 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
983 if (!SubstitutedArgs) {
1001 Trap.hasErrorOccurred()) {
1003 if (!Trap.hasErrorOccurred())
1008 Info.takeSFINAEDiagnostic(SubstDiag);
1016 Satisfaction.
Details.begin() + Size,
1019 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
1031 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
1034 if (Size != Satisfaction.
Details.size()) {
1036 Satisfaction.
Details.begin() + Size,
1041 return SubstitutedConceptId;
1044ExprResult ConstraintSatisfactionChecker::Evaluate(
1061 if (InstTemplate.isInvalid())
1072 Satisfaction.
Details.insert(Satisfaction.
Details.begin() + Size, ConceptId);
1082 UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint);
1083 llvm::FoldingSetNodeID
ID;
1086 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1087 .VisitConstraint(Constraint);
1092 auto &Cached = Iter->second.Satisfaction;
1096 Cached.Details.begin(), Cached.Details.end());
1097 return Iter->second.SubstExpr;
1100 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1106 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
1107 Satisfaction.
Details.begin() + Size,
1109 Cache.SubstExpr = CE;
1114ExprResult ConstraintSatisfactionChecker::Evaluate(
1118 unsigned EffectiveDetailEndIndex = Satisfaction.
Details.size();
1140 EffectiveDetailEndIndex,
1143 if (!BuildExpression)
1153 Conjunction ? BinaryOperatorKind::BO_LAnd
1154 : BinaryOperatorKind::BO_LOr,
1159ExprResult ConstraintSatisfactionChecker::Evaluate(
1162 switch (Constraint.
getKind()) {
1177 llvm_unreachable(
"Unknown ConstraintKind enum");
1188 *ConvertedExpr =
nullptr;
1190 if (AssociatedConstraints.empty()) {
1210 struct SynthesisContextPair {
1216 : Inst(S, InstantiationRange.
getBegin(),
1218 TemplateArgs, InstantiationRange),
1221 std::optional<SynthesisContextPair> SynthesisContext;
1222 if (!TopLevelConceptId)
1233 if (TopLevelConceptId)
1239 ExprResult Res = ConstraintSatisfactionChecker(
1242 ConvertedExpr !=
nullptr)
1243 .Evaluate(*
C, TemplateArgsLists);
1248 if (Res.
isUsable() && ConvertedExpr)
1249 *ConvertedExpr = Res.
get();
1260 llvm::TimeTraceScope TimeScope(
1261 "CheckConstraintSatisfaction", [TemplateIDRange,
this] {
1264 if (AssociatedConstraints.empty()) {
1270 return ::CheckConstraintSatisfaction(
1271 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1272 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1286 for (
auto List : TemplateArgsLists)
1288 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1291 if (TopLevelConceptId)
1294 llvm::FoldingSetNodeID ID;
1297 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1298 OutSatisfaction = *Cached;
1303 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1305 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1306 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1307 OutSatisfaction = std::move(*Satisfaction);
1311 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1320 OutSatisfaction = *Cached;
1325 OutSatisfaction = *Satisfaction;
1329 SatisfactionCache.InsertNode(Satisfaction.release());
1342 Expr *ConstraintExpr =
1350 return !ArgLoc.getArgument().isDependent() &&
1351 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1353 return ConstraintExpr;
1357 CSE, ConstraintExpr,
1365 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1371 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
1373 if (Inst.isInvalid())
1382 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(),
1384 if (addInstantiatedParametersToScope(
1391 if (FunctionTemplateDecl *FromMemTempl =
1393 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1403 FunctionDecl *InstantiatedFrom =
1409 Sema::InstantiatingTemplate::ConstraintsCheck{},
1410 InstantiatedFrom, ArrayRef<TemplateArgument>(),
1412 if (Inst.isInvalid())
1417 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1426std::optional<MultiLevelTemplateArgumentList>
1427Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1433 if (SetupConstraintScope(FD, MLTAL, Scope))
1434 return std::nullopt;
1442 bool ForOverloadResolution) {
1461 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1464 Satisfaction, UsageLoc,
1478 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1479 SetupConstraintCheckingTemplateArgumentsAndScope(
1487 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1488 ThisQuals =
Method->getMethodQualifiers();
1495 ForOverloadResolution);
1505 const Expr *ConstrExpr) {
1515 std::optional<LocalInstantiationScope> ScopeForParameters;
1517 ScopeForParameters.emplace(S,
true);
1521 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1523 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1525 if (!PVD->isParameterPack()) {
1526 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1545 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1546 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1550 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1559 std::optional<Sema::ContextRAII> ContextScope;
1563 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1575 return SubstConstr.
get();
1580 const Expr *NewConstr) {
1581 if (OldConstr == NewConstr)
1587 if (
const Expr *SubstConstr =
1590 OldConstr = SubstConstr;
1593 if (
const Expr *SubstConstr =
1596 NewConstr = SubstConstr;
1601 llvm::FoldingSetNodeID ID1, ID2;
1631 TemplateIDRange, Satisfaction))
1636 TemplateArgString =
" ";
1642 diag::err_template_arg_list_constraints_not_satisfied)
1644 << TemplateArgString << TemplateIDRange;
1656 Template->getAssociatedConstraints(TemplateAC);
1657 if (TemplateAC.empty()) {
1669 PointOfInstantiation, Satisfaction);
1677 assert(
Template &&
"Function is not a specialization");
1682 Template->getAssociatedConstraints(TemplateAC);
1683 if (TemplateAC.empty()) {
1693 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1694 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl,
Scope);
1701 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1702 ThisQuals =
Method->getMethodQualifiers();
1711 PointOfInstantiation, Satisfaction);
1718 "Diagnose() can only be used on an unsatisfied requirement");
1721 llvm_unreachable(
"Diagnosing a dependent requirement");
1725 if (!SubstDiag->DiagMessage.empty())
1726 S.
Diag(SubstDiag->DiagLoc,
1727 diag::note_expr_requirement_expr_substitution_error)
1728 << (
int)
First << SubstDiag->SubstitutedEntity
1729 << SubstDiag->DiagMessage;
1731 S.
Diag(SubstDiag->DiagLoc,
1732 diag::note_expr_requirement_expr_unknown_substitution_error)
1733 << (
int)
First << SubstDiag->SubstitutedEntity;
1743 if (!SubstDiag->DiagMessage.empty())
1744 S.
Diag(SubstDiag->DiagLoc,
1745 diag::note_expr_requirement_type_requirement_substitution_error)
1746 << (
int)
First << SubstDiag->SubstitutedEntity
1747 << SubstDiag->DiagMessage;
1752 note_expr_requirement_type_requirement_unknown_substitution_error)
1753 << (
int)
First << SubstDiag->SubstitutedEntity;
1763 llvm_unreachable(
"We checked this above");
1771 "Diagnose() can only be used on an unsatisfied requirement");
1774 llvm_unreachable(
"Diagnosing a dependent requirement");
1778 if (!SubstDiag->DiagMessage.empty())
1779 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1780 << (
int)
First << SubstDiag->SubstitutedEntity
1781 << SubstDiag->DiagMessage;
1783 S.
Diag(SubstDiag->DiagLoc,
1784 diag::note_type_requirement_unknown_substitution_error)
1785 << (
int)
First << SubstDiag->SubstitutedEntity;
1789 llvm_unreachable(
"Unknown satisfaction status");
1797 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1801 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1803 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1804 <<
Concept->getNamedConcept();
1806 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1836 const Expr *SubstExpr,
1839 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1840 switch (BO->getOpcode()) {
1852 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1863 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1875 if (BO->getLHS()->getType()->isIntegerType() &&
1876 BO->getRHS()->getType()->isIntegerType()) {
1879 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1882 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1885 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1887 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1900 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1903 if (!Req->isDependent() && !Req->isSatisfied()) {
1904 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1906 else if (
auto *T = dyn_cast<concepts::TypeRequirement>(Req))
1914 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1918 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1919 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1920 assert(TTE->getNumArgs() == 2);
1922 diag::note_is_deducible_constraint_evaluated_to_false)
1923 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1928 diag::note_atomic_constraint_evaluated_to_false)
1938 .
template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1940 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
1943 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1947 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
1962 "Attempted to diagnose a satisfied constraint");
1973 "Attempted to diagnose a satisfied constraint");
1981class SubstituteParameterMappings {
1993 bool RemovePacksForFoldExpr;
1995 SubstituteParameterMappings(
Sema &SemaRef,
1998 bool RemovePacksForFoldExpr)
1999 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
2000 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2009 SubstituteParameterMappings(
Sema &SemaRef,
2010 bool RemovePacksForFoldExpr =
false)
2012 RemovePacksForFoldExpr(RemovePacksForFoldExpr) {}
2014 bool substitute(NormalizedConstraint &N);
2017void SubstituteParameterMappings::buildParameterMapping(
2022 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2023 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2029 0, OccurringIndices);
2033 0, OccurringIndicesForSubsumption);
2040 0, OccurringIndices);
2044 ->getTemplateArgsAsWritten();
2047 0, OccurringIndices);
2055 I < TemplateParams->size(); ++I) {
2061 assert(Arg &&
"expected a default argument");
2062 DefaultArgs.emplace_back(std::move(*Arg));
2067 OccurringIndicesForSubsumption);
2070 unsigned Size = OccurringIndices.count();
2078 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2080 ? ArgsAsWritten->arguments()[I].getLocation()
2084 if (OccurringIndices[I]) {
2088 UsedParams.push_back(Param);
2098 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2102bool SubstituteParameterMappings::substitute(
2105 buildParameterMapping(N);
2114 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2115 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2117 auto SR =
Arguments[0].getSourceRange();
2118 InstLocBegin = SR.getBegin();
2119 InstLocEnd = SR.getEnd();
2123 SemaRef, InstLocBegin,
2126 {InstLocBegin, InstLocEnd});
2127 if (Inst.isInvalid())
2144 TD->getLocation(), SubstArgs,
2155 if (I < SubstArgs.
size())
2156 Loc = SubstArgs.
arguments()[I].getLocation();
2183 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2184 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2186 auto SR =
Arguments[0].getSourceRange();
2187 InstLocBegin = SR.getBegin();
2188 InstLocEnd = SR.getEnd();
2193 SemaRef, InstLocBegin,
2196 {InstLocBegin, InstLocEnd});
2197 if (Inst.isInvalid())
2208 CSE->getTemplateArgsAsWritten();
2214 CSE->getConceptNameInfo().getLoc(), Out,
2219 auto TemplateArgs = *MLTAL;
2222 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2223 RemovePacksForFoldExpr)
2231 assert(!ArgsAsWritten);
2240 assert(!ArgsAsWritten);
2245 return SubstituteParameterMappings(SemaRef,
true)
2251 assert(ArgsAsWritten);
2252 return substitute(CC);
2254 assert(!ArgsAsWritten);
2258 if (RemovePacksForFoldExpr) {
2262 if (AdjustConstraints(SemaRef, 0,
2264 .TransformTemplateArguments(InputArgLoc.begin(),
2265 InputArgLoc.end(), OutArgs))
2281 return SubstituteParameterMappings(SemaRef, &MLTAL,
2283 RemovePacksForFoldExpr)
2288 if (substitute(Compound.getLHS()))
2290 return substitute(Compound.getRHS());
2293 llvm_unreachable(
"Unknown ConstraintKind enum");
2300 assert(ACs.size() != 0);
2302 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2305 for (
unsigned I = 1; I < ACs.size(); ++I) {
2306 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2307 ACs[I].ArgPackSubstIndex);
2318 assert(E !=
nullptr);
2326 llvm::FoldingSetNodeID
ID;
2330 SatisfactionStackRAII StackRAII(S, D, ID);
2337 if (LogicalBinOp BO = E) {
2338 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2341 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2348 if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2364 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2366 AssociatedConstraint(Res.get(), SubstIndex));
2373 if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2375 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2376 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2381 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2385 if (FE->getInit()) {
2386 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2387 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2391 if (FE->isRightFold())
2404 auto *
Sub = fromConstraintExpr(S, D, FE->
getPattern(), SubstIndex);
2416 if (!ConstrainedDeclOrNestedReq) {
2417 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2418 *
this,
nullptr, AssociatedConstraints);
2420 SubstituteParameterMappings(*this).substitute(*Normalized))
2428 ConstrainedDeclOrNestedReq.dyn_cast<
const NamedDecl *>();
2429 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2430 if (CacheEntry == NormalizationCache.end()) {
2431 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2432 *
this, ND, AssociatedConstraints);
2434 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq,
nullptr);
2438 bool Failed = SubstituteParameterMappings(*this).substitute(*Normalized);
2440 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2445 return CacheEntry->second;
2468 if (It != BPacks.end())
2480 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2486 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2487 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2488 "use non-instantiated function declaration for constraints partial "
2503 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2504 auto CacheEntry = SubsumptionCache.find(Key);
2505 if (CacheEntry != SubsumptionCache.end()) {
2506 Result = CacheEntry->second;
2513 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2514 if (Depth2 > Depth1) {
2515 AC1[I].ConstraintExpr =
2516 AdjustConstraints(*
this, Depth2 - Depth1)
2517 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2519 }
else if (Depth1 > Depth2) {
2520 AC2[I].ConstraintExpr =
2521 AdjustConstraints(*
this, Depth1 - Depth2)
2522 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2531 const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2;
2532 if (Depth2 > Depth1)
2534 else if (Depth1 > Depth2)
2536 std::optional<bool> Subsumes = SC.
Subsumes(DeclAC1, AC1, DeclAC2, AC2);
2542 SubsumptionCache.try_emplace(Key, *Subsumes);
2553 if (AC1.empty() || AC2.empty())
2556 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2567 llvm::FoldingSetNodeID IDA, IDB;
2569 EB->Profile(IDB,
Context,
true);
2573 AmbiguousAtomic1 = EA;
2574 AmbiguousAtomic2 = EB;
2589 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2590 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2593 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2594 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2596 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2597 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2602 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2604 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2606 Diag(AmbiguousAtomic2->getBeginLoc(),
2607 diag::note_ambiguous_atomic_constraints_similar_expression)
2608 << AmbiguousAtomic2->getSourceRange();
2619 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2621uint16_t SubsumptionChecker::getNewLiteralId() {
2622 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2623 "too many constraints!");
2628 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2643 llvm::FoldingSetNodeID ID;
2644 ID.AddBoolean(Ori->hasParameterMapping());
2645 if (Ori->hasParameterMapping()) {
2646 const auto &Mapping = Ori->getParameterMapping();
2648 Ori->mappingOccurenceListForSubsumption();
2649 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2656 auto It = Elems.find(ID);
2657 if (It == Elems.end()) {
2660 MappedAtomicConstraint{
2661 Ori, {getNewLiteralId(), Literal::Atomic}}})
2663 ReverseMap[It->second.ID.Value] = Ori;
2665 return It->getSecond().ID;
2669 auto &Elems = FoldMap[Ori->getPattern()];
2671 FoldExpendedConstraintKey K;
2672 K.Kind = Ori->getFoldOperator();
2674 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2675 return K.Kind ==
Other.Kind;
2677 if (It == Elems.end()) {
2678 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2679 It = Elems.insert(Elems.end(), std::move(K));
2680 ReverseMap[It->ID.Value] = Ori;
2686 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2689 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2705template <
typename FormulaType>
2709 auto Add = [&,
this](Clause
C) {
2712 C.erase(llvm::unique(
C),
C.end());
2713 AddUniqueClauseToFormula(Res, std::move(
C));
2718 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2721 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2724 return Normalize<FormulaType>(
2725 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2728 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2730 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2731 Left = Normalize<FormulaType>(Compound.getLHS());
2732 Right = Normalize<FormulaType>(Compound.getRHS());
2735 if (Compound.getCompoundKind() == FormulaType::Kind) {
2736 unsigned SizeLeft =
Left.size();
2737 Res = std::move(Left);
2738 Res.reserve(SizeLeft +
Right.size());
2739 std::for_each(std::make_move_iterator(
Right.begin()),
2740 std::make_move_iterator(
Right.end()), Add);
2744 Res.reserve(
Left.size() *
Right.size());
2745 for (
const auto <ransform : Left) {
2746 for (
const auto &RTransform : Right) {
2748 Combined.reserve(LTransform.size() + RTransform.size());
2749 llvm::copy(LTransform, std::back_inserter(Combined));
2750 llvm::copy(RTransform, std::back_inserter(Combined));
2751 Add(std::move(Combined));
2757 llvm_unreachable(
"Unknown ConstraintKind enum");
2760void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2761 for (
auto &
Other : F) {
2762 if (llvm::equal(
C,
Other))
2772 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2774 return std::nullopt;
2777 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2779 return std::nullopt;
2781 return Subsumes(PNormalized, QNormalized);
2787 DNFFormula DNFP = DNF(*P);
2788 CNFFormula CNFQ = CNF(*Q);
2793 const CNFFormula &QCNF) {
2794 for (
const auto &Pi : PDNF) {
2795 for (
const auto &Qj : QCNF) {
2801 if (!DNFSubsumes(Pi, Qj))
2808bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2810 return llvm::any_of(P, [&](Literal LP) {
2811 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2817 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2820 auto It = FoldSubsumptionCache.find(Key);
2821 if (It == FoldSubsumptionCache.end()) {
2830 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2836 if (A.Kind != B.Kind)
2839 case Literal::Atomic:
2841 return A.Value == B.Value;
2843 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2844 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2845 case Literal::FoldExpanded:
2847 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2848 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2850 llvm_unreachable(
"unknown literal kind");
This file provides AST data structures related to concepts.
This file provides some common utility functions for processing Lambda related AST Constructs.
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 unsigned CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND)
static void DiagnoseUnsatisfiedConstraint(Sema &S, ArrayRef< UnsatisfiedConstraintRecord > Records, SourceLocation Loc, bool First=true, concepts::NestedRequirement *Req=nullptr)
static ExprResult SubstituteConceptsInConstraintExpression(Sema &S, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex)
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 const Expr * SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Decl *ND, const Expr *ConstrExpr)
static void diagnoseUnsatisfiedRequirement(Sema &S, concepts::ExprRequirement *Req, bool First)
static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, const ConceptReference *Concept, SourceLocation Loc, bool First)
static bool PreparePackForExpansion(Sema &S, const CXXBaseSpecifier &Base, const MultiLevelTemplateArgumentList &TemplateArgs, TypeSourceInfo *&Out, UnexpandedInfo &Info)
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
const TemplateArgument * getDefaultTemplateArgumentOrNone(const NamedDecl *P) const
Return the default argument of a template parameter, if one exists.
llvm::StringRef backupStr(llvm::StringRef S) const
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,...
SourceLocation getBeginLoc() const LLVM_READONLY
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.
Represents a C++ nested-name-specifier or a global scope specifier.
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.
Expr * getConstraintExpr() const
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
TemplateDecl * 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
ConceptReference * getConceptReference() const
const ImplicitConceptSpecializationDecl * getSpecializationDecl() const
const ASTConstraintSatisfaction & getSatisfaction() const
Get elaborated satisfaction info about the template arguments' satisfaction of the named concept.
ConceptDecl * getNamedConcept() const
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()
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.
unsigned getTemplateDepth() const
Determine the number of levels of template parameter surrounding this declaration.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceLocation getBeginLoc() const LLVM_READONLY
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
const AssociatedConstraint & getTrailingRequiresClause() const
Get the constraint-expression introduced by the trailing requires-clause in the function/member decla...
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.
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...
Represents difference between two FPOptions values.
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)
static ImplicitConceptSpecializationDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation SL, ArrayRef< TemplateArgument > ConvertedArgs)
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.
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
bool isAnyArgInstantiationDependent() const
This represents a decl that may have a name.
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.
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.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
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...
Scope - A scope is a transient data structure that is used while parsing the program.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
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...
Sema - This implements semantic analysis and AST building for C.
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
ExprResult SubstConceptTemplateArguments(const ConceptSpecializationExpr *CSE, const Expr *ConstraintExpr, const MultiLevelTemplateArgumentList &MLTAL)
Substitute concept template arguments in the constraint expression of a concept-id.
llvm::DenseMap< llvm::FoldingSetNodeID, UnsubstitutedConstraintSatisfactionCacheResult > UnsubstitutedConstraintSatisfactionCache
Cache the satisfaction of an atomic constraint.
bool ConstraintExpressionDependsOnEnclosingTemplate(const FunctionDecl *Friend, unsigned TemplateDepth, const Expr *Constraint)
void MarkUsedTemplateParametersForSubsumptionParameterMapping(const Expr *E, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are named in a given expression.
DiagnosticsEngine & getDiagnostics() const
void DiagnoseTypeTraitDetails(const Expr *E)
If E represents a built-in type trait, or a known standard type trait, try to print more information ...
bool CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions, bool Diagnose=true)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
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
ExprResult CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &ConceptNameInfo, NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const TemplateArgumentListInfo *TemplateArgs, bool DoCheckConstraintSatisfaction=true)
llvm::PointerUnion< const NamedDecl *, const concepts::NestedRequirement * > ConstrainedDeclOrNestedRequirement
bool SubstTemplateArguments(ArrayRef< TemplateArgumentLoc > Args, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs)
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 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.
bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out)
TemplateArgument getPackSubstitutedTemplateArgument(TemplateArgument Arg) const
sema::FunctionScopeInfo * getCurFunction() const
llvm::DenseMap< llvm::FoldingSetNodeID, TemplateArgumentLoc > * CurrentCachedTemplateArgs
Cache the instantiation results of template parameter mappings within concepts.
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, SourceLocation Loc={}, bool First=true)
Emit diagnostics explaining why a constraint expression was deemed unsatisfied.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(const Decl *D, std::optional< ArrayRef< TemplateArgument > > Innermost=std::nullopt, UnsignedOrNone NumLevels=std::nullopt, bool SkipInnerNonInstantiated=false)
Retrieve the template argument list(s) that should be used to instantiate the definition of the given...
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()
bool CheckFunctionSpecializationConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ConstraintSatisfaction &Satisfaction)
ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs)
void MarkUsedTemplateParameters(const Expr *E, bool OnlyDeduced, unsigned Depth, llvm::SmallBitVector &Used)
Mark which template parameters are used in a given expression.
@ 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 AreConstraintExpressionsEqual(const Decl *Old, const Expr *OldConstr, const Decl *New, const Expr *NewConstr)
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...
TemplateArgumentLoc getIdentityTemplateArgumentLoc(NamedDecl *Param, SourceLocation Location)
Get a template argument mapping the given template parameter to itself, e.g.
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...
bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions=true, bool *ConstraintsNotSatisfied=nullptr)
Check that the given template arguments can be provided to the given template, converting the argumen...
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionTemplateDecl *FTD)
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
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
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
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
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.
bool isNull() const
Determine whether this template name is NULL.
Stores a list of template parameters for a TemplateDecl and its derived classes.
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
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
UnresolvedUsingTypenameDecl * getDecl() const
NestedNameSpecifier getQualifier() const
Retrieve the nested-name-specifier that qualifies the name.
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...
__inline void unsigned int _2
uint32_t Literal
Literals are represented as positive integers.
bool Sub(InterpState &S, CodePtr OpPC)
bool Add(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
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
@ 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)
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
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.