This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: C++ EH vs Forced Unwinding, Round 3


On Thu, May 01, 2003 at 09:07:25PM -0700, Richard Henderson wrote:
> Anyway, I guess I'll go ahead with the ABI change, since I bet
> none of you are willing to budge on catch(...).  More to come.

Here's the updated patch.  This being the third time round
the hobby horse, someone else should eyeball it.


r~



gcc/
	* except.c: Revert 04-01 and 04-02 forced-unwind changes.
	* flags.h, toplev.c, doc/invoke.texi: Likewise.

	* unwind-dw2.c (_Unwind_GetCFA): Fix ptr->int conversion warning.
	* unwind.inc (_Unwind_DeleteException): Check for null
	exception_cleanup.

	* unwind-sjlj.c (_Unwind_SjLj_Resume_or_Rethrow): New.
	* unwind.inc (_Unwind_Resume_or_Rethrow): New.
	* unwind.h: Declare them.
	* libgcc-std.ver (GCC_3.3): Export them.

gcc/cp/
	* cfns.gperf: Comment out POSIX thread cancellation points,
	plus abort and raise.
	* cfns.h: Regenerate.

gcc/testsuite/
	* g++.dg/eh/forced1.C: Expect catch-all handlers to run.
	Verify exception_cleanup not called for rethrows.
	* g++.dg/eh/forced2.C: Test that exception_cleanup is called
	when exiting catch block without rethrowing.
	* g++.dg/eh/forced3.C: New.
	* g++.dg/eh/forced4.C: New.

libstdc++-v3/
	* libsupc++/eh_catch.cc (__cxa_begin_catch): Handle foreign exceptions.
	(__cxa_end_catch): Likewise.
	* libsupc++/eh_throw.cc (__cxa_rethrow): Likewise.  Use
	_Unwind_Resume_or_Rethrow.
	* libsupc++/eh_personality.cc (empty_exception_spec): New.
	(PERSONALITY_FUNCTION): Don't ignore terminate or catch-all
	for _UA_FORCE_UNWIND.  Honor empty filter spec for foreign
	exceptions.  Don't push terminate/unexpected to cxa functions.
	(__cxa_call_unexpected): Remove foreign exception fixmes.


Index: gcc/except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/except.c,v
retrieving revision 1.233.2.4
diff -c -p -d -u -r1.233.2.4 except.c
--- gcc/except.c	22 Apr 2003 15:50:54 -0000	1.233.2.4
+++ gcc/except.c	2 May 2003 07:54:43 -0000
@@ -562,9 +562,7 @@ expand_eh_region_end_cleanup (handler)
 
   emit_label (region->label);
 
-  if (flag_non_call_exceptions 
-      || flag_forced_unwind_exceptions
-      || region->may_contain_throw)
+  if (flag_non_call_exceptions || region->may_contain_throw)
     {
       /* Give the language a chance to specify an action to be taken if an
 	 exception is thrown that would propagate out of the HANDLER.  */
@@ -1133,40 +1131,21 @@ convert_from_eh_region_ranges_1 (pinsns,
 	}
       else if (INSN_P (insn))
 	{
-	  rtx note;
-	  switch (cur)
+	  if (cur > 0
+	      && ! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
+	      /* Calls can always potentially throw exceptions, unless
+		 they have a REG_EH_REGION note with a value of 0 or less.
+		 Which should be the only possible kind so far.  */
+	      && (GET_CODE (insn) == CALL_INSN
+		  /* If we wanted exceptions for non-call insns, then
+		     any may_trap_p instruction could throw.  */
+		  || (flag_non_call_exceptions
+		      && GET_CODE (PATTERN (insn)) != CLOBBER
+		      && GET_CODE (PATTERN (insn)) != USE
+		      && may_trap_p (PATTERN (insn)))))
 	    {
-	    default:
-	      /* An existing region note may be present to suppress
-		 exception handling.  Anything with a note value of -1
-		 cannot throw an exception of any kind.  A note value
-		 of 0 means that "normal" exceptions are suppressed,
-		 but not necessarily "forced unwind" exceptions.  */
-	      note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
-	      if (note)
-		{
-		  if (flag_forced_unwind_exceptions
-		      && INTVAL (XEXP (note, 0)) >= 0)
-		    XEXP (note, 0) = GEN_INT (cur);
-		  break;
-		}
-
-	      /* Calls can always potentially throw exceptions; if we wanted
-		 exceptions for non-call insns, then any may_trap_p
-		 instruction can throw.  */
-	      if (GET_CODE (insn) != CALL_INSN
-		  && (!flag_non_call_exceptions
-		      || GET_CODE (PATTERN (insn)) == CLOBBER
-		      || GET_CODE (PATTERN (insn)) == USE
-		      || !may_trap_p (PATTERN (insn))))
-		break;
-
-	      REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION,
-						  GEN_INT (cur),
+	      REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (cur),
 						  REG_NOTES (insn));
-
-	    case 0:
-	      break;
 	    }
 
 	  if (GET_CODE (insn) == CALL_INSN
@@ -1725,14 +1704,7 @@ build_post_landing_pads ()
 	    for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
 	      {
 		if (c->u.catch.type_list == NULL)
-		  {
-		    if (flag_forced_unwind_exceptions)
-		      emit_cmp_and_jump_insns
-			(cfun->eh->filter, const0_rtx, GT, NULL_RTX,
-			 word_mode, 0, c->label);
-		    else
-		      emit_jump (c->label);
-		  }
+		  emit_jump (c->label);
 		else
 		  {
 		    /* Need for one cmp/jump per type caught. Each type
@@ -1793,33 +1765,8 @@ build_post_landing_pads ()
 	  break;
 
 	case ERT_CLEANUP:
-	  region->post_landing_pad = region->label;
-	  break;
-
 	case ERT_MUST_NOT_THROW:
-	  /* See maybe_remove_eh_handler about removing region->label.  */
-	  if (flag_forced_unwind_exceptions && region->label)
-	    {
-	      region->post_landing_pad = gen_label_rtx ();
-
-	      start_sequence ();
-
-	      emit_label (region->post_landing_pad);
-	      emit_cmp_and_jump_insns (cfun->eh->filter, const0_rtx, GT,
-				       NULL_RTX, word_mode, 0, region->label);
-
-	      region->resume
-	        = emit_jump_insn (gen_rtx_RESX (VOIDmode,
-						region->region_number));
-	      emit_barrier ();
-
-	      seq = get_insns ();
-	      end_sequence ();
-
-	      emit_insn_before (seq, region->label);
-	    }
-	  else
-	    region->post_landing_pad = region->label;
+	  region->post_landing_pad = region->label;
 	  break;
 
 	case ERT_CATCH:
@@ -1999,21 +1946,6 @@ sjlj_find_directly_reachable_regions (lp
 	  if (rc != RNL_NOT_CAUGHT)
 	    break;
 	}
-
-      /* Forced unwind exceptions aren't blocked.  */
-      if (flag_forced_unwind_exceptions && rc == RNL_BLOCKED)
-	{
-          struct eh_region *r;
-	  for (r = region->outer; r ; r = r->outer)
-	    if (r->type == ERT_CLEANUP)
-	      {
-		rc = RNL_MAYBE_CAUGHT;
-		if (! region->label)
-		  region = r;
-		break;
-	      }
-	}
-
       if (rc == RNL_MAYBE_CAUGHT || rc == RNL_CAUGHT)
 	{
 	  lp_info[region->region_number].directly_reachable = 1;
@@ -2852,21 +2784,7 @@ reachable_handlers (insn)
   while (region)
     {
       if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
-	{
-	  /* Forced unwind exceptions are neither BLOCKED nor CAUGHT.
-	     Make sure the cleanup regions are reachable.  */
-	  if (flag_forced_unwind_exceptions)
-	    {
-	      while ((region = region->outer) != NULL)
-		if (region->type == ERT_CLEANUP)
-		  {
-		    add_reachable_handler (&info, region, region);
-		    break;
-		  }
-	    }
-	  break;
-	}
-
+	break;
       /* If we have processed one cleanup, there is no point in
 	 processing any more of them.  Each cleanup will have an edge
 	 to the next outer cleanup region, so the flow graph will be
@@ -2988,10 +2906,6 @@ can_throw_external (insn)
   if (INTVAL (XEXP (note, 0)) <= 0)
     return false;
 
-  /* Forced unwind excptions are not catchable.  */
-  if (flag_forced_unwind_exceptions && GET_CODE (insn) == CALL_INSN)
-    return true;
-
   region = cfun->eh->region_array[INTVAL (XEXP (note, 0))];
 
   type_thrown = NULL_TREE;
@@ -3346,26 +3260,12 @@ collect_one_action_chain (ar_hash, regio
 	{
 	  if (c->u.catch.type_list == NULL)
 	    {
-	      int filter;
-
-	      /* Forced exceptions run cleanups, always.  Record them if
-		 they exist.  */
-	      next = 0;
-	      if (flag_forced_unwind_exceptions)
-		{
-		  struct eh_region *r;
-		  for (r = c->outer; r ; r = r->outer)
-		    if (r->type == ERT_CLEANUP)
-		      {
-			next = add_action_record (ar_hash, 0, 0);
-			break;
-		      }
-		}
-
 	      /* Retrieve the filter from the head of the filter list
 		 where we have stored it (see assign_filter_values).  */
-	      filter = TREE_INT_CST_LOW (TREE_VALUE (c->u.catch.filter_list));
-	      next = add_action_record (ar_hash, filter, next);
+	      int filter
+		= TREE_INT_CST_LOW (TREE_VALUE (c->u.catch.filter_list));
+
+	      next = add_action_record (ar_hash, filter, 0);
 	    }
 	  else
 	    {
@@ -3410,13 +3310,6 @@ collect_one_action_chain (ar_hash, regio
 	 requires no call-site entry.  Note that this differs from
 	 the no handler or cleanup case in that we do require an lsda
 	 to be generated.  Return a magic -2 value to record this.  */
-      if (flag_forced_unwind_exceptions)
-	{
-	  struct eh_region *r;
-	  for (r = region->outer; r ; r = r->outer)
-	    if (r->type == ERT_CLEANUP)
-	      return 0;
-	}
       return -2;
 
     case ERT_CATCH:
Index: gcc/flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.93.4.1
diff -c -p -d -u -r1.93.4.1 flags.h
--- gcc/flags.h	2 Apr 2003 07:14:27 -0000	1.93.4.1
+++ gcc/flags.h	2 May 2003 07:54:43 -0000
@@ -485,10 +485,6 @@ extern int flag_unwind_tables;
 
 extern int flag_asynchronous_unwind_tables;
 
-/* Nonzero means allow for forced unwinding.  */
-
-extern int flag_forced_unwind_exceptions;
-
 /* Nonzero means don't place uninitialized global data in common storage
    by default.  */
 
Index: gcc/libgcc-std.ver
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc-std.ver,v
retrieving revision 1.16.2.2
diff -c -p -d -u -r1.16.2.2 libgcc-std.ver
--- gcc/libgcc-std.ver	15 Apr 2003 16:23:08 -0000	1.16.2.2
+++ gcc/libgcc-std.ver	2 May 2003 07:54:43 -0000
@@ -181,4 +181,6 @@ GCC_3.3 {
   _Unwind_FindEnclosingFunction
   _Unwind_GetCFA
   _Unwind_Backtrace
+  _Unwind_Resume_or_Rethrow
+  _Unwind_SjLj_Resume_or_Rethrow
 }
Index: gcc/toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.690.2.17
diff -c -p -d -u -r1.690.2.17 toplev.c
--- gcc/toplev.c	29 Apr 2003 14:31:50 -0000	1.690.2.17
+++ gcc/toplev.c	2 May 2003 07:54:45 -0000
@@ -727,10 +727,6 @@ int flag_unwind_tables = 0;
 
 int flag_asynchronous_unwind_tables = 0;
 
-/* Nonzero means allow for forced unwinding.  */
-
-int flag_forced_unwind_exceptions;
-
 /* Nonzero means don't place uninitialized global data in common storage
    by default.  */
 
@@ -1094,8 +1090,6 @@ static const lang_independent_options f_
    N_("Generate unwind tables exact at each instruction boundary") },
   {"non-call-exceptions", &flag_non_call_exceptions, 1,
    N_("Support synchronous non-call exceptions") },
-  {"forced-unwind-exceptions", &flag_forced_unwind_exceptions, 1,
-   N_("Support forced unwinding, e.g. for thread cancellation") },
   {"profile-arcs", &profile_arc_flag, 1,
    N_("Insert arc based program profiling code") },
   {"test-coverage", &flag_test_coverage, 1,
Index: gcc/unwind-dw2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind-dw2.c,v
retrieving revision 1.22.2.2
diff -c -p -d -u -r1.22.2.2 unwind-dw2.c
--- gcc/unwind-dw2.c	3 Apr 2003 02:11:09 -0000	1.22.2.2
+++ gcc/unwind-dw2.c	2 May 2003 07:54:45 -0000
@@ -171,7 +171,7 @@ _Unwind_GetGR (struct _Unwind_Context *c
 _Unwind_Word
 _Unwind_GetCFA (struct _Unwind_Context *context)
 {
-  return context->cfa;
+  return (_Unwind_Ptr) context->cfa;
 }
 
 /* Overwrite the saved value for register REG in CONTEXT with VAL.  */
Index: gcc/unwind-sjlj.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind-sjlj.c,v
retrieving revision 1.11.2.1
diff -c -p -d -u -r1.11.2.1 unwind-sjlj.c
--- gcc/unwind-sjlj.c	3 Apr 2003 02:11:09 -0000	1.11.2.1
+++ gcc/unwind-sjlj.c	2 May 2003 07:54:45 -0000
@@ -289,6 +289,7 @@ uw_identify_context (struct _Unwind_Cont
 #define _Unwind_RaiseException		_Unwind_SjLj_RaiseException
 #define _Unwind_ForcedUnwind		_Unwind_SjLj_ForcedUnwind
 #define _Unwind_Resume			_Unwind_SjLj_Resume
+#define _Unwind_Resume_or_Rethrow	_Unwind_SjLj_Resume_or_Rethrow
 
 #include "unwind.inc"
 
Index: gcc/unwind.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind.h,v
retrieving revision 1.7.2.3
diff -c -p -d -u -r1.7.2.3 unwind.h
--- gcc/unwind.h	15 Apr 2003 16:23:08 -0000	1.7.2.3
+++ gcc/unwind.h	2 May 2003 07:54:45 -0000
@@ -127,6 +127,10 @@ extern void _Unwind_DeleteException (str
    e.g. executing cleanup code, and not to implement rethrowing.  */
 extern void _Unwind_Resume (struct _Unwind_Exception *);
 
+/* @@@ Resume propagation of an FORCE_UNWIND exception, or to rethrow
+   a normal exception that was handled.  */
+extern void _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
+
 /* @@@ Use unwind data to perform a stack backtrace.  The trace callback
    is called for every stack frame in the call chain, but no cleanup
    actions are performed.  */
@@ -184,6 +188,7 @@ extern _Unwind_Reason_Code _Unwind_SjLj_
 extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind
      (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
 extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *);
+extern void _Unwind_SjLj_Resume_or_Rethrow (struct _Unwind_Exception *);
 
 /* @@@ The following provide access to the base addresses for text
    and data-relative addressing in the LDSA.  In order to stay link
Index: gcc/unwind.inc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/unwind.inc,v
retrieving revision 1.7.20.1
diff -c -p -d -u -r1.7.20.1 unwind.inc
--- gcc/unwind.inc	15 Apr 2003 16:23:08 -0000	1.7.20.1
+++ gcc/unwind.inc	2 May 2003 07:54:45 -0000
@@ -232,12 +232,40 @@ _Unwind_Resume (struct _Unwind_Exception
   uw_install_context (&this_context, &cur_context);
 }
 
+
+/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
+   a normal exception that was handled.  */
+
+void
+_Unwind_Resume_or_Rethrow (struct _Unwind_Exception *exc)
+{
+  struct _Unwind_Context this_context, cur_context;
+  _Unwind_Reason_Code code;
+
+  /* Choose between continuing to process _Unwind_RaiseException
+     or _Unwind_ForcedUnwind.  */
+  if (exc->private_1 == 0)
+    return _Unwind_RaiseException (exc);
+
+  uw_init_context (&this_context);
+  cur_context = this_context;
+
+  code = _Unwind_ForcedUnwind_Phase2 (exc, &cur_context);
+
+  if (code != _URC_INSTALL_CONTEXT)
+    abort ();
+
+  uw_install_context (&this_context, &cur_context);
+}
+
+
 /* A convenience function that calls the exception_cleanup field.  */
 
 void
 _Unwind_DeleteException (struct _Unwind_Exception *exc)
 {
-  (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+  if (exc->exception_cleanup)
+    (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
 }
 
 
@@ -274,4 +302,3 @@ _Unwind_Backtrace(_Unwind_Trace_Fn trace
 
   return code;
 }
-
Index: gcc/cp/cfns.gperf
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cfns.gperf,v
retrieving revision 1.2
diff -c -p -d -u -r1.2 cfns.gperf
--- gcc/cp/cfns.gperf	4 Apr 2000 20:46:23 -0000	1.2
+++ gcc/cp/cfns.gperf	2 May 2003 07:54:45 -0000
@@ -16,9 +16,9 @@ const char * libc_name_p PARAMS ((const 
 #   exception, unless it calls a program-supplied function that
 #   throws an exception.
 #
-# bsearch and qsort are commented out because they can call such functions.
+# Specific functions are commented out for the reason noted in each case.
 #
-abort
+# abort			-- synchronous exception from SIGABRT handler
 abs
 acos
 asctime
@@ -29,7 +29,7 @@ atexit
 atof
 atoi
 atol
-#bsearch
+#bsearch		-- calls user function which may throw exception
 btowc
 calloc
 ceil
@@ -43,41 +43,41 @@ div
 exit
 exp
 fabs
-fclose
+#fclose			-- POSIX thread cancellation point
 feof
 ferror
-fflush
-fgetc
-fgetpos
-fgets
-fgetwc
-fgetws
+#fflush			-- POSIX thread cancellation point
+#fgetc			-- POSIX thread cancellation point
+#fgetpos		-- POSIX thread cancellation point
+#fgets			-- POSIX thread cancellation point
+#fgetwc			-- POSIX thread cancellation point
+#fgetws			-- POSIX thread cancellation point
 floor
 fmod
-fopen
-fprintf
-fputc
-fputs
-fputwc
-fputws
-fread
+#fopen			-- POSIX thread cancellation point
+#fprintf		-- POSIX thread cancellation point
+#fputc			-- POSIX thread cancellation point
+#fputs			-- POSIX thread cancellation point
+#fputwc			-- POSIX thread cancellation point
+#fputws			-- POSIX thread cancellation point
+#fread			-- POSIX thread cancellation point
 free
-freopen
+#freopen		-- POSIX thread cancellation point
 frexp
-fscanf
+#fscanf			-- POSIX thread cancellation point
 fseek
-fsetpos
-ftell
+#fsetpos		-- POSIX thread cancellation point
+#ftell			-- POSIX thread cancellation point
 fwide
-fwprintf
-fwrite
-fwscanf
-getc
-getchar
+#fwprintf		-- POSIX thread cancellation point
+#fwrite			-- POSIX thread cancellation point
+#fwscanf		-- POSIX thread cancellation point
+#getc			-- POSIX thread cancellation point
+#getchar		-- POSIX thread cancellation point
 getenv
-gets
-getwc
-getwchar
+#gets			-- POSIX thread cancellation point
+#getwc			-- POSIX thread cancellation point
+#getwchar		-- POSIX thread cancellation point
 gmtime
 isalnum
 isalpha
@@ -125,22 +125,22 @@ memmove
 memset
 mktime
 modf
-perror
+#perror			-- POSIX thread cancellation point
 pow
-printf
-putc
-putchar
-puts
-putwc
-putwchar
-#qsort
-raise
+#printf			-- POSIX thread cancellation point
+#putc			-- POSIX thread cancellation point
+#putchar		-- POSIX thread cancellation point
+#puts			-- POSIX thread cancellation point
+#putwc			-- POSIX thread cancellation point
+#putwchar		-- POSIX thread cancellation point
+#qsort			-- calls user function which may throw exception
+#raise			-- synchronous exception from signal handler
 rand
 realloc
-remove
-rename
-rewind
-scanf
+#remove			-- POSIX thread cancellation point
+#rename			-- POSIX thread cancellation point
+#rewind			-- POSIX thread cancellation point
+#scanf			-- POSIX thread cancellation point
 setbuf
 setlocale
 setvbuf
@@ -157,7 +157,7 @@ strcmp
 strcoll
 strcpy
 strcspn
-strerror
+#strerror		-- POSIX thread cancellation point
 strftime
 strlen
 strncat
@@ -174,25 +174,25 @@ strtoul
 strxfrm
 swprintf
 swscanf
-system
+#system			-- POSIX thread cancellation point
 tan
 tanh
 time
-tmpfile
-tmpnam
+#tmpfile		-- POSIX thread cancellation point
+#tmpnam			-- POSIX thread cancellation point
 tolower
 toupper
 towctrans
 towlower
 towupper
-ungetc
-ungetwc
-vfprintf
-vfwprintf
-vprintf
+#ungetc			-- POSIX thread cancellation point
+#ungetwc		-- POSIX thread cancellation point
+#vfprintf		-- POSIX thread cancellation point
+#vfwprintf		-- POSIX thread cancellation point
+#vprintf		-- POSIX thread cancellation point
 vsprintf
 vswprintf
-vwprintf
+#vwprintf		-- POSIX thread cancellation point
 wcrtomb
 wcscat
 wcschr
@@ -225,5 +225,5 @@ wmemcmp
 wmemcpy
 wmemmove
 wmemset
-wprintf
-wscanf
+#wprintf		-- POSIX thread cancellation point
+#wscanf			-- POSIX thread cancellation point
Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.209.2.26
diff -c -p -d -u -r1.209.2.26 invoke.texi
--- gcc/doc/invoke.texi	23 Apr 2003 21:45:32 -0000	1.209.2.26
+++ gcc/doc/invoke.texi	2 May 2003 07:54:49 -0000
@@ -652,7 +652,7 @@ in the following sections.
 @gccoptlist{-fcall-saved-@var{reg}  -fcall-used-@var{reg} @gol
 -ffixed-@var{reg}  -fexceptions @gol
 -fnon-call-exceptions  -funwind-tables @gol
--fasynchronous-unwind-tables  -fforced-unwind-exceptions @gol
+-fasynchronous-unwind-tables @gol
 -finhibit-size-directive  -finstrument-functions @gol
 -fno-common  -fno-ident  -fno-gnu-linker @gol
 -fpcc-struct-return  -fpic  -fPIC @gol
@@ -10508,13 +10508,6 @@ not exist everywhere.  Moreover, it only
 instructions to throw exceptions, i.e.@: memory references or floating
 point instructions.  It does not allow exceptions to be thrown from
 arbitrary signal handlers such as @code{SIGALRM}.
-
-@item -fforced-unwind-exceptions
-@opindex fforced-unwind-exceptions
-Generate code that checks for non-catchable exceptions derived from
-@code{_Unwind_ForcedUnwind}, such as from @code{longjmp_unwind} or
-from pthread cancellation.  There is some amount of code-size 
-overhead associated with this, so it is not default.
 
 @item -funwind-tables
 @opindex funwind-tables
Index: gcc/testsuite/g++.dg/eh/forced1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/eh/forced1.C,v
retrieving revision 1.1.2.1
diff -c -p -d -u -r1.1.2.1 forced1.C
--- gcc/testsuite/g++.dg/eh/forced1.C	2 Apr 2003 07:14:29 -0000	1.1.2.1
+++ gcc/testsuite/g++.dg/eh/forced1.C	2 May 2003 07:54:50 -0000
@@ -1,7 +1,7 @@
 // { dg-do run }
-// { dg-options "-fforced-unwind-exceptions" }
 
-// Test that forced unwinding runs all cleanups, and only cleanups.
+// Test that forced unwinding runs all cleanups.  Also tests that
+// rethrowing doesn't call the exception object destructor.
 
 #include <unwind.h>
 #include <stdlib.h>
@@ -17,7 +17,7 @@ force_unwind_stop (int version, _Unwind_
 {
   if (actions & _UA_END_OF_STACK)
     {
-      if (test != 5)
+      if (test != 15)
         abort ();
       exit (0);
     }
@@ -25,14 +25,24 @@ force_unwind_stop (int version, _Unwind_
   return _URC_NO_REASON;
 }
 
+static void
+force_unwind_cleanup (_Unwind_Reason_Code, struct _Unwind_Exception *)
+{
+  abort ();
+}
+
 static void force_unwind ()
 {
   _Unwind_Exception *exc = new _Unwind_Exception;
   exc->exception_class = 0;
-  exc->exception_cleanup = 0;
-                   
+  exc->exception_cleanup = force_unwind_cleanup;
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
   _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
-                   
+#else
+  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
+
   abort ();
 }
 
@@ -54,18 +64,17 @@ static void doit ()
   
     } catch(...) { 
       test |= 2;
+      throw;
     }
 
   } catch(...) {
     test |= 8;
+    throw;
   }
 }
 
 int main()
 { 
-  try {
-    doit ();
-  } catch (...) {
-  }
+  doit ();
   abort ();
 }
Index: gcc/testsuite/g++.dg/eh/forced2.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/eh/forced2.C,v
retrieving revision 1.1.2.1
diff -c -p -d -u -r1.1.2.1 forced2.C
--- gcc/testsuite/g++.dg/eh/forced2.C	2 Apr 2003 07:14:29 -0000	1.1.2.1
+++ gcc/testsuite/g++.dg/eh/forced2.C	2 May 2003 07:54:50 -0000
@@ -1,13 +1,11 @@
 // { dg-do run }
-// { dg-options "-fforced-unwind-exceptions" }
 
-// Test that forced unwinding runs all cleanups, and only cleanups.
+// Test that leaving the catch block without rethrowing
+// does call the exception object destructor.
 
 #include <unwind.h>
 #include <stdlib.h>
 
-static int test = 0;
-
 static _Unwind_Reason_Code
 force_unwind_stop (int version, _Unwind_Action actions,
                    _Unwind_Exception_Class exc_class,
@@ -16,71 +14,36 @@ force_unwind_stop (int version, _Unwind_
                    void *stop_parameter)
 {
   if (actions & _UA_END_OF_STACK)
-    {
-      if (test != 5)
-        abort ();
-      exit (0);
-    }
-
+    abort ();
   return _URC_NO_REASON;
 }
 
-// Note that neither the noreturn nor the nothrow specification
-// affects forced unwinding.
-
-static void __attribute__((noreturn))
-force_unwind () throw()
-{
-  _Unwind_Exception *exc = new _Unwind_Exception;
-  exc->exception_class = 0;
-  exc->exception_cleanup = 0;
-                   
-  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
-                   
-  abort ();
-}
-
-struct S
-{
-  int bit;
-  S(int b) : bit(b) { }
-  ~S() { test |= bit; }
-};
-  
-static void doit_3 ()
+static void
+force_unwind_cleanup (_Unwind_Reason_Code, struct _Unwind_Exception *)
 {
-  S one(1);
-  force_unwind ();
+  exit (0);
 }
 
-static void doit_2 ()
+static void
+force_unwind ()
 {
-  try {
-    doit_3 ();
-  } catch (...) {
-    test |= 2;
-  }
-}
+  _Unwind_Exception *exc = new _Unwind_Exception;
+  exc->exception_class = 0;
+  exc->exception_cleanup = force_unwind_cleanup;
 
-static void doit_1 ()
-{
-  S four(4);
-  doit_2 ();
-}
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
 
-static void doit ()
-{
-  try {
-    doit_1 ();
-  } catch(...) {
-    test |= 8;
-  }
+  abort ();
 }
 
 int main()
 { 
   try {
-    doit ();
+    force_unwind ();
   } catch (...) {
   }
   abort ();
Index: gcc/testsuite/g++.dg/eh/forced3.C
===================================================================
RCS file: gcc/testsuite/g++.dg/eh/forced3.C
diff -N gcc/testsuite/g++.dg/eh/forced3.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/eh/forced3.C	2 May 2003 07:54:50 -0000
@@ -0,0 +1,55 @@
+// { dg-do run }
+
+// Test that forced unwinding calls std::unexpected going 
+// throw a nothrow function.
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <exception>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+                   _Unwind_Exception_Class exc_class,
+                   struct _Unwind_Exception *exc_obj,
+                   struct _Unwind_Context *context,
+                   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void __attribute__((noreturn))
+force_unwind ()
+{
+  _Unwind_Exception *exc = new _Unwind_Exception;
+  exc->exception_class = 0;
+  exc->exception_cleanup = 0;
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
+
+  abort ();
+}
+
+static void
+handle_unexpected ()
+{
+  exit (0);
+}
+
+static void
+doit () throw()
+{
+  force_unwind ();
+}
+
+int main()
+{ 
+  std::set_unexpected (handle_unexpected);
+  doit ();
+  abort ();
+}
Index: gcc/testsuite/g++.dg/eh/forced4.C
===================================================================
RCS file: gcc/testsuite/g++.dg/eh/forced4.C
diff -N gcc/testsuite/g++.dg/eh/forced4.C
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/g++.dg/eh/forced4.C	2 May 2003 07:54:50 -0000
@@ -0,0 +1,49 @@
+// { dg-do run }
+
+// Test that forced unwinding does not call std::unexpected going 
+// throw a function with a non-empty exception spec.
+
+#include <unwind.h>
+#include <stdlib.h>
+
+static _Unwind_Reason_Code
+force_unwind_stop (int version, _Unwind_Action actions,
+                   _Unwind_Exception_Class exc_class,
+                   struct _Unwind_Exception *exc_obj,
+                   struct _Unwind_Context *context,
+                   void *stop_parameter)
+{
+  if (actions & _UA_END_OF_STACK)
+    abort ();
+  return _URC_NO_REASON;
+}
+
+static void __attribute__((noreturn))
+force_unwind ()
+{
+  _Unwind_Exception *exc = new _Unwind_Exception;
+  exc->exception_class = 0;
+  exc->exception_cleanup = 0;
+
+#ifndef __USING_SJLJ_EXCEPTIONS__
+  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
+#else
+  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
+#endif
+
+  abort ();
+}
+
+static void
+doit () throw(int)
+{
+  force_unwind ();
+}
+
+int main()
+{ 
+  try {
+    doit ();
+  } catch (...) {
+  }
+}
Index: libstdc++-v3/libsupc++/eh_catch.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/eh_catch.cc,v
retrieving revision 1.3
diff -c -p -d -u -r1.3 eh_catch.cc
--- libstdc++-v3/libsupc++/eh_catch.cc	18 Nov 2001 02:09:23 -0000	1.3
+++ libstdc++-v3/libsupc++/eh_catch.cc	2 May 2003 07:54:52 -0000
@@ -1,5 +1,5 @@
 // -*- C++ -*- Exception handling routines for catching.
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
 //
 // This file is part of GNU CC.
 //
@@ -39,15 +39,28 @@ __cxa_begin_catch (void *exc_obj_in)
 {
   _Unwind_Exception *exceptionObject
     = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
-
-  // ??? Foreign exceptions can't be stacked here, and there doesn't
-  // appear to be any place to store for __cxa_end_catch to destroy.
-
-  __cxa_exception *header = __get_exception_header_from_ue (exceptionObject);
   __cxa_eh_globals *globals = __cxa_get_globals ();
   __cxa_exception *prev = globals->caughtExceptions;
-  int count = header->handlerCount;
+  __cxa_exception *header = __get_exception_header_from_ue (exceptionObject);
 
+  // Foreign exceptions can't be stacked here.  If the exception stack is
+  // empty, then fine.  Otherwise we really have no choice but to terminate.
+  // Note that this use of "header" is a lie.  It's fine so long as we only
+  // examine header->unwindHeader though.
+  if (header->unwindHeader.exception_class != __gxx_exception_class)
+    {
+      if (prev != 0)
+	std::terminate ();
+
+      // Remember for end_catch and rethrow.
+      globals->caughtExceptions = header;
+
+      // ??? No sensible value to return; we don't know what the 
+      // object is, much less where it is in relation to the header.
+      return 0;
+    }
+
+  int count = header->handlerCount;
   if (count < 0)
     // This exception was rethrown from an immediately enclosing region.
     count = -count + 1;
@@ -71,8 +84,22 @@ __cxa_end_catch ()
 {
   __cxa_eh_globals *globals = __cxa_get_globals_fast ();
   __cxa_exception *header = globals->caughtExceptions;
-  int count = header->handlerCount;
 
+  // A rethrow of a foreign exception will be removed from the
+  // the exception stack immediately by __cxa_rethrow.
+  if (!header)
+    return;
+
+  // A foreign exception couldn't have been stacked (see above),
+  // so by definition processing must be complete.
+  if (header->unwindHeader.exception_class != __gxx_exception_class)
+    {
+      globals->caughtExceptions = 0;
+      _Unwind_DeleteException (&header->unwindHeader);
+      return;
+    }
+
+  int count = header->handlerCount;
   if (count < 0)
     {
       // This exception was rethrown.  Decrement the (inverted) catch
@@ -92,7 +119,7 @@ __cxa_end_catch ()
     }
   else if (count < 0)
     // A bug in the exception handling library or compiler.
-    std::abort ();
+    std::terminate ();
 
   header->handlerCount = count;
 }
Index: libstdc++-v3/libsupc++/eh_personality.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/eh_personality.cc,v
retrieving revision 1.10
diff -c -p -d -u -r1.10 eh_personality.cc
--- libstdc++-v3/libsupc++/eh_personality.cc	15 Aug 2002 18:05:41 -0000	1.10
+++ libstdc++-v3/libsupc++/eh_personality.cc	2 May 2003 07:54:52 -0000
@@ -1,5 +1,5 @@
 // -*- C++ -*- The GNU C++ exception personality routine.
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
 //
 // This file is part of GNU CC.
 //
@@ -124,6 +124,8 @@ get_adjusted_ptr (const std::type_info *
   return false;
 }
 
+// Return true if THROW_TYPE matches one if the filter types.
+
 static bool
 check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
 		      void *thrown_ptr, _Unwind_Sword filter_value)
@@ -154,6 +156,18 @@ check_exception_spec (lsda_header_info *
     }
 }
 
+// Return true if the filter spec is empty, ie throw().
+
+static bool
+empty_exception_spec (lsda_header_info *info, _Unwind_Sword filter_value)
+{
+  const unsigned char *e = info->TType - filter_value - 1;
+  _Unwind_Word tmp;
+
+  e = read_uleb128 (e, &tmp);
+  return tmp == 0;
+}
+
 // Using a different personality function name causes link failures
 // when trying to mix code using different exception handling models.
 #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
@@ -197,6 +211,7 @@ PERSONALITY_FUNCTION (int version,
       && exception_class == __gxx_exception_class)
     {
       handler_switch_value = xh->handlerSwitchValue;
+      language_specific_data = xh->languageSpecificData;
       landing_pad = (_Unwind_Ptr) xh->catchTemp;
       found_type = (landing_pad == 0 ? found_terminate : found_handler);
       goto install_context;
@@ -275,7 +290,7 @@ PERSONALITY_FUNCTION (int version,
   // If ip is not present in the table, call terminate.  This is for
   // a destructor inside a cleanup, or a library routine the compiler
   // was not expecting to throw.
-  found_type = (actions & _UA_FORCE_UNWIND ? found_nothing : found_terminate);
+  found_type = found_terminate;
   goto do_something;
 
  found_something:
@@ -327,23 +342,15 @@ PERSONALITY_FUNCTION (int version,
 	      // Positive filter values are handlers.
 	      catch_type = get_ttype_entry (&info, ar_filter);
 
-	      // Null catch type is a catch-all handler.  We can catch
-	      // foreign exceptions with this.
-	      if (! catch_type)
-		{
-		  if (!(actions & _UA_FORCE_UNWIND))
-		    {
-		      saw_handler = true;
-		      break;
-		    }
-		}
-	      else if (throw_type)
+	      // Null catch type is a catch-all handler; we can catch foreign
+	      // exceptions with this.  Otherwise we must match types.
+	      if (! catch_type
+		  || (throw_type
+		      && get_adjusted_ptr (catch_type, throw_type,
+					   &thrown_ptr)))
 		{
-		  if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
-		    {
-		      saw_handler = true;
-		      break;
-		    }
+		  saw_handler = true;
+		  break;
 		}
 	    }
 	  else
@@ -352,9 +359,12 @@ PERSONALITY_FUNCTION (int version,
 	      // ??? How do foreign exceptions fit in?  As far as I can
 	      // see we can't match because there's no __cxa_exception
 	      // object to stuff bits in for __cxa_call_unexpected to use.
+	      // Allow them iff the exception spec is non-empty.  I.e.
+	      // a throw() specification results in __unexpected.
 	      if (throw_type
-		  && ! check_exception_spec (&info, throw_type, thrown_ptr,
-					     ar_filter))
+		  ? ! check_exception_spec (&info, throw_type, thrown_ptr,
+					    ar_filter)
+		  : empty_exception_spec (&info, ar_filter))
 		{
 		  saw_handler = true;
 		  break;
@@ -400,19 +410,37 @@ PERSONALITY_FUNCTION (int version,
     }
 
  install_context:
-  if (found_type == found_terminate)
+  // We can't use any of the cxa routines with foreign exceptions,
+  // because they all expect ue_header to be a struct __cxa_exception.
+  // So in that case, call terminate or unexpected directly.
+  if ((actions & _UA_FORCE_UNWIND)
+      || exception_class != __gxx_exception_class)
     {
-      __cxa_begin_catch (&xh->unwindHeader);
-      __terminate (xh->terminateHandler);
+      if (found_type == found_terminate)
+	std::terminate ();
+      else if (handler_switch_value < 0)
+	{
+	  try 
+	    { std::unexpected (); } 
+	  catch(...) 
+	    { std::terminate (); }
+	}
     }
-
-  // Cache the TType base value for __cxa_call_unexpected, as we won't
-  // have an _Unwind_Context then.
-  if (handler_switch_value < 0)
+  else
     {
-      parse_lsda_header (context, xh->languageSpecificData, &info);
-      xh->catchTemp = base_of_encoded_value (info.ttype_encoding,
-						      context);
+      if (found_type == found_terminate)
+	{
+	  __cxa_begin_catch (&xh->unwindHeader);
+	  __terminate (xh->terminateHandler);
+	}
+
+      // Cache the TType base value for __cxa_call_unexpected, as we won't
+      // have an _Unwind_Context then.
+      if (handler_switch_value < 0)
+	{
+	  parse_lsda_header (context, language_specific_data, &info);
+	  xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context);
+	}
     }
 
   _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
@@ -457,20 +485,19 @@ __cxa_call_unexpected (void *exc_obj_in)
   catch(...) 
     {
       // Get the exception thrown from unexpected.
-      // ??? Foreign exceptions can't be stacked this way.
-      
+
       __cxa_eh_globals *globals = __cxa_get_globals_fast ();
       __cxa_exception *new_xh = globals->caughtExceptions;
       void *new_ptr = new_xh + 1;
-      
+
       // We don't quite have enough stuff cached; re-parse the LSDA.
       parse_lsda_header (0, xh_lsda, &info);
-      
+
       // If this new exception meets the exception spec, allow it.
       if (check_exception_spec (&info, new_xh->exceptionType,
 				new_ptr, xh_switch_value))
 	__throw_exception_again;
-      
+
       // If the exception spec allows std::bad_exception, throw that.
       // We don't have a thrown object to compare against, but since
       // bad_exception doesn't have virtual bases, that's OK; just pass 0.
@@ -479,6 +506,7 @@ __cxa_call_unexpected (void *exc_obj_in)
       if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value))
 	throw std::bad_exception();
 #endif   
+
       // Otherwise, die.
       __terminate (xh_terminate_handler);
     }
Index: libstdc++-v3/libsupc++/eh_throw.cc
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/libsupc++/eh_throw.cc,v
retrieving revision 1.3
diff -c -p -d -u -r1.3 eh_throw.cc
--- libstdc++-v3/libsupc++/eh_throw.cc	15 Aug 2002 18:05:41 -0000	1.3
+++ libstdc++-v3/libsupc++/eh_throw.cc	2 May 2003 07:54:52 -0000
@@ -1,5 +1,5 @@
 // -*- C++ -*- Exception handling routines for throwing.
-// Copyright (C) 2001 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
 //
 // This file is part of GNU CC.
 //
@@ -90,12 +90,15 @@ __cxa_rethrow ()
   if (header)
     {
       // Tell __cxa_end_catch this is a rethrow.
-      header->handlerCount = -header->handlerCount;
+      if (header->unwindHeader.exception_class != __gxx_exception_class)
+	globals->caughtExceptions = 0;
+      else
+	header->handlerCount = -header->handlerCount;
 
 #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
-      _Unwind_SjLj_RaiseException (&header->unwindHeader);
+      _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader);
 #else
-      _Unwind_RaiseException (&header->unwindHeader);
+      _Unwind_Resume_or_Rethrow (&header->unwindHeader);
 #endif
   
       // Some sort of unwinding error.  Note that terminate is a handler.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]