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
