[clang] Objective C: use C++ exceptions on MinGW+GNUstep (PR #77255)
Frederik Carlier via cfe-commits
cfe-commits at lists.llvm.org
Sun Jan 7 13:37:32 PST 2024
https://github.com/qmfrederik updated https://github.com/llvm/llvm-project/pull/77255
>From 4212c79b5bb9168ae741b05b2c3388aa23e38693 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..c29f7483715d88
--- /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;
+ }
+}
\ No newline at end of file
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