36
36
#include " llvm/ADT/PointerUnion.h"
37
37
#include " llvm/ADT/SmallVector.h"
38
38
#include " llvm/ADT/StringExtras.h"
39
- #include " llvm/Support/Timer.h"
40
- #include " llvm/Support/WithColor.h"
41
39
#include < cstddef>
42
40
#include < optional>
43
41
@@ -345,7 +343,7 @@ static ExprResult EvaluateAtomicConstraint(
345
343
return SubstitutedExpression;
346
344
}
347
345
348
- static bool calculateConstraintSatisfaction (
346
+ static ExprResult calculateConstraintSatisfaction (
349
347
Sema &S, const NormalizedConstraint &Constraint, const NamedDecl *Template,
350
348
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
351
349
ConstraintSatisfaction &Satisfaction, UnsignedOrNone PackSubstitutionIndex);
@@ -417,7 +415,7 @@ SubstitutionInTemplateArguments(
417
415
return std::move (MLTAL);
418
416
}
419
417
420
- static bool calculateConstraintSatisfaction (
418
+ static ExprResult calculateConstraintSatisfaction (
421
419
Sema &S, const AtomicConstraint &Constraint, const NamedDecl *Template,
422
420
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
423
421
ConstraintSatisfaction &Satisfaction,
@@ -497,7 +495,7 @@ static bool calculateConstraintSatisfaction(
497
495
if (!Satisfaction.IsSatisfied )
498
496
Satisfaction.Details .emplace_back (SubstitutedAtomicExpr.get ());
499
497
500
- return SubstitutedAtomicExpr. isUsable () ;
498
+ return SubstitutedAtomicExpr;
501
499
}
502
500
503
501
static UnsignedOrNone EvaluateFoldExpandedConstraintSize (
@@ -533,7 +531,7 @@ static UnsignedOrNone EvaluateFoldExpandedConstraintSize(
533
531
return NumExpansions;
534
532
}
535
533
536
- static bool calculateConstraintSatisfaction (
534
+ static ExprResult calculateConstraintSatisfaction (
537
535
Sema &S, const FoldExpandedConstraint &FE, const NamedDecl *Template,
538
536
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
539
537
ConstraintSatisfaction &Satisfaction) {
@@ -568,12 +566,13 @@ static bool calculateConstraintSatisfaction(
568
566
Sema::ArgPackSubstIndexRAII SubstIndex (S, I);
569
567
Satisfaction.IsSatisfied = false ;
570
568
Satisfaction.ContainsErrors = false ;
571
- bool Success = calculateConstraintSatisfaction (
569
+ // FIXME
570
+ ExprResult Expr = calculateConstraintSatisfaction (
572
571
S, FE.getNormalizedPattern (), Template, TemplateNameLoc,
573
572
*SubstitutedArgs, Satisfaction, UnsignedOrNone (I));
574
573
// SFINAE errors shouldn't prevent disjunction from evaluating
575
574
// FIXME: Does !Success == SFINAE errors occurred?
576
- if (!Success && Conjunction)
575
+ if (!Expr. isUsable () && Conjunction)
577
576
return false ;
578
577
if (!Conjunction && Satisfaction.IsSatisfied ) {
579
578
Satisfaction.Details .erase (Satisfaction.Details .begin () +
@@ -589,25 +588,12 @@ static bool calculateConstraintSatisfaction(
589
588
return true ;
590
589
}
591
590
592
- static bool calculateConstraintSatisfaction (
591
+ static ExprResult calculateConstraintSatisfaction (
593
592
Sema &S, const ConceptIdConstraint &Constraint, const NamedDecl *Template,
594
593
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
595
594
ConstraintSatisfaction &Satisfaction,
596
595
UnsignedOrNone PackSubstitutionIndex) {
597
596
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
-
611
597
Sema::ContextRAII CurContext (
612
598
S, Constraint.getConceptId ()->getNamedConcept ()->getDeclContext (),
613
599
/* NewThisContext=*/ false );
@@ -620,67 +606,73 @@ static bool calculateConstraintSatisfaction(
620
606
621
607
auto Size = Satisfaction.Details .size ();
622
608
623
- bool Ok = calculateConstraintSatisfaction (
609
+ ExprResult E = calculateConstraintSatisfaction (
624
610
S, Constraint.getNormalizedConstraint (), Template, TemplateNameLoc, MLTAL,
625
611
Satisfaction, PackSubstitutionIndex);
626
612
627
- if (Size != Satisfaction.Details .size ()) {
613
+ if (!E.isUsable ())
614
+ return E;
628
615
629
- llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
630
- std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
631
- SubstitutionInTemplateArguments (S, Constraint, Template, MLTAL,
632
- SubstitutedOuterMost,
633
- PackSubstitutionIndex);
616
+ llvm::SmallVector<TemplateArgument> SubstitutedOuterMost;
617
+ std::optional<MultiLevelTemplateArgumentList> SubstitutedArgs =
618
+ SubstitutionInTemplateArguments (S, Constraint, Template, MLTAL,
619
+ SubstitutedOuterMost,
620
+ PackSubstitutionIndex);
634
621
635
- if (!SubstitutedArgs)
636
- return Ok ;
622
+ if (!SubstitutedArgs)
623
+ return E. isUsable () ;
637
624
638
- Sema::SFINAETrap Trap (S);
639
- Sema::ArgPackSubstIndexRAII SubstIndex (
640
- S, Constraint.getPackSubstitutionIndex ()
641
- ? Constraint.getPackSubstitutionIndex ()
642
- : PackSubstitutionIndex);
625
+ Sema::SFINAETrap Trap (S);
626
+ Sema::ArgPackSubstIndexRAII SubstIndex (
627
+ S, Constraint.getPackSubstitutionIndex ()
628
+ ? Constraint.getPackSubstitutionIndex ()
629
+ : PackSubstitutionIndex);
630
+
631
+ const ASTTemplateArgumentListInfo *Ori =
632
+ Constraint.getConceptId ()->getTemplateArgsAsWritten ();
633
+ TemplateArgumentListInfo OutArgs (Ori->LAngleLoc , Ori->RAngleLoc );
634
+
635
+ TemplateArgumentListInfo TransArgs (Ori->LAngleLoc , Ori->RAngleLoc );
636
+ unsigned Depth = Template && Template->getTemplateDepth ()
637
+ ? Template->getTemplateDepth () - 1
638
+ : 0 ;
639
+ AdjustConstraintDepth Adjust (S, Depth);
640
+ if (Adjust.TransformTemplateArguments (Ori->getTemplateArgs (),
641
+ Ori->NumTemplateArgs , TransArgs))
642
+ return false ;
643
643
644
- const ASTTemplateArgumentListInfo *Ori =
645
- Constraint.getConceptId ()->getTemplateArgsAsWritten ();
646
- TemplateArgumentListInfo OutArgs (Ori->LAngleLoc , Ori->RAngleLoc );
647
-
648
- TemplateArgumentListInfo TransArgs (Ori->LAngleLoc , Ori->RAngleLoc );
649
- unsigned Depth = Template && Template->getTemplateDepth ()
650
- ? Template->getTemplateDepth () - 1
651
- : 0 ;
652
- AdjustConstraintDepth Adjust (S, Depth);
653
- if (Adjust.TransformTemplateArguments (Ori->getTemplateArgs (),
654
- Ori->NumTemplateArgs , TransArgs))
655
- return Ok;
656
-
657
- if (S.SubstTemplateArguments (TransArgs.arguments (), *SubstitutedArgs,
658
- OutArgs) ||
659
- Trap.hasErrorOccurred ())
660
- return Ok;
644
+ if (S.SubstTemplateArguments (TransArgs.arguments (), *SubstitutedArgs,
645
+ OutArgs) ||
646
+ Trap.hasErrorOccurred ()) {
647
+ Satisfaction.ContainsErrors = true ;
648
+ Satisfaction.IsSatisfied = false ;
649
+ return false ;
650
+ }
661
651
662
- CXXScopeSpec SS;
663
- SS.Adopt (Constraint.getConceptId ()->getNestedNameSpecifierLoc ());
664
- ExprResult SubstitutedConceptId = S.CheckConceptTemplateId (
665
- SS, Constraint.getConceptId ()->getTemplateKWLoc (),
666
- Constraint.getConceptId ()->getConceptNameInfo (),
667
- Constraint.getConceptId ()->getFoundDecl (),
668
- Constraint.getConceptId ()->getNamedConcept (), &OutArgs,
669
- /* CheckConstraintSatisfaction=*/ false );
652
+ CXXScopeSpec SS;
653
+ SS.Adopt (Constraint.getConceptId ()->getNestedNameSpecifierLoc ());
654
+ ExprResult SubstitutedConceptId = S.CheckConceptTemplateId (
655
+ SS, Constraint.getConceptId ()->getTemplateKWLoc (),
656
+ Constraint.getConceptId ()->getConceptNameInfo (),
657
+ Constraint.getConceptId ()->getFoundDecl (),
658
+ Constraint.getConceptId ()->getNamedConcept (), &OutArgs,
659
+ /* CheckConstraintSatisfaction=*/ false );
670
660
671
- if (SubstitutedConceptId.isInvalid () || Trap.hasErrorOccurred ())
672
- return Ok;
661
+ if (SubstitutedConceptId.isInvalid () || Trap.hasErrorOccurred ())
662
+ return false ;
663
+
664
+ if (Size != Satisfaction.Details .size ()) {
673
665
674
666
Satisfaction.Details .insert (
675
667
Satisfaction.Details .begin () + Size,
676
668
UnsatisfiedConstraintRecord (
677
669
SubstitutedConceptId.getAs <ConceptSpecializationExpr>()
678
670
->getConceptReference ()));
679
671
}
680
- return Ok ;
672
+ return SubstitutedConceptId ;
681
673
}
682
674
683
- static bool calculateConstraintSatisfaction (
675
+ static ExprResult calculateConstraintSatisfaction (
684
676
Sema &S, const CompoundConstraint &Constraint, const NamedDecl *Template,
685
677
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
686
678
ConstraintSatisfaction &Satisfaction,
@@ -691,35 +683,49 @@ static bool calculateConstraintSatisfaction(
691
683
bool Conjunction =
692
684
Constraint.getCompoundKind () == NormalizedConstraint::CCK_Conjunction;
693
685
694
- bool Ok = calculateConstraintSatisfaction (
686
+ ExprResult LHS = calculateConstraintSatisfaction (
695
687
S, Constraint.getLHS (), Template, TemplateNameLoc, MLTAL, Satisfaction,
696
688
PackSubstitutionIndex);
697
689
698
- if (Conjunction && !Ok )
690
+ if (Conjunction && !LHS. isUsable () )
699
691
return false ;
700
692
701
- if (!Conjunction && Ok && Satisfaction.IsSatisfied &&
693
+ if (!Conjunction && LHS. isUsable () && Satisfaction.IsSatisfied &&
702
694
!Satisfaction.ContainsErrors )
703
- return true ;
695
+ return LHS ;
704
696
705
- if (Conjunction && Ok &&
697
+ if (Conjunction && LHS. isUsable () &&
706
698
(!Satisfaction.IsSatisfied || Satisfaction.ContainsErrors ))
707
- return true ;
699
+ return LHS ;
708
700
709
701
Satisfaction.ContainsErrors = false ;
710
702
Satisfaction.IsSatisfied = false ;
711
703
712
- Ok = calculateConstraintSatisfaction (S, Constraint. getRHS (), Template,
713
- TemplateNameLoc, MLTAL, Satisfaction,
714
- PackSubstitutionIndex);
715
- if (Ok && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors )
704
+ ExprResult RHS = calculateConstraintSatisfaction (
705
+ S, Constraint. getRHS (), Template, TemplateNameLoc, MLTAL, Satisfaction,
706
+ PackSubstitutionIndex);
707
+ if (RHS. isUsable () && Satisfaction.IsSatisfied && !Satisfaction.ContainsErrors )
716
708
Satisfaction.Details .erase (Satisfaction.Details .begin () +
717
709
EffectiveDetailEndIndex,
718
710
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{});
720
726
}
721
727
722
- static bool calculateConstraintSatisfaction (
728
+ static ExprResult calculateConstraintSatisfaction (
723
729
Sema &S, const NormalizedConstraint &Constraint, const NamedDecl *Template,
724
730
SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL,
725
731
ConstraintSatisfaction &Satisfaction,
@@ -753,7 +759,10 @@ static bool CheckConstraintSatisfaction(
753
759
ArrayRef<AssociatedConstraint> AssociatedConstraints,
754
760
const MultiLevelTemplateArgumentList &TemplateArgsLists,
755
761
SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction,
756
- const ConceptReference *TopLevelConceptId = nullptr ) {
762
+ Expr **ConvertedExpr, const ConceptReference *TopLevelConceptId = nullptr ) {
763
+
764
+ if (ConvertedExpr)
765
+ *ConvertedExpr = nullptr ;
757
766
758
767
if (AssociatedConstraints.empty ()) {
759
768
Satisfaction.IsSatisfied = true ;
@@ -792,26 +801,31 @@ static bool CheckConstraintSatisfaction(
792
801
S.ArgPackSubstIndex );
793
802
}
794
803
795
- return !calculateConstraintSatisfaction (
796
- S, *C, Template, TemplateIDRange.getBegin (), TemplateArgsLists,
797
- Satisfaction, S.ArgPackSubstIndex );
804
+ ExprResult Res = calculateConstraintSatisfaction (
805
+ S, *C, Template, TemplateIDRange.getBegin (), TemplateArgsLists,
806
+ Satisfaction, S.ArgPackSubstIndex );
807
+
808
+ if (ConvertedExpr)
809
+ *ConvertedExpr = Res.get ();
810
+
811
+ return !Res.isUsable ();
798
812
}
799
813
800
814
bool Sema::CheckConstraintSatisfaction (
801
815
ConstrainedDeclOrNestedRequirement Entity,
802
816
ArrayRef<AssociatedConstraint> AssociatedConstraints,
803
817
const MultiLevelTemplateArgumentList &TemplateArgsLists,
804
818
SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction,
805
- const ConceptReference *TopLevelConceptId) {
819
+ const ConceptReference *TopLevelConceptId, Expr **ConvertedExpr ) {
806
820
if (AssociatedConstraints.empty ()) {
807
821
OutSatisfaction.IsSatisfied = true ;
808
822
return false ;
809
823
}
810
824
const auto *Template = Entity.dyn_cast <const NamedDecl *>();
811
825
if (!Template) {
812
- return ::CheckConstraintSatisfaction (* this , nullptr , AssociatedConstraints,
813
- TemplateArgsLists, TemplateIDRange ,
814
- OutSatisfaction, TopLevelConceptId);
826
+ return ::CheckConstraintSatisfaction (
827
+ * this , nullptr , AssociatedConstraints, TemplateArgsLists ,
828
+ TemplateIDRange, OutSatisfaction, ConvertedExpr , TopLevelConceptId);
815
829
}
816
830
// Invalid templates could make their way here. Substituting them could result
817
831
// in dependent expressions.
@@ -842,13 +856,15 @@ bool Sema::CheckConstraintSatisfaction(
842
856
843
857
auto Satisfaction =
844
858
std::make_unique<ConstraintSatisfaction>(Owner, FlattenedArgs);
845
- if (::CheckConstraintSatisfaction (* this , Template, AssociatedConstraints,
846
- TemplateArgsLists, TemplateIDRange ,
847
- *Satisfaction, TopLevelConceptId)) {
859
+ if (::CheckConstraintSatisfaction (
860
+ * this , Template, AssociatedConstraints, TemplateArgsLists ,
861
+ TemplateIDRange, *Satisfaction, ConvertedExpr , TopLevelConceptId)) {
848
862
OutSatisfaction = *Satisfaction;
849
863
return true ;
850
864
}
851
865
866
+ // FIXME: cache ConvertedExpr for nested requirements?
867
+
852
868
if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos (ID, InsertPos)) {
853
869
// The evaluation of this constraint resulted in us trying to re-evaluate it
854
870
// recursively. This isn't really possible, except we try to form a
@@ -1595,7 +1611,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
1595
1611
SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
1596
1612
? ArgsAsWritten->arguments ()[I].getLocation ()
1597
1613
: SourceLocation ();
1598
- // FIXME: Investigate when we couldn't preserve the SourceLoc. What shall we do??
1614
+ // FIXME: Investigate when we couldn't preserve the SourceLoc. What shall
1615
+ // we do??
1599
1616
// assert(Loc.isValid());
1600
1617
if (OccurringIndices[I]) {
1601
1618
NamedDecl *Param = TemplateParams->begin ()[I];
@@ -1928,9 +1945,14 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
1928
1945
const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints (
1929
1946
ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
1930
1947
ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1931
- if (!ConstrainedDeclOrNestedReq)
1932
- return NormalizedConstraint::fromAssociatedConstraints (
1948
+ if (!ConstrainedDeclOrNestedReq) {
1949
+ auto *Normalized = NormalizedConstraint::fromAssociatedConstraints (
1933
1950
*this , nullptr , AssociatedConstraints);
1951
+ if (!Normalized || substituteParameterMappings (*this , *Normalized))
1952
+ return nullptr ;
1953
+
1954
+ return Normalized;
1955
+ }
1934
1956
1935
1957
// FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
1936
1958
const NamedDecl *ND =
0 commit comments