aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGObjC.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-10-01 10:32:24 +0000
committerJohn McCall <rjmccall@apple.com>2011-10-01 10:32:24 +0000
commit2b014d6c0c6b8ac94b416ac37dfc7931f20777a7 (patch)
tree55e9ed4baa751a871fee8bd1bb9ab62abd8d4be4 /lib/CodeGen/CGObjC.cpp
parentcdda47faab5c2c61c239491a1a091e071ed3e38e (diff)
When performing an @throw in ARC, retain + autorelease
the pointer, being sure to do so before running cleanups associated with that full-expression. rdar://10042689 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140945 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGObjC.cpp')
-rw-r--r--lib/CodeGen/CGObjC.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index d406e3a064..96ab3dcd68 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -2386,6 +2386,30 @@ CodeGenFunction::EmitARCRetainAutoreleaseScalarExpr(const Expr *e) {
return value;
}
+llvm::Value *CodeGenFunction::EmitObjCThrowOperand(const Expr *expr) {
+ // In ARC, retain and autorelease the expression.
+ if (getLangOptions().ObjCAutoRefCount) {
+ // Do so before running any cleanups for the full-expression.
+ // tryEmitARCRetainScalarExpr does make an effort to do things
+ // inside cleanups, but there are crazy cases like
+ // @throw A().foo;
+ // where a full retain+autorelease is required and would
+ // otherwise happen after the destructor for the temporary.
+ CodeGenFunction::RunCleanupsScope cleanups(*this);
+ if (const ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(expr))
+ expr = ewc->getSubExpr();
+
+ return EmitARCRetainAutoreleaseScalarExpr(expr);
+ }
+
+ // Otherwise, use the normal scalar-expression emission. The
+ // exception machinery doesn't do anything special with the
+ // exception like retaining it, so there's no safety associated with
+ // only running cleanups after the throw has started, and when it
+ // matters it tends to be substantially inferior code.
+ return EmitScalarExpr(expr);
+}
+
std::pair<LValue,llvm::Value*>
CodeGenFunction::EmitARCStoreStrong(const BinaryOperator *e,
bool ignored) {