From 564360be450b319aeafc26698be9811837bfb826 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 24 Jun 2010 00:08:06 +0000 Subject: [PATCH] Patch to correctly mangle block helper functions when block literal is declared inside a ctor/dtor. Fixes radr 8096995. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@106700 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBlocks.cpp | 8 ++--- lib/CodeGen/CodeGenFunction.h | 3 +- lib/CodeGen/CodeGenModule.cpp | 7 ++-- lib/CodeGen/CodeGenModule.h | 2 +- lib/CodeGen/Mangle.cpp | 18 +++++++--- lib/CodeGen/Mangle.h | 6 ++-- lib/CodeGen/MicrosoftCXXABI.cpp | 2 +- test/CodeGenCXX/block-in-ctor-dtor.cpp | 48 ++++++++++++++++++++++++++ 8 files changed, 78 insertions(+), 16 deletions(-) create mode 100644 test/CodeGenCXX/block-in-ctor-dtor.cpp diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index f07b7bbbda..6edfe4c102 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -228,7 +228,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { // block literal. // __invoke llvm::Function *Fn - = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, CurFuncDecl, + = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, BE, Info, CurFuncDecl, LocalDeclMap); BlockHasCopyDispose |= Info.BlockHasCopyDispose; Elts[3] = Fn; @@ -723,7 +723,7 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) { CGBlockInfo Info(n); llvm::DenseMap LocalDeclMap; llvm::Function *Fn - = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, 0, LocalDeclMap); + = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), BE, Info, 0, LocalDeclMap); assert(Info.BlockSize == BlockLiteralSize && "no imports allowed for global block"); @@ -762,7 +762,7 @@ llvm::Value *CodeGenFunction::LoadBlockStruct() { } llvm::Function * -CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, +CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const BlockExpr *BExpr, CGBlockInfo &Info, const Decl *OuterFuncDecl, llvm::DenseMap ldm) { @@ -835,7 +835,7 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic); MangleBuffer Name; - CGM.getMangledName(Name, BD); + CGM.getMangledName(GD, Name, BD); llvm::Function *Fn = llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, Name.getString(), &CGM.getModule()); diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index f797c2c4ff..32bffa105c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -500,7 +500,8 @@ public: const llvm::StructType *, std::vector *); - llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr, + llvm::Function *GenerateBlockFunction(GlobalDecl GD, + const BlockExpr *BExpr, CGBlockInfo &Info, const Decl *OuterFuncDecl, llvm::DenseMap ldm); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 6d94520ffd..cc97d86995 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -231,7 +231,7 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) { else if (const CXXDestructorDecl *D = dyn_cast(ND)) getMangleContext().mangleCXXDtor(D, GD.getDtorType(), Buffer); else if (const BlockDecl *BD = dyn_cast(ND)) - getMangleContext().mangleBlock(BD, Buffer); + getMangleContext().mangleBlock(GD, BD, Buffer); else getMangleContext().mangleName(ND, Buffer); @@ -245,8 +245,9 @@ llvm::StringRef CodeGenModule::getMangledName(GlobalDecl GD) { return Str; } -void CodeGenModule::getMangledName(MangleBuffer &Buffer, const BlockDecl *BD) { - getMangleContext().mangleBlock(BD, Buffer.getBuffer()); +void CodeGenModule::getMangledName(GlobalDecl GD, MangleBuffer &Buffer, + const BlockDecl *BD) { + getMangleContext().mangleBlock(GD, BD, Buffer.getBuffer()); } llvm::GlobalValue *CodeGenModule::GetGlobalValue(llvm::StringRef Name) { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index f092697fd4..4fbf34319f 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -465,7 +465,7 @@ public: unsigned &CallingConv); llvm::StringRef getMangledName(GlobalDecl GD); - void getMangledName(MangleBuffer &Buffer, const BlockDecl *BD); + void getMangledName(GlobalDecl GD, MangleBuffer &Buffer, const BlockDecl *BD); void EmitTentativeDefinition(const VarDecl *D); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 01838f98d4..154153aaeb 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -40,7 +40,7 @@ MiscNameMangler::MiscNameMangler(MangleContext &C, llvm::SmallVectorImpl &Res) : Context(C), Out(Res) { } -void MiscNameMangler::mangleBlock(const BlockDecl *BD) { +void MiscNameMangler::mangleBlock(GlobalDecl GD, const BlockDecl *BD) { // Mangle the context of the block. // FIXME: We currently mimic GCC's mangling scheme, which leaves much to be // desired. Come up with a better mangling scheme. @@ -55,6 +55,16 @@ void MiscNameMangler::mangleBlock(const BlockDecl *BD) { const NamedDecl *ND = cast(DC); if (IdentifierInfo *II = ND->getIdentifier()) Out << II->getName(); + else if (const CXXDestructorDecl *D = dyn_cast(ND)) { + llvm::SmallString<64> Buffer; + Context.mangleCXXDtor(D, GD.getDtorType(), Buffer); + Out << Buffer; + } + else if (const CXXConstructorDecl *D = dyn_cast(ND)) { + llvm::SmallString<64> Buffer; + Context.mangleCXXCtor(D, GD.getCtorType(), Buffer); + Out << Buffer; + } else { // FIXME: We were doing a mangleUnqualifiedName() before, but that's // a private member of a class that will soon itself be private to the @@ -857,7 +867,7 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (const BlockDecl *Block = dyn_cast(DC)) { manglePrefix(DC->getParent(), NoFunction); llvm::SmallString<64> Name; - Context.mangleBlock(Block, Name); + Context.mangleBlock(GlobalDecl(), Block, Name); Out << Name.size() << Name; return; } @@ -2180,10 +2190,10 @@ void MangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, Mangler.mangle(D); } -void MangleContext::mangleBlock(const BlockDecl *BD, +void MangleContext::mangleBlock(GlobalDecl GD, const BlockDecl *BD, llvm::SmallVectorImpl &Res) { MiscNameMangler Mangler(*this, Res); - Mangler.mangleBlock(BD); + Mangler.mangleBlock(GD, BD); } void MangleContext::mangleThunk(const CXXMethodDecl *MD, diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index d10334dcbb..ec575cc786 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -19,6 +19,7 @@ #define LLVM_CLANG_CODEGEN_MANGLE_H #include "CGCXX.h" +#include "GlobalDecl.h" #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" @@ -133,7 +134,8 @@ public: llvm::SmallVectorImpl &); virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, llvm::SmallVectorImpl &); - void mangleBlock(const BlockDecl *BD, llvm::SmallVectorImpl &); + void mangleBlock(GlobalDecl GD, + const BlockDecl *BD, llvm::SmallVectorImpl &); void mangleInitDiscriminator() { Discriminator = 0; @@ -163,7 +165,7 @@ public: llvm::raw_svector_ostream &getStream() { return Out; } - void mangleBlock(const BlockDecl *BD); + void mangleBlock(GlobalDecl GD, const BlockDecl *BD); void mangleObjCMethodName(const ObjCMethodDecl *MD); }; diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 3823c9dc20..ddf32ece58 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -402,7 +402,7 @@ void MicrosoftCXXNameMangler::manglePostfix(const DeclContext *DC, if (const BlockDecl *BD = dyn_cast(DC)) { llvm::SmallString<64> Name; - Context.mangleBlock(BD, Name); + Context.mangleBlock(GlobalDecl(), BD, Name); Out << Name << '@'; return manglePostfix(DC->getParent(), NoFunction); } diff --git a/test/CodeGenCXX/block-in-ctor-dtor.cpp b/test/CodeGenCXX/block-in-ctor-dtor.cpp new file mode 100644 index 0000000000..e4389a4eee --- /dev/null +++ b/test/CodeGenCXX/block-in-ctor-dtor.cpp @@ -0,0 +1,48 @@ +// RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s + +typedef void (^dispatch_block_t)(void); + +void dispatch_once(dispatch_block_t); + +class Zone { +public: + Zone(); + ~Zone(); +}; + +Zone::Zone() { + dispatch_once(^{}); + dispatch_once(^{}); +} + +Zone::~Zone() { + dispatch_once(^{}); + dispatch_once(^{}); +} + +class X : public virtual Zone { + X(); + ~X(); +}; + +X::X() { + dispatch_once(^{}); + dispatch_once(^{}); +}; + +X::~X() { + dispatch_once(^{}); + dispatch_once(^{}); +}; + + +// CHECK: define internal void @___ZN4ZoneC2Ev_block_invoke_ +// CHECK: define internal void @___ZN4ZoneC2Ev_block_invoke_ +// CHECK: define internal void @___ZN4ZoneD2Ev_block_invoke_ +// CHECK: define internal void @___ZN4ZoneD2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC1Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC1Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XC2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XD2Ev_block_invoke_ +// CHECK: define internal void @___ZN1XD2Ev_block_invoke_ -- 2.40.0