r352687 - [CodeGenObjC] Handle exceptions when calling objc_alloc or objc_allocWithZone

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Wed Jan 30 15:17:38 PST 2019


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}}




More information about the cfe-commits mailing list