[clang] [Clang] Keep unused template parameters in MLTAL with empty packs (PR #174698)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 6 21:55:30 PST 2026


https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/174698

Unused template parameters, though never referenced during substitution, must remain in the MLTAL to preserve consistent template parameter indices.

The null TemplateArgument played this role before, which caused a crash due to existing assumptions in computing depenedency, so an empty pack is used instead.

There is no release note because this is a regression from concept parameter mapping.

Fixes https://github.com/llvm/llvm-project/issues/174667

>From 0b1935f1bd7d60c74133ac739c36510542ac0791 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Wed, 7 Jan 2026 13:47:20 +0800
Subject: [PATCH] [Clang] Keep unused template parameters in MLTAL with empty
 packs

Unused template parameters, though never referenced during substitution,
must remain in the MLTAL to preserve consistent template parameter
indices.

The null type placeholder played this role before, which caused a crash
due to existing assumptions in computing depenedency, so an empty
pack is used instead.

There is no release note because this is a regression from concept
parameter mapping.
---
 clang/lib/Sema/SemaConcept.cpp       |  9 ++++++++-
 clang/test/SemaTemplate/concepts.cpp | 10 ++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 2674f0a7b8749..a52cebe5a62c2 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -639,7 +639,14 @@ ConstraintSatisfactionChecker::SubstitutionInTemplateArguments(
         llvm::to_vector_of<TemplateArgument>(MLTAL.getOutermost());
   unsigned Offset = 0;
   for (unsigned I = 0, MappedIndex = 0; I < Used.size(); I++) {
-    TemplateArgument Arg;
+    // For template parameters that are not used during substitution, they
+    // still need to exist in the MLTAL since template parameter indices remain
+    // unchanged.
+    // We need a placeholder to represent them: a null TemplateArgument doesn't
+    // fit well due to non-null assumptions elsewhere. An empty pack serves this
+    // purpose, and substitution checks would catch any mistakes if we really
+    // messed anything up.
+    TemplateArgument Arg = TemplateArgument::getEmptyPack();
     if (Used[I])
       Arg = S.Context.getCanonicalTemplateArgument(
           CTAI.SugaredConverted[MappedIndex++]);
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index eed8b786f9954..d93391baf9926 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1703,3 +1703,13 @@ struct : named_unit<"", thermodynamic_temperature, zeroth_kelvin> {
 struct ice_point : relative_point_origin<point<kelvin>> {};
 
 }
+
+namespace GH174667 {
+
+template<class T, class, class U>
+concept C = requires{ requires U(T(1)); };
+
+template<C<void, bool> T> int f();
+void main() { f<int>(); }
+
+}



More information about the cfe-commits mailing list