3636#include " llvm/ADT/PointerUnion.h"
3737#include " llvm/ADT/SmallVector.h"
3838#include " llvm/ADT/StringExtras.h"
39- #include " llvm/Support/Timer.h"
40- #include " llvm/Support/WithColor.h"
4139#include < cstddef>
4240#include < optional>
4341
@@ -345,7 +343,7 @@ static ExprResult EvaluateAtomicConstraint(
345343 return SubstitutedExpression;
346344}
347345
348- static bool calculateConstraintSatisfaction (
346+ static ExprResult calculateConstraintSatisfaction (
349347 Sema &S, const NormalizedConstraint &Constraint, const NamedDecl *Template,
350348 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
351349 ConstraintSatisfaction &Satisfaction, UnsignedOrNone PackSubstitutionIndex);
@@ -417,7 +415,7 @@ SubstitutionInTemplateArguments(
417415 return std::move (MLTAL);
418416}
419417
420- static bool calculateConstraintSatisfaction (
418+ static ExprResult calculateConstraintSatisfaction (
421419 Sema &S, const AtomicConstraint &Constraint, const NamedDecl *Template,
422420 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
423421 ConstraintSatisfaction &Satisfaction,
@@ -497,7 +495,7 @@ static bool calculateConstraintSatisfaction(
497495 if (!Satisfaction.IsSatisfied )
498496 Satisfaction.Details .emplace_back (SubstitutedAtomicExpr.get ());
499497
500- return SubstitutedAtomicExpr. isUsable () ;
498+ return SubstitutedAtomicExpr;
501499}
502500
503501static UnsignedOrNone EvaluateFoldExpandedConstraintSize (
@@ -533,7 +531,7 @@ static UnsignedOrNone EvaluateFoldExpandedConstraintSize(
533531 return NumExpansions;
534532}
535533
536- static bool calculateConstraintSatisfaction (
534+ static ExprResult calculateConstraintSatisfaction (
537535 Sema &S, const FoldExpandedConstraint &FE, const NamedDecl *Template,
538536 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
539537 ConstraintSatisfaction &Satisfaction) {
@@ -568,12 +566,13 @@ static bool calculateConstraintSatisfaction(
568566 Sema::ArgPackSubstIndexRAII SubstIndex (S, I);
569567 Satisfaction.IsSatisfied = false ;
570568 Satisfaction.ContainsErrors = false ;
571- bool Success = calculateConstraintSatisfaction (
569+ // FIXME
570+ ExprResult Expr = calculateConstraintSatisfaction (
572571 S, FE.getNormalizedPattern (), Template, TemplateNameLoc,
573572 *SubstitutedArgs, Satisfaction, UnsignedOrNone (I));
574573 // SFINAE errors shouldn't prevent disjunction from evaluating
575574 // FIXME: Does !Success == SFINAE errors occurred?
576- if (!Success && Conjunction)
575+ if (!Expr. isUsable () && Conjunction)
577576 return false ;
578577 if (!Conjunction && Satisfaction.IsSatisfied ) {
579578 Satisfaction.Details .erase (Satisfaction.Details .begin () +
@@ -589,25 +588,12 @@ static bool calculateConstraintSatisfaction(
589588 return true ;
590589}
591590
592- static bool calculateConstraintSatisfaction (
591+ static ExprResult calculateConstraintSatisfaction (
593592 Sema &S, const ConceptIdConstraint &Constraint, const NamedDecl *Template,
594593 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
595594 ConstraintSatisfaction &Satisfaction,
596595 UnsignedOrNone PackSubstitutionIndex) {
597596
598- // If the expression has been calculated, e.g. when we are in a nested
599- // requirement, do not compute it repeatedly.
600- if (auto *Expr = Constraint.getConceptSpecializationExpr ();
601- Expr && Expr->getDependence () == ExprDependence::None) {
602- auto &Calculated = Expr->getSatisfaction ();
603- Satisfaction.ContainsErrors = Calculated.ContainsErrors ;
604- Satisfaction.IsSatisfied = Calculated.IsSatisfied ;
605- Satisfaction.Details .insert (Satisfaction.Details .end (),
606- Calculated.records ().begin (),
607- Calculated.records ().end ());
608- return !Satisfaction.ContainsErrors ;
609- }
610-
611597 Sema::ContextRAII CurContext (
612598 S, Constraint.getConceptId ()->getNamedConcept ()->getDeclContext (),
613599 /* NewThisContext=*/ false );
@@ -620,11 +606,12 @@ static bool calculateConstraintSatisfaction(
620606
621607 auto Size = Satisfaction.Details .size ();
622608
623- bool Ok = calculateConstraintSatisfaction (
609+ ExprResult E = calculateConstraintSatisfaction (
624610 S, Constraint.getNormalizedConstraint (), Template, TemplateNameLoc, MLTAL,
625611 Satisfaction, PackSubstitutionIndex);
626612
627- if (Size != Satisfaction.Details .size ()) {
613+ if (!E.isUsable ())
614+ return E;
628615
629616 llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
630617 std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
@@ -633,7 +620,7 @@ static bool calculateConstraintSatisfaction(
633620 PackSubstitutionIndex);
634621
635622 if (!SubstitutedArgs)
636- return Ok ;
623+ return E. isUsable () ;
637624
638625 Sema::SFINAETrap Trap (S);
639626 Sema::ArgPackSubstIndexRAII SubstIndex (
@@ -652,12 +639,15 @@ static bool calculateConstraintSatisfaction(
652639 AdjustConstraintDepth Adjust (S, Depth);
653640 if (Adjust.TransformTemplateArguments (Ori->getTemplateArgs (),
654641 Ori->NumTemplateArgs , TransArgs))
655- return Ok ;
642+ return false ;
656643
657644 if (S.SubstTemplateArguments (TransArgs.arguments (), *SubstitutedArgs,
658645 OutArgs) ||
659- Trap.hasErrorOccurred ())
660- return Ok;
646+ Trap.hasErrorOccurred ()) {
647+ Satisfaction.ContainsErrors = true ;
648+ Satisfaction.IsSatisfied = false ;
649+ return false ;
650+ }
661651
662652 CXXScopeSpec SS;
663653 SS.Adopt (Constraint.getConceptId ()->getNestedNameSpecifierLoc ());
@@ -669,18 +659,20 @@ static bool calculateConstraintSatisfaction(
669659 /* CheckConstraintSatisfaction=*/ false );
670660
671661 if (SubstitutedConceptId.isInvalid () || Trap.hasErrorOccurred ())
672- return Ok;
662+ return false ;
663+
664+ if (Size != Satisfaction.Details .size ()) {
673665
674666 Satisfaction.Details .insert (
675667 Satisfaction.Details .begin () + Size,
676668 UnsatisfiedConstraintRecord (
677669 SubstitutedConceptId.getAs <ConceptSpecializationExpr>()
678670 ->getConceptReference ()));
679671 }
680- return Ok ;
672+ return SubstitutedConceptId ;
681673}
682674
683- static bool calculateConstraintSatisfaction (
675+ static ExprResult calculateConstraintSatisfaction (
684676 Sema &S, const CompoundConstraint &Constraint, const NamedDecl *Template,
685677 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
686678 ConstraintSatisfaction &Satisfaction,
@@ -691,35 +683,49 @@ static bool calculateConstraintSatisfaction(
691683 bool Conjunction =
692684 Constraint.getCompoundKind () == NormalizedConstraint::CCK_Conjunction;
693685
694- bool Ok = calculateConstraintSatisfaction (
686+ ExprResult LHS = calculateConstraintSatisfaction (
695687 S, Constraint.getLHS (), Template, TemplateNameLoc, MLTAL, Satisfaction,
696688 PackSubstitutionIndex);
697689
698- if (Conjunction && !Ok )
690+ if (Conjunction && !LHS. isUsable () )
699691 return false ;
700692
701- if (!Conjunction && Ok && Satisfaction.IsSatisfied &&
693+ if (!Conjunction && LHS. isUsable () && Satisfaction.IsSatisfied &&
702694 !Satisfaction.ContainsErrors )
703- return true ;
695+ return LHS ;
704696
705- if (Conjunction && Ok &&
697+ if (Conjunction && LHS. isUsable () &&
706698 (!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors ))
707- return true ;
699+ return LHS ;
708700
709701 Satisfaction.ContainsErrors = false ;
710702 Satisfaction.IsSatisfied = false ;
711703
712- Ok = calculateConstraintSatisfaction (S, Constraint. getRHS (), Template,
713- TemplateNameLoc, MLTAL, Satisfaction,
704+ ExprResult RHS = calculateConstraintSatisfaction (
705+ S, Constraint. getRHS (), Template, TemplateNameLoc, MLTAL, Satisfaction,
714706 PackSubstitutionIndex);
715- if (Ok && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors )
707+ if (RHS. isUsable () && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors )
716708 Satisfaction.Details .erase (Satisfaction.Details .begin () +
717709 EffectiveDetailEndIndex,
718710 Satisfaction.Details .end ());
719- return Ok;
711+
712+ if (!LHS.isUsable ())
713+ return RHS;
714+
715+ if (!RHS.isUsable ())
716+ return LHS;
717+
718+ return BinaryOperator::Create (
719+ S.Context , LHS.get (), RHS.get (),
720+ BinaryOperator::getOverloadedOpcode (
721+ Constraint.getCompoundKind () == NormalizedConstraint::CCK_Conjunction
722+ ? OO_AmpAmp
723+ : OO_PipePipe),
724+ S.Context .BoolTy , VK_PRValue, OK_Ordinary, Constraint.getBeginLoc (),
725+ FPOptionsOverride{});
720726}
721727
722- static bool calculateConstraintSatisfaction (
728+ static ExprResult calculateConstraintSatisfaction (
723729 Sema &S, const NormalizedConstraint &Constraint, const NamedDecl *Template,
724730 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
725731 ConstraintSatisfaction &Satisfaction,
@@ -753,7 +759,10 @@ static bool CheckConstraintSatisfaction(
753759 ArrayRef<AssociatedConstraint> AssociatedConstraints,
754760 const MultiLevelTemplateArgumentList &TemplateArgsLists,
755761 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
756- const ConceptReference *TopLevelConceptId = nullptr ) {
762+ Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr ) {
763+
764+ if (ConvertedExpr)
765+ *ConvertedExpr = nullptr ;
757766
758767 if (AssociatedConstraints.empty ()) {
759768 Satisfaction.IsSatisfied = true ;
@@ -790,7 +799,6 @@ static bool CheckConstraintSatisfaction(
790799 const_cast <NormalizedConstraint *>(C),
791800 Template, /* CSE=*/ nullptr ,
792801 S.ArgPackSubstIndex );
793- }
794802
795803 ExprResult Res = calculateConstraintSatisfaction (
796804 S, *C, Template, TemplateIDRange.getBegin (), TemplateArgsLists,
@@ -810,16 +818,16 @@ bool Sema::CheckConstraintSatisfaction(
810818 ArrayRef<AssociatedConstraint> AssociatedConstraints,
811819 const MultiLevelTemplateArgumentList &TemplateArgsLists,
812820 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
813- const ConceptReference *TopLevelConceptId) {
821+ const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr ) {
814822 if (AssociatedConstraints.empty ()) {
815823 OutSatisfaction.IsSatisfied = true ;
816824 return false ;
817825 }
818826 const auto *Template = Entity.dyn_cast <const NamedDecl *>();
819827 if (!Template) {
820- return ::CheckConstraintSatisfaction (* this , nullptr , AssociatedConstraints,
821- TemplateArgsLists, TemplateIDRange ,
822- OutSatisfaction, TopLevelConceptId);
828+ return ::CheckConstraintSatisfaction (
829+ * this , nullptr , AssociatedConstraints, TemplateArgsLists ,
830+ TemplateIDRange, OutSatisfaction, ConvertedExpr , TopLevelConceptId);
823831 }
824832 // Invalid templates could make their way here. Substituting them could result
825833 // in dependent expressions.
@@ -850,13 +858,15 @@ bool Sema::CheckConstraintSatisfaction(
850858
851859 auto Satisfaction =
852860 std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
853- if (::CheckConstraintSatisfaction (* this , Template, AssociatedConstraints,
854- TemplateArgsLists, TemplateIDRange ,
855- *Satisfaction, TopLevelConceptId)) {
861+ if (::CheckConstraintSatisfaction (
862+ * this , Template, AssociatedConstraints, TemplateArgsLists ,
863+ TemplateIDRange, *Satisfaction, ConvertedExpr , TopLevelConceptId)) {
856864 OutSatisfaction = *Satisfaction;
857865 return true ;
858866 }
859867
868+ // FIXME: cache ConvertedExpr for nested requirements?
869+
860870 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos (ID, InsertPos)) {
861871 // The evaluation of this constraint resulted in us trying to re-evaluate it
862872 // recursively. This isn't really possible, except we try to form a
@@ -1612,7 +1622,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
16121622 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
16131623 ? ArgsAsWritten->arguments ()[I].getLocation ()
16141624 : SourceLocation ();
1615- // FIXME: Investigate when we couldn't preserve the SourceLoc. What shall we do??
1625+ // FIXME: Investigate when we couldn't preserve the SourceLoc. What shall
1626+ // we do??
16161627 // assert(Loc.isValid());
16171628 if (OccurringIndices[I]) {
16181629 NamedDecl *Param = TemplateParams->begin ()[I];
@@ -1945,9 +1956,14 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
19451956const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints (
19461957 ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
19471958 ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1948- if (!ConstrainedDeclOrNestedReq)
1949- return NormalizedConstraint::fromAssociatedConstraints (
1959+ if (!ConstrainedDeclOrNestedReq) {
1960+ auto *Normalized = NormalizedConstraint::fromAssociatedConstraints (
19501961 *this , nullptr , AssociatedConstraints);
1962+ if (!Normalized || substituteParameterMappings (*this , *Normalized))
1963+ return nullptr ;
1964+
1965+ return Normalized;
1966+ }
19511967
19521968 // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
19531969 const NamedDecl *ND =
0 commit comments