https://github.com/eiytoq updated 
https://github.com/llvm/llvm-project/pull/181068

>From 7cf91845f223d7aa39e403c23aa21ab4688968a6 Mon Sep 17 00:00:00 2001
From: eiytoq <[email protected]>
Date: Sat, 28 Mar 2026 03:15:19 +0800
Subject: [PATCH 1/2] fix

---
 clang/docs/ReleaseNotes.rst                   |   1 +
 clang/lib/AST/ItaniumMangle.cpp               | 107 +++++++++++-------
 .../CodeGenCXX/dtor-local-lambda-mangle.cpp   |  28 +++++
 3 files changed, 97 insertions(+), 39 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 1ab3aae640607..ced3bc4a01613 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -411,6 +411,7 @@ Bug Fixes to C++ Support
 - Fix an error using an initializer list with array new for a type that is not 
default-constructible. (#GH81157)
 - We no longer consider conversion operators when copy-initializing from the 
same type. This was non
   conforming and could lead to recursive constraint satisfaction checking. 
(#GH149443)
+- 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 eea04b14eaf09..a7fef1f0388ed 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -514,6 +514,10 @@ class CXXNameMangler {
   void mangleUnscopedTemplateName(GlobalDecl GD, const DeclContext *DC,
                                   const AbiTagList *AdditionalAbiTags);
   void mangleSourceName(const IdentifierInfo *II);
+  void mangleConstructorName(const NamedDecl *ND,
+                             const AbiTagList *AdditionalAbiTags);
+  void mangleDestructorName(const NamedDecl *ND,
+                            const AbiTagList *AdditionalAbiTags);
   void mangleRegCallName(const IdentifierInfo *II);
   void mangleDeviceStubName(const IdentifierInfo *II);
   void mangleOCLDeviceStubName(const IdentifierInfo *II);
@@ -1699,48 +1703,12 @@ void CXXNameMangler::mangleUnqualifiedName(
   case DeclarationName::ObjCMultiArgSelector:
     llvm_unreachable("Can't mangle Objective-C selector names here!");
 
-  case DeclarationName::CXXConstructorName: {
-    const CXXRecordDecl *InheritedFrom = nullptr;
-    TemplateName InheritedTemplateName;
-    const TemplateArgumentList *InheritedTemplateArgs = nullptr;
-    if (auto Inherited =
-            cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) {
-      InheritedFrom = Inherited.getConstructor()->getParent();
-      InheritedTemplateName =
-          TemplateName(Inherited.getConstructor()->getPrimaryTemplate());
-      InheritedTemplateArgs =
-          Inherited.getConstructor()->getTemplateSpecializationArgs();
-    }
-
-    if (ND == Structor)
-      // If the named decl is the C++ constructor we're mangling, use the type
-      // we were given.
-      mangleCXXCtorType(static_cast<CXXCtorType>(StructorType), InheritedFrom);
-    else
-      // Otherwise, use the complete constructor name. This is relevant if a
-      // class with a constructor is declared within a constructor.
-      mangleCXXCtorType(Ctor_Complete, InheritedFrom);
-
-    // FIXME: The template arguments are part of the enclosing prefix or
-    // nested-name, but it's more convenient to mangle them here.
-    if (InheritedTemplateArgs)
-      mangleTemplateArgs(InheritedTemplateName, *InheritedTemplateArgs);
-
-    writeAbiTags(ND, AdditionalAbiTags);
+  case DeclarationName::CXXConstructorName:
+    mangleConstructorName(ND, AdditionalAbiTags);
     break;
-  }
 
   case DeclarationName::CXXDestructorName:
-    if (ND == Structor)
-      // If the named decl is the C++ destructor we're mangling, use the type 
we
-      // were given.
-      mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
-    else
-      // Otherwise, use the complete destructor name. This is relevant if a
-      // class with a destructor is declared within a destructor.
-      mangleCXXDtorType(Dtor_Complete);
-    assert(ND);
-    writeAbiTags(ND, AdditionalAbiTags);
+    mangleDestructorName(ND, AdditionalAbiTags);
     break;
 
   case DeclarationName::CXXOperatorName:
@@ -1767,6 +1735,51 @@ void CXXNameMangler::mangleUnqualifiedName(
   }
 }
 
+void CXXNameMangler::mangleConstructorName(
+    const NamedDecl *ND, const AbiTagList *AdditionalAbiTags) {
+  const CXXRecordDecl *InheritedFrom = nullptr;
+  TemplateName InheritedTemplateName;
+  const TemplateArgumentList *InheritedTemplateArgs = nullptr;
+  if (auto Inherited =
+          cast<CXXConstructorDecl>(ND)->getInheritedConstructor()) {
+    InheritedFrom = Inherited.getConstructor()->getParent();
+    InheritedTemplateName =
+        TemplateName(Inherited.getConstructor()->getPrimaryTemplate());
+    InheritedTemplateArgs =
+        Inherited.getConstructor()->getTemplateSpecializationArgs();
+  }
+
+  if (ND == Structor)
+    // If the named decl is the C++ constructor we're mangling, use the type
+    // we were given.
+    mangleCXXCtorType(static_cast<CXXCtorType>(StructorType), InheritedFrom);
+  else
+    // Otherwise, use the complete constructor name. This is relevant if a
+    // class with a constructor is declared within a constructor.
+    mangleCXXCtorType(Ctor_Complete, InheritedFrom);
+
+  // FIXME: The template arguments are part of the enclosing prefix or
+  // nested-name, but it's more convenient to mangle them here.
+  if (InheritedTemplateArgs)
+    mangleTemplateArgs(InheritedTemplateName, *InheritedTemplateArgs);
+
+  writeAbiTags(ND, AdditionalAbiTags);
+}
+
+void CXXNameMangler::mangleDestructorName(const NamedDecl *ND,
+                                          const AbiTagList *AdditionalAbiTags) 
{
+  if (ND == Structor)
+    // If the named decl is the C++ destructor we're mangling, use the type we
+    // were given.
+    mangleCXXDtorType(static_cast<CXXDtorType>(StructorType));
+  else
+    // Otherwise, use the complete destructor name. This is relevant if a
+    // class with a destructor is declared within a destructor.
+    mangleCXXDtorType(Dtor_Complete);
+  assert(ND);
+  writeAbiTags(ND, AdditionalAbiTags);
+}
+
 void CXXNameMangler::mangleRegCallName(const IdentifierInfo *II) {
   // <source-name> ::= <positive length number> __regcall3__ <identifier>
   // <number> ::= [n] <non-negative decimal integer>
@@ -2221,6 +2234,22 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, 
bool NoFunction) {
   if (mangleSubstitution(ND))
     return;
 
+  // Constructors and destructors can't be represented as a plain GlobalDecl,
+  // and prefix mangling only needs their spelling.
+  if (isa<CXXConstructorDecl>(ND)) {
+    manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
+    mangleConstructorName(ND, nullptr);
+    addSubstitution(ND);
+    return;
+  }
+
+  if (isa<CXXDestructorDecl>(ND)) {
+    manglePrefix(Context.getEffectiveDeclContext(ND), NoFunction);
+    mangleDestructorName(ND, nullptr);
+    addSubstitution(ND);
+    return;
+  }
+
   // Check if we have a template-prefix or a closure-prefix.
   const TemplateArgumentList *TemplateArgs = nullptr;
   if (GlobalDecl TD = isTemplate(ND, TemplateArgs)) {
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"

>From 4386a3b4616dbef40e175c85b480a9f278da53b5 Mon Sep 17 00:00:00 2001
From: eiytoq <[email protected]>
Date: Fri, 3 Apr 2026 20:13:18 +0800
Subject: [PATCH 2/2] address comments

---
 .../CodeGenCXX/dtor-local-lambda-mangle.cpp   | 20 +++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp 
b/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
index 49d3621ca00cf..8f8a1a1c526ed 100644
--- a/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
+++ b/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp
@@ -1,6 +1,6 @@
 // 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
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -O2 
-disable-llvm-passes -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 -O2 
-disable-llvm-passes -fclang-abi-compat=18 -emit-llvm -o - %s | FileCheck %s
 
 struct E {
   E();
@@ -19,10 +19,14 @@ E::~E() {
   } obj;
 }
 
-// CHECK-LABEL: define{{.*}} @"_ZZN1EC1EvEN3$_0C2Ev"
-// CHECK: call{{.*}} @"_ZZN1EC1EvENK3$_012anotherValueMUlvE_clEv"
-// CHECK-LABEL: define{{.*}} @"_ZZN1EC1EvENK3$_012anotherValueMUlvE_clEv"
+// CHECK-LABEL: define internal void @"_ZZN1EC1EvEN3$_0C2Ev"
+// CHECK: store i32 %{{.*}}, ptr %anotherValue, align 4, !tbaa 
![[CTOR_ACCESS:[0-9]+]]
 
-// CHECK-LABEL: define{{.*}} @"_ZZN1ED1EvEN3$_0C2Ev"
-// CHECK: call{{.*}} @"_ZZN1ED1EvENK3$_012anotherValueMUlvE_clEv"
-// CHECK-LABEL: define{{.*}} @"_ZZN1ED1EvENK3$_012anotherValueMUlvE_clEv"
+// CHECK-LABEL: define internal void @"_ZZN1ED1EvEN3$_0C2Ev"
+// CHECK: store i32 %{{.*}}, ptr %anotherValue, align 4, !tbaa 
![[DTOR_ACCESS:[0-9]+]]
+
+// CHECK: ![[CTOR_ACCESS]] = !{![[CTOR_TYPE:[0-9]+]], ![[INT:[0-9]+]], i64 0}
+// CHECK: ![[CTOR_TYPE]] = !{!"_ZTSZN1EC1EvE3$_0", ![[INT]], i64 0}
+
+// CHECK: ![[DTOR_ACCESS]] = !{![[DTOR_TYPE:[0-9]+]], ![[INT]], i64 0}
+// CHECK: ![[DTOR_TYPE]] = !{!"_ZTSZN1ED1EvE3$_0", ![[INT]], i64 0}

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

Reply via email to