diff options
| author | John McCall <rjmccall@apple.com> | 2011-10-01 10:32:24 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2011-10-01 10:32:24 +0000 |
| commit | 248512a573d6333c40d3fc99fe325960e11e060e (patch) | |
| tree | db6684e0d40d6ec5409b52923e2ae77ab344b56c | |
| parent | a55902bf98a4a0b5929ddd80c4ed8fffb2eb2af3 (diff) | |
| download | bcm5719-llvm-248512a573d6333c40d3fc99fe325960e11e060e.tar.gz bcm5719-llvm-248512a573d6333c40d3fc99fe325960e11e060e.zip | |
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
llvm-svn: 140945
| -rw-r--r-- | clang/lib/CodeGen/CGObjC.cpp | 24 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCGNU.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenObjC/arc-with-atthrow.m | 22 |
5 files changed, 41 insertions, 13 deletions
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index d406e3a0645..96ab3dcd686 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/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/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index c948c3270ee..6bdc519a260 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/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/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index d6eeba292a7..1b317c45f23 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/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/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 19541a97673..0f120923d61 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/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); diff --git a/clang/test/CodeGenObjC/arc-with-atthrow.m b/clang/test/CodeGenObjC/arc-with-atthrow.m index 984bf5582ed..e25ef3e3a08 100644 --- a/clang/test/CodeGenObjC/arc-with-atthrow.m +++ b/clang/test/CodeGenObjC/arc-with-atthrow.m @@ -1,15 +1,17 @@ // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fobjc-nonfragile-abi -fobjc-exceptions -o - %s | FileCheck %s // pr10411 +// rdar://10042689 -@interface NSException -+ (id)exception; -@end - -void test() -{ - @throw [NSException exception]; +id make(void); +void test() { + @throw make(); } -// CHECK: objc_retainAutoreleasedReturnValue -// CHECK: call void @objc_release -// CHECK: call void @objc_exception_throw +// TODO: We should probably emit this specific pattern without the reclaim. + +// CHECK: define void @test() +// CHECK: [[T0:%.*]] = call i8* @make() +// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]]) +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_autorelease(i8* [[T1]]) +// CHECK-NEXT: call void @objc_exception_throw(i8* [[T2]]) noreturn +// CHECK-NEXT: unreachable |

