|
35 | 35 | #include "llvm/ADT/PointerUnion.h"
|
36 | 36 | #include "llvm/ADT/SmallVector.h"
|
37 | 37 | #include "llvm/ADT/StringExtras.h"
|
| 38 | +#include "llvm/Support/Timer.h" |
| 39 | +#include "llvm/Support/WithColor.h" |
38 | 40 | #include <cstddef>
|
39 | 41 | #include <optional>
|
40 | 42 |
|
@@ -390,16 +392,23 @@ SubstitutionInTemplateArguments(
|
390 | 392 | Constraint.mappingOccurenceList();
|
391 | 393 | SubstitutedOuterMost =
|
392 | 394 | llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
|
| 395 | + unsigned Offset = 0; |
393 | 396 | for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
|
394 | 397 | TemplateArgument Arg;
|
395 | 398 | if (Used[I])
|
396 | 399 | Arg = S.Context.getCanonicalTemplateArgument(
|
397 | 400 | CTAI.SugaredConverted[MappedIndex++]);
|
398 |
| - if (I < SubstitutedOuterMost.size()) |
| 401 | + if (I < SubstitutedOuterMost.size()) { |
399 | 402 | SubstitutedOuterMost[I] = Arg;
|
400 |
| - else |
| 403 | + Offset = I + 1; |
| 404 | + } else { |
401 | 405 | SubstitutedOuterMost.push_back(Arg);
|
| 406 | + Offset = SubstitutedOuterMost.size(); |
402 | 407 | }
|
| 408 | + } |
| 409 | + if (Offset < SubstitutedOuterMost.size()) |
| 410 | + SubstitutedOuterMost.erase(SubstitutedOuterMost.begin() + Offset); |
| 411 | + |
403 | 412 | MLTAL.replaceOutermostTemplateArguments(
|
404 | 413 | const_cast<NamedDecl *>(Constraint.getConstraintDecl()),
|
405 | 414 | SubstitutedOuterMost);
|
@@ -765,7 +774,9 @@ static bool CheckConstraintSatisfaction(
|
765 | 774 | if (TopLevelConceptId)
|
766 | 775 | C = ConceptIdConstraint::Create(S.getASTContext(), TopLevelConceptId,
|
767 | 776 | const_cast<NormalizedConstraint *>(C),
|
768 |
| - Template, S.ArgPackSubstIndex); |
| 777 | + Template, /*CSE=*/nullptr, |
| 778 | + S.ArgPackSubstIndex); |
| 779 | + } |
769 | 780 |
|
770 | 781 | ExprResult Res = calculateConstraintSatisfaction(
|
771 | 782 | S, *C, Template, TemplateIDRange.getBegin(), TemplateArgsLists,
|
@@ -1551,27 +1562,6 @@ void Sema::DiagnoseUnsatisfiedConstraint(
|
1551 | 1562 | ConstraintExpr->getBeginLoc(), First);
|
1552 | 1563 | }
|
1553 | 1564 |
|
1554 |
| -const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints( |
1555 |
| - ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq, |
1556 |
| - ArrayRef<AssociatedConstraint> AssociatedConstraints) { |
1557 |
| - if (!ConstrainedDeclOrNestedReq) |
1558 |
| - return NormalizedConstraint::fromAssociatedConstraints( |
1559 |
| - *this, nullptr, AssociatedConstraints); |
1560 |
| - |
1561 |
| - // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement! |
1562 |
| - const NamedDecl *ND = |
1563 |
| - ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>(); |
1564 |
| - auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq); |
1565 |
| - if (CacheEntry == NormalizationCache.end()) { |
1566 |
| - auto *Normalized = NormalizedConstraint::fromAssociatedConstraints( |
1567 |
| - *this, ND, AssociatedConstraints); |
1568 |
| - CacheEntry = |
1569 |
| - NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized) |
1570 |
| - .first; |
1571 |
| - } |
1572 |
| - return CacheEntry->second; |
1573 |
| -} |
1574 |
| - |
1575 | 1565 | static bool
|
1576 | 1566 | substituteParameterMappings(Sema &S, NormalizedConstraint &N,
|
1577 | 1567 | const MultiLevelTemplateArgumentList &MLTAL,
|
@@ -1642,30 +1632,6 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
|
1642 | 1632 | if (Inst.isInvalid())
|
1643 | 1633 | return true;
|
1644 | 1634 |
|
1645 |
| - unsigned Hash; |
1646 |
| - llvm::FoldingSetNodeID ID; |
1647 |
| - auto &Context = S.getASTContext(); |
1648 |
| - if (N.getKind() == NormalizedConstraint::ConstraintKind::ConceptId) { |
1649 |
| - ID.AddPointer(static_cast<ConceptIdConstraint &>(N) |
1650 |
| - .getConceptId() |
1651 |
| - ->getNamedConcept() |
1652 |
| - ->getCanonicalDecl()); |
1653 |
| - for (auto &ArgLoc : static_cast<ConceptIdConstraint &>(N) |
1654 |
| - .getConceptId() |
1655 |
| - ->getTemplateArgsAsWritten() |
1656 |
| - ->arguments()) |
1657 |
| - ArgLoc.getArgument().Profile(ID, Context); |
1658 |
| - |
1659 |
| - Hash = ID.ComputeHash(); |
1660 |
| - if (auto Iter = S.ParameterMappingCache.find(Hash); |
1661 |
| - Iter != S.ParameterMappingCache.end()) { |
1662 |
| - N.updateParameterMapping(N.mappingOccurenceList(), Iter->second, |
1663 |
| - N.getUsedTemplateParamList()); |
1664 |
| - return false; |
1665 |
| - } |
1666 |
| - } |
1667 |
| - // FIXME: Cache for atomic constraints. |
1668 |
| - |
1669 | 1635 | // TransformTemplateArguments is unable to preserve the source location of a
|
1670 | 1636 | // pack. The SourceLocation is necessary for the instantiation location.
|
1671 | 1637 | // FIXME: The BaseLoc will be used as the location of the pack expansion,
|
@@ -1699,23 +1665,46 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
|
1699 | 1665 | CTAI.SugaredConverted.size());
|
1700 | 1666 | N.updateParameterMapping(N.mappingOccurenceList(), Mapping,
|
1701 | 1667 | N.getUsedTemplateParamList());
|
1702 |
| - if (N.getKind() == NormalizedConstraint::ConstraintKind::ConceptId) |
1703 |
| - S.ParameterMappingCache.insert({Hash, Mapping}); |
1704 | 1668 | return false;
|
1705 | 1669 | }
|
1706 | 1670 |
|
1707 | 1671 | static bool
|
1708 | 1672 | substituteParameterMappings(Sema &S, ConceptIdConstraint &N,
|
1709 | 1673 | const MultiLevelTemplateArgumentList &MLTAL,
|
1710 | 1674 | const ASTTemplateArgumentListInfo *ArgsAsWritten) {
|
1711 |
| - |
1712 |
| - if (N.getConstraintDecl()) { |
1713 |
| - substituteParameterMappings( |
| 1675 | + assert(N.getConstraintDecl()); |
| 1676 | +#if 0 |
| 1677 | + return substituteParameterMappings( |
1714 | 1678 | S, static_cast<NormalizedConstraintWithParamMapping &>(N), MLTAL,
|
1715 | 1679 | ArgsAsWritten);
|
| 1680 | +#else |
| 1681 | + auto TemplateArgs = MLTAL; |
| 1682 | + if (N.getConstraintDecl()) { |
| 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 | + if (S.SubstTemplateArgumentsInParameterMapping( |
| 1692 | + CSE->getTemplateArgsAsWritten()->arguments(), N.getBeginLoc(), |
| 1693 | + MLTAL, Out)) |
| 1694 | + return true; |
| 1695 | + Sema::CheckTemplateArgumentInfo CTAI; |
| 1696 | + if (S.CheckTemplateArgumentList(CSE->getNamedConcept(), |
| 1697 | + CSE->getConceptNameInfo().getLoc(), Out, |
| 1698 | + /*DefaultArgs=*/{}, |
| 1699 | + /*PartialTemplateArgs=*/false, CTAI, |
| 1700 | + /*UpdateArgsWithConversions=*/false)) |
| 1701 | + return true; |
| 1702 | + TemplateArgs.replaceOutermostTemplateArguments( |
| 1703 | + TemplateArgs.getAssociatedDecl(0).first, CTAI.CanonicalConverted); |
1716 | 1704 | }
|
1717 |
| - return substituteParameterMappings(S, N.getNormalizedConstraint(), MLTAL, |
1718 |
| - ArgsAsWritten); |
| 1705 | + return substituteParameterMappings(S, N.getNormalizedConstraint(), |
| 1706 | + TemplateArgs, ArgsAsWritten); |
| 1707 | +#endif |
1719 | 1708 | }
|
1720 | 1709 |
|
1721 | 1710 | static bool
|
@@ -1758,10 +1747,40 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
|
1758 | 1747 | // Don't build Subst* nodes to model lambda expressions.
|
1759 | 1748 | // The transform of Subst* is oblivious to the lambda type.
|
1760 | 1749 | MLTAL.setKind(TemplateSubstitutionKind::Rewrite);
|
| 1750 | + Sema::InstantiatingTemplate Inst( |
| 1751 | + S, N.getBeginLoc(), |
| 1752 | + Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, |
| 1753 | + CSE->getNamedConcept(), {N.getBeginLoc(), N.getEndLoc()}); |
| 1754 | + if (Inst.isInvalid()) |
| 1755 | + return true; |
| 1756 | + |
1761 | 1757 | return substituteParameterMappings(S, N, MLTAL,
|
1762 | 1758 | CSE->getTemplateArgsAsWritten());
|
1763 | 1759 | }
|
1764 | 1760 |
|
| 1761 | +static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N) { |
| 1762 | + switch (N.getKind()) { |
| 1763 | + case NormalizedConstraint::ConstraintKind::Atomic: |
| 1764 | + return false; |
| 1765 | + case NormalizedConstraint::ConstraintKind::FoldExpanded: { |
| 1766 | + Sema::ArgPackSubstIndexRAII _(S, std::nullopt); |
| 1767 | + return substituteParameterMappings( |
| 1768 | + S, static_cast<FoldExpandedConstraint &>(N).getNormalizedPattern()); |
| 1769 | + } |
| 1770 | + case NormalizedConstraint::ConstraintKind::ConceptId: { |
| 1771 | + auto &CC = static_cast<ConceptIdConstraint &>(N); |
| 1772 | + return substituteParameterMappings(S, CC.getNormalizedConstraint(), |
| 1773 | + CC.getConceptSpecializationExpr()); |
| 1774 | + } |
| 1775 | + case NormalizedConstraint::ConstraintKind::Compound: { |
| 1776 | + auto &Compound = static_cast<CompoundConstraint &>(N); |
| 1777 | + if (substituteParameterMappings(S, Compound.getLHS())) |
| 1778 | + return true; |
| 1779 | + return substituteParameterMappings(S, Compound.getRHS()); |
| 1780 | + } |
| 1781 | + } |
| 1782 | +} |
| 1783 | + |
1765 | 1784 | NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints(
|
1766 | 1785 | Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
|
1767 | 1786 | assert(ACs.size() != 0);
|
@@ -1840,11 +1859,11 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
|
1840 | 1859 | if (!SubNF)
|
1841 | 1860 | return nullptr;
|
1842 | 1861 | }
|
1843 |
| - if (substituteParameterMappings(S, *SubNF, CSE)) |
1844 |
| - return nullptr; |
| 1862 | + // if (substituteParameterMappings(S, *SubNF, CSE)) |
| 1863 | + // return nullptr; |
1845 | 1864 |
|
1846 | 1865 | return ConceptIdConstraint::Create(
|
1847 |
| - S.getASTContext(), CSE->getConceptReference(), SubNF, D, SubstIndex); |
| 1866 | + S.getASTContext(), CSE->getConceptReference(), SubNF, D, CSE, SubstIndex); |
1848 | 1867 |
|
1849 | 1868 | } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
|
1850 | 1869 | FE && S.getLangOpts().CPlusPlus26 &&
|
@@ -1886,6 +1905,29 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
|
1886 | 1905 | return AtomicConstraint::Create(S.getASTContext(), E, D, SubstIndex);
|
1887 | 1906 | }
|
1888 | 1907 |
|
| 1908 | +const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints( |
| 1909 | + ConstrainedDeclOrNestedRequirement ConstrainedDeclOrNestedReq, |
| 1910 | + ArrayRef<AssociatedConstraint> AssociatedConstraints) { |
| 1911 | + if (!ConstrainedDeclOrNestedReq) |
| 1912 | + return NormalizedConstraint::fromAssociatedConstraints( |
| 1913 | + *this, nullptr, AssociatedConstraints); |
| 1914 | + |
| 1915 | + // FIXME: ConstrainedDeclOrNestedReq is never a NestedRequirement! |
| 1916 | + const NamedDecl *ND = |
| 1917 | + ConstrainedDeclOrNestedReq.dyn_cast<const NamedDecl *>(); |
| 1918 | + auto CacheEntry = NormalizationCache.find(ConstrainedDeclOrNestedReq); |
| 1919 | + if (CacheEntry == NormalizationCache.end()) { |
| 1920 | + auto *Normalized = NormalizedConstraint::fromAssociatedConstraints( |
| 1921 | + *this, ND, AssociatedConstraints); |
| 1922 | + CacheEntry = |
| 1923 | + NormalizationCache.try_emplace(ConstrainedDeclOrNestedReq, Normalized) |
| 1924 | + .first; |
| 1925 | + if (!Normalized || substituteParameterMappings(*this, *Normalized)) |
| 1926 | + return nullptr; |
| 1927 | + } |
| 1928 | + return CacheEntry->second; |
| 1929 | +} |
| 1930 | + |
1889 | 1931 | bool FoldExpandedConstraint::AreCompatibleForSubsumption(
|
1890 | 1932 | const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {
|
1891 | 1933 |
|
|
0 commit comments