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/4] 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/4] [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/4] 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()); >From 618281e1175fe3ba53b1b4368a26c11b711a6694 Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Sun, 12 Apr 2026 00:23:30 +0800 Subject: [PATCH 4/4] Add fix for GH188505 --- clang/lib/Sema/SemaConcept.cpp | 7 ++-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 4 +-- clang/test/SemaCXX/cxx2c-fold-exprs.cpp | 42 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 25b483b5e30b9..3f04922a5647e 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -905,8 +905,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow( UnsignedOrNone(I), Satisfaction, /*BuildExpression=*/false) .Evaluate(Constraint.getNormalizedPattern(), *SubstitutedArgs); - if (BuildExpression && Expr.isUsable()) { - if (Out.isUnset()) + if (BuildExpression) { + if (Out.isUnset() || !Expr.isUsable()) Out = Expr; else Out = BinaryOperator::Create(S.Context, Out.get(), Expr.get(), @@ -915,8 +915,6 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow( S.Context.BoolTy, VK_PRValue, OK_Ordinary, Constraint.getBeginLoc(), FPOptionsOverride{}); - } else { - assert(!BuildExpression || !Satisfaction.IsSatisfied); } if (!Conjunction && Satisfaction.IsSatisfied) { Satisfaction.Details.erase(Satisfaction.Details.begin() + @@ -1039,7 +1037,6 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( const MultiLevelTemplateArgumentList &MLTAL) { const ConceptReference *ConceptId = Constraint.getConceptId(); - Sema::InstantiatingTemplate InstTemplate( S, ConceptId->getBeginLoc(), Sema::InstantiatingTemplate::ConstraintsCheck{}, diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 80e3b1a5b11f7..8dfe33f8684bd 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2810,8 +2810,8 @@ TemplateInstantiator::TransformNestedRequirement( return nullptr; Success = !SemaRef.CheckConstraintSatisfaction( - Req, AssociatedConstraint(Constraint, SemaRef.ArgPackSubstIndex), - TemplateArgs, Constraint->getSourceRange(), Satisfaction, + Req, AssociatedConstraint(Constraint), TemplateArgs, + Constraint->getSourceRange(), Satisfaction, /*TopLevelConceptId=*/nullptr, &NewConstraint); } diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp index f681fc6f594c2..0312022912dca 100644 --- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp +++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp @@ -556,3 +556,45 @@ check_all<F, A, B, C> x; } } + +namespace GH188505 { + +template <class _Tp, class _Up> +concept same_as = __is_same(_Tp, _Up) && __is_same(_Up, _Tp); + +template <typename T, typename... Ts> +concept AnyOf = (same_as<T, Ts> || ...); + +struct Constant +{ + template <typename T> + using alias = const T; +}; + +struct Mutable +{ + template <typename T> + using alias = __remove_cv(T); +}; + +template <template <typename> typename M, typename T> +concept MutabilityAliasFor = requires { + requires AnyOf<M<T>, const T, __remove_cv(T)>; + requires same_as<M<M<T>>, M<T>>; +}; + +template <template <typename> typename M, typename... Ts> +concept MutabilityAliasForAllOf = (MutabilityAliasFor<M, Ts> && ...); + +template <template <typename T> typename M> +concept MutabilityAlias = MutabilityAliasForAllOf<M, int, char, double>; + +static_assert(AnyOf<char, const char, char>); + +static_assert(MutabilityAliasFor<Constant::alias, int>); +static_assert(MutabilityAliasForAllOf<Constant::alias, char, int>); + +static_assert(MutabilityAlias<Constant::alias>); +static_assert(MutabilityAlias<Mutable::alias>); + +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
