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

Reply via email to