29#include "llvm/ADT/DenseMap.h"
30#include "llvm/ADT/PointerUnion.h"
31#include "llvm/ADT/StringExtras.h"
32#include "llvm/Support/SaveAndRestore.h"
41 const Expr *LHS =
nullptr;
42 const Expr *RHS =
nullptr;
45 LogicalBinOp(
const Expr *E) {
46 if (
auto *BO = dyn_cast<BinaryOperator>(E)) {
50 Loc = BO->getExprLoc();
51 }
else if (
auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
53 if (OO->getNumArgs() == 2) {
54 Op = OO->getOperator();
57 Loc = OO->getOperatorLoc();
62 bool isAnd()
const {
return Op == OO_AmpAmp; }
63 bool isOr()
const {
return Op == OO_PipePipe; }
64 explicit operator bool()
const {
return isAnd() || isOr(); }
66 const Expr *getLHS()
const {
return LHS; }
67 const Expr *getRHS()
const {
return RHS; }
71 return recreateBinOp(SemaRef, LHS,
const_cast<Expr *
>(getRHS()));
76 assert((isAnd() || isOr()) &&
"Not the right kind of op?");
77 assert((!LHS.isInvalid() && !RHS.isInvalid()) &&
"not good expressions?");
79 if (!LHS.isUsable() || !RHS.isUsable())
93 Token NextToken,
bool *PossibleNonPrimary,
94 bool IsTrailingRequiresClause) {
100 if (LogicalBinOp BO = ConstraintExpression) {
102 PossibleNonPrimary) &&
105 }
else if (
auto *
C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
111 auto CheckForNonPrimary = [&] {
112 if (!PossibleNonPrimary)
115 *PossibleNonPrimary =
126 (NextToken.
is(tok::l_paren) &&
127 (IsTrailingRequiresClause ||
145 CheckForNonPrimary();
151 diag::err_non_bool_atomic_constraint)
153 CheckForNonPrimary();
157 if (PossibleNonPrimary)
158 *PossibleNonPrimary =
false;
163struct SatisfactionStackRAII {
165 bool Inserted =
false;
167 const llvm::FoldingSetNodeID &FSNID)
174 ~SatisfactionStackRAII() {
186 for (
const auto &List : *MLTAL)
204 bool SkipForSpecialization =
false) {
210 true, SkipForSpecialization);
215class AdjustConstraintDepth :
public TreeTransform<AdjustConstraintDepth> {
216 unsigned TemplateDepth = 0;
219 using inherited = TreeTransform<AdjustConstraintDepth>;
220 AdjustConstraintDepth(Sema &SemaRef,
unsigned TemplateDepth)
221 : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
223 using inherited::TransformTemplateTypeParmType;
224 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB,
225 TemplateTypeParmTypeLoc TL,
bool) {
228 TemplateTypeParmDecl *NewTTPDecl =
nullptr;
229 if (TemplateTypeParmDecl *OldTTPDecl =
T->getDecl())
230 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>(
233 QualType
Result = getSema().Context.getTemplateTypeParmType(
234 T->getDepth() + TemplateDepth,
T->getIndex(),
T->isParameterPack(),
236 TemplateTypeParmTypeLoc NewTL = TLB.
push<TemplateTypeParmTypeLoc>(
Result);
241 bool AlreadyTransformed(QualType
T) {
257 using inherited = RecursiveASTVisitor<HashParameterMapping>;
261 const MultiLevelTemplateArgumentList &TemplateArgs;
262 llvm::FoldingSetNodeID &
ID;
263 llvm::SmallVector<TemplateArgument, 10> UsedTemplateArgs;
265 UnsignedOrNone OuterPackSubstIndex;
267 bool shouldVisitTemplateInstantiations()
const {
return true; }
270 HashParameterMapping(Sema &SemaRef,
271 const MultiLevelTemplateArgumentList &TemplateArgs,
272 llvm::FoldingSetNodeID &ID,
273 UnsignedOrNone OuterPackSubstIndex)
274 : SemaRef(SemaRef), TemplateArgs(TemplateArgs),
ID(
ID),
275 OuterPackSubstIndex(OuterPackSubstIndex) {}
277 bool VisitTemplateTypeParmType(TemplateTypeParmType *
T) {
288 TemplateArgument Arg = TemplateArgs(
T->getDepth(),
T->getIndex());
292 "Missing argument pack");
297 UsedTemplateArgs.push_back(
302 bool VisitDeclRefExpr(DeclRefExpr *E) {
304 NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D);
306 return TraverseDecl(D);
317 "Missing argument pack");
321 UsedTemplateArgs.push_back(
326 bool VisitTypedefType(TypedefType *TT) {
327 return inherited::TraverseType(TT->
desugar());
330 bool TraverseDecl(Decl *D) {
331 if (
auto *VD = dyn_cast<ValueDecl>(D)) {
332 if (
auto *Var = dyn_cast<VarDecl>(VD))
333 TraverseStmt(Var->getInit());
334 return TraverseType(VD->getType());
337 return inherited::TraverseDecl(D);
340 bool TraverseCallExpr(CallExpr *CE) {
341 inherited::TraverseStmt(CE->
getCallee());
344 inherited::TraverseStmt(Arg);
349 bool TraverseTypeLoc(TypeLoc TL,
bool TraverseQualifier =
true) {
354 bool TraverseTagType(
const TagType *
T,
bool TraverseQualifier) {
362 bool TraverseInjectedClassNameType(InjectedClassNameType *
T,
363 bool TraverseQualifier) {
364 return TraverseTemplateArguments(
T->getTemplateArgs(SemaRef.
Context));
367 bool TraverseTemplateArgument(
const TemplateArgument &Arg) {
370 Sema::ArgPackSubstIndexRAII _1(SemaRef, std::nullopt);
371 llvm::SaveAndRestore<UnsignedOrNone>
_2(OuterPackSubstIndex,
373 return inherited::TraverseTemplateArgument(Arg);
376 Sema::ArgPackSubstIndexRAII _1(SemaRef, OuterPackSubstIndex);
377 return inherited::TraverseTemplateArgument(Arg);
380 bool TraverseSizeOfPackExpr(SizeOfPackExpr *SOPE) {
381 return TraverseDecl(SOPE->
getPack());
384 bool VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E) {
388 void VisitConstraint(
const NormalizedConstraintWithParamMapping &Constraint) {
390 for (
const auto &List : TemplateArgs)
391 for (
const TemplateArgument &Arg : List.Args)
397 llvm::ArrayRef<TemplateArgumentLoc> Mapping =
399 for (
auto &ArgLoc : Mapping) {
400 TemplateArgument Canonical =
403 UsedTemplateArgs.push_back(Canonical);
404 TraverseTemplateArgument(Canonical);
407 for (
auto &
Used : UsedTemplateArgs) {
408 llvm::FoldingSetNodeID R;
415class ConstraintSatisfactionChecker {
418 SourceLocation TemplateNameLoc;
419 UnsignedOrNone PackSubstitutionIndex;
421 ConstraintSatisfaction &Satisfaction;
425 EvaluateAtomicConstraint(
const Expr *AtomicExpr,
426 const MultiLevelTemplateArgumentList &MLTAL);
428 UnsignedOrNone EvaluateFoldExpandedConstraintSize(
429 const FoldExpandedConstraint &FE,
430 const MultiLevelTemplateArgumentList &MLTAL);
433 std::optional<MultiLevelTemplateArgumentList> SubstitutionInTemplateArguments(
434 const NormalizedConstraintWithParamMapping &Constraint,
435 const MultiLevelTemplateArgumentList &MLTAL,
436 llvm::SmallVector<TemplateArgument> &SubstitutedOuterMost);
438 ExprResult EvaluateSlow(
const AtomicConstraint &Constraint,
439 const MultiLevelTemplateArgumentList &MLTAL);
442 const MultiLevelTemplateArgumentList &MLTAL);
444 ExprResult EvaluateSlow(
const FoldExpandedConstraint &Constraint,
445 const MultiLevelTemplateArgumentList &MLTAL);
448 const MultiLevelTemplateArgumentList &MLTAL);
450 ExprResult EvaluateSlow(
const ConceptIdConstraint &Constraint,
451 const MultiLevelTemplateArgumentList &MLTAL,
455 const MultiLevelTemplateArgumentList &MLTAL);
458 const MultiLevelTemplateArgumentList &MLTAL);
461 ConstraintSatisfactionChecker(Sema &SemaRef,
const NamedDecl *
Template,
462 SourceLocation TemplateNameLoc,
463 UnsignedOrNone PackSubstitutionIndex,
464 ConstraintSatisfaction &Satisfaction)
466 PackSubstitutionIndex(PackSubstitutionIndex),
467 Satisfaction(Satisfaction) {}
470 const MultiLevelTemplateArgumentList &MLTAL);
473StringRef allocateStringFromConceptDiagnostic(
const Sema &S,
483ExprResult ConstraintSatisfactionChecker::EvaluateAtomicConstraint(
489 llvm::FoldingSetNodeID
ID;
492 Satisfaction.IsSatisfied =
false;
493 Satisfaction.ContainsErrors =
true;
496 SatisfactionStackRAII StackRAII(S,
Template, ID);
507 if (Inst.isInvalid())
512 SubstitutedExpression =
515 if (SubstitutedExpression.
isInvalid() || Trap.hasErrorOccurred()) {
519 if (!Trap.hasErrorOccurred())
526 Info.takeSFINAEDiagnostic(SubstDiag);
533 Satisfaction.Details.emplace_back(
536 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
537 Satisfaction.IsSatisfied =
false;
558 SubstitutedExpression.
get(),
561 return SubstitutedExpression;
564std::optional<MultiLevelTemplateArgumentList>
565ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
571 return std::move(MLTAL);
584 if (Inst.isInvalid())
593 : PackSubstitutionIndex);
598 Satisfaction.IsSatisfied =
false;
606 TD->getLocation(), SubstArgs,
615 SubstitutedOutermost =
616 llvm::to_vector_of<TemplateArgument>(MLTAL.
getOutermost());
618 for (
unsigned I = 0, MappedIndex = 0; I <
Used.size(); I++) {
623 if (I < SubstitutedOutermost.size()) {
624 SubstitutedOutermost[I] = Arg;
627 SubstitutedOutermost.push_back(Arg);
628 Offset = SubstitutedOutermost.size();
631 if (Offset < SubstitutedOutermost.size())
632 SubstitutedOutermost.erase(SubstitutedOutermost.begin() + Offset);
637 return std::move(SubstitutedTemplateArgs);
640ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
645 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
646 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
647 if (!SubstitutedArgs) {
648 Satisfaction.IsSatisfied =
false;
653 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint(
659 if (SubstitutedAtomicExpr.
isUnset())
669 Satisfaction.IsSatisfied =
false;
670 Satisfaction.ContainsErrors =
true;
673 Satisfaction.Details.emplace_back(
675 SubstitutedAtomicExpr.get()->getBeginLoc(),
676 allocateStringFromConceptDiagnostic(S, Msg)});
677 return SubstitutedAtomicExpr;
681 Satisfaction.IsSatisfied =
true;
682 Satisfaction.ContainsErrors =
false;
683 return SubstitutedAtomicExpr;
690 EvalResult.
Diag = &EvaluationDiags;
693 !EvaluationDiags.empty()) {
697 diag::err_non_constant_constraint_expression)
700 S.
Diag(PDiag.first, PDiag.second);
705 "evaluating bool expression didn't produce int");
706 Satisfaction.IsSatisfied = EvalResult.
Val.
getInt().getBoolValue();
707 if (!Satisfaction.IsSatisfied)
708 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.
get());
710 return SubstitutedAtomicExpr;
713ExprResult ConstraintSatisfactionChecker::Evaluate(
717 unsigned Size = Satisfaction.Details.size();
718 llvm::FoldingSetNodeID
ID;
722 : PackSubstitutionIndex;
726 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
727 .VisitConstraint(Constraint);
731 auto &Cached = Iter->second.Satisfaction;
732 Satisfaction.ContainsErrors = Cached.ContainsErrors;
733 Satisfaction.IsSatisfied = Cached.IsSatisfied;
734 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
735 Cached.Details.begin(), Cached.Details.end());
736 return Iter->second.SubstExpr;
739 ExprResult E = EvaluateSlow(Constraint, MLTAL);
742 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
743 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
744 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
745 Satisfaction.Details.begin() + Size,
746 Satisfaction.Details.end());
754ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
765 assert(!Unexpanded.empty() &&
"Pack expansion without parameter packs?");
767 bool RetainExpansion =
false;
771 false, Expand, RetainExpansion,
773 !Expand || RetainExpansion)
776 if (NumExpansions && S.
getLangOpts().BracketDepth < *NumExpansions) {
778 clang::diag::err_fold_expression_limit_exceeded)
784 return NumExpansions;
787ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
793 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
798 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
799 SubstitutionInTemplateArguments(
801 MLTAL, SubstitutedOutermost);
802 if (!SubstitutedArgs) {
803 Satisfaction.IsSatisfied =
false;
809 EvaluateFoldExpandedConstraintSize(Constraint, *SubstitutedArgs);
813 if (*NumExpansions == 0) {
814 Satisfaction.IsSatisfied = Conjunction;
818 for (
unsigned I = 0; I < *NumExpansions; I++) {
820 Satisfaction.IsSatisfied =
false;
821 Satisfaction.ContainsErrors =
false;
823 ConstraintSatisfactionChecker(S,
Template, TemplateNameLoc,
826 if (
Expr.isUsable()) {
831 Conjunction ? BinaryOperatorKind::BO_LAnd
832 : BinaryOperatorKind::BO_LOr,
837 assert(!Satisfaction.IsSatisfied);
839 if (!Conjunction && Satisfaction.IsSatisfied) {
840 Satisfaction.Details.erase(Satisfaction.Details.begin() +
841 EffectiveDetailEndIndex,
842 Satisfaction.Details.end());
845 if (Satisfaction.IsSatisfied != Conjunction)
852ExprResult ConstraintSatisfactionChecker::Evaluate(
856 llvm::FoldingSetNodeID
ID;
858 HashParameterMapping(S, MLTAL, ID, std::nullopt).VisitConstraint(Constraint);
863 auto &Cached = Iter->second.Satisfaction;
864 Satisfaction.ContainsErrors = Cached.ContainsErrors;
865 Satisfaction.IsSatisfied = Cached.IsSatisfied;
866 Satisfaction.Details.insert(Satisfaction.Details.end(),
867 Cached.Details.begin(), Cached.Details.end());
868 return Iter->second.SubstExpr;
871 unsigned Size = Satisfaction.Details.size();
873 ExprResult E = EvaluateSlow(Constraint, MLTAL);
875 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
876 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
877 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
878 Satisfaction.Details.begin() + Size,
879 Satisfaction.Details.end());
885ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
891 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
892 SubstitutionInTemplateArguments(Constraint, MLTAL, SubstitutedOutermost);
894 if (!SubstitutedArgs) {
895 Satisfaction.IsSatisfied =
false;
904 : PackSubstitutionIndex);
915 Trap.hasErrorOccurred()) {
916 Satisfaction.IsSatisfied =
false;
917 if (!Trap.hasErrorOccurred())
922 Info.takeSFINAEDiagnostic(SubstDiag);
929 Satisfaction.Details.insert(
930 Satisfaction.Details.begin() + Size,
933 allocateStringFromConceptDiagnostic(S, SubstDiag.second)});
945 if (SubstitutedConceptId.
isInvalid() || Trap.hasErrorOccurred())
948 if (Size != Satisfaction.Details.size()) {
949 Satisfaction.Details.insert(
950 Satisfaction.Details.begin() + Size,
955 return SubstitutedConceptId;
958ExprResult ConstraintSatisfactionChecker::Evaluate(
967 : PackSubstitutionIndex;
981 if (InstTemplate.isInvalid())
984 unsigned Size = Satisfaction.Details.size();
989 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size, ConceptId);
996 if (Satisfaction.IsSatisfied)
999 llvm::FoldingSetNodeID
ID;
1002 HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
1003 .VisitConstraint(Constraint);
1008 auto &Cached = Iter->second.Satisfaction;
1009 Satisfaction.ContainsErrors = Cached.ContainsErrors;
1010 Satisfaction.IsSatisfied = Cached.IsSatisfied;
1011 Satisfaction.Details.insert(Satisfaction.Details.begin() + Size,
1012 Cached.Details.begin(), Cached.Details.end());
1013 return Iter->second.SubstExpr;
1016 ExprResult CE = EvaluateSlow(Constraint, MLTAL, Size);
1020 Cache.Satisfaction.ContainsErrors = Satisfaction.ContainsErrors;
1021 Cache.Satisfaction.IsSatisfied = Satisfaction.IsSatisfied;
1022 Cache.Satisfaction.Details.insert(
Cache.Satisfaction.Details.end(),
1023 Satisfaction.Details.begin() + Size,
1024 Satisfaction.Details.end());
1025 Cache.SubstExpr = CE;
1030ExprResult ConstraintSatisfactionChecker::Evaluate(
1034 unsigned EffectiveDetailEndIndex = Satisfaction.Details.size();
1041 if (Conjunction && (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors))
1044 if (!Conjunction && LHS.
isUsable() && Satisfaction.IsSatisfied &&
1045 !Satisfaction.ContainsErrors)
1048 Satisfaction.ContainsErrors =
false;
1049 Satisfaction.IsSatisfied =
false;
1053 if (RHS.
isUsable() && Satisfaction.IsSatisfied &&
1054 !Satisfaction.ContainsErrors)
1055 Satisfaction.Details.erase(Satisfaction.Details.begin() +
1056 EffectiveDetailEndIndex,
1057 Satisfaction.Details.end());
1066 Conjunction ? BinaryOperatorKind::BO_LAnd
1067 : BinaryOperatorKind::BO_LOr,
1072ExprResult ConstraintSatisfactionChecker::Evaluate(
1075 switch (Constraint.
getKind()) {
1090 llvm_unreachable(
"Unknown ConstraintKind enum");
1101 *ConvertedExpr =
nullptr;
1103 if (AssociatedConstraints.empty()) {
1118 std::optional<Sema::InstantiatingTemplate> SynthesisContext;
1119 if (!TopLevelConceptId) {
1120 SynthesisContext.emplace(S, TemplateIDRange.
getBegin(),
1133 if (TopLevelConceptId)
1142 .Evaluate(*
C, TemplateArgsLists);
1147 if (Res.
isUsable() && ConvertedExpr)
1148 *ConvertedExpr = Res.
get();
1159 if (AssociatedConstraints.empty()) {
1165 return ::CheckConstraintSatisfaction(
1166 *
this,
nullptr, AssociatedConstraints, TemplateArgsLists,
1167 TemplateIDRange, OutSatisfaction, ConvertedExpr, TopLevelConceptId);
1181 for (
auto List : TemplateArgsLists)
1183 FlattenedArgs.emplace_back(
Context.getCanonicalTemplateArgument(Arg));
1186 if (TopLevelConceptId)
1189 llvm::FoldingSetNodeID ID;
1192 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1193 OutSatisfaction = *Cached;
1198 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
1200 *
this,
Template, AssociatedConstraints, TemplateArgsLists,
1201 TemplateIDRange, *Satisfaction, ConvertedExpr, TopLevelConceptId)) {
1202 OutSatisfaction = std::move(*Satisfaction);
1206 if (
auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) {
1215 OutSatisfaction = *Cached;
1220 OutSatisfaction = *Satisfaction;
1224 SatisfactionCache.InsertNode(Satisfaction.release());
1246 return !ArgLoc.getArgument().isDependent() &&
1247 ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
1249 return Concept->getConstraintExpr();
1272 Constraints.emplace_back(Res.
get());
1284bool Sema::SetupConstraintScope(
1289 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
1293 InstantiatingTemplate Inst(
1298 if (Inst.isInvalid())
1309 if (addInstantiatedParametersToScope(
1318 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(),
1328 FunctionDecl *InstantiatedFrom =
1335 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
1336 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
1338 if (Inst.isInvalid())
1343 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL))
1352std::optional<MultiLevelTemplateArgumentList>
1353Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
1356 MultiLevelTemplateArgumentList MLTAL;
1363 false, std::nullopt,
1370 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
1371 return std::nullopt;
1379 bool ForOverloadResolution) {
1398 if (
const auto *MD = dyn_cast<CXXConversionDecl>(FD);
1401 Satisfaction, UsageLoc,
1415 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1416 SetupConstraintCheckingTemplateArgumentsAndScope(
1424 if (
auto *
Method = dyn_cast<CXXMethodDecl>(FD)) {
1425 ThisQuals =
Method->getMethodQualifiers();
1432 ForOverloadResolution);
1442 const Expr *ConstrExpr) {
1466 std::optional<LocalInstantiationScope> ScopeForParameters;
1469 ScopeForParameters.emplace(S,
true);
1473 FD =
Template->getInstantiatedFromMemberTemplate()->getTemplatedDecl();
1475 if (ScopeForParameters->getInstantiationOfIfExists(PVD))
1477 if (!PVD->isParameterPack()) {
1478 ScopeForParameters->InstantiatedLocal(PVD, PVD);
1497 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD);
1498 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD);
1502 std::optional<Sema::CXXThisScopeRAII> ThisScope;
1511 std::optional<Sema::ContextRAII> ContextScope;
1519 if (
auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
1531 return SubstConstr.
get();
1535 const Expr *OldConstr,
1537 const Expr *NewConstr) {
1538 if (OldConstr == NewConstr)
1541 if (Old && !
New.isInvalid() && !
New.ContainsDecl(Old) &&
1543 if (
const Expr *SubstConstr =
1546 OldConstr = SubstConstr;
1549 if (
const Expr *SubstConstr =
1552 NewConstr = SubstConstr;
1557 llvm::FoldingSetNodeID ID1, ID2;
1570 "Non-function templates don't need to be checked");
1591 TemplateIDRange, Satisfaction))
1596 TemplateArgString =
" ";
1602 diag::err_template_arg_list_constraints_not_satisfied)
1604 << TemplateArgString << TemplateIDRange;
1616 Template->getAssociatedConstraints(TemplateAC);
1617 if (TemplateAC.empty()) {
1636 SemaRef, PointOfInstantiation,
1638 PointOfInstantiation);
1639 if (Inst.isInvalid())
1649 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
1660 return ::CheckFunctionConstraintsWithoutInstantiation(
1661 *
this, PointOfInstantiation,
Decl->getDescribedFunctionTemplate(),
1662 TemplateArgs, Satisfaction);
1667 Template->getAssociatedConstraints(TemplateAC);
1668 if (TemplateAC.empty()) {
1678 std::optional<MultiLevelTemplateArgumentList> MLTAL =
1679 SetupConstraintCheckingTemplateArgumentsAndScope(
Decl, TemplateArgs,
1687 if (
auto *
Method = dyn_cast<CXXMethodDecl>(
Decl)) {
1688 ThisQuals =
Method->getMethodQualifiers();
1697 PointOfInstantiation, Satisfaction);
1704 "Diagnose() can only be used on an unsatisfied requirement");
1707 llvm_unreachable(
"Diagnosing a dependent requirement");
1711 if (!SubstDiag->DiagMessage.empty())
1712 S.
Diag(SubstDiag->DiagLoc,
1713 diag::note_expr_requirement_expr_substitution_error)
1714 << (
int)
First << SubstDiag->SubstitutedEntity
1715 << SubstDiag->DiagMessage;
1717 S.
Diag(SubstDiag->DiagLoc,
1718 diag::note_expr_requirement_expr_unknown_substitution_error)
1719 << (
int)
First << SubstDiag->SubstitutedEntity;
1729 if (!SubstDiag->DiagMessage.empty())
1730 S.
Diag(SubstDiag->DiagLoc,
1731 diag::note_expr_requirement_type_requirement_substitution_error)
1732 << (
int)
First << SubstDiag->SubstitutedEntity
1733 << SubstDiag->DiagMessage;
1738 note_expr_requirement_type_requirement_unknown_substitution_error)
1739 << (
int)
First << SubstDiag->SubstitutedEntity;
1749 llvm_unreachable(
"We checked this above");
1757 "Diagnose() can only be used on an unsatisfied requirement");
1760 llvm_unreachable(
"Diagnosing a dependent requirement");
1764 if (!SubstDiag->DiagMessage.empty())
1765 S.
Diag(SubstDiag->DiagLoc, diag::note_type_requirement_substitution_error)
1766 << (
int)
First << SubstDiag->SubstitutedEntity
1767 << SubstDiag->DiagMessage;
1769 S.
Diag(SubstDiag->DiagLoc,
1770 diag::note_type_requirement_unknown_substitution_error)
1771 << (
int)
First << SubstDiag->SubstitutedEntity;
1775 llvm_unreachable(
"Unknown satisfaction status");
1783 if (
Concept->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
1787 note_single_arg_concept_specialization_constraint_evaluated_to_false)
1789 <<
Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument()
1790 <<
Concept->getNamedConcept();
1792 S.
Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false)
1822 const Expr *SubstExpr,
1825 if (
const BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
1826 switch (BO->getOpcode()) {
1838 BO->getLHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1849 BO->getRHS()->EvaluateKnownConstInt(S.
Context).getBoolValue();
1861 if (BO->getLHS()->getType()->isIntegerType() &&
1862 BO->getRHS()->getType()->isIntegerType()) {
1865 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.
Context,
1868 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.
Context,
1871 if (!SimplifiedLHS.
Diag && !SimplifiedRHS.
Diag) {
1873 diag::note_atomic_constraint_evaluated_to_false_elaborated)
1886 }
else if (
auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
1889 if (!Req->isDependent() && !Req->isSatisfied()) {
1890 if (
auto *E = dyn_cast<concepts::ExprRequirement>(Req))
1892 else if (
auto *
T = dyn_cast<concepts::TypeRequirement>(Req))
1900 }
else if (
auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
1904 }
else if (
auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr);
1905 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) {
1906 assert(TTE->getNumArgs() == 2);
1908 diag::note_is_deducible_constraint_evaluated_to_false)
1909 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType();
1914 diag::note_atomic_constraint_evaluated_to_false)
1924 .
template dyn_cast<const ConstraintSubstitutionDiagnostic *>()) {
1926 S.
Diag(
Diag->first, diag::note_nested_requirement_substitution_error)
1929 S.
Diag(
Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
1933 if (
const auto *
Concept = dyn_cast<const ConceptReference *>(
Record)) {
1948 "Attempted to diagnose a satisfied constraint");
1959 "Attempted to diagnose a satisfied constraint");
1967class SubstituteParameterMappings {
1975 SubstituteParameterMappings(
Sema &SemaRef,
1979 : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten),
1980 InFoldExpr(InFoldExpr) {}
1989 SubstituteParameterMappings(
Sema &SemaRef,
bool InFoldExpr =
false)
1991 InFoldExpr(InFoldExpr) {}
1993 bool substitute(NormalizedConstraint &N);
1996void SubstituteParameterMappings::buildParameterMapping(
2001 llvm::SmallBitVector OccurringIndices(TemplateParams->
size());
2002 llvm::SmallBitVector OccurringIndicesForSubsumption(TemplateParams->
size());
2008 0, OccurringIndices);
2012 0, OccurringIndicesForSubsumption);
2019 0, OccurringIndices);
2023 ->getTemplateArgsAsWritten();
2026 0, OccurringIndices);
2028 unsigned Size = OccurringIndices.count();
2036 for (
unsigned I = 0, J = 0,
C = TemplateParams->
size(); I !=
C; ++I) {
2038 ? ArgsAsWritten->arguments()[I].getLocation()
2042 if (OccurringIndices[I]) {
2046 UsedParams.push_back(Param);
2056 std::move(OccurringIndices), std::move(OccurringIndicesForSubsumption),
2060bool SubstituteParameterMappings::substitute(
2063 buildParameterMapping(N);
2072 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2073 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2075 auto SR =
Arguments[0].getSourceRange();
2076 InstLocBegin = SR.getBegin();
2077 InstLocEnd = SR.getEnd();
2080 SemaRef, InstLocBegin,
2083 {InstLocBegin, InstLocEnd});
2084 if (Inst.isInvalid())
2100 TD->getLocation(), SubstArgs,
2111 if (I < SubstArgs.
size())
2112 Loc = SubstArgs.
arguments()[I].getLocation();
2139 InstLocBegin = ArgsAsWritten->getLAngleLoc();
2140 InstLocEnd = ArgsAsWritten->getRAngleLoc();
2142 auto SR =
Arguments[0].getSourceRange();
2143 InstLocBegin = SR.getBegin();
2144 InstLocEnd = SR.getEnd();
2148 SemaRef, InstLocBegin,
2151 {InstLocBegin, InstLocEnd});
2152 if (Inst.isInvalid())
2161 CSE->getTemplateArgsAsWritten();
2168 CSE->getConceptNameInfo().getLoc(), Out,
2173 auto TemplateArgs = *MLTAL;
2176 return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten,
2185 assert(!ArgsAsWritten);
2194 assert(!ArgsAsWritten);
2199 return SubstituteParameterMappings(SemaRef,
true)
2205 assert(ArgsAsWritten);
2206 return substitute(CC);
2208 assert(!ArgsAsWritten);
2218 return SubstituteParameterMappings(
2224 if (substitute(Compound.getLHS()))
2226 return substitute(Compound.getRHS());
2229 llvm_unreachable(
"Unknown ConstraintKind enum");
2236 assert(ACs.size() != 0);
2238 fromConstraintExpr(S, D, ACs[0].ConstraintExpr, ACs[0].ArgPackSubstIndex);
2241 for (
unsigned I = 1; I < ACs.size(); ++I) {
2242 auto *
Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr,
2243 ACs[I].ArgPackSubstIndex);
2254 assert(E !=
nullptr);
2262 llvm::FoldingSetNodeID
ID;
2266 SatisfactionStackRAII StackRAII(S, D, ID);
2273 if (LogicalBinOp BO = E) {
2274 auto *LHS = fromConstraintExpr(S, D, BO.getLHS(), SubstIndex);
2277 auto *RHS = fromConstraintExpr(S, D, BO.getRHS(), SubstIndex);
2283 }
else if (
auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
2286 Sema::InstantiatingTemplate Inst(
2288 Sema::InstantiatingTemplate::ConstraintNormalization{},
2291 if (Inst.isInvalid())
2312 SubNF = NormalizedConstraint::fromAssociatedConstraints(
2313 S, CD, AssociatedConstraint(Res.
get(), SubstIndex));
2323 }
else if (
auto *FE = dyn_cast<const CXXFoldExpr>(E);
2325 (FE->getOperator() == BinaryOperatorKind::BO_LAnd ||
2326 FE->getOperator() == BinaryOperatorKind::BO_LOr)) {
2331 FE->getOperator() == BinaryOperatorKind::BO_LAnd
2335 if (FE->getInit()) {
2336 auto *LHS = fromConstraintExpr(S, D, FE->getLHS(), SubstIndex);
2337 auto *RHS = fromConstraintExpr(S, D, FE->getRHS(), SubstIndex);
2341 if (FE->isRightFold())
2354 auto *
Sub = fromConstraintExpr(S, D, FE->
getPattern(), SubstIndex);
2366 if (!ConstrainedDeclOrNestedReq) {
2367 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2368 *
this,
nullptr, AssociatedConstraints);
2370 SubstituteParameterMappings(*this).substitute(*Normalized))
2378 ConstrainedDeclOrNestedReq.dyn_cast<
const NamedDecl *>();
2379 auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq);
2380 if (CacheEntry == NormalizationCache.end()) {
2381 auto *Normalized = NormalizedConstraint::fromAssociatedConstraints(
2382 *
this, ND, AssociatedConstraints);
2384 NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized)
2387 SubstituteParameterMappings(*this).substitute(*Normalized))
2390 return CacheEntry->second;
2413 if (It != BPacks.end())
2425 if (
const auto *FD1 = dyn_cast<FunctionDecl>(D1)) {
2431 const auto *FD2 = dyn_cast<FunctionDecl>(D2);
2432 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) &&
2433 "use non-instantiated function declaration for constraints partial "
2448 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2};
2449 auto CacheEntry = SubsumptionCache.find(Key);
2450 if (CacheEntry != SubsumptionCache.end()) {
2451 Result = CacheEntry->second;
2458 for (
size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
2459 if (Depth2 > Depth1) {
2460 AC1[I].ConstraintExpr =
2461 AdjustConstraintDepth(*
this, Depth2 - Depth1)
2462 .TransformExpr(
const_cast<Expr *
>(AC1[I].ConstraintExpr))
2464 }
else if (Depth1 > Depth2) {
2465 AC2[I].ConstraintExpr =
2466 AdjustConstraintDepth(*
this, Depth1 - Depth2)
2467 .TransformExpr(
const_cast<Expr *
>(AC2[I].ConstraintExpr))
2473 std::optional<bool> Subsumes = SC.
Subsumes(D1, AC1, D2, AC2);
2479 SubsumptionCache.try_emplace(Key, *Subsumes);
2490 if (AC1.empty() || AC2.empty())
2493 const Expr *AmbiguousAtomic1 =
nullptr, *AmbiguousAtomic2 =
nullptr;
2504 llvm::FoldingSetNodeID IDA, IDB;
2506 EB->Profile(IDB,
Context,
true);
2510 AmbiguousAtomic1 = EA;
2511 AmbiguousAtomic2 = EB;
2528 bool Is1AtLeastAs2Normally = SC.
Subsumes(Normalized1, Normalized2);
2529 bool Is2AtLeastAs1Normally = SC.
Subsumes(Normalized2, Normalized1);
2532 bool Is1AtLeastAs2 = SC2.
Subsumes(Normalized1, Normalized2);
2533 bool Is2AtLeastAs1 = SC2.
Subsumes(Normalized2, Normalized1);
2535 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
2536 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
2541 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
2543 Diag(AmbiguousAtomic1->
getBeginLoc(), diag::note_ambiguous_atomic_constraints)
2545 Diag(AmbiguousAtomic2->getBeginLoc(),
2546 diag::note_ambiguous_atomic_constraints_similar_expression)
2547 << AmbiguousAtomic2->getSourceRange();
2558 : SemaRef(SemaRef), Callable(Callable), NextID(1) {}
2560uint16_t SubsumptionChecker::getNewLiteralId() {
2561 assert((
unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) &&
2562 "too many constraints!");
2567 auto &Elems = AtomicMap[Ori->getConstraintExpr()];
2582 llvm::FoldingSetNodeID ID;
2583 ID.AddBoolean(Ori->hasParameterMapping());
2584 if (Ori->hasParameterMapping()) {
2585 const auto &Mapping = Ori->getParameterMapping();
2587 Ori->mappingOccurenceListForSubsumption();
2588 for (
auto [Idx, TAL] : llvm::enumerate(Mapping)) {
2595 auto It = Elems.find(ID);
2596 if (It == Elems.end()) {
2599 MappedAtomicConstraint{
2600 Ori, {getNewLiteralId(), Literal::Atomic}}})
2602 ReverseMap[It->second.ID.Value] = Ori;
2604 return It->getSecond().ID;
2608 auto &Elems = FoldMap[Ori->getPattern()];
2610 FoldExpendedConstraintKey K;
2611 K.Kind = Ori->getFoldOperator();
2613 auto It = llvm::find_if(Elems, [&K](
const FoldExpendedConstraintKey &
Other) {
2614 return K.Kind ==
Other.Kind;
2616 if (It == Elems.end()) {
2617 K.ID = {getNewLiteralId(), Literal::FoldExpanded};
2618 It = Elems.insert(Elems.end(), std::move(K));
2619 ReverseMap[It->ID.Value] = Ori;
2625 return SubsumptionChecker::Normalize<CNFFormula>(
C);
2628 return SubsumptionChecker::Normalize<DNFFormula>(
C);
2644template <
typename FormulaType>
2648 auto Add = [&,
this](Clause
C) {
2651 C.erase(llvm::unique(
C),
C.end());
2652 AddUniqueClauseToFormula(Res, std::move(
C));
2657 return {{find(&
static_cast<const AtomicConstraint &
>(NC))}};
2660 return {{find(&
static_cast<const FoldExpandedConstraint &
>(NC))}};
2663 return Normalize<FormulaType>(
2664 static_cast<const ConceptIdConstraint &
>(NC).getNormalizedConstraint());
2667 const auto &Compound =
static_cast<const CompoundConstraint &
>(NC);
2669 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] {
2670 Left = Normalize<FormulaType>(Compound.getLHS());
2671 Right = Normalize<FormulaType>(Compound.getRHS());
2674 if (Compound.getCompoundKind() == FormulaType::Kind) {
2675 Res = std::move(Left);
2676 Res.reserve(
Left.size() +
Right.size());
2677 std::for_each(std::make_move_iterator(
Right.begin()),
2678 std::make_move_iterator(
Right.end()), Add);
2682 Res.reserve(
Left.size() *
Right.size());
2683 for (
const auto <ransform : Left) {
2684 for (
const auto &RTransform : Right) {
2686 Combined.reserve(LTransform.size() + RTransform.size());
2687 llvm::copy(LTransform, std::back_inserter(Combined));
2688 llvm::copy(RTransform, std::back_inserter(Combined));
2689 Add(std::move(Combined));
2695 llvm_unreachable(
"Unknown ConstraintKind enum");
2698void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause
C) {
2699 for (
auto &
Other : F) {
2700 if (llvm::equal(
C,
Other))
2710 SemaRef.getNormalizedAssociatedConstraints(DP, P);
2712 return std::nullopt;
2715 SemaRef.getNormalizedAssociatedConstraints(DQ, Q);
2717 return std::nullopt;
2719 return Subsumes(PNormalized, QNormalized);
2725 DNFFormula DNFP = DNF(*P);
2726 CNFFormula CNFQ = CNF(*Q);
2731 const CNFFormula &QCNF) {
2732 for (
const auto &Pi : PDNF) {
2733 for (
const auto &Qj : QCNF) {
2739 if (!DNFSubsumes(Pi, Qj))
2746bool SubsumptionChecker::DNFSubsumes(
const Clause &P,
const Clause &Q) {
2748 return llvm::any_of(P, [&](Literal LP) {
2749 return llvm::any_of(Q, [
this, LP](Literal LQ) {
return Subsumes(LP, LQ); });
2755 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{
2758 auto It = FoldSubsumptionCache.find(Key);
2759 if (It == FoldSubsumptionCache.end()) {
2768 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first;
2774 if (A.Kind != B.Kind)
2777 case Literal::Atomic:
2779 return A.Value == B.Value;
2781 *
static_cast<const AtomicConstraint *
>(ReverseMap[A.Value]),
2782 *
static_cast<const AtomicConstraint *
>(ReverseMap[B.Value]));
2783 case Literal::FoldExpanded:
2785 static_cast<const FoldExpandedConstraint *
>(ReverseMap[A.Value]),
2786 static_cast<const FoldExpandedConstraint *
>(ReverseMap[B.Value]));
2788 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)
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)
TemplateArgument getCanonicalTemplateArgument(const TemplateArgument &Arg) const
Retrieve the "canonical" template argument.
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.
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
SourceLocation getExprLoc() const LLVM_READONLY
ArrayRef< TemplateArgument > getTemplateArguments() const
const ASTTemplateArgumentListInfo * getTemplateArgsAsWritten() const
ConceptReference * getConceptReference() 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.
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
SourceLocation getLocation() const
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)
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.
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...
Scope - A scope is a transient data structure that is used while parsing the program.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial 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...
bool hasErrorOccurred() const
Determine whether any SFINAE errors have been trapped.
SourceLocation getLocation() const
const DeclContext * getDeclContext() const
const NamedDecl * getDecl() const
const DeclContext * getLexicalDeclContext() const
Sema - This implements semantic analysis and AST building for C.
TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, SourceLocation Loc, NamedDecl *TemplateParam=nullptr)
Allocate a TemplateArgumentLoc where all locations have been initialized to the given location.
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 ...
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 FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD)
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
std::optional< sema::TemplateDeductionInfo * > isSFINAEContext() const
Determines whether we are currently in a context where template argument substitution failures are no...
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)
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()
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 CheckParameterPacksForExpansion(SourceLocation EllipsisLoc, SourceRange PatternRange, ArrayRef< UnexpandedParameterPack > Unexpanded, const MultiLevelTemplateArgumentList &TemplateArgs, bool FailOnPackProducingTemplates, bool &ShouldExpand, bool &RetainExpansion, UnsignedOrNone &NumExpansions)
Determine whether we could expand a pack expansion with the given set of parameter packs into separat...
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.
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef< TemplateArgument > TemplateArgs, ConstraintSatisfaction &Satisfaction)
bool SubstTemplateArgumentsInParameterMapping(ArrayRef< TemplateArgumentLoc > Args, SourceLocation BaseLoc, const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes)
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...
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
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
Location wrapper for a TemplateArgument.
Represents a template argument.
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const
Used to insert TemplateArguments into FoldingSets.
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.
Stores a list of template parameters for a TemplateDecl and its derived classes.
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
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)
@ 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.
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)
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
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.
bool isInvalid() const
Determines whether we have exceeded the maximum recursive template instantiations.
constexpr unsigned toInternalRepresentation() const