aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/CGObjC.cpp24
-rw-r--r--lib/CodeGen/CGObjCGNU.cpp2
-rw-r--r--lib/CodeGen/CGObjCMac.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.h2
4 files changed, 29 insertions, 3 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) {
diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp
index c948c3270e..6bdc519a26 100644
--- a/lib/CodeGen/CGObjCGNU.cpp
+++ b/lib/CodeGen/CGObjCGNU.cpp
@@ -2277,7 +2277,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
llvm::Value *ExceptionAsObject;
if (const Expr *ThrowExpr = S.getThrowExpr()) {
- llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
+ llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
ExceptionAsObject = Exception;
} else {
assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index d6eeba292a..1b317c45f2 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -3204,7 +3204,7 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
llvm::Value *ExceptionAsObject;
if (const Expr *ThrowExpr = S.getThrowExpr()) {
- llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
+ llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
ExceptionAsObject =
CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
} else {
@@ -6002,7 +6002,7 @@ void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
const ObjCAtThrowStmt &S) {
if (const Expr *ThrowExpr = S.getThrowExpr()) {
- llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
+ llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
CGF.EmitCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception)
.setDoesNotReturn();
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 19541a9767..0f120923d6 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -2141,6 +2141,8 @@ public:
std::pair<LValue,llvm::Value*>
EmitARCStoreStrong(const BinaryOperator *e, bool ignored);
+ llvm::Value *EmitObjCThrowOperand(const Expr *expr);
+
llvm::Value *EmitObjCProduceObject(QualType T, llvm::Value *Ptr);
llvm::Value *EmitObjCConsumeObject(QualType T, llvm::Value *Ptr);
llvm::Value *EmitObjCExtendObjectLifetime(QualType T, llvm::Value *Ptr);