[clang] [Clang] Fix new initializer list mangling (PR #232629)

Kunal Dubey via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 16 12:48:36 PDT 2026


https://github.com/xakep8 updated https://github.com/llvm/llvm-project/pull/232629

>From f3c48140c61e2f59818258a5a77caecb20d44a52 Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Fri, 16 Oct 2026 11:37:51 +0530
Subject: [PATCH 1/3] [Clang] Avoid numbering lambdas with invalid types

While reporting an error, Clang can still create a lambda whose type is
invalid. It then tries to assign an internal number to that lambda,
which requires processing the invalid type and could crash the compiler.

Skipped this numbering step when the lambda type already contains errors.
The original source error is still reported without the extra crash.
---
 clang/docs/ReleaseNotes.md            |  3 +++
 clang/lib/Sema/SemaLambda.cpp         |  3 +++
 clang/test/SemaCXX/crash-GH170185.cpp | 14 ++++++++++++++
 3 files changed, 20 insertions(+)
 create mode 100644 clang/test/SemaCXX/crash-GH170185.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7d3f0eb702553d..45550b20dc38c8 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -814,6 +814,9 @@ features cannot lower the translation-unit ABI level;
 
 #### Bug Fixes to C++ Support
 
+- Fixed a crash when a lambda parameter type contains an invalid non-type
+  template argument. (#GH170185)
+
 - Fixed lambdas with specifiers or attributes after the capture list being
   misparsed as function declarations in direct-initialization contexts under
   `-fms-extensions` or in HLSL mode.
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 0c9a92cdd0c320..ec74102c0ecaf7 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -489,6 +489,9 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
 void Sema::handleLambdaNumbering(
     CXXRecordDecl *Class, CXXMethodDecl *Method,
     std::optional<CXXRecordDecl::LambdaNumbering> NumberingOverride) {
+  if (Method->getType()->containsErrors())
+    return;
+
   ContextRAII ManglingContext(*this, Class->getDeclContext());
 
   auto getMangleNumberingContext =
diff --git a/clang/test/SemaCXX/crash-GH170185.cpp b/clang/test/SemaCXX/crash-GH170185.cpp
new file mode 100644
index 00000000000000..21fb071a1e80fe
--- /dev/null
+++ b/clang/test/SemaCXX/crash-GH170185.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+struct Foo; // expected-note 2 {{forward declaration of 'Foo'}}
+
+template <Foo X> // expected-error {{non-type template parameter has incomplete type 'Foo'}}
+struct Arr;
+
+Foo f; // expected-error {{variable has incomplete type 'Foo'}}
+
+void foo() {
+  []() {
+    (void)[&](Arr<f>) {};
+  }();
+}

>From 372f14a31a80cbbd02f7b9db735df90bd9c4af7d Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Fri, 16 Oct 2026 15:40:35 +0530
Subject: [PATCH 2/3] [Clang] Move the invalid lambda check before numbering

Check the lambda type in ActOnStartOfLambdaDefinition before calling
handleLambdaNumbering, instead of handling invalid types inside the
numbering function.
---
 clang/lib/Sema/SemaLambda.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index ec74102c0ecaf7..ec883d2ccb1d12 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -489,9 +489,6 @@ bool Sema::DiagnoseInvalidExplicitObjectParameterInLambda(
 void Sema::handleLambdaNumbering(
     CXXRecordDecl *Class, CXXMethodDecl *Method,
     std::optional<CXXRecordDecl::LambdaNumbering> NumberingOverride) {
-  if (Method->getType()->containsErrors())
-    return;
-
   ContextRAII ManglingContext(*this, Class->getDeclContext());
 
   auto getMangleNumberingContext =
@@ -1534,7 +1531,8 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
   if (LangOpts.OpenMP)
     OpenMP().ActOnFinishedFunctionDefinitionInOpenMPAssumeScope(Method);
 
-  handleLambdaNumbering(Class, Method);
+  if (!Method->getType()->containsErrors())
+    handleLambdaNumbering(Class, Method);
 
   for (auto &&C : LSI->Captures) {
     if (!C.isVariableCapture())

>From 29210d7e12f72b0dec170ac6d53a1a4cb136c2ef Mon Sep 17 00:00:00 2001
From: Kunal Dubey <xakep8 at protonmail.com>
Date: Fri, 16 Oct 2026 12:32:04 +0530
Subject: [PATCH 3/3] [Clang] Fix Incorrect mangling for "new
 std::initializer_list<int>{1}"

---
 clang/lib/AST/ItaniumMangle.cpp        |  2 ++
 clang/test/CodeGenCXX/mangle-exprs.cpp | 20 +++++++++++++++++++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index ddde9d48606df3..441aad41edc0d2 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -5344,6 +5344,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
       else
         Out << "pi";
       const Expr *Init = New->getInitializer();
+      if (const auto *SILE = dyn_cast<CXXStdInitializerListExpr>(Init))
+        Init = SILE->getSubExpr()->IgnoreImplicit();
       if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) {
         // Directly inline the initializers.
         for (CXXConstructExpr::const_arg_iterator I = CCE->arg_begin(),
diff --git a/clang/test/CodeGenCXX/mangle-exprs.cpp b/clang/test/CodeGenCXX/mangle-exprs.cpp
index b75f2cf3607b3f..574cd81952d9ae 100644
--- a/clang/test/CodeGenCXX/mangle-exprs.cpp
+++ b/clang/test/CodeGenCXX/mangle-exprs.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -Wno-error=return-type -std=c++11 -fclang-abi-compat=latest -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
+// RUN: %clang_cc1 -Wno-error=return-type -Wno-dangling-initializer-list -std=c++11 -fclang-abi-compat=latest -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s
 
 namespace std {
   typedef decltype(sizeof(int)) size_t;
@@ -212,6 +212,24 @@ namespace test4 {
 
 }
 
+namespace new_std_initializer_list {
+  template <int N>
+  void empty(decltype((N, new std::initializer_list<int>{}))) {}
+
+  template <int N>
+  void one(decltype((N, new std::initializer_list<int>{1}))) {}
+
+  template <int N>
+  void two(decltype((N, new std::initializer_list<int>{1, 2}))) {}
+
+  // CHECK-LABEL: define {{.*}} @_ZN24new_std_initializer_list5emptyILi0EEEvDTcmT_nw_St16initializer_listIiEilEE
+  template void empty<0>(std::initializer_list<int> *);
+  // CHECK-LABEL: define {{.*}} @_ZN24new_std_initializer_list3oneILi0EEEvDTcmT_nw_St16initializer_listIiEilLi1EEE
+  template void one<0>(std::initializer_list<int> *);
+  // CHECK-LABEL: define {{.*}} @_ZN24new_std_initializer_list3twoILi0EEEvDTcmT_nw_St16initializer_listIiEilLi1ELi2EEE
+  template void two<0>(std::initializer_list<int> *);
+}
+
 namespace test5 {
   template <typename T> void a(decltype(noexcept(T()))) {}
   template void a<int>(decltype(noexcept(int())));



More information about the cfe-commits mailing list