[clang] [Clang] Fix another parameter mapping substitution bug (PR #162155)

Corentin Jabot via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 6 23:14:49 PDT 2025


https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/162155

>From 4c5ce91bd13b136846cd88cab9b7913f22c7a219 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Mon, 6 Oct 2025 22:18:03 +0200
Subject: [PATCH 1/3] [Clang] Fix another parameter mapping substitution bug

When a template parameter pack is named before
it can be substituted, it might not have a corresponding mapping.

Fixes #162125
---
 clang/lib/Sema/SemaConcept.cpp       |  3 +-
 clang/test/SemaTemplate/concepts.cpp | 41 +++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 999e302c02535..cb42d651a6586 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -277,7 +277,8 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
   bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
     // A lambda expression can introduce template parameters that don't have
     // corresponding template arguments yet.
-    if (T->getDepth() >= TemplateArgs.getNumLevels())
+    if (T->getDepth() >= TemplateArgs.getNumLevels()
+        || !TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
       return true;
 
     TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index e5e081ffb9d0f..3671dc6ff84de 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify %s
+// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify=expected,cxx20 %s
+// RUN: %clang_cc1 -std=c++2c -ferror-limit 0 -verify=expected %s
 
 namespace PR47043 {
   template<typename T> concept True = true;
@@ -1405,3 +1406,41 @@ static_assert(!std::is_constructible_v<span<4>, array<int, 3>>);
 }
 
 }
+
+
+namespace GH162125 {
+template<typename, int size>
+concept true_int = (size, true);
+
+template<typename, typename... Ts>
+concept true_types = true_int<void, sizeof...(Ts)>;
+
+template<typename, typename... Ts>
+concept true_types2 = true_int<void, Ts...[0]{1}>; // cxx20-warning {{pack indexing is a C++2c extension}}
+
+template<typename... Ts>
+struct s {
+  template<typename T> requires true_types<T, Ts...> && true_types2<T, Ts...>
+  static void f(T);
+};
+void(*test)(int) = &s<bool>::f<int>;
+}
+
+namespace GH162125_reversed {
+template<int size, typename>
+concept true_int = (size, true);
+
+template<typename, typename... Ts>
+concept true_types = true_int<sizeof...(Ts), void>;
+
+template<typename, typename... Ts>
+concept true_types2 = true_int<Ts...[0]{1}, void>;
+
+template<typename... Ts>
+struct s {
+  template<typename T> requires true_types<T, Ts...> && true_types2<T, Ts...>
+  static void f(T);
+};
+
+void(*test)(int) = &s<bool>::f<int>;
+}

>From 28cf852dbfa3e88509ec7a40ac0309b5938feba0 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Mon, 6 Oct 2025 22:43:14 +0200
Subject: [PATCH 2/3] format

---
 clang/lib/Sema/SemaConcept.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index cb42d651a6586..2590a7a1444c3 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -277,8 +277,8 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
   bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
     // A lambda expression can introduce template parameters that don't have
     // corresponding template arguments yet.
-    if (T->getDepth() >= TemplateArgs.getNumLevels()
-        || !TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
+    if (T->getDepth() >= TemplateArgs.getNumLevels() ||
+        !TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
       return true;
 
     TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());

>From 0c22e9d8ae77042f37cb09eb1c02dca853e9b7c6 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Tue, 7 Oct 2025 08:14:13 +0200
Subject: [PATCH 3/3] address feedback

---
 clang/lib/Sema/SemaConcept.cpp       | 8 ++++++--
 clang/test/SemaTemplate/concepts.cpp | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 2590a7a1444c3..8946f1bfc7a95 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -277,8 +277,12 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
   bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
     // A lambda expression can introduce template parameters that don't have
     // corresponding template arguments yet.
-    if (T->getDepth() >= TemplateArgs.getNumLevels() ||
-        !TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
+    if (T->getDepth() >= TemplateArgs.getNumLevels())
+      return true;
+
+    // There might not be a corresponding template argument before substituting
+    // into the parameter mapping, e.g. a sizeof... expression.
+    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
       return true;
 
     TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp
index 3671dc6ff84de..3b7c138f83364 100644
--- a/clang/test/SemaTemplate/concepts.cpp
+++ b/clang/test/SemaTemplate/concepts.cpp
@@ -1434,7 +1434,7 @@ template<typename, typename... Ts>
 concept true_types = true_int<sizeof...(Ts), void>;
 
 template<typename, typename... Ts>
-concept true_types2 = true_int<Ts...[0]{1}, void>;
+concept true_types2 = true_int<Ts...[0]{1}, void>; // cxx20-warning {{pack indexing is a C++2c extension}}
 
 template<typename... Ts>
 struct s {



More information about the cfe-commits mailing list