[clang] [Clang] Fix Itanium mangling crash for local lambda in ctor/dtor (PR #181068)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 20 21:21:33 PST 2026
https://github.com/eiytoq updated https://github.com/llvm/llvm-project/pull/181068
>From 7287e9f118801cf9bb9c75fa01e9ca7704a97aee Mon Sep 17 00:00:00 2001
From: eiytoq <eiytoq at outlook.com>
Date: Thu, 12 Feb 2026 09:25:21 +0800
Subject: [PATCH] [Clang] Fix Itanium mangling crash for local lambda in
ctor/dtor
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/AST/ItaniumMangle.cpp | 22 +++++++++++++--
.../CodeGenCXX/dtor-local-lambda-mangle.cpp | 28 +++++++++++++++++++
3 files changed, 48 insertions(+), 3 deletions(-)
create mode 100644 clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 0bbe75b215cad..00995ceae73c4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -302,6 +302,7 @@ Bug Fixes to C++ Support
- Fixed a bug where captured variables in non-mutable lambdas were incorrectly treated as mutable
when used inside decltype in the return type. (#GH180460)
- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
+- Fixed a crash in Itanium C++ name mangling for a lambda in a local class field initializer inside a constructor/destructor. (#GH176395)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index df00760fa911b..822898f9fbe78 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -2195,18 +2195,34 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
if (mangleSubstitution(ND))
return;
+ auto getPrefixGlobalDecl = [this](const NamedDecl *ND) -> GlobalDecl {
+ if (const auto *CD = dyn_cast<CXXConstructorDecl>(ND)) {
+ if (ND == Structor)
+ return GlobalDecl(CD, static_cast<CXXCtorType>(StructorType));
+ return GlobalDecl(CD, Ctor_Complete);
+ }
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(ND)) {
+ if (ND == Structor)
+ return GlobalDecl(DD, static_cast<CXXDtorType>(StructorType));
+ return GlobalDecl(DD, Dtor_Complete);
+ }
+ if (const auto *FD = dyn_cast<FunctionDecl>(ND))
+ return GlobalDecl(FD);
+ return GlobalDecl(ND);
+ };
+
// Check if we have a template-prefix or a closure-prefix.
const TemplateArgumentList *TemplateArgs = nullptr;
- if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
+ if (GlobalDecl TD = isTemplate(getPrefixGlobalDecl(ND), TemplateArgs)) {
mangleTemplatePrefix(TD);
mangleTemplateArgs(asTemplateName(TD), *TemplateArgs);
} else if (const NamedDecl *PrefixND = getClosurePrefix(ND)) {
mangleClosurePrefix(PrefixND, NoFunction);
- mangleUnqualifiedName(ND, nullptr, nullptr);
+ mangleUnqualifiedName(getPrefixGlobalDecl(ND), nullptr, nullptr);
} else {
const DeclContext *DC = Context.getEffectiveDeclContext(ND);
manglePrefix(DC, NoFunction);
- mangleUnqualifiedName(ND, DC, nullptr);
+ mangleUnqualifiedName(getPrefixGlobalDecl(ND), DC, nullptr);
}
addSubstitution(ND);
diff --git a/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp b/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
new file mode 100644
index 0000000000000..49d3621ca00cf
--- /dev/null
+++ b/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -O2 -emit-llvm -o /dev/null %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -fclang-abi-compat=18 -emit-llvm -o - %s | FileCheck %s
+
+struct E {
+ E();
+ ~E();
+};
+
+E::E() {
+ struct {
+ int anotherValue = [] { return 1; }();
+ } obj;
+}
+
+E::~E() {
+ struct {
+ int anotherValue = [] { return 2; }();
+ } obj;
+}
+
+// CHECK-LABEL: define{{.*}} @"_ZZN1EC1EvEN3$_0C2Ev"
+// CHECK: call{{.*}} @"_ZZN1EC1EvENK3$_012anotherValueMUlvE_clEv"
+// CHECK-LABEL: define{{.*}} @"_ZZN1EC1EvENK3$_012anotherValueMUlvE_clEv"
+
+// CHECK-LABEL: define{{.*}} @"_ZZN1ED1EvEN3$_0C2Ev"
+// CHECK: call{{.*}} @"_ZZN1ED1EvENK3$_012anotherValueMUlvE_clEv"
+// CHECK-LABEL: define{{.*}} @"_ZZN1ED1EvENK3$_012anotherValueMUlvE_clEv"
More information about the cfe-commits
mailing list