Author: epilk Date: Wed Jan 30 15:17:38 2019 New Revision: 352687 URL: http://llvm.org/viewvc/llvm-project?rev=352687&view=rev Log: [CodeGenObjC] Handle exceptions when calling objc_alloc or objc_allocWithZone
objc_alloc and objc_allocWithZone may throw exceptions if the underlying method does. If we're in a @try block, then make sure we emit an invoke instead of a call. rdar://47610407 Differential revision: https://reviews.llvm.org/D57476 Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=352687&r1=352686&r2=352687&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Wed Jan 30 15:17:38 2019 @@ -2022,7 +2022,8 @@ static llvm::Value *emitObjCValueOperati llvm::Value *value, llvm::Type *returnType, llvm::Constant *&fn, - StringRef fnName) { + StringRef fnName, + bool MayThrow) { if (isa<llvm::ConstantPointerNull>(value)) return value; @@ -2042,10 +2043,14 @@ static llvm::Value *emitObjCValueOperati value = CGF.Builder.CreateBitCast(value, CGF.Int8PtrTy); // Call the function. - llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value); + llvm::CallBase *Inst = nullptr; + if (MayThrow) + Inst = CGF.EmitCallOrInvoke(fn, value); + else + Inst = CGF.EmitNounwindRuntimeCall(fn, value); // Cast the result back to the original type. - return CGF.Builder.CreateBitCast(call, origType); + return CGF.Builder.CreateBitCast(Inst, origType); } /// Produce the code to do a retain. Based on the type, calls one of: @@ -2493,7 +2498,7 @@ llvm::Value *CodeGenFunction::EmitObjCAl llvm::Type *resultType) { return emitObjCValueOperation(*this, value, resultType, CGM.getObjCEntrypoints().objc_alloc, - "objc_alloc"); + "objc_alloc", /*MayThrow=*/true); } /// Allocate the given objc object. @@ -2502,7 +2507,7 @@ llvm::Value *CodeGenFunction::EmitObjCAl llvm::Type *resultType) { return emitObjCValueOperation(*this, value, resultType, CGM.getObjCEntrypoints().objc_allocWithZone, - "objc_allocWithZone"); + "objc_allocWithZone", /*MayThrow=*/true); } /// Produce the code to do a primitive release. @@ -2543,18 +2548,20 @@ void CodeGenFunction::emitARCIntrinsicUs /// call i8* \@objc_autorelease(i8* %value) llvm::Value *CodeGenFunction::EmitObjCAutorelease(llvm::Value *value, llvm::Type *returnType) { - return emitObjCValueOperation(*this, value, returnType, - CGM.getObjCEntrypoints().objc_autoreleaseRuntimeFunction, - "objc_autorelease"); + return emitObjCValueOperation( + *this, value, returnType, + CGM.getObjCEntrypoints().objc_autoreleaseRuntimeFunction, + "objc_autorelease", /*MayThrow=*/false); } /// Retain the given object, with normal retain semantics. /// call i8* \@objc_retain(i8* %value) llvm::Value *CodeGenFunction::EmitObjCRetainNonBlock(llvm::Value *value, llvm::Type *returnType) { - return emitObjCValueOperation(*this, value, returnType, - CGM.getObjCEntrypoints().objc_retainRuntimeFunction, - "objc_retain"); + return emitObjCValueOperation( + *this, value, returnType, + CGM.getObjCEntrypoints().objc_retainRuntimeFunction, "objc_retain", + /*MayThrow=*/false); } /// Release the given object. Modified: cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m?rev=352687&r1=352686&r2=352687&view=diff ============================================================================== --- cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m (original) +++ cfe/trunk/test/CodeGenObjC/convert-messages-to-runtime-calls.m Wed Jan 30 15:17:38 2019 @@ -1,12 +1,12 @@ -// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls | FileCheck %s --check-prefix=MSGS -// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS -// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS -// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS -// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS -// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=MSGS +// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fno-objc-convert-messages-to-runtime-calls -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS +// RUN: %clang_cc1 -fobjc-runtime=macosx-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS +// RUN: %clang_cc1 -fobjc-runtime=macosx-10.9.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS +// RUN: %clang_cc1 -fobjc-runtime=macosx-fragile-10.10.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS +// RUN: %clang_cc1 -fobjc-runtime=ios-8.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS +// RUN: %clang_cc1 -fobjc-runtime=ios-7.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=MSGS // Note: This line below is for tvos for which the driver passes through to use the ios9.0 runtime. -// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS -// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s | FileCheck %s --check-prefix=CALLS +// RUN: %clang_cc1 -fobjc-runtime=ios-9.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS +// RUN: %clang_cc1 -fobjc-runtime=watchos-2.0 -emit-llvm -o - %s -fobjc-exceptions -fexceptions | FileCheck %s --check-prefix=CALLS #define nil (id)0 @@ -38,6 +38,19 @@ void test1(id x) { [x autorelease]; } +// CHECK-LABEL: define {{.*}}void @check_invoke +void check_invoke() { + // MSGS: {{invoke.*@objc_msgSend}} + // MSGS: {{invoke.*@objc_msgSend}} + // CALLS: {{invoke.*@objc_alloc}} + // CALLS: {{invoke.*@objc_allocWithZone}} + @try { + [NSObject alloc]; + [NSObject allocWithZone:nil]; + } @catch (...) { + } +} + // CHECK-LABEL: define {{.*}}void @test2 void test2(void* x) { // MSGS: {{call.*@objc_msgSend}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits