summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Pilkington <erik.pilkington@gmail.com>2019-01-30 23:17:38 +0000
committerErik Pilkington <erik.pilkington@gmail.com>2019-01-30 23:17:38 +0000
commitd006280585434ee43aa8c9c3e9b5588a68105279 (patch)
treece910ef8507c2881dd74d103f47e88c14acab92d
parentfb3023497a11e4dc7d1c032dfc13dabd28791781 (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@352687 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGObjC.cpp29
-rw-r--r--test/CodeGenObjC/convert-messages-to-runtime-calls.m29
2 files changed, 39 insertions, 19 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 3e64080e7b..9a212969f4 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -2022,7 +2022,8 @@ static llvm::Value *emitObjCValueOperation(CodeGenFunction &CGF,
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 *emitObjCValueOperation(CodeGenFunction &CGF,
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::EmitObjCAlloc(llvm::Value *value,
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::EmitObjCAllocWithZone(llvm::Value *value,
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::emitARCIntrinsicUse(CodeGenFunction &CGF, Address addr,
/// 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.
diff --git a/test/CodeGenObjC/convert-messages-to-runtime-calls.m b/test/CodeGenObjC/convert-messages-to-runtime-calls.m
index 8ce024fe80..39a26475ea 100644
--- a/test/CodeGenObjC/convert-messages-to-runtime-calls.m
+++ b/test/CodeGenObjC/convert-messages-to-runtime-calls.m
@@ -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}}