Skip to content

Commit 9ede4ec

Browse files
committed
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.
1 parent b8dca4f commit 9ede4ec

File tree

5 files changed

+87
-18
lines changed

5 files changed

+87
-18
lines changed

clang/lib/CodeGen/CGException.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,9 @@ static const EHPersonality &getObjCPersonality(const TargetInfo &Target,
156156
case ObjCRuntime::WatchOS:
157157
return EHPersonality::NeXT_ObjC;
158158
case ObjCRuntime::GNUstep:
159-
if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
159+
if (T.isOSCygMing())
160+
return EHPersonality::GNU_CPlusPlus_SEH;
161+
else if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
160162
return EHPersonality::GNUstep_ObjC;
161163
[[fallthrough]];
162164
case ObjCRuntime::GCC:
@@ -210,7 +212,8 @@ static const EHPersonality &getObjCXXPersonality(const TargetInfo &Target,
210212
return getObjCPersonality(Target, L);
211213

212214
case ObjCRuntime::GNUstep:
213-
return EHPersonality::GNU_ObjCXX;
215+
return Target.getTriple().isOSCygMing() ? EHPersonality::GNU_CPlusPlus_SEH
216+
: EHPersonality::GNU_ObjCXX;
214217

215218
// The GCC runtime's personality function inherently doesn't support
216219
// mixed EH. Use the ObjC personality just to avoid returning null.

clang/lib/CodeGen/CGObjCGNU.cpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,8 @@ class CGObjCGNU : public CGObjCRuntime {
168168
/// Does the current target use SEH-based exceptions? False implies
169169
/// Itanium-style DWARF unwinding.
170170
bool usesSEHExceptions;
171+
/// Does the current target uses C++-based exceptions?
172+
bool usesCxxExceptions;
171173

172174
/// Helper to check if we are targeting a specific runtime version or later.
173175
bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) {
@@ -819,12 +821,18 @@ class CGObjCGNUstep : public CGObjCGNU {
819821
SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
820822
PtrToObjCSuperTy, SelectorTy);
821823
// If we're in ObjC++ mode, then we want to make
822-
if (usesSEHExceptions) {
823-
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
824-
// void objc_exception_rethrow(void)
825-
ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
824+
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
825+
if (usesCxxExceptions) {
826+
// void *__cxa_begin_catch(void *e)
827+
EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
828+
// void __cxa_end_catch(void)
829+
ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy);
830+
// void objc_exception_rethrow(void*)
831+
ExceptionReThrowFn.init(&CGM, "__cxa_rethrow", PtrTy);
832+
} else if (usesSEHExceptions) {
833+
// void objc_exception_rethrow(void)
834+
ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
826835
} else if (CGM.getLangOpts().CPlusPlus) {
827-
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
828836
// void *__cxa_begin_catch(void *e)
829837
EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
830838
// void __cxa_end_catch(void)
@@ -833,15 +841,13 @@ class CGObjCGNUstep : public CGObjCGNU {
833841
ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy,
834842
PtrTy);
835843
} else if (R.getVersion() >= VersionTuple(1, 7)) {
836-
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
837844
// id objc_begin_catch(void *e)
838845
EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy);
839846
// void objc_end_catch(void)
840847
ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy);
841848
// void _Unwind_Resume_or_Rethrow(void*)
842849
ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, PtrTy);
843850
}
844-
llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
845851
SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy,
846852
SelectorTy, IdTy, PtrDiffTy);
847853
SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy,
@@ -2126,6 +2132,9 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
21262132
msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
21272133
usesSEHExceptions =
21282134
cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
2135+
usesCxxExceptions =
2136+
cgm.getContext().getTargetInfo().getTriple().isOSCygMing() &&
2137+
isRuntime(ObjCRuntime::GNUstep, 2);
21292138

21302139
CodeGenTypes &Types = CGM.getTypes();
21312140
IntTy = cast<llvm::IntegerType>(
@@ -2212,7 +2221,10 @@ CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
22122221

22132222
// void objc_exception_throw(id);
22142223
ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
2215-
ExceptionReThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
2224+
ExceptionReThrowFn.init(&CGM,
2225+
usesCxxExceptions ? "objc_exception_rethrow"
2226+
: "objc_exception_throw",
2227+
VoidTy, IdTy);
22162228
// int objc_sync_enter(id);
22172229
SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy);
22182230
// int objc_sync_exit(id);
@@ -2389,7 +2401,7 @@ llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
23892401
if (usesSEHExceptions)
23902402
return CGM.getCXXABI().getAddrOfRTTIDescriptor(T);
23912403

2392-
if (!CGM.getLangOpts().CPlusPlus)
2404+
if (!CGM.getLangOpts().CPlusPlus && !usesCxxExceptions)
23932405
return CGObjCGNU::GetEHType(T);
23942406

23952407
// For Objective-C++, we want to provide the ability to catch both C++ and
@@ -3995,7 +4007,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
39954007
ExceptionAsObject = CGF.ObjCEHValueStack.back();
39964008
isRethrow = true;
39974009
}
3998-
if (isRethrow && usesSEHExceptions) {
4010+
if (isRethrow && (usesSEHExceptions || usesCxxExceptions)) {
39994011
// For SEH, ExceptionAsObject may be undef, because the catch handler is
40004012
// not passed it for catchalls and so it is not visible to the catch
40014013
// funclet. The real thrown object will still be live on the stack at this
@@ -4005,8 +4017,7 @@ void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
40054017
// argument.
40064018
llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn);
40074019
Throw->setDoesNotReturn();
4008-
}
4009-
else {
4020+
} else {
40104021
ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
40114022
llvm::CallBase *Throw =
40124023
CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s
2+
// RUN: FileCheck --check-prefixes=CHECK-MINGW-OBJC2 < %t %s
3+
4+
// RUN: %clang_cc1 -triple x86_64-w64-windows-gnu -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s
5+
// RUN: FileCheck --check-prefixes=CHECK-MINGW-GCC < %t %s
6+
7+
// RUN: %clang_cc1 -triple x86_64-w64-windows-msvc -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s
8+
// RUN: FileCheck --check-prefixes=CHECK-MSVC-OBJC2 < %t %s
9+
10+
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -o %t %s
11+
// RUN: FileCheck --check-prefixes=CHECK-LINUX-OBJC2 < %t %s
12+
13+
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -emit-llvm -fobjc-runtime=gcc -fexceptions -fobjc-exceptions -o %t %s
14+
// RUN: FileCheck --check-prefixes=CHECK-LINUX-GCC < %t %s
15+
@interface Foo @end
16+
17+
void throwing(void) {
18+
@try
19+
{
20+
// CHECK-MINGW-OBJC2: personality ptr @__gxx_personality_seh0
21+
// CHECK-MINGW-OBJC2: invoke void @objc_exception_throw
22+
23+
// CHECK-MINGW-GCC: personality ptr @__gnu_objc_personality_v0
24+
// CHECK-MINGW-GCC: invoke void @objc_exception_throw
25+
26+
// CHECK-MSVC-OBJC2: personality ptr @__CxxFrameHandler3
27+
// CHECK-MSVC-OBJC2: invoke void @objc_exception_throw
28+
29+
// CHECK-LINUX-OBJC2: personality ptr @__gnustep_objc_personality_v0
30+
// CHECK-LINUX-OBJC2: invoke void @objc_exception_throw
31+
32+
// CHECK-LINUX-GCC: personality ptr @__gnu_objc_personality_v0
33+
@throw(@"error!");
34+
}
35+
@catch(...)
36+
{
37+
// CHECK-MINGW-OBJC2: call ptr @__cxa_begin_catch
38+
// CHECK-MINGW-OBJC2: invoke ptr @__cxa_rethrow
39+
// CHECK-MINGW-OBJC2: invoke void @__cxa_end_catch
40+
41+
// CHECK-MINGW-GCC: call void @objc_exception_throw
42+
43+
// CHECK-MSVC-OBJC2: call void @objc_exception_rethrow
44+
45+
// CHECK-LINUX-OBJC2: call ptr @objc_begin_catch
46+
// CHECK-LINUX-OBJC2: invoke void @objc_exception_throw
47+
// CHECK-LINUX-OBJC2: invoke void @objc_end_catch()
48+
49+
// CHECK-LINUX-GCC: invoke void @objc_exception_throw
50+
51+
@throw;
52+
}
53+
}

clang/test/CodeGenObjC/personality.m

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@
2727
// 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
2828
// 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
2929
// 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
30-
// 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
31-
// 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
30+
// 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
31+
// 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
3232
// 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
3333
// 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
3434
// 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 @@
5050
// CHECK-OBJFW-SJLJ: personality ptr @__gnu_objc_personality_sj0
5151

5252
// CHECK-WIN-MSVC: personality ptr @__CxxFrameHandler3
53+
// CHECK-WIN-GNU: personality ptr @__gxx_personality_seh0
5354

5455
// CHECK-MACOSX-FRAGILE-MINGW-DWARF: personality ptr @__gcc_personality_v0
5556
// CHECK-MACOSX-FRAGILE-MINGW-SEH: personality ptr @__gcc_personality_seh0

clang/test/CodeGenObjCXX/personality.mm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@
5050
// 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
5151
// 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
5252
// 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
53-
// 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
54-
// 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
53+
// 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
54+
// 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
5555
// 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
5656
// 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
5757
// 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;
8181
// CHECK-OBJFW-SJLJ: personality ptr @__gnu_objc_personality_sj0
8282

8383
// CHECK-WIN-MSVC: personality ptr @__CxxFrameHandler3
84+
// CHECK-WIN-GNU: personality ptr @__gxx_personality_seh0
8485

8586
void f(void) {
8687
@try {

0 commit comments

Comments
 (0)