@@ -1639,6 +1639,258 @@ void Sema::DiagnoseUnsatisfiedConstraint(
1639
1639
ConstraintExpr->getBeginLoc(), First);
1640
1640
}
1641
1641
1642
+ namespace {
1643
+
1644
+ class SubstituteParameterMappings {
1645
+ Sema &SemaRef;
1646
+
1647
+ const MultiLevelTemplateArgumentList *MLTAL;
1648
+ const ASTTemplateArgumentListInfo *ArgsAsWritten;
1649
+
1650
+ SubstituteParameterMappings (Sema &SemaRef,
1651
+ const MultiLevelTemplateArgumentList *MLTAL,
1652
+ const ASTTemplateArgumentListInfo *ArgsAsWritten)
1653
+ : SemaRef(SemaRef), MLTAL(MLTAL), ArgsAsWritten(ArgsAsWritten) {}
1654
+
1655
+ void buildParameterMapping (NormalizedConstraintWithParamMapping &N);
1656
+
1657
+ bool substitute (NormalizedConstraintWithParamMapping &N);
1658
+
1659
+ bool substitute (ConceptIdConstraint &CC);
1660
+
1661
+ public:
1662
+ SubstituteParameterMappings (Sema &SemaRef)
1663
+ : SemaRef(SemaRef), MLTAL(nullptr ), ArgsAsWritten(nullptr ) {}
1664
+
1665
+ bool substitute (NormalizedConstraint &N);
1666
+ };
1667
+
1668
+ void SubstituteParameterMappings::buildParameterMapping (
1669
+ NormalizedConstraintWithParamMapping &N) {
1670
+ TemplateParameterList *TemplateParams =
1671
+ cast<TemplateDecl>(N.getConstraintDecl ())->getTemplateParameters ();
1672
+
1673
+ llvm::SmallBitVector OccurringIndices (TemplateParams->size ());
1674
+
1675
+ if (N.getKind () == NormalizedConstraint::ConstraintKind::Atomic) {
1676
+ SemaRef.MarkUsedTemplateParameters (
1677
+ static_cast <AtomicConstraint &>(N).getConstraintExpr (),
1678
+ /* OnlyDeduced=*/ false ,
1679
+ /* Depth=*/ 0 , OccurringIndices);
1680
+ } else if (N.getKind () == NormalizedConstraint::ConstraintKind::ConceptId) {
1681
+ auto *Args = static_cast <ConceptIdConstraint &>(N)
1682
+ .getConceptId ()
1683
+ ->getTemplateArgsAsWritten ();
1684
+ if (Args)
1685
+ SemaRef.MarkUsedTemplateParameters (Args->arguments (),
1686
+ /* Depth=*/ 0 , OccurringIndices);
1687
+ }
1688
+ TemplateArgumentLoc *TempArgs =
1689
+ new (SemaRef.Context ) TemplateArgumentLoc[OccurringIndices.count ()];
1690
+ llvm::SmallVector<NamedDecl *> UsedParams;
1691
+ for (unsigned I = 0 , J = 0 , C = TemplateParams->size (); I != C; ++I) {
1692
+ SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
1693
+ ? ArgsAsWritten->arguments ()[I].getLocation ()
1694
+ : SourceLocation ();
1695
+ // FIXME: Investigate why we couldn't always preserve the SourceLoc. We
1696
+ // can't assert Loc.isValid() now.
1697
+ if (OccurringIndices[I]) {
1698
+ NamedDecl *Param = TemplateParams->begin ()[I];
1699
+ new (&(TempArgs)[J]) TemplateArgumentLoc (
1700
+ SemaRef.getIdentityTemplateArgumentLoc (Param, Loc));
1701
+ UsedParams.push_back (Param);
1702
+ J++;
1703
+ }
1704
+ }
1705
+ auto *UsedList = TemplateParameterList::Create (
1706
+ SemaRef.Context , TemplateParams->getTemplateLoc (),
1707
+ TemplateParams->getLAngleLoc (), UsedParams,
1708
+ /* RAngleLoc=*/ SourceLocation (),
1709
+ /* RequiresClause=*/ nullptr );
1710
+ N.updateParameterMapping (
1711
+ OccurringIndices,
1712
+ MutableArrayRef<TemplateArgumentLoc>{TempArgs, OccurringIndices.count ()},
1713
+ UsedList);
1714
+ }
1715
+
1716
+ bool SubstituteParameterMappings::substitute (
1717
+ NormalizedConstraintWithParamMapping &N) {
1718
+ if (!N.hasParameterMapping ())
1719
+ buildParameterMapping (N);
1720
+
1721
+ SourceLocation InstLocBegin, InstLocEnd;
1722
+ llvm::ArrayRef Arguments = ArgsAsWritten->arguments ();
1723
+ if (Arguments.empty ()) {
1724
+ InstLocBegin = ArgsAsWritten->getLAngleLoc ();
1725
+ InstLocEnd = ArgsAsWritten->getRAngleLoc ();
1726
+ } else {
1727
+ // FIXME: Is it useful?
1728
+ auto SR = Arguments[0 ].getSourceRange ();
1729
+ InstLocBegin = SR.getBegin ();
1730
+ InstLocEnd = SR.getEnd ();
1731
+ }
1732
+ Sema::InstantiatingTemplate Inst (
1733
+ SemaRef, InstLocBegin,
1734
+ Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
1735
+ const_cast <NamedDecl *>(N.getConstraintDecl ()),
1736
+ {InstLocBegin, InstLocEnd});
1737
+ if (Inst.isInvalid ())
1738
+ return true ;
1739
+
1740
+ // TransformTemplateArguments is unable to preserve the source location of a
1741
+ // pack. The SourceLocation is necessary for the instantiation location.
1742
+ // FIXME: The BaseLoc will be used as the location of the pack expansion,
1743
+ // which is wrong.
1744
+ TemplateArgumentListInfo SubstArgs;
1745
+ if (SemaRef.SubstTemplateArgumentsInParameterMapping (
1746
+ N.getParameterMapping (), N.getBeginLoc (), *MLTAL, SubstArgs))
1747
+ return true ;
1748
+ Sema::CheckTemplateArgumentInfo CTAI;
1749
+ auto *TD =
1750
+ const_cast <TemplateDecl *>(cast<TemplateDecl>(N.getConstraintDecl ()));
1751
+ if (SemaRef.CheckTemplateArgumentList (TD, N.getUsedTemplateParamList (),
1752
+ TD->getLocation (), SubstArgs,
1753
+ /* DefaultArguments=*/ {},
1754
+ /* PartialTemplateArgs=*/ false , CTAI))
1755
+ return true ;
1756
+
1757
+ TemplateArgumentLoc *TempArgs =
1758
+ new (SemaRef.Context ) TemplateArgumentLoc[CTAI.SugaredConverted .size ()];
1759
+
1760
+ for (unsigned I = 0 ; I < CTAI.SugaredConverted .size (); ++I) {
1761
+ SourceLocation Loc;
1762
+ // If this is an empty pack, we have no corresponding SubstArgs.
1763
+ if (I < SubstArgs.size ())
1764
+ Loc = SubstArgs.arguments ()[I].getLocation ();
1765
+
1766
+ TempArgs[I] = SemaRef.getTrivialTemplateArgumentLoc (
1767
+ CTAI.SugaredConverted [I], QualType (), Loc);
1768
+ }
1769
+
1770
+ MutableArrayRef<TemplateArgumentLoc> Mapping (TempArgs,
1771
+ CTAI.SugaredConverted .size ());
1772
+ N.updateParameterMapping (N.mappingOccurenceList (), Mapping,
1773
+ N.getUsedTemplateParamList ());
1774
+ return false ;
1775
+ }
1776
+
1777
+ bool SubstituteParameterMappings::substitute (ConceptIdConstraint &CC) {
1778
+ assert (CC.getConstraintDecl () && MLTAL && ArgsAsWritten);
1779
+
1780
+ if (substitute (static_cast <NormalizedConstraintWithParamMapping &>(CC)))
1781
+ return true ;
1782
+
1783
+ auto *CSE = CC.getConceptSpecializationExpr ();
1784
+ assert (CSE);
1785
+ assert (!CC.getBeginLoc ().isInvalid ());
1786
+
1787
+ SourceLocation InstLocBegin, InstLocEnd;
1788
+ if (llvm::ArrayRef Arguments = ArgsAsWritten->arguments ();
1789
+ Arguments.empty ()) {
1790
+ InstLocBegin = ArgsAsWritten->getLAngleLoc ();
1791
+ InstLocEnd = ArgsAsWritten->getRAngleLoc ();
1792
+ } else {
1793
+ // FIXME: Is it useful?
1794
+ auto SR = Arguments[0 ].getSourceRange ();
1795
+ InstLocBegin = SR.getBegin ();
1796
+ InstLocEnd = SR.getEnd ();
1797
+ }
1798
+ // This is useful for name lookup across modules; see Sema::getLookupModules.
1799
+ Sema::InstantiatingTemplate Inst (
1800
+ SemaRef, InstLocBegin,
1801
+ Sema::InstantiatingTemplate::ParameterMappingSubstitution{},
1802
+ const_cast <NamedDecl *>(CC.getConstraintDecl ()),
1803
+ {InstLocBegin, InstLocEnd});
1804
+ if (Inst.isInvalid ())
1805
+ return true ;
1806
+
1807
+ TemplateArgumentListInfo Out;
1808
+ // TransformTemplateArguments is unable to preserve the source location of a
1809
+ // pack. The SourceLocation is necessary for the instantiation location.
1810
+ // FIXME: The BaseLoc will be used as the location of the pack expansion,
1811
+ // which is wrong.
1812
+ const ASTTemplateArgumentListInfo *ArgsAsWritten =
1813
+ CSE->getTemplateArgsAsWritten ();
1814
+ if (SemaRef.SubstTemplateArgumentsInParameterMapping (
1815
+ ArgsAsWritten->arguments (), CC.getBeginLoc (), *MLTAL, Out))
1816
+ return true ;
1817
+ Sema::CheckTemplateArgumentInfo CTAI;
1818
+ if (SemaRef.CheckTemplateArgumentList (CSE->getNamedConcept (),
1819
+ CSE->getConceptNameInfo ().getLoc (), Out,
1820
+ /* DefaultArgs=*/ {},
1821
+ /* PartialTemplateArgs=*/ false , CTAI,
1822
+ /* UpdateArgsWithConversions=*/ false ))
1823
+ return true ;
1824
+ auto TemplateArgs = *MLTAL;
1825
+ TemplateArgs.replaceOutermostTemplateArguments (
1826
+ TemplateArgs.getAssociatedDecl (0 ).first , CTAI.SugaredConverted );
1827
+ return SubstituteParameterMappings (SemaRef, &TemplateArgs, ArgsAsWritten)
1828
+ .substitute (CC.getNormalizedConstraint ());
1829
+ }
1830
+
1831
+ bool SubstituteParameterMappings::substitute (NormalizedConstraint &N) {
1832
+ switch (N.getKind ()) {
1833
+ case NormalizedConstraint::ConstraintKind::Atomic: {
1834
+ if (!MLTAL) {
1835
+ assert (!ArgsAsWritten);
1836
+ return false ;
1837
+ }
1838
+ return substitute (static_cast <NormalizedConstraintWithParamMapping &>(N));
1839
+ }
1840
+ case NormalizedConstraint::ConstraintKind::FoldExpanded: {
1841
+ auto &FE = static_cast <FoldExpandedConstraint &>(N);
1842
+ if (!MLTAL) {
1843
+ assert (!ArgsAsWritten);
1844
+ return substitute (FE.getNormalizedPattern ());
1845
+ }
1846
+ // FIXME: This is not used.
1847
+ ConstraintSatisfaction CS;
1848
+ UnsignedOrNone PackSize = EvaluateFoldExpandedConstraintSize (
1849
+ SemaRef, FE, /* Template=*/ nullptr , /* TemplateNameLoc=*/ SourceLocation (),
1850
+ *MLTAL, CS);
1851
+ if (!PackSize)
1852
+ return true ;
1853
+
1854
+ // Do we need to do something else when pack is empty?
1855
+ if (!*PackSize)
1856
+ return false ;
1857
+ Sema::ArgPackSubstIndexRAII _ (SemaRef, std::nullopt);
1858
+ return substitute (FE.getNormalizedPattern ());
1859
+ }
1860
+ case NormalizedConstraint::ConstraintKind::ConceptId: {
1861
+ auto &CC = static_cast <ConceptIdConstraint &>(N);
1862
+ if (MLTAL) {
1863
+ assert (ArgsAsWritten);
1864
+ return substitute (CC);
1865
+ }
1866
+ assert (!ArgsAsWritten);
1867
+ const ConceptSpecializationExpr *CSE = CC.getConceptSpecializationExpr ();
1868
+ ConceptDecl *Concept = CSE->getNamedConcept ();
1869
+ MultiLevelTemplateArgumentList MLTAL = SemaRef.getTemplateInstantiationArgs (
1870
+ Concept, Concept->getLexicalDeclContext (),
1871
+ /* Final=*/ true , CSE->getTemplateArguments (),
1872
+ /* RelativeToPrimary=*/ true ,
1873
+ /* Pattern=*/ nullptr ,
1874
+ /* ForConstraintInstantiation=*/ true );
1875
+
1876
+ // Don't build Subst* nodes to model lambda expressions.
1877
+ // The transform of Subst* is oblivious to the lambda type.
1878
+ MLTAL.setKind (TemplateSubstitutionKind::Rewrite);
1879
+ return SubstituteParameterMappings (SemaRef, &MLTAL,
1880
+ CSE->getTemplateArgsAsWritten ())
1881
+ .substitute (CC.getNormalizedConstraint ());
1882
+ }
1883
+ case NormalizedConstraint::ConstraintKind::Compound: {
1884
+ auto &Compound = static_cast <CompoundConstraint &>(N);
1885
+ if (substitute (Compound.getLHS ()))
1886
+ return true ;
1887
+ return substitute (Compound.getRHS ());
1888
+ }
1889
+ }
1890
+ }
1891
+
1892
+ } // namespace
1893
+ #if 0
1642
1894
static bool
1643
1895
substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1644
1896
const MultiLevelTemplateArgumentList &MLTAL,
@@ -1831,9 +2083,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraint &N,
1831
2083
if (!*PackSize)
1832
2084
return false;
1833
2085
Sema::ArgPackSubstIndexRAII _(S, std::nullopt);
1834
- return substituteParameterMappings (
1835
- S, static_cast <FoldExpandedConstraint &>(N).getNormalizedPattern (),
1836
- MLTAL, ArgsAsWritten);
2086
+ return substituteParameterMappings(S, FE.getNormalizedPattern(), MLTAL,
2087
+ ArgsAsWritten);
1837
2088
}
1838
2089
case NormalizedConstraint::ConstraintKind::ConceptId:
1839
2090
return substituteParameterMappings(S, static_cast<ConceptIdConstraint &>(N),
@@ -1893,6 +2144,7 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N) {
1893
2144
}
1894
2145
}
1895
2146
}
2147
+ #endif
1896
2148
1897
2149
NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints (
1898
2150
Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
@@ -2024,7 +2276,8 @@ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
2024
2276
if (!ConstrainedDeclOrNestedReq) {
2025
2277
auto *Normalized = NormalizedConstraint::fromAssociatedConstraints (
2026
2278
*this , nullptr , AssociatedConstraints);
2027
- if (!Normalized || substituteParameterMappings (*this , *Normalized))
2279
+ if (!Normalized ||
2280
+ SubstituteParameterMappings (*this ).substitute (*Normalized))
2028
2281
return nullptr ;
2029
2282
2030
2283
return Normalized;
@@ -2040,7 +2293,8 @@ const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints(
2040
2293
CacheEntry =
2041
2294
NormalizationCache.try_emplace (ConstrainedDeclOrNestedReq, Normalized)
2042
2295
.first ;
2043
- if (!Normalized || substituteParameterMappings (*this , *Normalized))
2296
+ if (!Normalized ||
2297
+ SubstituteParameterMappings (*this ).substitute (*Normalized))
2044
2298
return nullptr ;
2045
2299
}
2046
2300
return CacheEntry->second ;
0 commit comments