@@ -405,7 +405,7 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
405405
406406 void VisitConstraint (const NormalizedConstraintWithParamMapping &Constraint) {
407407 if (!Constraint.hasParameterMapping ()) {
408- for (auto List : TemplateArgs)
408+ for (const auto & List : TemplateArgs)
409409 for (const TemplateArgument &Arg : List.Args )
410410 SemaRef.Context .getCanonicalTemplateArgument (Arg).Profile (
411411 ID, SemaRef.Context );
@@ -459,6 +459,9 @@ class ConstraintSatisfactionChecker {
459459 ExprResult Evaluate (const AtomicConstraint &Constraint,
460460 const MultiLevelTemplateArgumentList &MLTAL);
461461
462+ ExprResult EvaluateSlow (const FoldExpandedConstraint &Constraint,
463+ const MultiLevelTemplateArgumentList &MLTAL);
464+
462465 ExprResult Evaluate (const FoldExpandedConstraint &Constraint,
463466 const MultiLevelTemplateArgumentList &MLTAL);
464467
@@ -732,7 +735,6 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
732735
733736 ID.AddPointer (Constraint.getConstraintExpr ());
734737 ID.AddInteger (OuterPackSubstIndex.toInternalRepresentation ());
735- ID.AddBoolean (Constraint.hasParameterMapping ());
736738 HashParameterMapping (S, MLTAL, ID, OuterPackSubstIndex)
737739 .VisitConstraint (Constraint);
738740
@@ -794,16 +796,16 @@ ConstraintSatisfactionChecker::EvaluateFoldExpandedConstraintSize(
794796 return NumExpansions;
795797}
796798
797- ExprResult ConstraintSatisfactionChecker::Evaluate (
799+ ExprResult ConstraintSatisfactionChecker::EvaluateSlow (
798800 const FoldExpandedConstraint &Constraint,
799801 const MultiLevelTemplateArgumentList &MLTAL) {
802+
800803 bool Conjunction = Constraint.getFoldOperator () ==
801804 FoldExpandedConstraint::FoldOperatorKind::And;
802805 unsigned EffectiveDetailEndIndex = Satisfaction.Details .size ();
803806
804807 llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
805808 // FIXME: Is PackSubstitutionIndex correct?
806- // TODO: We might want to cache the substitution of fold expanded constraints.
807809 llvm::SaveAndRestore _ (PackSubstitutionIndex, S.ArgPackSubstIndex );
808810 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
809811 SubstitutionInTemplateArguments (
@@ -859,10 +861,41 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
859861 return Out;
860862}
861863
864+ ExprResult ConstraintSatisfactionChecker::Evaluate (
865+ const FoldExpandedConstraint &Constraint,
866+ const MultiLevelTemplateArgumentList &MLTAL) {
867+
868+ llvm::FoldingSetNodeID ID;
869+ ID.AddPointer (Constraint.getPattern ());
870+ HashParameterMapping (S, MLTAL, ID, std::nullopt ).VisitConstraint (Constraint);
871+
872+ if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache .find (ID);
873+ Iter != S.UnsubstitutedConstraintSatisfactionCache .end ()) {
874+
875+ auto &Cached = Iter->second .Satisfaction ;
876+ Satisfaction.ContainsErrors = Cached.ContainsErrors ;
877+ Satisfaction.IsSatisfied = Cached.IsSatisfied ;
878+ Satisfaction.Details .insert (Satisfaction.Details .end (),
879+ Cached.Details .begin (), Cached.Details .end ());
880+ return Iter->second .SubstExpr ;
881+ }
882+
883+ unsigned Size = Satisfaction.Details .size ();
884+
885+ ExprResult E = EvaluateSlow (Constraint, MLTAL);
886+ UnsubstitutedConstraintSatisfactionCacheResult Cache;
887+ Cache.Satisfaction .ContainsErrors = Satisfaction.ContainsErrors ;
888+ Cache.Satisfaction .IsSatisfied = Satisfaction.IsSatisfied ;
889+ std::copy (Satisfaction.Details .begin () + Size, Satisfaction.Details .end (),
890+ std::back_inserter (Cache.Satisfaction .Details ));
891+ Cache.SubstExpr = E;
892+ S.UnsubstitutedConstraintSatisfactionCache .insert ({ID, std::move (Cache)});
893+ return E;
894+ }
895+
862896ExprResult ConstraintSatisfactionChecker::EvaluateSlow (
863897 const ConceptIdConstraint &Constraint,
864- const MultiLevelTemplateArgumentList &MLTAL,
865- unsigned Size) {
898+ const MultiLevelTemplateArgumentList &MLTAL, unsigned Size) {
866899 const ConceptReference *ConceptId = Constraint.getConceptId ();
867900
868901 llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
@@ -907,8 +940,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow(
907940 Satisfaction.Details .insert (
908941 Satisfaction.Details .begin () + Size,
909942 new (S.Context ) ConstraintSatisfaction::SubstitutionDiagnostic{
910- SubstDiag.first ,
911- allocateStringFromConceptDiagnostic (S, SubstDiag.second )});
943+ SubstDiag.first ,
944+ allocateStringFromConceptDiagnostic (S, SubstDiag.second )});
912945 return ExprError ();
913946 }
914947
@@ -944,10 +977,11 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
944977 ? Constraint.getPackSubstitutionIndex ()
945978 : PackSubstitutionIndex;
946979
947- Sema::InstantiatingTemplate _ (S, ConceptId->getBeginLoc (),
948- Sema::InstantiatingTemplate::ConstraintsCheck{},
949- ConceptId->getNamedConcept (), MLTAL.getInnermost (),
950- Constraint.getSourceRange ());
980+ Sema::InstantiatingTemplate _ (S, ConceptId->getBeginLoc (),
981+ Sema::InstantiatingTemplate::ConstraintsCheck{},
982+ ConceptId->getNamedConcept (),
983+ MLTAL.getInnermost (),
984+ Constraint.getSourceRange ());
951985
952986 unsigned Size = Satisfaction.Details .size ();
953987
@@ -967,11 +1001,9 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
9671001 llvm::FoldingSetNodeID ID;
9681002 ID.AddPointer (Constraint.getConceptId ());
9691003 ID.AddInteger (OuterPackSubstIndex.toInternalRepresentation ());
970- ID.AddBoolean (Constraint.hasParameterMapping ());
9711004 HashParameterMapping (S, MLTAL, ID, OuterPackSubstIndex)
9721005 .VisitConstraint (Constraint);
9731006
974-
9751007 if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache .find (ID);
9761008 Iter != S.UnsubstitutedConstraintSatisfactionCache .end ()) {
9771009
@@ -984,7 +1016,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
9841016 }
9851017
9861018 ExprResult CE = EvaluateSlow (Constraint, MLTAL, Size);
987- if (CE.isInvalid ())
1019+ if (CE.isInvalid ())
9881020 return E;
9891021 UnsubstitutedConstraintSatisfactionCacheResult Cache;
9901022 Cache.Satisfaction .ContainsErrors = Satisfaction.ContainsErrors ;
0 commit comments