2222
2323void  test_cxx_eh_implementation ();
2424
25+ // Weak references to C++ runtime functions.  We don't bother testing that 
26+ // these are 0 before calling them, because if they are not resolved then we 
27+ // should not be in a code path that involves a C++ exception. 
28+ __attribute__((weak )) void  * __cxa_begin_catch (void  * e );
29+ __attribute__((weak )) void  __cxa_end_catch (void );
30+ __attribute__((weak )) void  __cxa_rethrow (void );
31+ 
2532
2633/** 
2734 * Class of exceptions to distinguish between this and other exception types. 
@@ -75,6 +82,35 @@ typedef enum
7582	handler_class 
7683} handler_type ;
7784
85+ enum  exception_type 
86+ {
87+ 	NONE ,
88+ 	CXX ,
89+ 	OBJC ,
90+ 	FOREIGN ,
91+ 	BOXED_FOREIGN 
92+ };
93+ struct  thread_data 
94+ {
95+ 	enum  exception_type  current_exception_type ;
96+ 	id  lastThrownObject ;
97+ 	BOOL  cxxCaughtException ;
98+ 	struct  objc_exception  * caughtExceptions ;
99+ };
100+ 
101+ static  __thread struct  thread_data  thread_data ;
102+ 
103+ static  struct  thread_data  * get_thread_data (void )
104+ {
105+ 	return  & thread_data ;
106+ }
107+ 
108+ static  struct  thread_data  * get_thread_data_fast (void )
109+ {
110+ 	return  & thread_data ;
111+ }
112+ 
113+ 
78114/** 
79115 * Saves the result of the landing pad that we have found.  For ARM, this is 
80116 * stored in the generic unwind structure, while on other platforms it is 
@@ -147,13 +183,35 @@ static void cleanup(_Unwind_Reason_Code reason, struct _Unwind_Exception *e)
147183					unwindHeader))); 
148184					*/ 
149185}
186+ 
187+ void  objc_exception_rethrow (struct  _Unwind_Exception  * e );
188+ 
150189/** 
151190 * Throws an Objective-C exception.  This function is, unfortunately, used for 
152191 * rethrowing caught exceptions too, even in @finally() blocks.  Unfortunately, 
153192 * this means that we have some problems if the exception is boxed. 
154193 */ 
155194void  objc_exception_throw (id  object )
156195{
196+ 	struct  thread_data  * td  =  get_thread_data ();
197+ 	fprintf (stderr , "Throwing %p, in flight exception: %p\n" , object , td -> lastThrownObject );
198+ 	fprintf (stderr , "Exception caught by C++: %d\n" , td -> cxxCaughtException );
199+ 	// If C++ caught the exception, then we may need to make C++ rethrow it if 
200+ 	// we want to preserve exception state.  Rethrows should be handled with 
201+ 	// objc_exception_rethrow, but clang appears to do the wrong thing for some 
202+ 	// cases. 
203+ 	if  (td -> cxxCaughtException )
204+ 	{
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 )))
211+ 		{
212+ 			__cxa_rethrow ();
213+ 		}
214+ 	}
157215
158216	SEL  rethrow_sel  =  sel_registerName ("rethrow" );
159217	if  ((nil  !=  object ) && 
@@ -175,6 +233,9 @@ void objc_exception_throw(id object)
175233
176234	ex -> object  =  object ;
177235
236+ 	td -> lastThrownObject  =  object ;
237+ 	td -> cxxCaughtException  =  NO ;
238+ 
178239	_Unwind_Reason_Code  err  =  _Unwind_RaiseException (& ex -> unwindHeader );
179240	free (ex );
180241	if  (_URC_END_OF_STACK  ==  err  &&  0  !=  _objc_unexpected_exception )
@@ -480,6 +541,7 @@ static inline _Unwind_Reason_Code internal_objc_personality(int version,
480541	_Unwind_SetGR (context , __builtin_eh_return_data_regno (1 ), selector );
481542
482543	DEBUG_LOG ("Installing context, selector %d\n" , (int )selector );
544+ 	get_thread_data ()-> cxxCaughtException  =  NO ;
483545	return  _URC_INSTALL_CONTEXT ;
484546}
485547
@@ -513,48 +575,20 @@ BEGIN_PERSONALITY_FUNCTION(__gnustep_objcxx_personality_v0)
513575		int  ret  =  CALL_PERSONALITY_FUNCTION (__gxx_personality_v0 );
514576		exceptionObject -> private_1  =  ex -> cxx_exception -> private_1 ;
515577		exceptionObject -> private_2  =  ex -> cxx_exception -> private_2 ;
578+ 		if  (ret  ==  _URC_INSTALL_CONTEXT )
579+ 		{
580+ 			get_thread_data ()-> cxxCaughtException  =  YES ;
581+ 		}
516582		return  ret ;
517583	}
518584	return  CALL_PERSONALITY_FUNCTION (__gxx_personality_v0 );
519585}
520586
521- // Weak references to C++ runtime functions.  We don't bother testing that 
522- // these are 0 before calling them, because if they are not resolved then we 
523- // should not be in a code path that involves a C++ exception. 
524- __attribute__((weak )) void  * __cxa_begin_catch (void  * e );
525- __attribute__((weak )) void  __cxa_end_catch (void );
526- __attribute__((weak )) void  __cxa_rethrow (void );
527- 
528- enum  exception_type 
529- {
530- 	NONE ,
531- 	CXX ,
532- 	OBJC ,
533- 	FOREIGN ,
534- 	BOXED_FOREIGN 
535- };
536- struct  thread_data 
537- {
538- 	enum  exception_type  current_exception_type ;
539- 	struct  objc_exception  * caughtExceptions ;
540- };
541- 
542- static  __thread struct  thread_data  thread_data ;
543- 
544- static  struct  thread_data  * get_thread_data (void )
545- {
546- 	return  & thread_data ;
547- }
548- 
549- static  struct  thread_data  * get_thread_data_fast (void )
550- {
551- 	return  & thread_data ;
552- }
553- 
554587id  objc_begin_catch (struct  _Unwind_Exception  * exceptionObject )
555588{
556589	struct  thread_data  * td  =  get_thread_data ();
557590	DEBUG_LOG ("Beginning catch %p\n" , exceptionObject );
591+ 	td -> cxxCaughtException  =  NO ;
558592	if  (exceptionObject -> exception_class  ==  objc_exception_class )
559593	{
560594		td -> current_exception_type  =  OBJC ;
0 commit comments