From c44656ede6261bb1dfebeadf57d3d4bfbd45f0d4 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 30 Oct 2015 00:56:02 +0000 Subject: [PATCH] Initialize @catch variables correctly in fragile-runtime ARC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@251677 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGObjCMac.cpp | 4 ++-- lib/CodeGen/CGObjCRuntime.cpp | 43 ++++++++++++++++++++-------------- lib/CodeGen/CGObjCRuntime.h | 4 ++++ test/CodeGenObjC/fragile-arc.m | 41 ++++++++++++++++++++++++++++++-- 4 files changed, 70 insertions(+), 22 deletions(-) diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index e3cba265ef..830bdb031b 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -4135,7 +4135,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); // These types work out because ConvertType(id) == i8*. - CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam)); + EmitInitOfCatchParam(CGF, Caught, CatchParam); } CGF.EmitStmt(CatchStmt->getCatchBody()); @@ -4182,7 +4182,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::Value *Tmp = CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(CatchParam->getType())); - CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam)); + EmitInitOfCatchParam(CGF, Tmp, CatchParam); CGF.EmitStmt(CatchStmt->getCatchBody()); diff --git a/lib/CodeGen/CGObjCRuntime.cpp b/lib/CodeGen/CGObjCRuntime.cpp index b2ca5c8d0e..7be9ae9960 100644 --- a/lib/CodeGen/CGObjCRuntime.cpp +++ b/lib/CodeGen/CGObjCRuntime.cpp @@ -256,24 +256,7 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType); CGF.EmitAutoVarDecl(*CatchParam); - - Address CatchParamAddr = CGF.GetAddrOfLocalVar(CatchParam); - - switch (CatchParam->getType().getQualifiers().getObjCLifetime()) { - case Qualifiers::OCL_Strong: - CastExn = CGF.EmitARCRetainNonBlock(CastExn); - // fallthrough - - case Qualifiers::OCL_None: - case Qualifiers::OCL_ExplicitNone: - case Qualifiers::OCL_Autoreleasing: - CGF.Builder.CreateStore(CastExn, CatchParamAddr); - break; - - case Qualifiers::OCL_Weak: - CGF.EmitARCInitWeak(CatchParamAddr, CastExn); - break; - } + EmitInitOfCatchParam(CGF, CastExn, CatchParam); } CGF.ObjCEHValueStack.push_back(Exn); @@ -297,6 +280,30 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF, CGF.EmitBlock(Cont.getBlock()); } +void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF, + llvm::Value *exn, + const VarDecl *paramDecl) { + + Address paramAddr = CGF.GetAddrOfLocalVar(paramDecl); + + switch (paramDecl->getType().getQualifiers().getObjCLifetime()) { + case Qualifiers::OCL_Strong: + exn = CGF.EmitARCRetainNonBlock(exn); + // fallthrough + + case Qualifiers::OCL_None: + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + CGF.Builder.CreateStore(exn, paramAddr); + return; + + case Qualifiers::OCL_Weak: + CGF.EmitARCInitWeak(paramAddr, exn); + return; + } + llvm_unreachable("invalid ownership qualifier"); +} + namespace { struct CallSyncExit final : EHScopeStack::Cleanup { llvm::Value *SyncExitFn; diff --git a/lib/CodeGen/CGObjCRuntime.h b/lib/CodeGen/CGObjCRuntime.h index 1632713c32..9b0706770a 100644 --- a/lib/CodeGen/CGObjCRuntime.h +++ b/lib/CodeGen/CGObjCRuntime.h @@ -100,6 +100,10 @@ protected: llvm::Constant *beginCatchFn, llvm::Constant *endCatchFn, llvm::Constant *exceptionRethrowFn); + + void EmitInitOfCatchParam(CodeGenFunction &CGF, llvm::Value *exn, + const VarDecl *paramDecl); + /// Emits an \@synchronize() statement, using the \p syncEnterFn and /// \p syncExitFn arguments as the functions called to lock and unlock /// the object. This function can be called by subclasses that use diff --git a/test/CodeGenObjC/fragile-arc.m b/test/CodeGenObjC/fragile-arc.m index c3a4c088d0..ecb955bd34 100644 --- a/test/CodeGenObjC/fragile-arc.m +++ b/test/CodeGenObjC/fragile-arc.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s -// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s -check-prefix=GLOBALS +// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s -check-prefix=GLOBALS @class Opaque; @@ -136,3 +136,40 @@ void testBlockLayoutStrong(id x) { void testBlockLayoutWeak(__weak id x) { useBlock(^{ (void) x; }); } + +// CHECK-LABEL: define void @testCatch() +// CHECK: [[X:%.*]] = alloca [[A:%.*]]*, align 4 +// CHECK: [[Y:%.*]] = alloca i8*, align 4 +// CHECK: call void @objc_exception_try_enter +// CHECK: br i1 +// CHECK: call void @checkpoint(i32 0) +// CHECK: call void @objc_exception_try_exit +// CHECK: br label +// CHECK: call void @checkpoint(i32 3) +// CHECK: [[EXN:%.*]] = call i8* @objc_exception_extract +// CHECK: call i32 @objc_exception_match( +// CHECK: br i1 +// CHECK: [[T0:%.*]] = bitcast i8* [[EXN]] to [[A]]* +// CHECK: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* +// CHECK: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* +// CHECK: store [[A]]* [[T3]], [[A]]** [[X]] +// CHECK: call void @checkpoint(i32 1) +// CHECK: [[T0:%.*]] = bitcast [[A]]** [[X]] to i8** +// CHECK: call void @objc_storeStrong(i8** [[T0]], i8* null) +// CHECK: br label +// CHECK: [[T0:%.*]] = call i8* @objc_retain(i8* [[EXN]]) +// CHECK: store i8* [[T0]], i8** [[Y]] +// CHECK: call void @checkpoint(i32 2) +// CHECK: call void @objc_storeStrong(i8** [[Y]], i8* null) +extern void checkpoint(int n); +void testCatch() { + @try { + checkpoint(0); + } @catch (A *x) { + checkpoint(1); + } @catch (id y) { + checkpoint(2); + } + checkpoint(3); +} -- 2.40.0