17
17
#include " clang/AST/Decl.h"
18
18
#include " clang/AST/DeclCXX.h"
19
19
#include " clang/AST/DeclTemplate.h"
20
+ #include " clang/AST/DependenceFlags.h"
20
21
#include " clang/AST/Expr.h"
21
22
#include " clang/AST/ExprConcepts.h"
22
23
#include " clang/AST/TemplateBase.h"
35
36
#include " llvm/ADT/PointerUnion.h"
36
37
#include " llvm/ADT/SmallVector.h"
37
38
#include " llvm/ADT/StringExtras.h"
39
+ #include " llvm/Support/Timer.h"
40
+ #include " llvm/Support/WithColor.h"
38
41
#include < cstddef>
39
42
#include < optional>
40
43
@@ -390,16 +393,23 @@ SubstitutionInTemplateArguments(
390
393
Constraint.mappingOccurenceList ();
391
394
SubstitutedOuterMost =
392
395
llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost ());
396
+ unsigned Offset = 0 ;
393
397
for (unsigned I = 0 , MappedIndex = 0 ; I < Used.size (); I++) {
394
398
TemplateArgument Arg;
395
399
if (Used[I])
396
400
Arg = S.Context .getCanonicalTemplateArgument (
397
401
CTAI.SugaredConverted [MappedIndex++]);
398
- if (I < SubstitutedOuterMost.size ())
402
+ if (I < SubstitutedOuterMost.size ()) {
399
403
SubstitutedOuterMost[I] = Arg;
400
- else
404
+ Offset = I + 1 ;
405
+ } else {
401
406
SubstitutedOuterMost.push_back (Arg);
407
+ Offset = SubstitutedOuterMost.size ();
408
+ }
402
409
}
410
+ if (Offset < SubstitutedOuterMost.size ())
411
+ SubstitutedOuterMost.erase (SubstitutedOuterMost.begin () + Offset);
412
+
403
413
MLTAL.replaceOutermostTemplateArguments (
404
414
const_cast <NamedDecl *>(Constraint.getConstraintDecl ()),
405
415
SubstitutedOuterMost);
@@ -585,6 +595,19 @@ static bool calculateConstraintSatisfaction(
585
595
ConstraintSatisfaction &Satisfaction,
586
596
UnsignedOrNone PackSubstitutionIndex) {
587
597
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
+
588
611
Sema::ContextRAII CurContext (
589
612
S, Constraint.getConceptId ()->getNamedConcept ()->getDeclContext (),
590
613
/* NewThisContext=*/ false );
@@ -765,7 +788,8 @@ static bool CheckConstraintSatisfaction(
765
788
if (TopLevelConceptId) {
766
789
C = ConceptIdConstraint::Create (S.getASTContext (), TopLevelConceptId,
767
790
const_cast <NormalizedConstraint *>(C),
768
- Template, S.ArgPackSubstIndex );
791
+ Template, /* CSE=*/ nullptr ,
792
+ S.ArgPackSubstIndex );
769
793
}
770
794
771
795
return !calculateConstraintSatisfaction (
@@ -1535,26 +1559,6 @@ void Sema::DiagnoseUnsatisfiedConstraint(
1535
1559
ConstraintExpr->getBeginLoc(), First);
1536
1560
}
1537
1561
1538
- const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints (
1539
- ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
1540
- ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1541
- if (!ConstrainedDeclOrNestedReq)
1542
- return NormalizedConstraint::fromAssociatedConstraints (
1543
- *this , nullptr , AssociatedConstraints);
1544
-
1545
- const NamedDecl *ND =
1546
- ConstrainedDeclOrNestedReq.dyn_cast <const NamedDecl *>();
1547
- auto CacheEntry = NormalizationCache.find (ConstrainedDeclOrNestedReq);
1548
- if (CacheEntry == NormalizationCache.end ()) {
1549
- auto *Normalized = NormalizedConstraint::fromAssociatedConstraints (
1550
- *this , ND, AssociatedConstraints);
1551
- CacheEntry =
1552
- NormalizationCache.try_emplace (ConstrainedDeclOrNestedReq, Normalized)
1553
- .first ;
1554
- }
1555
- return CacheEntry->second ;
1556
- }
1557
-
1558
1562
static bool
1559
1563
substituteParameterMappings (Sema &S, NormalizedConstraint &N,
1560
1564
const MultiLevelTemplateArgumentList &MLTAL,
@@ -1591,6 +1595,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
1591
1595
SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
1592
1596
? ArgsAsWritten->arguments ()[I].getLocation ()
1593
1597
: SourceLocation ();
1598
+ // FIXME: Investigate when we couldn't preserve the SourceLoc. What shall we do??
1599
+ // assert(Loc.isValid());
1594
1600
if (OccurringIndices[I]) {
1595
1601
NamedDecl *Param = TemplateParams->begin ()[I];
1596
1602
new (&(TempArgs)[J])
@@ -1624,6 +1630,7 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
1624
1630
{InstLocBegin, InstLocEnd});
1625
1631
if (Inst.isInvalid ())
1626
1632
return true ;
1633
+
1627
1634
// TransformTemplateArguments is unable to preserve the source location of a
1628
1635
// pack. The SourceLocation is necessary for the instantiation location.
1629
1636
// FIXME: The BaseLoc will be used as the location of the pack expansion,
@@ -1646,16 +1653,17 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
1646
1653
// If this is an empty pack, we have no corresponding SubstArgs.
1647
1654
if (I < SubstArgs.size ())
1648
1655
Loc = SubstArgs.arguments ()[I].getLocation ();
1656
+ // assert(Loc.isValid());
1649
1657
TempArgs[I] = S.getTrivialTemplateArgumentLoc (CTAI.SugaredConverted [I],
1650
1658
QualType (), Loc);
1651
1659
}
1652
1660
// llvm::copy(SubstArgs.arguments(), TempArgs);
1653
1661
// N.updateParameterMapping(
1654
1662
// N.mappingOccurenceList(),
1655
1663
// MutableArrayRef<TemplateArgumentLoc>(TempArgs, SubstArgs.size()));
1656
- N. updateParameterMapping (N. mappingOccurenceList () ,
1657
- MutableArrayRef<TemplateArgumentLoc>(
1658
- TempArgs, CTAI. SugaredConverted . size ()) ,
1664
+ MutableArrayRef<TemplateArgumentLoc> Mapping (TempArgs ,
1665
+ CTAI. SugaredConverted . size ());
1666
+ N. updateParameterMapping (N. mappingOccurenceList (), Mapping ,
1659
1667
N.getUsedTemplateParamList ());
1660
1668
return false ;
1661
1669
}
@@ -1664,14 +1672,59 @@ static bool
1664
1672
substituteParameterMappings (Sema &S, ConceptIdConstraint &N,
1665
1673
const MultiLevelTemplateArgumentList &MLTAL,
1666
1674
const ASTTemplateArgumentListInfo *ArgsAsWritten) {
1667
-
1675
+ assert (N.getConstraintDecl ());
1676
+ #if 0
1677
+ return substituteParameterMappings(
1678
+ S, static_cast<NormalizedConstraintWithParamMapping &>(N), MLTAL,
1679
+ ArgsAsWritten);
1680
+ #else
1681
+ auto TemplateArgs = MLTAL;
1668
1682
if (N.getConstraintDecl ()) {
1669
- substituteParameterMappings (
1670
- S, static_cast <NormalizedConstraintWithParamMapping &>(N), MLTAL,
1671
- ArgsAsWritten);
1683
+ if (substituteParameterMappings (
1684
+ S, static_cast <NormalizedConstraintWithParamMapping &>(N),
1685
+ TemplateArgs, ArgsAsWritten))
1686
+ return true ;
1687
+ auto *CSE = N.getConceptSpecializationExpr ();
1688
+ assert (CSE);
1689
+ TemplateArgumentListInfo Out;
1690
+ assert (!N.getBeginLoc ().isInvalid ());
1691
+ // TransformTemplateArguments is unable to preserve the source location of a
1692
+ // pack. The SourceLocation is necessary for the instantiation location.
1693
+ // FIXME: The BaseLoc will be used as the location of the pack expansion,
1694
+ // which is wrong.
1695
+ ArgsAsWritten = CSE->getTemplateArgsAsWritten ();
1696
+ SourceLocation InstLocBegin =
1697
+ ArgsAsWritten->arguments ().empty ()
1698
+ ? ArgsAsWritten->getLAngleLoc ()
1699
+ : ArgsAsWritten->arguments ().front ().getSourceRange ().getBegin ();
1700
+ SourceLocation InstLocEnd =
1701
+ ArgsAsWritten->arguments ().empty ()
1702
+ ? ArgsAsWritten->getRAngleLoc ()
1703
+ : ArgsAsWritten->arguments ().front ().getSourceRange ().getEnd ();
1704
+ Sema::InstantiatingTemplate Inst (
1705
+ S, InstLocBegin,
1706
+ Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
1707
+ const_cast <NamedDecl *>(N.getConstraintDecl ()),
1708
+ {InstLocBegin, InstLocEnd});
1709
+ if (Inst.isInvalid ())
1710
+ return true ;
1711
+
1712
+ if (S.SubstTemplateArgumentsInParameterMapping (ArgsAsWritten->arguments (),
1713
+ N.getBeginLoc (), MLTAL, Out))
1714
+ return true ;
1715
+ Sema::CheckTemplateArgumentInfo CTAI;
1716
+ if (S.CheckTemplateArgumentList (CSE->getNamedConcept (),
1717
+ CSE->getConceptNameInfo ().getLoc (), Out,
1718
+ /* DefaultArgs=*/ {},
1719
+ /* PartialTemplateArgs=*/ false , CTAI,
1720
+ /* UpdateArgsWithConversions=*/ false ))
1721
+ return true ;
1722
+ TemplateArgs.replaceOutermostTemplateArguments (
1723
+ TemplateArgs.getAssociatedDecl (0 ).first , CTAI.CanonicalConverted );
1672
1724
}
1673
- return substituteParameterMappings (S, N.getNormalizedConstraint (), MLTAL,
1674
- ArgsAsWritten);
1725
+ return substituteParameterMappings (S, N.getNormalizedConstraint (),
1726
+ TemplateArgs, ArgsAsWritten);
1727
+ #endif
1675
1728
}
1676
1729
1677
1730
static bool
@@ -1714,10 +1767,40 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1714
1767
// Don't build Subst* nodes to model lambda expressions.
1715
1768
// The transform of Subst* is oblivious to the lambda type.
1716
1769
MLTAL.setKind (TemplateSubstitutionKind::Rewrite);
1770
+ Sema::InstantiatingTemplate Inst (
1771
+ S, N.getBeginLoc (),
1772
+ Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
1773
+ CSE->getNamedConcept (), {N.getBeginLoc (), N.getEndLoc ()});
1774
+ if (Inst.isInvalid ())
1775
+ return true ;
1776
+
1717
1777
return substituteParameterMappings (S, N, MLTAL,
1718
1778
CSE->getTemplateArgsAsWritten ());
1719
1779
}
1720
1780
1781
+ static bool substituteParameterMappings (Sema &S, NormalizedConstraint &N) {
1782
+ switch (N.getKind ()) {
1783
+ case NormalizedConstraint::ConstraintKind::Atomic:
1784
+ return false ;
1785
+ case NormalizedConstraint::ConstraintKind::FoldExpanded: {
1786
+ Sema::ArgPackSubstIndexRAII _ (S, std::nullopt );
1787
+ return substituteParameterMappings (
1788
+ S, static_cast <FoldExpandedConstraint &>(N).getNormalizedPattern ());
1789
+ }
1790
+ case NormalizedConstraint::ConstraintKind::ConceptId: {
1791
+ auto &CC = static_cast <ConceptIdConstraint &>(N);
1792
+ return substituteParameterMappings (S, CC.getNormalizedConstraint (),
1793
+ CC.getConceptSpecializationExpr ());
1794
+ }
1795
+ case NormalizedConstraint::ConstraintKind::Compound: {
1796
+ auto &Compound = static_cast <CompoundConstraint &>(N);
1797
+ if (substituteParameterMappings (S, Compound.getLHS ()))
1798
+ return true ;
1799
+ return substituteParameterMappings (S, Compound.getRHS ());
1800
+ }
1801
+ }
1802
+ }
1803
+
1721
1804
NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints (
1722
1805
Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
1723
1806
assert (ACs.size () != 0 );
@@ -1796,11 +1879,11 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
1796
1879
if (!SubNF)
1797
1880
return nullptr ;
1798
1881
}
1799
- if (substituteParameterMappings (S, *SubNF, CSE))
1800
- return nullptr ;
1882
+ // if (substituteParameterMappings(S, *SubNF, CSE))
1883
+ // return nullptr;
1801
1884
1802
1885
return ConceptIdConstraint::Create (
1803
- S.getASTContext (), CSE->getConceptReference (), SubNF, D, SubstIndex);
1886
+ S.getASTContext (), CSE->getConceptReference (), SubNF, D, CSE, SubstIndex);
1804
1887
1805
1888
} else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
1806
1889
FE && S.getLangOpts ().CPlusPlus26 &&
@@ -1842,6 +1925,29 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
1842
1925
return AtomicConstraint::Create (S.getASTContext (), E, D, SubstIndex);
1843
1926
}
1844
1927
1928
+ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints (
1929
+ ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq,
1930
+ ArrayRef<AssociatedConstraint> AssociatedConstraints) {
1931
+ if (!ConstrainedDeclOrNestedReq)
1932
+ return NormalizedConstraint::fromAssociatedConstraints (
1933
+ *this , nullptr , AssociatedConstraints);
1934
+
1935
+ // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement!
1936
+ const NamedDecl *ND =
1937
+ ConstrainedDeclOrNestedReq.dyn_cast <const NamedDecl *>();
1938
+ auto CacheEntry = NormalizationCache.find (ConstrainedDeclOrNestedReq);
1939
+ if (CacheEntry == NormalizationCache.end ()) {
1940
+ auto *Normalized = NormalizedConstraint::fromAssociatedConstraints (
1941
+ *this , ND, AssociatedConstraints);
1942
+ CacheEntry =
1943
+ NormalizationCache.try_emplace (ConstrainedDeclOrNestedReq, Normalized)
1944
+ .first ;
1945
+ if (!Normalized || substituteParameterMappings (*this , *Normalized))
1946
+ return nullptr ;
1947
+ }
1948
+ return CacheEntry->second ;
1949
+ }
1950
+
1845
1951
bool FoldExpandedConstraint::AreCompatibleForSubsumption (
1846
1952
const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {
1847
1953
0 commit comments