https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/186735
>From d9166d1e298b6e464e0b7da445d3dc7ac158e36d Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Mon, 16 Mar 2026 12:49:49 +0800 Subject: [PATCH 1/2] [Clang] Fix a concept subsumption bug when template depths are adjusted We cannot reuse the cached normalization results if any template depth adjustments (in subsumption checking) are involved. --- clang/include/clang/Sema/SemaConcept.h | 3 ++- clang/lib/Sema/SemaConcept.cpp | 11 +++++++---- clang/test/SemaTemplate/concepts.cpp | 19 +++++++++++++++++++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h index bdd997b18cb08..e6644f1bd1bee 100644 --- a/clang/include/clang/Sema/SemaConcept.h +++ b/clang/include/clang/Sema/SemaConcept.h @@ -431,7 +431,8 @@ class SubsumptionChecker { std::optional<bool> Subsumes(const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ, - ArrayRef<AssociatedConstraint> Q); + ArrayRef<AssociatedConstraint> Q, + bool DepthAdjusted); bool Subsumes(const NormalizedConstraint *P, const NormalizedConstraint *Q); diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 38791940247cb..16cbec22c823b 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -2544,7 +2544,8 @@ bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1, } SubsumptionChecker SC(*this); - std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2); + std::optional<bool> Subsumes = + SC.Subsumes(D1, AC1, D2, AC2, /*DepthAdjusted=*/Depth1 != Depth2); if (!Subsumes) { // Normalization failed return true; @@ -2778,14 +2779,16 @@ void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) { std::optional<bool> SubsumptionChecker::Subsumes( const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ, - ArrayRef<AssociatedConstraint> Q) { + ArrayRef<AssociatedConstraint> Q, bool DepthAdjusted) { const NormalizedConstraint *PNormalized = - SemaRef.getNormalizedAssociatedConstraints(DP, P); + SemaRef.getNormalizedAssociatedConstraints(DepthAdjusted ? nullptr : DP, + P); if (!PNormalized) return std::nullopt; const NormalizedConstraint *QNormalized = - SemaRef.getNormalizedAssociatedConstraints(DQ, Q); + SemaRef.getNormalizedAssociatedConstraints(DepthAdjusted ? nullptr : DQ, + Q); if (!QNormalized) return std::nullopt; diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index 1d2ada3e0a398..628499bebea83 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1659,6 +1659,25 @@ void foo() { call(""); } } +namespace GH186624 { + +template <class T> +concept C = __is_unsigned(T); + +template <C T> +struct encoder_interface {}; + +template <template <C> class CodecInterface, C T> +CodecInterface<T>* create_codec() { + return nullptr; +} + +encoder_interface<unsigned>* create_encoder() { + return create_codec<encoder_interface, unsigned>(); +} + +} + namespace GH170856 { template <unsigned N, unsigned M> struct symbol_text { >From 3e6274c4055cac9bb2634c6970e7c2af13bc18d8 Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Mon, 16 Mar 2026 19:35:49 +0800 Subject: [PATCH 2/2] Do not break ABI --- clang/include/clang/Sema/SemaConcept.h | 3 +-- clang/lib/Sema/SemaConcept.cpp | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h index e6644f1bd1bee..bdd997b18cb08 100644 --- a/clang/include/clang/Sema/SemaConcept.h +++ b/clang/include/clang/Sema/SemaConcept.h @@ -431,8 +431,7 @@ class SubsumptionChecker { std::optional<bool> Subsumes(const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ, - ArrayRef<AssociatedConstraint> Q, - bool DepthAdjusted); + ArrayRef<AssociatedConstraint> Q); bool Subsumes(const NormalizedConstraint *P, const NormalizedConstraint *Q); diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 16cbec22c823b..0cd35ef6d90c2 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -14,6 +14,7 @@ #include "TreeTransform.h" #include "clang/AST/ASTConcept.h" #include "clang/AST/ASTLambda.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprConcepts.h" #include "clang/AST/RecursiveASTVisitor.h" @@ -2544,8 +2545,15 @@ bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1, } SubsumptionChecker SC(*this); - std::optional<bool> Subsumes = - SC.Subsumes(D1, AC1, D2, AC2, /*DepthAdjusted=*/Depth1 != Depth2); + // Associated declarations are used as a cache key in the event they were + // normalized earlier during concept checking. However we cannot reuse these + // cached results if any of the template depths have been adjusted. + const NamedDecl *DeclAC1 = D1, *DeclAC2 = D2; + if (Depth2 > Depth1) + DeclAC1 = nullptr; + else if (Depth1 > Depth2) + DeclAC2 = nullptr; + std::optional<bool> Subsumes = SC.Subsumes(DeclAC1, AC1, DeclAC2, AC2); if (!Subsumes) { // Normalization failed return true; @@ -2779,16 +2787,14 @@ void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) { std::optional<bool> SubsumptionChecker::Subsumes( const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ, - ArrayRef<AssociatedConstraint> Q, bool DepthAdjusted) { + ArrayRef<AssociatedConstraint> Q) { const NormalizedConstraint *PNormalized = - SemaRef.getNormalizedAssociatedConstraints(DepthAdjusted ? nullptr : DP, - P); + SemaRef.getNormalizedAssociatedConstraints(DP, P); if (!PNormalized) return std::nullopt; const NormalizedConstraint *QNormalized = - SemaRef.getNormalizedAssociatedConstraints(DepthAdjusted ? nullptr : DQ, - Q); + SemaRef.getNormalizedAssociatedConstraints(DQ, Q); if (!QNormalized) return std::nullopt; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
