[Clang] Fix concept cache for normalized fold expressions (#190312)

When both outer and inner pack substitution indexes are present, we
should cache both. Otherwise we will have wrong cached result.

This is a regression fix so no release note.

Fixes https://github.com/llvm/llvm-project/issues/190169
This commit is contained in:
Younan Zhang 2026-04-05 10:36:50 +08:00 committed by GitHub
parent 00d5f660f4
commit 257cc5ad89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 15 deletions

View File

@ -488,6 +488,12 @@ class ConstraintSatisfactionChecker {
ConceptDecl *ParentConcept = nullptr;
private:
template <class Constraint>
UnsignedOrNone getOuterPackIndex(const Constraint &C) const {
return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex()
: PackSubstitutionIndex;
}
ExprResult
EvaluateAtomicConstraint(const Expr *AtomicExpr,
const MultiLevelTemplateArgumentList &MLTAL);
@ -798,14 +804,11 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
unsigned Size = Satisfaction.Details.size();
llvm::FoldingSetNodeID ID;
UnsignedOrNone OuterPackSubstIndex =
Constraint.getPackSubstitutionIndex()
? Constraint.getPackSubstitutionIndex()
: PackSubstitutionIndex;
ID.AddPointer(Constraint.getConstraintExpr());
ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
ID.AddInteger(
Constraint.getPackSubstitutionIndex().toInternalRepresentation());
ID.AddInteger(PackSubstitutionIndex.toInternalRepresentation());
HashParameterMapping(S, MLTAL, ID, getOuterPackIndex(Constraint))
.VisitConstraint(Constraint);
if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
@ -1034,12 +1037,6 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
const MultiLevelTemplateArgumentList &MLTAL) {
const ConceptReference *ConceptId = Constraint.getConceptId();
UnsignedOrNone OuterPackSubstIndex =
Constraint.getPackSubstitutionIndex()
? Constraint.getPackSubstitutionIndex()
: PackSubstitutionIndex;
Sema::InstantiatingTemplate InstTemplate(
S, ConceptId->getBeginLoc(),
Sema::InstantiatingTemplate::ConstraintsCheck{},
@ -1075,8 +1072,10 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
llvm::FoldingSetNodeID ID;
ID.AddPointer(Constraint.getConceptId());
ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation());
HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex)
ID.AddInteger(
Constraint.getPackSubstitutionIndex().toInternalRepresentation());
ID.AddInteger(PackSubstitutionIndex.toInternalRepresentation());
HashParameterMapping(S, MLTAL, ID, getOuterPackIndex(Constraint))
.VisitConstraint(Constraint);
if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);

View File

@ -508,3 +508,17 @@ static_assert(!__callable<__mdispatch<int>>);
}
}
namespace GH190169 {
template <typename Type, typename... Choices>
concept OneOf = (... || __is_same(Type, Choices));
template <typename F, typename... Ts>
using check = decltype((F{}(Ts{}), ...));
using X = check<decltype([](auto val) {
[](OneOf<int, char> auto) {}(val);
}), char>;
}