1717#include " clang/AST/Decl.h"
1818#include " clang/AST/DeclCXX.h"
1919#include " clang/AST/DeclTemplate.h"
20+ #include " clang/AST/DependenceFlags.h"
2021#include " clang/AST/Expr.h"
2122#include " clang/AST/ExprConcepts.h"
2223#include " clang/AST/TemplateBase.h"
3536#include " llvm/ADT/PointerUnion.h"
3637#include " llvm/ADT/SmallVector.h"
3738#include " llvm/ADT/StringExtras.h"
39+ #include " llvm/Support/Timer.h"
40+ #include " llvm/Support/WithColor.h"
3841#include < cstddef>
3942#include < optional>
4043
@@ -390,16 +393,23 @@ SubstitutionInTemplateArguments(
390393 Constraint.mappingOccurenceList ();
391394 SubstitutedOuterMost =
392395 llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost ());
396+ unsigned Offset = 0 ;
393397 for (unsigned I = 0 , MappedIndex = 0 ; I < Used.size (); I++) {
394398 TemplateArgument Arg;
395399 if (Used[I])
396400 Arg = S.Context .getCanonicalTemplateArgument (
397401 CTAI.SugaredConverted [MappedIndex++]);
398- if (I < SubstitutedOuterMost.size ())
402+ if (I < SubstitutedOuterMost.size ()) {
399403 SubstitutedOuterMost[I] = Arg;
400- else
404+ Offset = I + 1 ;
405+ } else {
401406 SubstitutedOuterMost.push_back (Arg);
407+ Offset = SubstitutedOuterMost.size ();
408+ }
402409 }
410+ if (Offset < SubstitutedOuterMost.size ())
411+ SubstitutedOuterMost.erase (SubstitutedOuterMost.begin () + Offset);
412+
403413 MLTAL.replaceOutermostTemplateArguments (
404414 const_cast <NamedDecl *>(Constraint.getConstraintDecl ()),
405415 SubstitutedOuterMost);
@@ -585,6 +595,19 @@ static bool calculateConstraintSatisfaction(
585595 ConstraintSatisfaction &Satisfaction,
586596 UnsignedOrNone PackSubstitutionIndex) {
587597
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+
588611 Sema::ContextRAII CurContext (
589612 S, Constraint.getConceptId ()->getNamedConcept ()->getDeclContext (),
590613 /* NewThisContext=*/ false );
@@ -765,7 +788,8 @@ static bool CheckConstraintSatisfaction(
765788 if (TopLevelConceptId) {
766789 C = ConceptIdConstraint::Create (S.getASTContext (), TopLevelConceptId,
767790 const_cast <NormalizedConstraint *>(C),
768- Template, S.ArgPackSubstIndex );
791+ Template, /* CSE=*/ nullptr ,
792+ S.ArgPackSubstIndex );
769793 }
770794
771795 return !calculateConstraintSatisfaction (
@@ -1535,26 +1559,6 @@ void Sema::DiagnoseUnsatisfiedConstraint(
15351559 ConstraintExpr->getBeginLoc(), First);
15361560}
15371561
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-
15581562static bool
15591563substituteParameterMappings (Sema &S, NormalizedConstraint &N,
15601564 const MultiLevelTemplateArgumentList &MLTAL,
@@ -1591,6 +1595,8 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
15911595 SourceLocation Loc = ArgsAsWritten->NumTemplateArgs > I
15921596 ? ArgsAsWritten->arguments ()[I].getLocation ()
15931597 : SourceLocation ();
1598+ // FIXME: Investigate when we couldn't preserve the SourceLoc. What shall we do??
1599+ // assert(Loc.isValid());
15941600 if (OccurringIndices[I]) {
15951601 NamedDecl *Param = TemplateParams->begin ()[I];
15961602 new (&(TempArgs)[J])
@@ -1624,6 +1630,7 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
16241630 {InstLocBegin, InstLocEnd});
16251631 if (Inst.isInvalid ())
16261632 return true ;
1633+
16271634 // TransformTemplateArguments is unable to preserve the source location of a
16281635 // pack. The SourceLocation is necessary for the instantiation location.
16291636 // FIXME: The BaseLoc will be used as the location of the pack expansion,
@@ -1646,16 +1653,17 @@ substituteParameterMappings(Sema &S, NormalizedConstraintWithParamMapping &N,
16461653 // If this is an empty pack, we have no corresponding SubstArgs.
16471654 if (I < SubstArgs.size ())
16481655 Loc = SubstArgs.arguments ()[I].getLocation ();
1656+ // assert(Loc.isValid());
16491657 TempArgs[I] = S.getTrivialTemplateArgumentLoc (CTAI.SugaredConverted [I],
16501658 QualType (), Loc);
16511659 }
16521660 // llvm::copy(SubstArgs.arguments(), TempArgs);
16531661 // N.updateParameterMapping(
16541662 // N.mappingOccurenceList(),
16551663 // 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 ,
16591667 N.getUsedTemplateParamList ());
16601668 return false ;
16611669}
@@ -1664,14 +1672,59 @@ static bool
16641672substituteParameterMappings (Sema &S, ConceptIdConstraint &N,
16651673 const MultiLevelTemplateArgumentList &MLTAL,
16661674 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;
16681682 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 );
16721724 }
1673- return substituteParameterMappings (S, N.getNormalizedConstraint (), MLTAL,
1674- ArgsAsWritten);
1725+ return substituteParameterMappings (S, N.getNormalizedConstraint (),
1726+ TemplateArgs, ArgsAsWritten);
1727+ #endif
16751728}
16761729
16771730static bool
@@ -1714,10 +1767,40 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
17141767 // Don't build Subst* nodes to model lambda expressions.
17151768 // The transform of Subst* is oblivious to the lambda type.
17161769 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+
17171777 return substituteParameterMappings (S, N, MLTAL,
17181778 CSE->getTemplateArgsAsWritten ());
17191779}
17201780
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+
17211804NormalizedConstraint *NormalizedConstraint::fromAssociatedConstraints (
17221805 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) {
17231806 assert (ACs.size () != 0 );
@@ -1796,11 +1879,11 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
17961879 if (!SubNF)
17971880 return nullptr ;
17981881 }
1799- if (substituteParameterMappings (S, *SubNF, CSE))
1800- return nullptr ;
1882+ // if (substituteParameterMappings(S, *SubNF, CSE))
1883+ // return nullptr;
18011884
18021885 return ConceptIdConstraint::Create (
1803- S.getASTContext (), CSE->getConceptReference (), SubNF, D, SubstIndex);
1886+ S.getASTContext (), CSE->getConceptReference (), SubNF, D, CSE, SubstIndex);
18041887
18051888 } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E);
18061889 FE && S.getLangOpts ().CPlusPlus26 &&
@@ -1842,6 +1925,29 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
18421925 return AtomicConstraint::Create (S.getASTContext (), E, D, SubstIndex);
18431926}
18441927
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+
18451951bool FoldExpandedConstraint::AreCompatibleForSubsumption (
18461952 const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) {
18471953
0 commit comments