https://github.com/eiytoq updated https://github.com/llvm/llvm-project/pull/181068
>From 4b933aa6dcfa52165fd4b51af3ebf90e368a3857 Mon Sep 17 00:00:00 2001 From: eiytoq <[email protected]> Date: Sun, 5 Apr 2026 09:31:39 +0800 Subject: [PATCH] fix --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ItaniumMangle.cpp | 114 ++++++++++++------ .../CodeGenCXX/dtor-local-lambda-mangle.cpp | 33 +++++ 3 files changed, 109 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..5e76dffcca051 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,29 @@ 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)) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND); + const TemplateDecl *TD = FD->getPrimaryTemplate()) { + mangleTemplatePrefix(TD); + mangleTemplateArgs(asTemplateName(TD), + *FD->getTemplateSpecializationArgs()); + } else { + 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..2c0269ecdaec5 --- /dev/null +++ b/clang/test/CodeGenCXX/dtor-local-lambda-mangle.cpp @@ -0,0 +1,33 @@ +// 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 -O2 -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s + +struct E { + E(); + template<typename T> + E(T t); + ~E(); +}; + +E::E() { + struct { + // CHECK-DAG: _ZTSN1EC13$_012anotherValueMUlvE_E + int anotherValue = [x = 1] { return x; }(); + } obj; +} + +template<typename T> +E::E(T t) { + struct { + // CHECK-DAG: _ZTSN1EC1IiEUt_UlvE_E + int anotherValue = [x = 1] { return x; }(); + } obj; +} + +E::~E() { + struct { + // CHECK-DAG: _ZTSN1ED13$_012anotherValueMUlvE_E + int anotherValue = [x = 2] { return x; }(); + } obj; +} + +E e(1); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
