diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-06-22 16:12:01 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-06-22 16:12:01 +0000 |
commit | d7b23167763f43d3e76b0de26141b1e52613ee3c (patch) | |
tree | 71644c427688cfee6c871d4b65502cb81fbe0964 /lib/CodeGen/CodeGenFunction.h | |
parent | b4b7b5034bb8304ed03416635bf64c75c39889fc (diff) |
When binding a reference to an Automatic Reference Counting temporary,
retain/release the temporary object appropriately. Previously, we
would only perform the retain/release operations when the reference
would extend the lifetime of the temporary, but this does the wrong
thing across calls.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133620 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 57 |
1 files changed, 55 insertions, 2 deletions
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 1aaa700f7e..0b24525029 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -223,6 +223,16 @@ public: } }; + 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> @@ -258,6 +268,27 @@ public: : a0_saved(a0), a1_saved(a1) {} }; + template <class T, class A0, class A1, class A2> + class ConditionalCleanup3 : public Cleanup { + typedef typename DominatingValue<A0>::saved_type A0_saved; + typedef typename DominatingValue<A1>::saved_type A1_saved; + typedef typename DominatingValue<A2>::saved_type A2_saved; + A0_saved a0_saved; + A1_saved a1_saved; + A2_saved a2_saved; + + void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { + 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); + } + + public: + ConditionalCleanup3(A0_saved a0, A1_saved a1, A2_saved a2) + : a0_saved(a0), a1_saved(a1), a2_saved(a2) {} + }; + private: // The implementation for this class is in CGException.h and // CGException.cpp; the definition is here because it's used as a @@ -697,6 +728,27 @@ public: initFullExprCleanup(); } + /// pushFullExprCleanup - Push a cleanup to be run at the end of the + /// current full-expression. Safe against the possibility that + /// we're currently inside a conditionally-evaluated expression. + template <class T, class A0, class A1, class A2> + void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1, A2 a2) { + // 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); + } + + typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0); + typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1); + typename DominatingValue<A2>::saved_type a2_saved = saveValueInCond(a2); + + typedef EHScopeStack::ConditionalCleanup3<T, A0, A1, A2> CleanupType; + EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved, a2_saved); + initFullExprCleanup(); + } + /// PushDestructorCleanup - Push a cleanup to call the /// complete-object destructor of an object of the given type at the /// given address. Does nothing if T is not a C++ class type with a @@ -2036,9 +2088,10 @@ public: llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr); void PushARCReleaseCleanup(CleanupKind kind, QualType type, - llvm::Value *addr, bool precise); + llvm::Value *addr, bool precise, + bool forFullExpr = false); void PushARCWeakReleaseCleanup(CleanupKind kind, QualType type, - llvm::Value *addr); + llvm::Value *addr, bool forFullExpr = false); void PushARCFieldReleaseCleanup(CleanupKind cleanupKind, const FieldDecl *Field); void PushARCFieldWeakReleaseCleanup(CleanupKind cleanupKind, |