Skip to content

Commit a357cb9

Browse files
triplefngreweDavid Chisnall
authored
tests: Test that we can throw and catch the same exception multiple times sequentially. (#188)
This originally came up as an issue with libc++abi support (#152), but is not specific to that ABI. * Use the C++ runtime to check for uncaught C++ exceptions. As discussed in #152, use the function defined in the Itanium C++ ABI to check whether the thrown exception is the current caught C++ exception and needs rethrowing via `__cxa_rethrow()`. Co-authored-by: Niels Grewe <grewe@ocean-insights.com> Co-authored-by: David Chisnall <gnustep@theravensnest.org>
1 parent 14619f2 commit a357cb9

File tree

3 files changed

+45
-8
lines changed

3 files changed

+45
-8
lines changed

Test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ addtest_variants("CXXExceptions" "CXXException.m;CXXException.cc" true)
143143
addtest_variants("ForwardDeclareProtocolAccess" "ForwardDeclareProtocolAccess.m;ForwardDeclareProtocol.m" true)
144144
if (ENABLE_OBJCXX)
145145
addtest_variants(ObjCXXEHInterop "ObjCXXEHInterop.mm;ObjCXXEHInterop.m" true)
146+
addtest_variants(ObjCXXEHInteropTwice "ObjCXXEHInteropTwice.mm" true)
146147
# This test is failing on Win32, but not for any obvious reason. Disable
147148
# it for now to keep CI happy.
148149
if (WIN32)

Test/ObjCXXEHInteropTwice.mm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#import "Test.h"
2+
3+
#import "stdio.h"
4+
5+
6+
void excerciseExceptionCXX(Test *e) {
7+
@try {
8+
printf("Raising Test\n");
9+
@throw e;
10+
} @catch (Test *localException) {
11+
printf("Caught\n");
12+
}
13+
}
14+
15+
int main(void)
16+
{
17+
Test *e = [Test new];
18+
excerciseExceptionCXX(e);
19+
excerciseExceptionCXX(e);
20+
[e release];
21+
}
22+

eh_personality.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,32 @@
2121
#endif
2222

2323
void test_cxx_eh_implementation();
24+
/**
25+
* The Itanium C++ public structure for in-flight exception status.
26+
*/
27+
struct __cxa_eh_globals
28+
{
29+
/**
30+
* The head exception object. By convention, this is actually the end of
31+
* the `__cxa_exception` structure and points to the address of the thrown
32+
* object. This is either an `id*` or a pointer to a C++ type that we're
33+
* not going to look at.
34+
*/
35+
struct __cxa_exception *caughtExceptions;
36+
/**
37+
* The number of in-flight exceptions thrown.
38+
*/
39+
unsigned int uncaughtExceptions;
40+
};
41+
2442

2543
// Weak references to C++ runtime functions. We don't bother testing that
2644
// these are 0 before calling them, because if they are not resolved then we
2745
// should not be in a code path that involves a C++ exception.
2846
__attribute__((weak)) void *__cxa_begin_catch(void *e);
2947
__attribute__((weak)) void __cxa_end_catch(void);
3048
__attribute__((weak)) void __cxa_rethrow(void);
49+
__attribute__((weak)) struct __cxa_eh_globals *__cxa_get_globals(void);
3150

3251

3352
/**
@@ -93,7 +112,6 @@ enum exception_type
93112
struct thread_data
94113
{
95114
enum exception_type current_exception_type;
96-
id lastThrownObject;
97115
BOOL cxxCaughtException;
98116
struct objc_exception *caughtExceptions;
99117
};
@@ -202,12 +220,9 @@ void objc_exception_throw(id object)
202220
// cases.
203221
if (td->cxxCaughtException)
204222
{
205-
// For catchalls, we may result in our being passed the pointer to the
206-
// object, not the object.
207-
if ((object == td->lastThrownObject) ||
208-
((object != nil) &&
209-
!isSmallObject(object) &&
210-
(*(id*)object == td->lastThrownObject)))
223+
struct __cxa_eh_globals *globals = __cxa_get_globals();
224+
if ((globals->caughtExceptions != NULL) &&
225+
(*(id*)globals->caughtExceptions == object))
211226
{
212227
__cxa_rethrow();
213228
}
@@ -233,7 +248,6 @@ void objc_exception_throw(id object)
233248

234249
ex->object = object;
235250

236-
td->lastThrownObject = object;
237251
td->cxxCaughtException = NO;
238252

239253
_Unwind_Reason_Code err = _Unwind_RaiseException(&ex->unwindHeader);

0 commit comments

Comments
 (0)