https://github.com/wx257osn2 updated https://github.com/llvm/llvm-project/pull/184406
>From 2a6f2f9184e45cbedb0758d053c9bc573d1478aa Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Tue, 3 Mar 2026 21:39:30 +0900 Subject: [PATCH 01/11] add test --- .../SemaCXX/cxx2c-template-template-param.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/clang/test/SemaCXX/cxx2c-template-template-param.cpp b/clang/test/SemaCXX/cxx2c-template-template-param.cpp index 704df3112277f..6ba18a253d34c 100644 --- a/clang/test/SemaCXX/cxx2c-template-template-param.cpp +++ b/clang/test/SemaCXX/cxx2c-template-template-param.cpp @@ -432,5 +432,21 @@ template <typename T, template <typename...> concept C1> concept TestBinary = T::a || C1<T>; static_assert(TestBinary<int, A>); +} + +namespace concept_template_parameter_as_second_parameter { + +template <typename> +concept Any = true; + +template <typename T, template <typename...> concept C> +concept Wrap = C<T>; + +template <typename T, Wrap<Any> U> +void f(T&&, U&&) {} + +void test() { + f(0, 1); +} } >From 554457662fdc3a24b2d929ff82294fc376145c17 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Tue, 3 Mar 2026 22:33:43 +0900 Subject: [PATCH 02/11] early return --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index b4d8158525f04..32b406b551247 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4481,11 +4481,10 @@ ExprResult Sema::SubstConceptTemplateArguments( ExprResult TransformUnresolvedLookupExpr(UnresolvedLookupExpr *E, bool IsAddressOfOperand = false) { - if (E->isConceptReference()) { - ExprResult Res = SemaRef.SubstExpr(E, MLTAL); - return Res; - } - return E; + if (!E->isConceptReference()) + return E; + + return SemaRef.SubstExpr(E, MLTAL); } }; >From a4be99ae34ed291563005892a6466e6859488c56 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Wed, 4 Mar 2026 00:17:20 +0900 Subject: [PATCH 03/11] resolve concept with correct template id --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 32b406b551247..5015c6d4a460a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4484,7 +4484,36 @@ ExprResult Sema::SubstConceptTemplateArguments( if (!E->isConceptReference()) return E; - return SemaRef.SubstExpr(E, MLTAL); + NamedDecl *D = *E->decls_begin(); + ConceptDecl *ResolvedConcept = nullptr; + + if (const auto * const TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { + const auto Depth = TTP->getDepth(); + const auto Pos = TTP->getPosition(); + if (Depth < MLTAL.getNumLevels() && + MLTAL.hasTemplateArgument(Depth, Pos)) { + TemplateArgument Arg = MLTAL(Depth, Pos); + if (Arg.getKind() == TemplateArgument::Template) + ResolvedConcept = dyn_cast_or_null<ConceptDecl>( + Arg.getAsTemplate().getAsTemplateDecl()); + } + } else + ResolvedConcept = dyn_cast<ConceptDecl>(D); + + if (ResolvedConcept == nullptr) + return E; + + TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); + if (TransformTemplateArguments(E->getTemplateArgs(), + E->getNumTemplateArgs(), TransArgs)) + return ExprError(); + + CXXScopeSpec SS; + DeclarationNameInfo NameInfo(ResolvedConcept->getDeclName(), + E->getNameLoc()); + return SemaRef.CheckConceptTemplateId(SS, SourceLocation(), NameInfo, + ResolvedConcept, ResolvedConcept, + &TransArgs, false); } }; >From ec1a8d3767d8cab315b46b6b6695345a44676506 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 00:58:46 +0900 Subject: [PATCH 04/11] remove const --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 5015c6d4a460a..147cbe2974463 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4487,7 +4487,7 @@ ExprResult Sema::SubstConceptTemplateArguments( NamedDecl *D = *E->decls_begin(); ConceptDecl *ResolvedConcept = nullptr; - if (const auto * const TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { const auto Depth = TTP->getDepth(); const auto Pos = TTP->getPosition(); if (Depth < MLTAL.getNumLevels() && >From 80540cf4906e0c1e24c6c32609346916302ea90b Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 00:59:07 +0900 Subject: [PATCH 05/11] s/const auto/unsigned/ --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 147cbe2974463..e94718c20e1da 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4488,8 +4488,8 @@ ExprResult Sema::SubstConceptTemplateArguments( ConceptDecl *ResolvedConcept = nullptr; if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { - const auto Depth = TTP->getDepth(); - const auto Pos = TTP->getPosition(); + unsigned Depth = TTP->getDepth(); + unsigned Pos = TTP->getPosition(); if (Depth < MLTAL.getNumLevels() && MLTAL.hasTemplateArgument(Depth, Pos)) { TemplateArgument Arg = MLTAL(Depth, Pos); >From d0bdc4734568e84b5015ce213e14803088a778a3 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 01:19:39 +0900 Subject: [PATCH 06/11] use assert instead of if --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index e94718c20e1da..feb8684c680d4 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -40,6 +40,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" #include "llvm/Support/TimeProfiler.h" +#include <iterator> #include <optional> using namespace clang; @@ -4484,19 +4485,20 @@ ExprResult Sema::SubstConceptTemplateArguments( if (!E->isConceptReference()) return E; + assert(std::next(E->decls_begin()) == E->decls_end() && + "ConceptReference must have single declaration"); NamedDecl *D = *E->decls_begin(); ConceptDecl *ResolvedConcept = nullptr; if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { unsigned Depth = TTP->getDepth(); unsigned Pos = TTP->getPosition(); - if (Depth < MLTAL.getNumLevels() && - MLTAL.hasTemplateArgument(Depth, Pos)) { - TemplateArgument Arg = MLTAL(Depth, Pos); - if (Arg.getKind() == TemplateArgument::Template) - ResolvedConcept = dyn_cast_or_null<ConceptDecl>( - Arg.getAsTemplate().getAsTemplateDecl()); - } + assert(Depth < MLTAL.getNumLevels() && + MLTAL.hasTemplateArgument(Depth, Pos)); + TemplateArgument Arg = MLTAL(Depth, Pos); + assert(Arg.getKind() == TemplateArgument::Template); + ResolvedConcept = dyn_cast_or_null<ConceptDecl>( + Arg.getAsTemplate().getAsTemplateDecl()); } else ResolvedConcept = dyn_cast<ConceptDecl>(D); >From 3d3c6507ea296be77a83d31e3d0e5c5aa967e606 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 01:23:38 +0900 Subject: [PATCH 07/11] move early return into inner branch --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index feb8684c680d4..ada0ed390419c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4499,11 +4499,11 @@ ExprResult Sema::SubstConceptTemplateArguments( assert(Arg.getKind() == TemplateArgument::Template); ResolvedConcept = dyn_cast_or_null<ConceptDecl>( Arg.getAsTemplate().getAsTemplateDecl()); + if (ResolvedConcept == nullptr) + return E; } else ResolvedConcept = dyn_cast<ConceptDecl>(D); - if (ResolvedConcept == nullptr) - return E; TemplateArgumentListInfo TransArgs(E->getLAngleLoc(), E->getRAngleLoc()); if (TransformTemplateArguments(E->getTemplateArgs(), >From d9fabd87e58f09d1fcabbd63f6e705100c6a1205 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 01:50:35 +0900 Subject: [PATCH 08/11] add test --- .../SemaCXX/cxx2c-template-template-param.cpp | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/clang/test/SemaCXX/cxx2c-template-template-param.cpp b/clang/test/SemaCXX/cxx2c-template-template-param.cpp index 6ba18a253d34c..6214e96905409 100644 --- a/clang/test/SemaCXX/cxx2c-template-template-param.cpp +++ b/clang/test/SemaCXX/cxx2c-template-template-param.cpp @@ -450,3 +450,23 @@ void test() { } } + +namespace multi_level_concept_template_parameter { + +template <typename> +concept Any = true; + +template <typename T, template <typename...> concept C0, template <typename...> concept C1> +concept Both = C0<T> && C1<T>; + +template <typename T, template <typename...> concept C> +concept Wrap = Both<T, Any, C>; + +template <typename T, Wrap<Any> U> +void f(T&&, U&&) {} + +void test() { + f(0, 1); +} + +} >From 67bd89112bb5c3e265f518ef79e39b98c29d6e08 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 01:51:28 +0900 Subject: [PATCH 09/11] getAsTemplateDecl() should be non-null for concepts --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index ada0ed390419c..c05a801baaa49 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4497,7 +4497,7 @@ ExprResult Sema::SubstConceptTemplateArguments( MLTAL.hasTemplateArgument(Depth, Pos)); TemplateArgument Arg = MLTAL(Depth, Pos); assert(Arg.getKind() == TemplateArgument::Template); - ResolvedConcept = dyn_cast_or_null<ConceptDecl>( + ResolvedConcept = dyn_cast<ConceptDecl>( Arg.getAsTemplate().getAsTemplateDecl()); if (ResolvedConcept == nullptr) return E; >From 63da972275fd047fbd311145bd80aa0690ea8901 Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 02:18:55 +0900 Subject: [PATCH 10/11] check number of decls directly --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index c05a801baaa49..adca9e1598be7 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4485,7 +4485,7 @@ ExprResult Sema::SubstConceptTemplateArguments( if (!E->isConceptReference()) return E; - assert(std::next(E->decls_begin()) == E->decls_end() && + assert(E->getNumDecls() == 1 && "ConceptReference must have single declaration"); NamedDecl *D = *E->decls_begin(); ConceptDecl *ResolvedConcept = nullptr; >From 6ee8afedabed559a5dab86ead640acf01ebdf6ea Mon Sep 17 00:00:00 2001 From: I <[email protected]> Date: Thu, 5 Mar 2026 02:21:34 +0900 Subject: [PATCH 11/11] revert to use assert --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index adca9e1598be7..557b2fe660247 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -4493,12 +4493,13 @@ ExprResult Sema::SubstConceptTemplateArguments( if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { unsigned Depth = TTP->getDepth(); unsigned Pos = TTP->getPosition(); - assert(Depth < MLTAL.getNumLevels() && - MLTAL.hasTemplateArgument(Depth, Pos)); - TemplateArgument Arg = MLTAL(Depth, Pos); - assert(Arg.getKind() == TemplateArgument::Template); - ResolvedConcept = dyn_cast<ConceptDecl>( - Arg.getAsTemplate().getAsTemplateDecl()); + if (Depth < MLTAL.getNumLevels() && + MLTAL.hasTemplateArgument(Depth, Pos)) { + TemplateArgument Arg = MLTAL(Depth, Pos); + assert(Arg.getKind() == TemplateArgument::Template); + ResolvedConcept = dyn_cast<ConceptDecl>( + Arg.getAsTemplate().getAsTemplateDecl()); + } if (ResolvedConcept == nullptr) return E; } else _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
