Skip to content

Commit

Permalink
[CodeGenObjC] Handle exceptions when calling objc_alloc or objc_alloc…
Browse files Browse the repository at this point in the history
…WithZone

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

llvm-svn: 352687
  • Loading branch information
epilk committed Jan 30, 2019
1 parent 547a83b commit 1f7eda5
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 19 deletions.
29 changes: 18 additions & 11 deletions clang/lib/CodeGen/CGObjC.cpp
Expand Up @@ -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;

Expand All @@ -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:
Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
29 changes: 21 additions & 8 deletions clang/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

Expand Down Expand Up @@ -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}}
Expand Down

0 comments on commit 1f7eda5

Please sign in to comment.