https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/191484
>From c5f66b42960bfeaa8b7e12f1da783e3758266c35 Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Fri, 10 Apr 2026 23:10:05 +0800 Subject: [PATCH 1/3] Revert "[Clang] Fix concept cache for normalized fold expressions" This reverts commit 257cc5ad89840cdfba4affcc8fe62cf9d02d9017. --- clang/lib/Sema/SemaConcept.cpp | 29 +++++++++++++------------ clang/test/SemaCXX/cxx2c-fold-exprs.cpp | 14 ------------ 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 5cd2c3d326ff7..a58a3874149b7 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -493,12 +493,6 @@ class ConstraintSatisfactionChecker { CachedTemplateArgs; private: - template <class Constraint> - UnsignedOrNone getOuterPackIndex(const Constraint &C) const { - return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex() - : PackSubstitutionIndex; - } - ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL); @@ -812,11 +806,14 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( unsigned Size = Satisfaction.Details.size(); llvm::FoldingSetNodeID ID; + UnsignedOrNone OuterPackSubstIndex = + Constraint.getPackSubstitutionIndex() + ? Constraint.getPackSubstitutionIndex() + : PackSubstitutionIndex; + ID.AddPointer(Constraint.getConstraintExpr()); - ID.AddInteger( - Constraint.getPackSubstitutionIndex().toInternalRepresentation()); - ID.AddInteger(PackSubstitutionIndex.toInternalRepresentation()); - HashParameterMapping(S, MLTAL, ID, getOuterPackIndex(Constraint)) + ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation()); + HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex) .VisitConstraint(Constraint); if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID); @@ -1045,6 +1042,12 @@ 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{}, @@ -1080,10 +1083,8 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( llvm::FoldingSetNodeID ID; ID.AddPointer(Constraint.getConceptId()); - ID.AddInteger( - Constraint.getPackSubstitutionIndex().toInternalRepresentation()); - ID.AddInteger(PackSubstitutionIndex.toInternalRepresentation()); - HashParameterMapping(S, MLTAL, ID, getOuterPackIndex(Constraint)) + ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation()); + HashParameterMapping(S, MLTAL, ID, OuterPackSubstIndex) .VisitConstraint(Constraint); if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID); diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp index 5b993fead4877..89ddcbaf11583 100644 --- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp +++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp @@ -508,17 +508,3 @@ 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>; - -} >From e9e59a9d4f3926a5b36dca944bb10a9c0d68fd16 Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Sat, 11 Apr 2026 02:30:32 +0800 Subject: [PATCH 2/3] [Clang] Track constraint's SubstIndex only if it contains outer parameter packs I believe that is the intent of SubstIndex in AssociatedConstraint. So this applies the checking explicitly, in case nested SubstIndexes confuses our poor constraint evaluator. I reverted the previous fix 257cc5a because that was wrong. No release note because this is a regression fix. --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 8 +++- clang/lib/Sema/TreeTransform.h | 5 ++- clang/test/SemaCXX/cxx2c-fold-exprs.cpp | 48 ++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 5381a5a6f110d..80e3b1a5b11f7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3085,7 +3085,13 @@ bool Sema::SubstTypeConstraint( if (!EvaluateConstraints && !inParameterMappingSubstitution()) { UnsignedOrNone Index = TC->getArgPackSubstIndex(); - if (!Index) + bool ContainsUnexpandedPack = + TemplArgInfo && + llvm::any_of( + TemplArgInfo->arguments(), [](const TemplateArgumentLoc &TA) { + return TA.getArgument().containsUnexpandedParameterPack(); + }); + if (!Index && ContainsUnexpandedPack) Index = SemaRef.ArgPackSubstIndex; Inst->setTypeConstraint(TC->getConceptReference(), TC->getImmediatelyDeclaredConstraint(), Index); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 8ae5df367e0dd..4c941e234d78d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -16004,7 +16004,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { assert(FPTL && "Not a FunctionProtoType?"); AssociatedConstraint TRC = E->getCallOperator()->getTrailingRequiresClause(); - if (!TRC.ArgPackSubstIndex) + // If the concept refers to any outer parameter packs, we track the SubstIndex + // for evaluation. + if (TRC && TRC.ConstraintExpr->containsUnexpandedParameterPack() && + !TRC.ArgPackSubstIndex) TRC.ArgPackSubstIndex = SemaRef.ArgPackSubstIndex; getSema().CompleteLambdaCallOperator( diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp index 89ddcbaf11583..f681fc6f594c2 100644 --- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp +++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp @@ -508,3 +508,51 @@ static_assert(!__callable<__mdispatch<int>>); } } + +namespace GH190169 { + +namespace _1 { + +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>; + +} + +namespace _2 { + +template <typename T, typename U> +concept Same = __is_same(T, U); + +template <typename Type, typename... Choices> +concept OneOf = (... || Same<Type, Choices>); + +template <class... Ts> +struct visitor : Ts... { using Ts::operator()...; }; + +struct A {}; +struct B {}; +struct C {}; + +template <typename F, typename T, typename = decltype(F{}(T{}))> +struct check {}; + +template <typename F, typename... Ts> +struct check_all : check<F, Ts>... {}; + +using F = decltype([](auto val) { + visitor{[](const A&) {}, + [](const OneOf<B, C> auto&) {}}(val); +}); + +check_all<F, A, B, C> x; + +} + +} >From 7b28c32b33dcf7951f8ff7ac38617aef871e970d Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Sat, 11 Apr 2026 23:37:46 +0800 Subject: [PATCH 3/3] Add back getOuterPackIndex --- clang/lib/Sema/SemaConcept.cpp | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index a58a3874149b7..25b483b5e30b9 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -493,6 +493,12 @@ class ConstraintSatisfactionChecker { CachedTemplateArgs; private: + template <class Constraint> + UnsignedOrNone getOuterPackIndex(const Constraint &C) const { + return C.getPackSubstitutionIndex() ? C.getPackSubstitutionIndex() + : PackSubstitutionIndex; + } + ExprResult EvaluateAtomicConstraint(const Expr *AtomicExpr, const MultiLevelTemplateArgumentList &MLTAL); @@ -658,10 +664,7 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments( return std::nullopt; TemplateArgumentListInfo SubstArgs; - Sema::ArgPackSubstIndexRAII SubstIndex( - S, Constraint.getPackSubstitutionIndex() - ? Constraint.getPackSubstitutionIndex() - : PackSubstitutionIndex); + Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint)); llvm::SaveAndRestore PushTemplateArgsCache(S.CurrentCachedTemplateArgs, &CachedTemplateArgs); @@ -806,10 +809,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( unsigned Size = Satisfaction.Details.size(); llvm::FoldingSetNodeID ID; - UnsignedOrNone OuterPackSubstIndex = - Constraint.getPackSubstitutionIndex() - ? Constraint.getPackSubstitutionIndex() - : PackSubstitutionIndex; + UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint); ID.AddPointer(Constraint.getConstraintExpr()); ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation()); @@ -979,10 +979,7 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow( return ExprError(); } - Sema::ArgPackSubstIndexRAII SubstIndex( - S, Constraint.getPackSubstitutionIndex() - ? Constraint.getPackSubstitutionIndex() - : PackSubstitutionIndex); + Sema::ArgPackSubstIndexRAII SubstIndex(S, getOuterPackIndex(Constraint)); const ASTTemplateArgumentListInfo *Ori = ConceptId->getTemplateArgsAsWritten(); @@ -1043,11 +1040,6 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( const ConceptReference *ConceptId = Constraint.getConceptId(); - UnsignedOrNone OuterPackSubstIndex = - Constraint.getPackSubstitutionIndex() - ? Constraint.getPackSubstitutionIndex() - : PackSubstitutionIndex; - Sema::InstantiatingTemplate InstTemplate( S, ConceptId->getBeginLoc(), Sema::InstantiatingTemplate::ConstraintsCheck{}, @@ -1081,6 +1073,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( if (Satisfaction.IsSatisfied) return E; + UnsignedOrNone OuterPackSubstIndex = getOuterPackIndex(Constraint); llvm::FoldingSetNodeID ID; ID.AddPointer(Constraint.getConceptId()); ID.AddInteger(OuterPackSubstIndex.toInternalRepresentation()); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
