diff options
author | John McCall <rjmccall@apple.com> | 2011-07-12 00:15:30 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-07-12 00:15:30 +0000 |
commit | 5fcf8da33dfb9a54f047718223ddba16a263f6c1 (patch) | |
tree | 75ba783c9f84f57aaa7c8e5e0c1f667c1fe83d89 /clang/lib | |
parent | cdc2297ee1475125b2b55edb61df14b722c2cc10 (diff) | |
download | bcm5719-llvm-5fcf8da33dfb9a54f047718223ddba16a263f6c1.tar.gz bcm5719-llvm-5fcf8da33dfb9a54f047718223ddba16a263f6c1.zip |
Do full-expression cleanups in a much more sensible way that still lets
people write useful cleanup classes.
llvm-svn: 134942
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGCleanup.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGException.cpp | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 33 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGTemporaries.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 69 |
5 files changed, 26 insertions, 96 deletions
diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp index f75253bf788..4147c241c25 100644 --- a/clang/lib/CodeGen/CGCleanup.cpp +++ b/clang/lib/CodeGen/CGCleanup.cpp @@ -256,9 +256,7 @@ void CodeGenFunction::initFullExprCleanup() { if (cleanup.isEHCleanup()) cleanup.setTestFlagInEHCleanup(); } -EHScopeStack::Cleanup::~Cleanup() { - llvm_unreachable("Cleanup is indestructable"); -} +void EHScopeStack::Cleanup::anchor() {} /// All the branch fixups on the EH stack have propagated out past the /// outermost normal cleanup; resolve them all by adding cases to the diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 35429e3b841..c25b9a68831 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -323,9 +323,10 @@ static llvm::Constant *getCleanupValue(CodeGenFunction &CGF) { namespace { /// A cleanup to free the exception object if its initialization /// throws. - struct FreeException { - static void Emit(CodeGenFunction &CGF, bool forEH, - llvm::Value *exn) { + struct FreeException : EHScopeStack::Cleanup { + llvm::Value *exn; + FreeException(llvm::Value *exn) : exn(exn) {} + void Emit(CodeGenFunction &CGF, bool forEH) { CGF.Builder.CreateCall(getFreeExceptionFn(CGF), exn) ->setDoesNotThrow(); } diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 2f0d827fc3b..8ea481f23a5 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1902,23 +1902,6 @@ namespace { CallReleaseForObject(QualType type, llvm::Value *addr, CodeGenFunction::Destroyer *destroyer) : ObjCReleasingCleanup(type, addr, destroyer) {} - - using ObjCReleasingCleanup::Emit; - static void Emit(CodeGenFunction &CGF, bool IsForEH, - QualType type, llvm::Value *addr, - CodeGenFunction::Destroyer *destroyer) { - // EHScopeStack::Cleanup objects can never have their destructors called, - // so use placement new to construct our temporary object. - union { - void* align; - char data[sizeof(CallReleaseForObject)]; - }; - - CallReleaseForObject *Object - = new (&align) CallReleaseForObject(type, addr, destroyer); - Object->Emit(CGF, IsForEH); - (void)data[0]; - } }; /// A cleanup that calls @objc_storeStrong(nil) on all the objects to @@ -1965,22 +1948,6 @@ namespace { struct CallWeakReleaseForObject : ObjCReleasingCleanup { CallWeakReleaseForObject(QualType type, llvm::Value *addr) : ObjCReleasingCleanup(type, addr, CodeGenFunction::destroyARCWeak) {} - - using ObjCReleasingCleanup::Emit; - static void Emit(CodeGenFunction &CGF, bool IsForEH, - QualType type, llvm::Value *addr) { - // EHScopeStack::Cleanup objects can never have their destructors called, - // so use placement new to construct our temporary object. - union { - void* align; - char data[sizeof(CallWeakReleaseForObject)]; - }; - - CallWeakReleaseForObject *Object - = new (&align) CallWeakReleaseForObject(type, addr); - Object->Emit(CGF, IsForEH); - (void)data[0]; - } }; diff --git a/clang/lib/CodeGen/CGTemporaries.cpp b/clang/lib/CodeGen/CGTemporaries.cpp index 3b4c50910bf..7e07b4e5c8c 100644 --- a/clang/lib/CodeGen/CGTemporaries.cpp +++ b/clang/lib/CodeGen/CGTemporaries.cpp @@ -16,9 +16,12 @@ using namespace clang; using namespace CodeGen; namespace { - struct DestroyTemporary { - static void Emit(CodeGenFunction &CGF, bool forEH, - const CXXDestructorDecl *dtor, llvm::Value *addr) { + struct DestroyTemporary : EHScopeStack::Cleanup { + const CXXDestructorDecl *dtor; + llvm::Value *addr; + DestroyTemporary(const CXXDestructorDecl *dtor, llvm::Value *addr) + : dtor(dtor), addr(addr) {} + void Emit(CodeGenFunction &CGF, bool forEH) { CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*ForVirtualBase=*/false, addr); } diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 968222e334a..74324e4dc0c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -181,15 +181,13 @@ public: /// Cleanup implementations should generally be declared in an /// anonymous namespace. class Cleanup { + // Anchor the construction vtable. + virtual void anchor(); public: - // Anchor the construction vtable. We use the destructor because - // gcc gives an obnoxious warning if there are virtual methods - // with an accessible non-virtual destructor. Unfortunately, - // declaring this destructor makes it non-trivial, but there - // doesn't seem to be any other way around this warning. - // - // This destructor will never be called. - virtual ~Cleanup(); + // Provide a virtual destructor to suppress a very common warning + // that unfortunately cannot be suppressed without this. Cleanups + // should not rely on this destructor ever being called. + virtual ~Cleanup() {} /// Emit the cleanup. For normal cleanups, this is run in the /// same EH context as when the cleanup was pushed, i.e. the @@ -201,38 +199,6 @@ public: virtual void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) = 0; }; - /// UnconditionalCleanupN stores its N parameters and just passes - /// them to the real cleanup function. - template <class T, class A0> - class UnconditionalCleanup1 : public Cleanup { - A0 a0; - public: - UnconditionalCleanup1(A0 a0) : a0(a0) {} - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { - T::Emit(CGF, IsForEHCleanup, a0); - } - }; - - template <class T, class A0, class A1> - class UnconditionalCleanup2 : public Cleanup { - A0 a0; A1 a1; - public: - UnconditionalCleanup2(A0 a0, A1 a1) : a0(a0), a1(a1) {} - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { - T::Emit(CGF, IsForEHCleanup, a0, a1); - } - }; - - template <class T, class A0, class A1, class A2> - class UnconditionalCleanup3 : public Cleanup { - A0 a0; A1 a1; A2 a2; - public: - UnconditionalCleanup3(A0 a0, A1 a1, A2 a2) : a0(a0), a1(a1), a2(a2) {} - void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { - T::Emit(CGF, IsForEHCleanup, a0, a1, a2); - } - }; - /// ConditionalCleanupN stores the saved form of its N parameters, /// then restores them and performs the cleanup. template <class T, class A0> @@ -242,7 +208,7 @@ public: void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); - T::Emit(CGF, IsForEHCleanup, a0); + T(a0).Emit(CGF, IsForEHCleanup); } public: @@ -260,7 +226,7 @@ public: void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved); - T::Emit(CGF, IsForEHCleanup, a0, a1); + T(a0, a1).Emit(CGF, IsForEHCleanup); } public: @@ -281,12 +247,12 @@ public: A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved); A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved); A2 a2 = DominatingValue<A2>::restore(CGF, a2_saved); - T::Emit(CGF, IsForEHCleanup, a0, a1, a2); + T(a0, a1, a2).Emit(CGF, IsForEHCleanup); } public: ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2) - : a0_saved(a0), a1_saved(a1), a2_saved(a2) {} + : a0_saved(a0), a1_saved(a1), a2_saved(a2) {} }; private: @@ -696,10 +662,8 @@ public: void pushFullExprCleanup(CleanupKind kind, A0 a0) { // If we're not in a conditional branch, or if none of the // arguments requires saving, then use the unconditional cleanup. - if (!isInConditionalBranch()) { - typedef EHScopeStack::UnconditionalCleanup1<T, A0> CleanupType; - return EHStack.pushCleanup<CleanupType>(kind, a0); - } + if (!isInConditionalBranch()) + return EHStack.pushCleanup<T>(kind, a0); typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0); @@ -715,10 +679,8 @@ public: void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1) { // If we're not in a conditional branch, or if none of the // arguments requires saving, then use the unconditional cleanup. - if (!isInConditionalBranch()) { - typedef EHScopeStack::UnconditionalCleanup2<T, A0, A1> CleanupType; - return EHStack.pushCleanup<CleanupType>(kind, a0, a1); - } + if (!isInConditionalBranch()) + return EHStack.pushCleanup<T>(kind, a0, a1); typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0); typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1); @@ -736,8 +698,7 @@ public: // If we're not in a conditional branch, or if none of the // arguments requires saving, then use the unconditional cleanup. if (!isInConditionalBranch()) { - typedef EHScopeStack::UnconditionalCleanup3<T, A0, A1, A2> CleanupType; - return EHStack.pushCleanup<CleanupType>(kind, a0, a1, a2); + return EHStack.pushCleanup<T>(kind, a0, a1, a2); } typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0); |