From 1425b4556a9b97e5b1cbca441ee08bee151fdb9f Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 26 Jan 2012 03:33:36 +0000 Subject: [PATCH] Use function pointers, rather than references, to pass Destroyers around, in the process cleaning up the various gcc/msvc compiler workarounds. llvm-svn: 149036 --- clang/lib/CodeGen/CGBlocks.cpp | 6 ++-- clang/lib/CodeGen/CGClass.cpp | 4 +-- clang/lib/CodeGen/CGCleanup.cpp | 4 +-- clang/lib/CodeGen/CGDecl.cpp | 48 ++++++++++++----------------- clang/lib/CodeGen/CGDeclCXX.cpp | 2 +- clang/lib/CodeGen/CGExpr.cpp | 10 ++---- clang/lib/CodeGen/CGObjC.cpp | 8 ++--- clang/lib/CodeGen/CodeGenFunction.h | 14 ++++----- 8 files changed, 41 insertions(+), 55 deletions(-) diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index e6ecb6a88bc1..c6d5be059c97 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -535,9 +535,9 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { // Block captures count as local values and have imprecise semantics. // They also can't be arrays, so need to worry about that. if (dtorKind == QualType::DK_objc_strong_lifetime) { - destroyer = &CodeGenFunction::destroyARCStrongImprecise; + destroyer = CodeGenFunction::destroyARCStrongImprecise; } else { - destroyer = &CGF.getDestroyer(dtorKind); + destroyer = CGF.getDestroyer(dtorKind); } // GEP down to the address. @@ -554,7 +554,7 @@ static void enterBlockScope(CodeGenFunction &CGF, BlockDecl *block) { cleanupKind = InactiveNormalAndEHCleanup; CGF.pushDestroy(cleanupKind, addr, variable->getType(), - *destroyer, useArrayEHCleanup); + destroyer, useArrayEHCleanup); // Remember where that cleanup was. capture.setCleanup(CGF.EHStack.stable_begin()); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 8a305fde2d48..45df88afe99a 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -945,13 +945,13 @@ namespace { class DestroyField : public EHScopeStack::Cleanup { const FieldDecl *field; - CodeGenFunction::Destroyer &destroyer; + CodeGenFunction::Destroyer *destroyer; bool useEHCleanupForArray; public: DestroyField(const FieldDecl *field, CodeGenFunction::Destroyer *destroyer, bool useEHCleanupForArray) - : field(field), destroyer(*destroyer), + : field(field), destroyer(destroyer), useEHCleanupForArray(useEHCleanupForArray) {} void Emit(CodeGenFunction &CGF, Flags flags) { diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index f1f17afdb451..645ef2520dea 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -1098,8 +1098,6 @@ llvm::Value *CodeGenFunction::getNormalCleanupDestSlot() { void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, QualType TempType, llvm::Value *Ptr) { - // This local is a GCC and MSVC compiler workaround. - Destroyer *destroyer = &destroyCXXObject; - pushDestroy(NormalAndEHCleanup, Ptr, TempType, *destroyer, + pushDestroy(NormalAndEHCleanup, Ptr, TempType, destroyCXXObject, /*useEHCleanup*/ true); } diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 7c7501ba946b..018521bef896 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -310,12 +310,12 @@ namespace { DestroyObject(llvm::Value *addr, QualType type, CodeGenFunction::Destroyer *destroyer, bool useEHCleanupForArray) - : addr(addr), type(type), destroyer(*destroyer), + : addr(addr), type(type), destroyer(destroyer), useEHCleanupForArray(useEHCleanupForArray) {} llvm::Value *addr; QualType type; - CodeGenFunction::Destroyer &destroyer; + CodeGenFunction::Destroyer *destroyer; bool useEHCleanupForArray; void Emit(CodeGenFunction &CGF, Flags flags) { @@ -430,7 +430,7 @@ static void EmitAutoVarWithLifetime(CodeGenFunction &CGF, const VarDecl &var, break; case Qualifiers::OCL_Strong: { - CodeGenFunction::Destroyer &destroyer = + CodeGenFunction::Destroyer *destroyer = (var.hasAttr() ? CodeGenFunction::destroyARCStrongPrecise : CodeGenFunction::destroyARCStrongImprecise); @@ -1111,7 +1111,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup( } // If we haven't chosen a more specific destroyer, use the default. - if (!destroyer) destroyer = &getDestroyer(dtorKind); + if (!destroyer) destroyer = getDestroyer(dtorKind); // Use an EH cleanup in array destructors iff the destructor itself // is being pushed as an EH cleanup. @@ -1155,25 +1155,17 @@ void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) { enterByrefCleanup(emission); } -CodeGenFunction::Destroyer & +CodeGenFunction::Destroyer * CodeGenFunction::getDestroyer(QualType::DestructionKind kind) { - // This is surprisingly compiler-dependent. GCC 4.2 can't bind - // references to functions directly in returns, and using '*&foo' - // confuses MSVC. Luckily, the following code pattern works in both. - Destroyer *destroyer = 0; switch (kind) { case QualType::DK_none: llvm_unreachable("no destroyer for trivial dtor"); case QualType::DK_cxx_destructor: - destroyer = &destroyCXXObject; - break; + return destroyCXXObject; case QualType::DK_objc_strong_lifetime: - destroyer = &destroyARCStrongPrecise; - break; + return destroyARCStrongPrecise; case QualType::DK_objc_weak_lifetime: - destroyer = &destroyARCWeak; - break; + return destroyARCWeak; } - return *destroyer; } /// pushDestroy - Push the standard destructor for the given type. @@ -1187,7 +1179,7 @@ void CodeGenFunction::pushDestroy(QualType::DestructionKind dtorKind, } void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, llvm::Value *addr, - QualType type, Destroyer &destroyer, + QualType type, Destroyer *destroyer, bool useEHCleanupForArray) { pushFullExprCleanup(cleanupKind, addr, type, destroyer, useEHCleanupForArray); @@ -1205,7 +1197,7 @@ void CodeGenFunction::pushDestroy(CleanupKind cleanupKind, llvm::Value *addr, /// used when destroying array elements, in case one of the /// destructions throws an exception void CodeGenFunction::emitDestroy(llvm::Value *addr, QualType type, - Destroyer &destroyer, + Destroyer *destroyer, bool useEHCleanupForArray) { const ArrayType *arrayType = getContext().getAsArrayType(type); if (!arrayType) @@ -1242,7 +1234,7 @@ void CodeGenFunction::emitDestroy(llvm::Value *addr, QualType type, void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, llvm::Value *end, QualType type, - Destroyer &destroyer, + Destroyer *destroyer, bool checkZeroLength, bool useEHCleanup) { assert(!type->isArrayType()); @@ -1293,7 +1285,7 @@ void CodeGenFunction::emitArrayDestroy(llvm::Value *begin, static void emitPartialArrayDestroy(CodeGenFunction &CGF, llvm::Value *begin, llvm::Value *end, QualType type, - CodeGenFunction::Destroyer &destroyer) { + CodeGenFunction::Destroyer *destroyer) { // If the element type is itself an array, drill down. unsigned arrayDepth = 0; while (const ArrayType *arrayType = CGF.getContext().getAsArrayType(type)) { @@ -1326,13 +1318,13 @@ namespace { llvm::Value *ArrayBegin; llvm::Value *ArrayEnd; QualType ElementType; - CodeGenFunction::Destroyer &Destroyer; + CodeGenFunction::Destroyer *Destroyer; public: RegularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEnd, QualType elementType, CodeGenFunction::Destroyer *destroyer) : ArrayBegin(arrayBegin), ArrayEnd(arrayEnd), - ElementType(elementType), Destroyer(*destroyer) {} + ElementType(elementType), Destroyer(destroyer) {} void Emit(CodeGenFunction &CGF, Flags flags) { emitPartialArrayDestroy(CGF, ArrayBegin, ArrayEnd, @@ -1347,14 +1339,14 @@ namespace { llvm::Value *ArrayBegin; llvm::Value *ArrayEndPointer; QualType ElementType; - CodeGenFunction::Destroyer &Destroyer; + CodeGenFunction::Destroyer *Destroyer; public: IrregularPartialArrayDestroy(llvm::Value *arrayBegin, llvm::Value *arrayEndPointer, QualType elementType, CodeGenFunction::Destroyer *destroyer) : ArrayBegin(arrayBegin), ArrayEndPointer(arrayEndPointer), - ElementType(elementType), Destroyer(*destroyer) {} + ElementType(elementType), Destroyer(destroyer) {} void Emit(CodeGenFunction &CGF, Flags flags) { llvm::Value *arrayEnd = CGF.Builder.CreateLoad(ArrayEndPointer); @@ -1377,10 +1369,10 @@ namespace { void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, llvm::Value *arrayEndPointer, QualType elementType, - Destroyer &destroyer) { + Destroyer *destroyer) { pushFullExprCleanup(EHCleanup, arrayBegin, arrayEndPointer, - elementType, &destroyer); + elementType, destroyer); } /// pushRegularPartialArrayCleanup - Push an EH cleanup to destroy @@ -1396,10 +1388,10 @@ void CodeGenFunction::pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, void CodeGenFunction::pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, llvm::Value *arrayEnd, QualType elementType, - Destroyer &destroyer) { + Destroyer *destroyer) { pushFullExprCleanup(EHCleanup, arrayBegin, arrayEnd, - elementType, &destroyer); + elementType, destroyer); } namespace { diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp index 2f32381c5efc..8206dd56ee55 100644 --- a/clang/lib/CodeGen/CGDeclCXX.cpp +++ b/clang/lib/CodeGen/CGDeclCXX.cpp @@ -343,7 +343,7 @@ void CodeGenFunction::GenerateCXXGlobalDtorFunc(llvm::Function *Fn, llvm::Function * CodeGenFunction::generateDestroyHelper(llvm::Constant *addr, QualType type, - Destroyer &destroyer, + Destroyer *destroyer, bool useEHCleanupForArray) { FunctionArgList args; ImplicitParamDecl dst(0, SourceLocation(), 0, getContext().VoidPtrTy); diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 41fbb836b5ce..0e19a4015af0 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -487,21 +487,17 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr *E, case Qualifiers::OCL_Strong: { bool precise = VD && VD->hasAttr(); CleanupKind cleanupKind = getARCCleanupKind(); - // This local is a GCC and MSVC compiler workaround. - Destroyer *destroyer = precise ? &destroyARCStrongPrecise : - &destroyARCStrongImprecise; pushDestroy(cleanupKind, ReferenceTemporary, ObjCARCReferenceLifetimeType, - *destroyer, cleanupKind & EHCleanup); + precise ? destroyARCStrongPrecise : destroyARCStrongImprecise, + cleanupKind & EHCleanup); break; } case Qualifiers::OCL_Weak: { - // This local is a GCC and MSVC compiler workaround. - Destroyer *destroyer = &destroyARCWeak; // __weak objects always get EH cleanups; otherwise, exceptions // could cause really nasty crashes instead of mere leaks. pushDestroy(NormalAndEHCleanup, ReferenceTemporary, - ObjCARCReferenceLifetimeType, *destroyer, true); + ObjCARCReferenceLifetimeType, destroyARCWeak, true); break; } } diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 581d463b8734..446bef124932 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1047,13 +1047,13 @@ namespace { private: llvm::Value *addr; const ObjCIvarDecl *ivar; - CodeGenFunction::Destroyer &destroyer; + CodeGenFunction::Destroyer *destroyer; bool useEHCleanupForArray; public: DestroyIvar(llvm::Value *addr, const ObjCIvarDecl *ivar, CodeGenFunction::Destroyer *destroyer, bool useEHCleanupForArray) - : addr(addr), ivar(ivar), destroyer(*destroyer), + : addr(addr), ivar(ivar), destroyer(destroyer), useEHCleanupForArray(useEHCleanupForArray) {} void Emit(CodeGenFunction &CGF, Flags flags) { @@ -1093,11 +1093,11 @@ static void emitCXXDestructMethod(CodeGenFunction &CGF, // Use a call to objc_storeStrong to destroy strong ivars, for the // general benefit of the tools. if (dtorKind == QualType::DK_objc_strong_lifetime) { - destroyer = &destroyARCStrongWithStore; + destroyer = destroyARCStrongWithStore; // Otherwise use the default for the destruction kind. } else { - destroyer = &CGF.getDestroyer(dtorKind); + destroyer = CGF.getDestroyer(dtorKind); } CleanupKind cleanupKind = CGF.getCleanupKind(dtorKind); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 0c13951aa52d..e105f31f0f2e 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1244,27 +1244,27 @@ public: void pushIrregularPartialArrayCleanup(llvm::Value *arrayBegin, llvm::Value *arrayEndPointer, QualType elementType, - Destroyer &destroyer); + Destroyer *destroyer); void pushRegularPartialArrayCleanup(llvm::Value *arrayBegin, llvm::Value *arrayEnd, QualType elementType, - Destroyer &destroyer); + Destroyer *destroyer); void pushDestroy(QualType::DestructionKind dtorKind, llvm::Value *addr, QualType type); void pushDestroy(CleanupKind kind, llvm::Value *addr, QualType type, - Destroyer &destroyer, bool useEHCleanupForArray); - void emitDestroy(llvm::Value *addr, QualType type, Destroyer &destroyer, + Destroyer *destroyer, bool useEHCleanupForArray); + void emitDestroy(llvm::Value *addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray); llvm::Function *generateDestroyHelper(llvm::Constant *addr, QualType type, - Destroyer &destroyer, + Destroyer *destroyer, bool useEHCleanupForArray); void emitArrayDestroy(llvm::Value *begin, llvm::Value *end, - QualType type, Destroyer &destroyer, + QualType type, Destroyer *destroyer, bool checkZeroLength, bool useEHCleanup); - Destroyer &getDestroyer(QualType::DestructionKind destructionKind); + Destroyer *getDestroyer(QualType::DestructionKind destructionKind); /// Determines whether an EH cleanup is required to destroy a type /// with the given destruction kind.