aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenFunction.h
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-06-22 16:12:01 +0000
committerDouglas Gregor <dgregor@apple.com>2011-06-22 16:12:01 +0000
commitd7b23167763f43d3e76b0de26141b1e52613ee3c (patch)
tree71644c427688cfee6c871d4b65502cb81fbe0964 /lib/CodeGen/CodeGenFunction.h
parentb4b7b5034bb8304ed03416635bf64c75c39889fc (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.h57
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,