https://github.com/AZero13 created 
https://github.com/llvm/llvm-project/pull/207626

This patch addresses a regression in C++17 relaxed template template parameter 
matching (P0522 / CWG2398). When partial ordering template template parameters, 
Clang attempts to match synthesized arguments from the parameter template 
against the argument template. When dealing with non-type template parameters, 
standard function deduction rules require strictly matching the parameter's 
type against the argument's type. If the argument template has a dependent 
non-type template parameter (e.g., `template<typename T, T v>`) and the 
parameter template expects a non-dependent type (e.g., `template<typename U, 
int v>`), Clang would match `T` against `int` and incorrectly deduce `T = int`. 
This spurious deduction conflicts with the prior deduction of `T = U` from the 
type parameter, resulting in a premature substitution failure (`conflicting 
deduction 'U' against 'int' for parameter T`). This patch fixes this by 
extending the `TDF_SkipNonDependent` relaxation check during template template 
partial ordering. By skipping deduction when *either* the parameter or argument 
type is non-dependent, we prevent this spurious conflict and allow `T` to 
remain deduced as `U`. The final validity of the substituted value is then 
correctly deferred to SFINAE evaluation in `CheckTemplateArgumentList`.

Fixes #207395

>From 9e28a5c76baecc8bce3ac79ac8dc4b51ff255af8 Mon Sep 17 00:00:00 2001
From: AZero13 <[email protected]>
Date: Sun, 5 Jul 2026 20:31:01 -0400
Subject: [PATCH] [clang] Fix template template parameter deduction for
 dependent non-type template parameters (CWG2398)

This patch addresses a regression in C++17 relaxed template template parameter 
matching (P0522 / CWG2398), resolving issue #207395.
When partial ordering template template parameters, Clang attempts to match 
synthesized arguments from the parameter template against the argument 
template. When dealing with non-type template parameters, standard function 
deduction rules require strictly matching the parameter's type against the 
argument's type.
If the argument template has a dependent non-type template parameter (e.g., 
`template<typename T, T v>`) and the parameter template expects a non-dependent 
type (e.g., `template<typename U, int v>`), Clang would match `T` against `int` 
and incorrectly deduce `T = int`. This spurious deduction conflicts with the 
prior deduction of `T = U` from the type parameter, resulting in a premature 
substitution failure (`conflicting deduction 'U' against 'int' for parameter 
T`).
This patch fixes this by extending the `TDF_SkipNonDependent` relaxation check 
during template template partial ordering. By skipping deduction when *either* 
the parameter or argument type is non-dependent, we prevent this spurious 
conflict and allow `T` to remain deduced as `U`. The final validity of the 
substituted value is then correctly deferred to SFINAE evaluation in 
`CheckTemplateArgumentList`.

Fixes #207395
---
 clang/lib/Sema/SemaTemplateDeduction.cpp           | 14 ++++++++++++--
 .../test/SemaTemplate/temp_arg_template_p0522.cpp  | 10 ++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp 
b/clang/lib/Sema/SemaTemplateDeduction.cpp
index d93b528facbcc..91f282e487179 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1833,10 +1833,20 @@ static TemplateDeductionResult 
DeduceTemplateArgumentsByTypeMatch(
     }
   }
 
+  // In the context of partial ordering (where TDF_SkipNonDependent is set),
+  // we may be matching a dependent parameter type (like `T` from 
`template<typename T, T V>`)
+  // against a non-dependent argument type (like `int` from `template<typename 
U, int>`).
+  // If we try to deduce `T` from `int`, we'll incorrectly deduce `T = int`, 
which
+  // conflicts with the deduction of `T = U` from the type parameter. By 
skipping 
+  // deduction when either type is non-dependent, we prevent this spurious 
conflict 
+  // and allow CheckTemplateArgumentList to perform the final validity check.
+  if (TDF & TDF_SkipNonDependent) {
+    if (!P->isDependentType() || !A->isDependentType())
+      return TemplateDeductionResult::Success;
+  }
+
   // If the parameter type is not dependent, there is nothing to deduce.
   if (!P->isDependentType()) {
-    if (TDF & TDF_SkipNonDependent)
-      return TemplateDeductionResult::Success;
     if ((TDF & TDF_IgnoreQualifiers) ? S.Context.hasSameUnqualifiedType(P, A)
                                      : S.Context.hasSameType(P, A))
       return TemplateDeductionResult::Success;
diff --git a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp 
b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
index bde811c3bf685..fe250e2ceeb69 100644
--- a/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
+++ b/clang/test/SemaTemplate/temp_arg_template_p0522.cpp
@@ -175,3 +175,13 @@ namespace GH181166 {
   template <class ...Ts> struct B {};
   using T = decltype(f<B>());
 } // namespace GH181166
+
+namespace CWG2398_DependentNonType {
+  template<typename T, T V> struct my_constant {}; 
+  template <template<typename U, int> class Constant> void f(Constant<int, 
1>); 
+  using go = decltype(f(my_constant<int, 1>()));
+
+  template<typename T, int V> struct my_constant2 {}; 
+  template <template<typename U, U> class Constant> void f2(Constant<int, 1>); 
+  using go2 = decltype(f2(my_constant2<int, 1>()));
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to