[clang] Objective C: use C++ exceptions on MinGW+GNUstep (PR #77255)

David Chisnall via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 8 00:29:13 PST 2024


https://github.com/davidchisnall updated https://github.com/llvm/llvm-project/pull/77255

>From 6195e6c57b5b461dda2bffec0e5497ceb659f82c Mon Sep 17 00:00:00 2001
From: Frederik Carlier <frederik.carlier at keysight.com>
Date: Thu, 4 Jan 2024 11:10:05 -0800
Subject: [PATCH] Objective C: use C++ exceptions on MinGW+GNUstep

The GNUstep Objective C runtime (libobjc2) is adding support for
MinGW.  This runtime uses C++ exceptions in that configuration.
---
 clang/lib/CodeGen/CGException.cpp             |  9 +++-
 clang/lib/CodeGen/CGObjCGNU.cpp               | 35 ++++++++----
 .../test/CodeGenObjC/exceptions-personality.m | 53 +++++++++++++++++++
 clang/test/CodeGenObjC/personality.m          |  5 +-
 clang/test/CodeGenObjCXX/personality.mm       |  5 +-
 5 files changed, 92 insertions(+), 15 deletions(-)
 create mode 100644 clang/test/CodeGenObjC/exceptions-personality.m

diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp
index 0d507da5c1ba92..cadd6f6ad75daa 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -156,7 +156,9 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target,
   case ObjCRuntime::WatchOS:
     return EHPersonality::NeXT_ObjC;
   case ObjCRuntime::GNUstep:
-    if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
+    if (T.isOSCygMing())
+      return EHPersonality::GNU_CPlusPlus_SEH;
+    else if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
       return EHPersonality::GNUstep_ObjC;
     [[fallthrough]];
   case ObjCRuntime::GCC:
@@ -210,7 +212,10 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target,
     return getObjCPersonality(Target, L);
 
   case ObjCRuntime::GNUstep:
-    return EHPersonality::GNU_ObjCXX;
+    if (Target.getTriple().isOSCygMing())
+      return EHPersonality::GNU_CPlusPlus_SEH;
+    else
+      return EHPersonality::GNU_ObjCXX;
 
   // The GCC runtime's personality function inherently doesn't support
   // mixed EH.  Use the ObjC personality just to avoid returning null.
diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp
index 4ca1a8cce64d89..2b3a5da87fb778 100644
--- a/clang/lib/CodeGen/CGObjCGNU.cpp
+++ b/clang/lib/CodeGen/CGObjCGNU.cpp
@@ -819,10 +819,19 @@ class CGObjCGNUstep : public CGObjCGNU {
       SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
                              PtrToObjCSuperTy, SelectorTy);
       // If we're in ObjC++ mode, then we want to make
-      if (usesSEHExceptions) {
-          llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
-          // void objc_exception_rethrow(void)
-          ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
+      if (CGM.getTarget().getTriple().isOSCygMing() &&
+          isRuntime(ObjCRuntime::GNUstep, 2)) {
+        llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
+        // void *__cxa_begin_catch(void *e)
+        EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
+        // void __cxa_end_catch(void)
+        ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy);
+        // void objc_exception_rethrow(void*)
+        ExceptionReThrowFn.init(&CGM, "__cxa_rethrow", PtrTy);
+      } else if (usesSEHExceptions) {
+        llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
+        // void objc_exception_rethrow(void)
+        ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
       } else if (CGM.getLangOpts().CPlusPlus) {
         llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
         // void *__cxa_begin_catch(void *e)
@@ -2210,7 +2219,12 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
 
   // void objc_exception_throw(id);
   ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
-  ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
+  if ((CGM.getTarget().getTriple().isOSCygMing() &&
+       isRuntime(ObjCRuntime::GNUstep, 2))) {
+    ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, IdTy);
+  } else {
+    ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
+  }
   // int objc_sync_enter(id);
   SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy);
   // int objc_sync_exit(id);
@@ -2387,7 +2401,9 @@ llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
   if (usesSEHExceptions)
     return CGM.getCXXABI().getAddrOfRTTIDescriptor(T);
 
-  if (!CGM.getLangOpts().CPlusPlus)
+  if (!CGM.getLangOpts().CPlusPlus &&
+      !(CGM.getTarget().getTriple().isOSCygMing() &&
+        isRuntime(ObjCRuntime::GNUstep, 2)))
     return CGObjCGNU::GetEHType(T);
 
   // For Objective-C++, we want to provide the ability to catch both C++ and
@@ -3993,7 +4009,9 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
     ExceptionAsObject = CGF.ObjCEHValueStack.back();
     isRethrow = true;
   }
-  if (isRethrow && usesSEHExceptions) {
+  if (isRethrow &&
+      (usesSEHExceptions || (CGM.getTarget().getTriple().isOSCygMing() &&
+                             isRuntime(ObjCRuntime::GNUstep, 2)))) {
     // For SEH, ExceptionAsObject may be undef, because the catch handler is
     // not passed it for catchalls and so it is not visible to the catch
     // funclet.  The real thrown object will still be live on the stack at this
@@ -4003,8 +4021,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
     // argument.
     llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn);
     Throw->setDoesNotReturn();
-  }
-  else {
+  } else {
     ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
     llvm::CallBase *Throw =
         CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
diff --git a/clang/test/CodeGenObjC/exceptions-personality.m b/clang/test/CodeGenObjC/exceptions-personality.m
new file mode 100644
index 00000000000000..9c25ee38b6d7cf
--- /dev/null
+++ b/clang/test/CodeGenObjC/exceptions-personality.m
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu  -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s
+// RUN: FileCheck --check-prefixes=CHECK-MINGW-OBJC2 < %t %s
+
+// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu  -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s
+// RUN: FileCheck --check-prefixes=CHECK-MINGW-GCC < %t %s
+
+// RUN: %clang_cc1 -triple x86_64-w64-windows-msvc  -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s
+// RUN: FileCheck --check-prefixes=CHECK-MSVC-OBJC2 < %t %s
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu  -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s
+// RUN: FileCheck --check-prefixes=CHECK-LINUX-OBJC2 < %t %s
+
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu  -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s
+// RUN: FileCheck --check-prefixes=CHECK-LINUX-GCC < %t %s
+ at interface Foo @end
+
+void throwing(void) {
+  @try
+  {
+    // CHECK-MINGW-OBJC2: personality ptr @__gxx_personality_seh0
+    // CHECK-MINGW-OBJC2: invoke void @objc_exception_throw
+
+    // CHECK-MINGW-GCC: personality ptr @__gnu_objc_personality_v0
+    // CHECK-MINGW-GCC: invoke void @objc_exception_throw
+
+    // CHECK-MSVC-OBJC2: personality ptr @__CxxFrameHandler3
+    // CHECK-MSVC-OBJC2: invoke void @objc_exception_throw
+
+    // CHECK-LINUX-OBJC2: personality ptr @__gnustep_objc_personality_v0
+    // CHECK-LINUX-OBJC2: invoke void @objc_exception_throw
+
+    // CHECK-LINUX-GCC: personality ptr @__gnu_objc_personality_v0
+    @throw(@"error!");
+  }
+  @catch(...) 
+  {
+    // CHECK-MINGW-OBJC2: call ptr @__cxa_begin_catch
+    // CHECK-MINGW-OBJC2: invoke ptr @__cxa_rethrow
+    // CHECK-MINGW-OBJC2: invoke void @__cxa_end_catch
+    
+    // CHECK-MINGW-GCC: call void @objc_exception_throw
+
+    // CHECK-MSVC-OBJC2: call void @objc_exception_rethrow
+
+    // CHECK-LINUX-OBJC2: call ptr @objc_begin_catch
+    // CHECK-LINUX-OBJC2: invoke void @objc_exception_throw
+    // CHECK-LINUX-OBJC2: invoke void @objc_end_catch()
+
+    // CHECK-LINUX-GCC: invoke void @objc_exception_throw
+    
+    @throw;
+  }
+}
diff --git a/clang/test/CodeGenObjC/personality.m b/clang/test/CodeGenObjC/personality.m
index 6ec67ace3f1ac3..ede0aa34eaf625 100644
--- a/clang/test/CodeGenObjC/personality.m
+++ b/clang/test/CodeGenObjC/personality.m
@@ -27,8 +27,8 @@
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=ios -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=macosx -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
-// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
-// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=seh -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=sjlj -fobjc-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SJLJ
@@ -50,6 +50,7 @@
 // CHECK-OBJFW-SJLJ: personality ptr @__gnu_objc_personality_sj0
 
 // CHECK-WIN-MSVC: personality ptr @__CxxFrameHandler3
+// CHECK-WIN-GNU: personality ptr @__gxx_personality_seh0
 
 // CHECK-MACOSX-FRAGILE-MINGW-DWARF: personality ptr @__gcc_personality_v0
 // CHECK-MACOSX-FRAGILE-MINGW-SEH: personality ptr @__gcc_personality_seh0
diff --git a/clang/test/CodeGenObjCXX/personality.mm b/clang/test/CodeGenObjCXX/personality.mm
index c6debe6f60c2a2..b8c7af962bd0bd 100644
--- a/clang/test/CodeGenObjCXX/personality.mm
+++ b/clang/test/CodeGenObjCXX/personality.mm
@@ -50,8 +50,8 @@
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=dwarf -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=seh -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=sjlj -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=watchos -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-NS
-// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP-1_7
-// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GNUSTEP
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep-1.7 -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU
+// RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gnustep -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-WIN-GNU
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=dwarf -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=seh -fobjc-exceptions -fcxx-exceptions -fobjc-runtime=gcc -S -emit-llvm %s -o - | FileCheck %s -check-prefix CHECK-GCC-SEH
@@ -81,6 +81,7 @@ + (void)e:(id)xception;
 // CHECK-OBJFW-SJLJ: personality ptr @__gnu_objc_personality_sj0
 
 // CHECK-WIN-MSVC: personality ptr @__CxxFrameHandler3
+// CHECK-WIN-GNU: personality ptr @__gxx_personality_seh0
 
 void f(void) {
   @try {



More information about the cfe-commits mailing list