]> granicus.if.org Git - clang/commitdiff
Call objc_terminate() instead of abort() when a cleanup throws an
authorJohn McCall <rjmccall@apple.com>
Wed, 6 Jul 2011 01:22:26 +0000 (01:22 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 6 Jul 2011 01:22:26 +0000 (01:22 +0000)
exception in Objective-C;  in Objective-C++ we still use std::terminate().
This is only available in very recent runtimes.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134456 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Driver/CC1Options.td
include/clang/Driver/ObjCRuntime.h
include/clang/Frontend/CodeGenOptions.h
lib/CodeGen/CGException.cpp
lib/Driver/ToolChain.cpp
lib/Driver/ToolChains.cpp
lib/Driver/Tools.cpp
lib/Frontend/CompilerInvocation.cpp
test/CodeGenObjC/terminate.m [new file with mode: 0644]

index aab0213b9520065b7c9e67147aaadf7573a88f44..6f38ea519947fa55cb07611a008510f32b165d18 100644 (file)
@@ -500,6 +500,8 @@ def fobjc_runtime_has_arc : Flag<"-fobjc-runtime-has-arc">,
   HelpText<"The target Objective-C runtime provides ARC entrypoints">;
 def fobjc_runtime_has_weak : Flag<"-fobjc-runtime-has-weak">,
   HelpText<"The target Objective-C runtime supports ARC weak operations">;
+def fobjc_runtime_has_terminate : Flag<"-fobjc-runtime-has-terminate">,
+  HelpText<"The target Objective-C runtime provides an objc_terminate entrypoint">;
 def fobjc_gc : Flag<"-fobjc-gc">,
   HelpText<"Enable Objective-C garbage collection">;
 def fobjc_gc_only : Flag<"-fobjc-gc-only">,
index 241354f15e89d3981a2f98b59fe002bb061207cd..55164604338db83d38e1d9e3d1c505933d665bee 100644 (file)
@@ -30,7 +30,14 @@ public:
   /// True if the runtime supports ARC zeroing __weak.
   unsigned HasWeak : 1;
 
-  ObjCRuntime() : RuntimeKind(NeXT), HasARC(false), HasWeak(false) {}
+  /// True if the runtime provides the following entrypoint:
+  ///   void objc_terminate(void);
+  /// If available, this will be called instead of abort() when an
+  /// exception is thrown out of an EH cleanup.
+  unsigned HasTerminate : 1;
+
+  ObjCRuntime() : RuntimeKind(NeXT), HasARC(false), HasWeak(false),
+    HasTerminate(false) {}
 };
 
 }
index d415d0a889a4be600e9048b7f7f2e16ad9341455..5d040b4f266cc04ff806cca3e8c919b92831001e 100644 (file)
@@ -77,6 +77,7 @@ public:
   unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss
   unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use.
   unsigned ObjCRuntimeHasARC : 1; /// The target runtime supports ARC natively
+  unsigned ObjCRuntimeHasTerminate : 1; /// The ObjC runtime has objc_terminate
   unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is
                                      /// enabled.
   unsigned OptimizationLevel : 3; /// The -O[0-4] option specified.
@@ -141,7 +142,6 @@ public:
 public:
   CodeGenOptions() {
     AsmVerbose = 0;
-    ObjCAutoRefCountExceptions = 0;
     CXAAtExit = 1;
     CXXCtorDtorAliases = 0;
     DataSections = 0;
@@ -168,7 +168,10 @@ public:
     NoNaNsFPMath = 0;
     NoZeroInitializedInBSS = 0;
     NumRegisterParameters = 0;
+    ObjCAutoRefCountExceptions = 0;
     ObjCDispatchMethod = Legacy;
+    ObjCRuntimeHasARC = 0;
+    ObjCRuntimeHasTerminate = 0;
     OmitLeafFramePointer = 0;
     OptimizationLevel = 0;
     OptimizeSize = 0;
index 1a4a5f988a5818527a4ab45d111f452c72305ca6..af54f396868d4177623ce48d86e296db5260b4da 100644 (file)
@@ -137,8 +137,17 @@ static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) {
     llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 
                             /*IsVarArgs=*/false);
 
-  return CGF.CGM.CreateRuntimeFunction(FTy, 
-      CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort");
+  llvm::StringRef name;
+
+  // In C++, use std::terminate().
+  if (CGF.getLangOptions().CPlusPlus)
+    name = "_ZSt9terminatev"; // FIXME: mangling!
+  else if (CGF.getLangOptions().ObjC1 &&
+           CGF.CGM.getCodeGenOpts().ObjCRuntimeHasTerminate)
+    name = "objc_terminate";
+  else
+    name = "abort";
+  return CGF.CGM.CreateRuntimeFunction(FTy, name);
 }
 
 static llvm::Constant *getCatchallRethrowFn(CodeGenFunction &CGF,
index 0cce5175492943afc872e8bed01593b844b139e0..74b65918f34fa039daa2baca0b107c7583a6d5dd 100644 (file)
@@ -55,12 +55,14 @@ void ToolChain::configureObjCRuntime(ObjCRuntime &runtime) const {
     // Assume a minimal NeXT runtime.
     runtime.HasARC = false;
     runtime.HasWeak = false;
+    runtime.HasTerminate = false;
     return;
 
   case ObjCRuntime::GNU:
     // Assume a maximal GNU runtime.
     runtime.HasARC = true;
     runtime.HasWeak = true;
+    runtime.HasTerminate = false; // to be added
     return;
   }
   llvm_unreachable("invalid runtime kind!");
index 68ebc1b6b35776db16b1407466e137f442d80792..1619ef8f84a96b155b27753fa610e0a7c7111959 100644 (file)
@@ -99,6 +99,13 @@ void Darwin::configureObjCRuntime(ObjCRuntime &runtime) const {
     return ToolChain::configureObjCRuntime(runtime);
 
   runtime.HasARC = runtime.HasWeak = hasARCRuntime();
+
+  // So far, objc_terminate is only available in iOS 5.
+  // FIXME: do the simulator logic properly.
+  if (!ARCRuntimeForSimulator && isTargetIPhoneOS())
+    runtime.HasTerminate = !isIPhoneOSVersionLT(5);
+  else
+    runtime.HasTerminate = false;
 }
 
 // FIXME: Can we tablegen this?
index d0fd914bf0dcefef728a6d2f8ad821bf57e239bf..d4d41d28d53eb1cfdefef56053ca951b7e69aa0a 100644 (file)
@@ -1781,6 +1781,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
       CmdArgs.push_back("-fobjc-runtime-has-arc");
     if (objCRuntime.HasWeak)
       CmdArgs.push_back("-fobjc-runtime-has-weak");
+    if (objCRuntime.HasTerminate)
+      CmdArgs.push_back("-fobjc-runtime-has-terminate");
 
     // Compute the Objective-C ABI "version" to use. Version numbers are
     // slightly confusing for historical reasons:
index 31c86432b754053ba29f425036dc169725f49383..fd57f59e641fa5be8eb90f3ad52833174da148c6 100644 (file)
@@ -125,6 +125,8 @@ static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
   }
   if (Opts.ObjCRuntimeHasARC)
     Res.push_back("-fobjc-runtime-has-arc");
+  if (Opts.ObjCRuntimeHasTerminate)
+    Res.push_back("-fobjc-runtime-has-terminate");
   if (Opts.EmitGcovArcs)
     Res.push_back("-femit-coverage-data");
   if (Opts.EmitGcovNotes)
@@ -979,6 +981,7 @@ static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
   Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
   Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
   Opts.ObjCRuntimeHasARC = Args.hasArg(OPT_fobjc_runtime_has_arc);
+  Opts.ObjCRuntimeHasTerminate = Args.hasArg(OPT_fobjc_runtime_has_terminate);
   Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
   Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
   Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
diff --git a/test/CodeGenObjC/terminate.m b/test/CodeGenObjC/terminate.m
new file mode 100644 (file)
index 0000000..f04eb6a
--- /dev/null
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -fobjc-runtime-has-terminate -o - %s | FileCheck %s -check-prefix=CHECK-WITH
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -o - %s | FileCheck %s -check-prefix=CHECK-WITHOUT
+
+void destroy(void**);
+
+// rdar://problem/9519113
+void test0(void) {
+  void test0_helper(void);
+  void *ptr __attribute__((cleanup(destroy)));
+  test0_helper();
+
+  // CHECK-WITH:       define void @test0()
+  // CHECK-WITH:         [[PTR:%.*]] = alloca i8*,
+  // CHECK-WITH:         call void @destroy(i8** [[PTR]])
+  // CHECK-WITH-NEXT:    ret void
+  // CHECK-WITH:         invoke void @destroy(i8** [[PTR]])
+  // CHECK-WITH:         call i8* @llvm.eh.exception()
+  // CHECK-WITH-NEXT:    @llvm.eh.selector
+  // CHECK-WITH-NEXT:    call void @objc_terminate()
+
+  // CHECK-WITHOUT:    define void @test0()
+  // CHECK-WITHOUT:      [[PTR:%.*]] = alloca i8*,
+  // CHECK-WITHOUT:      call void @destroy(i8** [[PTR]])
+  // CHECK-WITHOUT-NEXT: ret void
+  // CHECK-WITHOUT:      invoke void @destroy(i8** [[PTR]])
+  // CHECK-WITHOUT:      call i8* @llvm.eh.exception()
+  // CHECK-WITHOUT-NEXT: @llvm.eh.selector
+  // CHECK-WITHOUT-NEXT: call void @abort()
+}