Commit a944ceb9 by Richard Henderson Committed by Richard Henderson

except.c: Revert 04-01 and 04-02 forced-unwind changes.

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.

From-SVN: r66583
parent a21d83cd
2003-05-07 Richard Henderson <rth@redhat.com> 2003-05-07 Richard Henderson <rth@redhat.com>
PR c++/10570
* 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.
2003-05-07 Richard Henderson <rth@redhat.com>
* unwind-dw2.c (_Unwind_GetCFA): Cast pointer to _Unwind_Ptr, * unwind-dw2.c (_Unwind_GetCFA): Cast pointer to _Unwind_Ptr,
not _Unwind_Word. not _Unwind_Word.
......
2003-05-07 Richard Henderson <rth@redhat.com>
PR c++/10570
* cfns.gperf: Comment out POSIX thread cancellation points,
plus abort and raise.
* cfns.h: Regenerate.
2003-05-07 Jason Merrill <jason@redhat.com> 2003-05-07 Jason Merrill <jason@redhat.com>
* call.c (build_conditional_expr): Don't assume that the folded * call.c (build_conditional_expr): Don't assume that the folded
......
...@@ -16,9 +16,9 @@ const char * libc_name_p (const char *, unsigned int); ...@@ -16,9 +16,9 @@ const char * libc_name_p (const char *, unsigned int);
# exception, unless it calls a program-supplied function that # exception, unless it calls a program-supplied function that
# throws an exception. # 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 abs
acos acos
asctime asctime
...@@ -29,7 +29,7 @@ atexit ...@@ -29,7 +29,7 @@ atexit
atof atof
atoi atoi
atol atol
#bsearch #bsearch -- calls user function which may throw exception
btowc btowc
calloc calloc
ceil ceil
...@@ -43,41 +43,41 @@ div ...@@ -43,41 +43,41 @@ div
exit exit
exp exp
fabs fabs
fclose #fclose -- POSIX thread cancellation point
feof feof
ferror ferror
fflush #fflush -- POSIX thread cancellation point
fgetc #fgetc -- POSIX thread cancellation point
fgetpos #fgetpos -- POSIX thread cancellation point
fgets #fgets -- POSIX thread cancellation point
fgetwc #fgetwc -- POSIX thread cancellation point
fgetws #fgetws -- POSIX thread cancellation point
floor floor
fmod fmod
fopen #fopen -- POSIX thread cancellation point
fprintf #fprintf -- POSIX thread cancellation point
fputc #fputc -- POSIX thread cancellation point
fputs #fputs -- POSIX thread cancellation point
fputwc #fputwc -- POSIX thread cancellation point
fputws #fputws -- POSIX thread cancellation point
fread #fread -- POSIX thread cancellation point
free free
freopen #freopen -- POSIX thread cancellation point
frexp frexp
fscanf #fscanf -- POSIX thread cancellation point
fseek fseek
fsetpos #fsetpos -- POSIX thread cancellation point
ftell #ftell -- POSIX thread cancellation point
fwide fwide
fwprintf #fwprintf -- POSIX thread cancellation point
fwrite #fwrite -- POSIX thread cancellation point
fwscanf #fwscanf -- POSIX thread cancellation point
getc #getc -- POSIX thread cancellation point
getchar #getchar -- POSIX thread cancellation point
getenv getenv
gets #gets -- POSIX thread cancellation point
getwc #getwc -- POSIX thread cancellation point
getwchar #getwchar -- POSIX thread cancellation point
gmtime gmtime
isalnum isalnum
isalpha isalpha
...@@ -125,22 +125,22 @@ memmove ...@@ -125,22 +125,22 @@ memmove
memset memset
mktime mktime
modf modf
perror #perror -- POSIX thread cancellation point
pow pow
printf #printf -- POSIX thread cancellation point
putc #putc -- POSIX thread cancellation point
putchar #putchar -- POSIX thread cancellation point
puts #puts -- POSIX thread cancellation point
putwc #putwc -- POSIX thread cancellation point
putwchar #putwchar -- POSIX thread cancellation point
#qsort #qsort -- calls user function which may throw exception
raise #raise -- synchronous exception from signal handler
rand rand
realloc realloc
remove #remove -- POSIX thread cancellation point
rename #rename -- POSIX thread cancellation point
rewind #rewind -- POSIX thread cancellation point
scanf #scanf -- POSIX thread cancellation point
setbuf setbuf
setlocale setlocale
setvbuf setvbuf
...@@ -157,7 +157,7 @@ strcmp ...@@ -157,7 +157,7 @@ strcmp
strcoll strcoll
strcpy strcpy
strcspn strcspn
strerror #strerror -- POSIX thread cancellation point
strftime strftime
strlen strlen
strncat strncat
...@@ -174,25 +174,25 @@ strtoul ...@@ -174,25 +174,25 @@ strtoul
strxfrm strxfrm
swprintf swprintf
swscanf swscanf
system #system -- POSIX thread cancellation point
tan tan
tanh tanh
time time
tmpfile #tmpfile -- POSIX thread cancellation point
tmpnam #tmpnam -- POSIX thread cancellation point
tolower tolower
toupper toupper
towctrans towctrans
towlower towlower
towupper towupper
ungetc #ungetc -- POSIX thread cancellation point
ungetwc #ungetwc -- POSIX thread cancellation point
vfprintf #vfprintf -- POSIX thread cancellation point
vfwprintf #vfwprintf -- POSIX thread cancellation point
vprintf #vprintf -- POSIX thread cancellation point
vsprintf vsprintf
vswprintf vswprintf
vwprintf #vwprintf -- POSIX thread cancellation point
wcrtomb wcrtomb
wcscat wcscat
wcschr wcschr
...@@ -225,5 +225,5 @@ wmemcmp ...@@ -225,5 +225,5 @@ wmemcmp
wmemcpy wmemcpy
wmemmove wmemmove
wmemset wmemset
wprintf #wprintf -- POSIX thread cancellation point
wscanf #wscanf -- POSIX thread cancellation point
...@@ -665,7 +665,7 @@ in the following sections. ...@@ -665,7 +665,7 @@ in the following sections.
@gccoptlist{-fcall-saved-@var{reg} -fcall-used-@var{reg} @gol @gccoptlist{-fcall-saved-@var{reg} -fcall-used-@var{reg} @gol
-ffixed-@var{reg} -fexceptions @gol -ffixed-@var{reg} -fexceptions @gol
-fnon-call-exceptions -funwind-tables @gol -fnon-call-exceptions -funwind-tables @gol
-fasynchronous-unwind-tables -fforced-unwind-exceptions @gol -fasynchronous-unwind-tables @gol
-finhibit-size-directive -finstrument-functions @gol -finhibit-size-directive -finstrument-functions @gol
-fno-common -fno-ident -fno-gnu-linker @gol -fno-common -fno-ident -fno-gnu-linker @gol
-fpcc-struct-return -fpic -fPIC @gol -fpcc-struct-return -fpic -fPIC @gol
...@@ -10849,13 +10849,6 @@ instructions to throw exceptions, i.e.@: memory references or floating ...@@ -10849,13 +10849,6 @@ instructions to throw exceptions, i.e.@: memory references or floating
point instructions. It does not allow exceptions to be thrown from point instructions. It does not allow exceptions to be thrown from
arbitrary signal handlers such as @code{SIGALRM}. 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 @item -funwind-tables
@opindex funwind-tables @opindex funwind-tables
Similar to @option{-fexceptions}, except that it will just generate any needed Similar to @option{-fexceptions}, except that it will just generate any needed
......
...@@ -564,9 +564,7 @@ expand_eh_region_end_cleanup (handler) ...@@ -564,9 +564,7 @@ expand_eh_region_end_cleanup (handler)
emit_label (region->label); emit_label (region->label);
if (flag_non_call_exceptions if (flag_non_call_exceptions || region->may_contain_throw)
|| flag_forced_unwind_exceptions
|| region->may_contain_throw)
{ {
/* Give the language a chance to specify an action to be taken if an /* Give the language a chance to specify an action to be taken if an
exception is thrown that would propagate out of the HANDLER. */ exception is thrown that would propagate out of the HANDLER. */
...@@ -1135,40 +1133,21 @@ convert_from_eh_region_ranges_1 (pinsns, orig_sp, cur) ...@@ -1135,40 +1133,21 @@ convert_from_eh_region_ranges_1 (pinsns, orig_sp, cur)
} }
else if (INSN_P (insn)) else if (INSN_P (insn))
{ {
rtx note; if (cur > 0
switch (cur) && ! find_reg_note (insn, REG_EH_REGION, NULL_RTX)
{ /* Calls can always potentially throw exceptions, unless
default: they have a REG_EH_REGION note with a value of 0 or less.
/* An existing region note may be present to suppress Which should be the only possible kind so far. */
exception handling. Anything with a note value of -1 && (GET_CODE (insn) == CALL_INSN
cannot throw an exception of any kind. A note value /* If we wanted exceptions for non-call insns, then
of 0 means that "normal" exceptions are suppressed, any may_trap_p instruction could throw. */
but not necessarily "forced unwind" exceptions. */ || (flag_non_call_exceptions
note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); && GET_CODE (PATTERN (insn)) != CLOBBER
if (note) && GET_CODE (PATTERN (insn)) != USE
&& may_trap_p (PATTERN (insn)))))
{ {
if (flag_forced_unwind_exceptions REG_NOTES (insn) = alloc_EXPR_LIST (REG_EH_REGION, GEN_INT (cur),
&& 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)); REG_NOTES (insn));
case 0:
break;
} }
if (GET_CODE (insn) == CALL_INSN if (GET_CODE (insn) == CALL_INSN
...@@ -1727,14 +1706,7 @@ build_post_landing_pads () ...@@ -1727,14 +1706,7 @@ build_post_landing_pads ()
for (c = region->u.try.catch; c ; c = c->u.catch.next_catch) for (c = region->u.try.catch; c ; c = c->u.catch.next_catch)
{ {
if (c->u.catch.type_list == NULL) 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 else
{ {
/* Need for one cmp/jump per type caught. Each type /* Need for one cmp/jump per type caught. Each type
...@@ -1795,32 +1767,7 @@ build_post_landing_pads () ...@@ -1795,32 +1767,7 @@ build_post_landing_pads ()
break; break;
case ERT_CLEANUP: case ERT_CLEANUP:
region->post_landing_pad = region->label;
break;
case ERT_MUST_NOT_THROW: 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; break;
...@@ -2001,21 +1948,6 @@ sjlj_find_directly_reachable_regions (lp_info) ...@@ -2001,21 +1948,6 @@ sjlj_find_directly_reachable_regions (lp_info)
if (rc != RNL_NOT_CAUGHT) if (rc != RNL_NOT_CAUGHT)
break; 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) if (rc == RNL_MAYBE_CAUGHT || rc == RNL_CAUGHT)
{ {
lp_info[region->region_number].directly_reachable = 1; lp_info[region->region_number].directly_reachable = 1;
...@@ -2854,21 +2786,7 @@ reachable_handlers (insn) ...@@ -2854,21 +2786,7 @@ reachable_handlers (insn)
while (region) while (region)
{ {
if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT) 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 /* If we have processed one cleanup, there is no point in
processing any more of them. Each cleanup will have an edge processing any more of them. Each cleanup will have an edge
to the next outer cleanup region, so the flow graph will be to the next outer cleanup region, so the flow graph will be
...@@ -2990,10 +2908,6 @@ can_throw_external (insn) ...@@ -2990,10 +2908,6 @@ can_throw_external (insn)
if (INTVAL (XEXP (note, 0)) <= 0) if (INTVAL (XEXP (note, 0)) <= 0)
return false; 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))]; region = cfun->eh->region_array[INTVAL (XEXP (note, 0))];
type_thrown = NULL_TREE; type_thrown = NULL_TREE;
...@@ -3348,26 +3262,12 @@ collect_one_action_chain (ar_hash, region) ...@@ -3348,26 +3262,12 @@ collect_one_action_chain (ar_hash, region)
{ {
if (c->u.catch.type_list == NULL) 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 /* Retrieve the filter from the head of the filter list
where we have stored it (see assign_filter_values). */ where we have stored it (see assign_filter_values). */
filter = TREE_INT_CST_LOW (TREE_VALUE (c->u.catch.filter_list)); int filter
next = add_action_record (ar_hash, filter, next); = TREE_INT_CST_LOW (TREE_VALUE (c->u.catch.filter_list));
next = add_action_record (ar_hash, filter, 0);
} }
else else
{ {
...@@ -3412,13 +3312,6 @@ collect_one_action_chain (ar_hash, region) ...@@ -3412,13 +3312,6 @@ collect_one_action_chain (ar_hash, region)
requires no call-site entry. Note that this differs from requires no call-site entry. Note that this differs from
the no handler or cleanup case in that we do require an lsda the no handler or cleanup case in that we do require an lsda
to be generated. Return a magic -2 value to record this. */ 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; return -2;
case ERT_CATCH: case ERT_CATCH:
......
...@@ -475,10 +475,6 @@ extern int flag_unwind_tables; ...@@ -475,10 +475,6 @@ extern int flag_unwind_tables;
extern int flag_asynchronous_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 /* Nonzero means don't place uninitialized global data in common storage
by default. */ by default. */
......
...@@ -181,6 +181,8 @@ GCC_3.3 { ...@@ -181,6 +181,8 @@ GCC_3.3 {
_Unwind_FindEnclosingFunction _Unwind_FindEnclosingFunction
_Unwind_GetCFA _Unwind_GetCFA
_Unwind_Backtrace _Unwind_Backtrace
_Unwind_Resume_or_Rethrow
_Unwind_SjLj_Resume_or_Rethrow
} }
%inherit GCC_3.4 GCC_3.3 %inherit GCC_3.4 GCC_3.3
......
2003-05-07 Richard Henderson <rth@redhat.com>
PR c++/10570
* 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.
2003-05-07 Aldy Hernandez <aldyh@redhat.com> 2003-05-07 Aldy Hernandez <aldyh@redhat.com>
* gcc.dg/20030505.c: Fix triplet. * gcc.dg/20030505.c: Fix triplet.
......
// { dg-do run } // { 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 <unwind.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -17,7 +17,7 @@ force_unwind_stop (int version, _Unwind_Action actions, ...@@ -17,7 +17,7 @@ force_unwind_stop (int version, _Unwind_Action actions,
{ {
if (actions & _UA_END_OF_STACK) if (actions & _UA_END_OF_STACK)
{ {
if (test != 5) if (test != 15)
abort (); abort ();
exit (0); exit (0);
} }
...@@ -25,11 +25,17 @@ force_unwind_stop (int version, _Unwind_Action actions, ...@@ -25,11 +25,17 @@ force_unwind_stop (int version, _Unwind_Action actions,
return _URC_NO_REASON; return _URC_NO_REASON;
} }
static void
force_unwind_cleanup (_Unwind_Reason_Code, struct _Unwind_Exception *)
{
abort ();
}
static void force_unwind () static void force_unwind ()
{ {
_Unwind_Exception *exc = new _Unwind_Exception; _Unwind_Exception *exc = new _Unwind_Exception;
exc->exception_class = 0; exc->exception_class = 0;
exc->exception_cleanup = 0; exc->exception_cleanup = force_unwind_cleanup;
#ifndef __USING_SJLJ_EXCEPTIONS__ #ifndef __USING_SJLJ_EXCEPTIONS__
_Unwind_ForcedUnwind (exc, force_unwind_stop, 0); _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
...@@ -58,18 +64,17 @@ static void doit () ...@@ -58,18 +64,17 @@ static void doit ()
} catch(...) { } catch(...) {
test |= 2; test |= 2;
throw;
} }
} catch(...) { } catch(...) {
test |= 8; test |= 8;
throw;
} }
} }
int main() int main()
{ {
try {
doit (); doit ();
} catch (...) {
}
abort (); abort ();
} }
// { dg-do run } // { 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 <unwind.h>
#include <stdlib.h> #include <stdlib.h>
static int test = 0;
static _Unwind_Reason_Code static _Unwind_Reason_Code
force_unwind_stop (int version, _Unwind_Action actions, force_unwind_stop (int version, _Unwind_Action actions,
_Unwind_Exception_Class exc_class, _Unwind_Exception_Class exc_class,
...@@ -16,24 +14,22 @@ force_unwind_stop (int version, _Unwind_Action actions, ...@@ -16,24 +14,22 @@ force_unwind_stop (int version, _Unwind_Action actions,
void *stop_parameter) void *stop_parameter)
{ {
if (actions & _UA_END_OF_STACK) if (actions & _UA_END_OF_STACK)
{
if (test != 5)
abort (); abort ();
exit (0);
}
return _URC_NO_REASON; return _URC_NO_REASON;
} }
// Note that neither the noreturn nor the nothrow specification static void
// affects forced unwinding. force_unwind_cleanup (_Unwind_Reason_Code, struct _Unwind_Exception *)
{
exit (0);
}
static void __attribute__((noreturn)) static void
force_unwind () throw() force_unwind ()
{ {
_Unwind_Exception *exc = new _Unwind_Exception; _Unwind_Exception *exc = new _Unwind_Exception;
exc->exception_class = 0; exc->exception_class = 0;
exc->exception_cleanup = 0; exc->exception_cleanup = force_unwind_cleanup;
#ifndef __USING_SJLJ_EXCEPTIONS__ #ifndef __USING_SJLJ_EXCEPTIONS__
_Unwind_ForcedUnwind (exc, force_unwind_stop, 0); _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
...@@ -44,47 +40,10 @@ force_unwind () throw() ...@@ -44,47 +40,10 @@ force_unwind () throw()
abort (); abort ();
} }
struct S
{
int bit;
S(int b) : bit(b) { }
~S() { test |= bit; }
};
static void doit_3 ()
{
S one(1);
force_unwind ();
}
static void doit_2 ()
{
try {
doit_3 ();
} catch (...) {
test |= 2;
}
}
static void doit_1 ()
{
S four(4);
doit_2 ();
}
static void doit ()
{
try {
doit_1 ();
} catch(...) {
test |= 8;
}
}
int main() int main()
{ {
try { try {
doit (); force_unwind ();
} catch (...) { } catch (...) {
} }
abort (); abort ();
......
// { 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 ();
}
// { 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 (...) {
}
}
...@@ -740,10 +740,6 @@ int flag_unwind_tables = 0; ...@@ -740,10 +740,6 @@ int flag_unwind_tables = 0;
int flag_asynchronous_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 /* Nonzero means don't place uninitialized global data in common storage
by default. */ by default. */
...@@ -1128,8 +1124,6 @@ static const lang_independent_options f_options[] = ...@@ -1128,8 +1124,6 @@ static const lang_independent_options f_options[] =
N_("Generate unwind tables exact at each instruction boundary") }, N_("Generate unwind tables exact at each instruction boundary") },
{"non-call-exceptions", &flag_non_call_exceptions, 1, {"non-call-exceptions", &flag_non_call_exceptions, 1,
N_("Support synchronous non-call exceptions") }, 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, {"profile-arcs", &profile_arc_flag, 1,
N_("Insert arc based program profiling code") }, N_("Insert arc based program profiling code") },
{"test-coverage", &flag_test_coverage, 1, {"test-coverage", &flag_test_coverage, 1,
......
...@@ -285,6 +285,7 @@ uw_identify_context (struct _Unwind_Context *context) ...@@ -285,6 +285,7 @@ uw_identify_context (struct _Unwind_Context *context)
#define _Unwind_RaiseException _Unwind_SjLj_RaiseException #define _Unwind_RaiseException _Unwind_SjLj_RaiseException
#define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind #define _Unwind_ForcedUnwind _Unwind_SjLj_ForcedUnwind
#define _Unwind_Resume _Unwind_SjLj_Resume #define _Unwind_Resume _Unwind_SjLj_Resume
#define _Unwind_Resume_or_Rethrow _Unwind_SjLj_Resume_or_Rethrow
#include "unwind.inc" #include "unwind.inc"
......
...@@ -127,6 +127,10 @@ extern void _Unwind_DeleteException (struct _Unwind_Exception *); ...@@ -127,6 +127,10 @@ extern void _Unwind_DeleteException (struct _Unwind_Exception *);
e.g. executing cleanup code, and not to implement rethrowing. */ e.g. executing cleanup code, and not to implement rethrowing. */
extern void _Unwind_Resume (struct _Unwind_Exception *); extern void _Unwind_Resume (struct _Unwind_Exception *);
/* @@@ Resume propagation of an FORCE_UNWIND exception, or to rethrow
a normal exception that was handled. */
extern _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (struct _Unwind_Exception *);
/* @@@ Use unwind data to perform a stack backtrace. The trace callback /* @@@ Use unwind data to perform a stack backtrace. The trace callback
is called for every stack frame in the call chain, but no cleanup is called for every stack frame in the call chain, but no cleanup
actions are performed. */ actions are performed. */
...@@ -184,6 +188,7 @@ extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException ...@@ -184,6 +188,7 @@ extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException
extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind
(struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *);
extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *); extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *);
extern _Unwind_Reason_Code _Unwind_SjLj_Resume_or_Rethrow (struct _Unwind_Exception *);
/* @@@ The following provide access to the base addresses for text /* @@@ The following provide access to the base addresses for text
and data-relative addressing in the LDSA. In order to stay link and data-relative addressing in the LDSA. In order to stay link
......
...@@ -232,11 +232,39 @@ _Unwind_Resume (struct _Unwind_Exception *exc) ...@@ -232,11 +232,39 @@ _Unwind_Resume (struct _Unwind_Exception *exc)
uw_install_context (&this_context, &cur_context); uw_install_context (&this_context, &cur_context);
} }
/* Resume propagation of an FORCE_UNWIND exception, or to rethrow
a normal exception that was handled. */
_Unwind_Reason_Code
_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. */ /* A convenience function that calls the exception_cleanup field. */
void void
_Unwind_DeleteException (struct _Unwind_Exception *exc) _Unwind_DeleteException (struct _Unwind_Exception *exc)
{ {
if (exc->exception_cleanup)
(*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc); (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
} }
...@@ -274,4 +302,3 @@ _Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument) ...@@ -274,4 +302,3 @@ _Unwind_Backtrace(_Unwind_Trace_Fn trace, void * trace_argument)
return code; return code;
} }
2003-05-07 Richard Henderson <rth@redhat.com>
PR c++/10570
* 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.
2003-05-07 Benjamin Kosnik <bkoz@redhat.com> 2003-05-07 Benjamin Kosnik <bkoz@redhat.com>
* testsuite/27_io/ios_base/cons: New. * testsuite/27_io/ios_base/cons: New.
......
// -*- C++ -*- Exception handling routines for catching. // -*- 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. // This file is part of GNU CC.
// //
...@@ -39,15 +39,28 @@ __cxa_begin_catch (void *exc_obj_in) ...@@ -39,15 +39,28 @@ __cxa_begin_catch (void *exc_obj_in)
{ {
_Unwind_Exception *exceptionObject _Unwind_Exception *exceptionObject
= reinterpret_cast <_Unwind_Exception *>(exc_obj_in); = 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_eh_globals *globals = __cxa_get_globals ();
__cxa_exception *prev = globals->caughtExceptions; __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) if (count < 0)
// This exception was rethrown from an immediately enclosing region. // This exception was rethrown from an immediately enclosing region.
count = -count + 1; count = -count + 1;
...@@ -71,8 +84,22 @@ __cxa_end_catch () ...@@ -71,8 +84,22 @@ __cxa_end_catch ()
{ {
__cxa_eh_globals *globals = __cxa_get_globals_fast (); __cxa_eh_globals *globals = __cxa_get_globals_fast ();
__cxa_exception *header = globals->caughtExceptions; __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) if (count < 0)
{ {
// This exception was rethrown. Decrement the (inverted) catch // This exception was rethrown. Decrement the (inverted) catch
...@@ -92,7 +119,7 @@ __cxa_end_catch () ...@@ -92,7 +119,7 @@ __cxa_end_catch ()
} }
else if (count < 0) else if (count < 0)
// A bug in the exception handling library or compiler. // A bug in the exception handling library or compiler.
std::abort (); std::terminate ();
header->handlerCount = count; header->handlerCount = count;
} }
......
// -*- C++ -*- The GNU C++ exception personality routine. // -*- 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. // This file is part of GNU CC.
// //
...@@ -124,6 +124,8 @@ get_adjusted_ptr (const std::type_info *catch_type, ...@@ -124,6 +124,8 @@ get_adjusted_ptr (const std::type_info *catch_type,
return false; return false;
} }
// Return true if THROW_TYPE matches one if the filter types.
static bool static bool
check_exception_spec (lsda_header_info *info, const std::type_info *throw_type, check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
void *thrown_ptr, _Unwind_Sword filter_value) void *thrown_ptr, _Unwind_Sword filter_value)
...@@ -154,6 +156,18 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type, ...@@ -154,6 +156,18 @@ check_exception_spec (lsda_header_info *info, const std::type_info *throw_type,
} }
} }
// 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 // Using a different personality function name causes link failures
// when trying to mix code using different exception handling models. // when trying to mix code using different exception handling models.
#ifdef _GLIBCPP_SJLJ_EXCEPTIONS #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
...@@ -197,6 +211,7 @@ PERSONALITY_FUNCTION (int version, ...@@ -197,6 +211,7 @@ PERSONALITY_FUNCTION (int version,
&& exception_class == __gxx_exception_class) && exception_class == __gxx_exception_class)
{ {
handler_switch_value = xh->handlerSwitchValue; handler_switch_value = xh->handlerSwitchValue;
language_specific_data = xh->languageSpecificData;
landing_pad = (_Unwind_Ptr) xh->catchTemp; landing_pad = (_Unwind_Ptr) xh->catchTemp;
found_type = (landing_pad == 0 ? found_terminate : found_handler); found_type = (landing_pad == 0 ? found_terminate : found_handler);
goto install_context; goto install_context;
...@@ -275,7 +290,7 @@ PERSONALITY_FUNCTION (int version, ...@@ -275,7 +290,7 @@ PERSONALITY_FUNCTION (int version,
// If ip is not present in the table, call terminate. This is for // If ip is not present in the table, call terminate. This is for
// a destructor inside a cleanup, or a library routine the compiler // a destructor inside a cleanup, or a library routine the compiler
// was not expecting to throw. // was not expecting to throw.
found_type = (actions & _UA_FORCE_UNWIND ? found_nothing : found_terminate); found_type = found_terminate;
goto do_something; goto do_something;
found_something: found_something:
...@@ -327,34 +342,29 @@ PERSONALITY_FUNCTION (int version, ...@@ -327,34 +342,29 @@ PERSONALITY_FUNCTION (int version,
// Positive filter values are handlers. // Positive filter values are handlers.
catch_type = get_ttype_entry (&info, ar_filter); catch_type = get_ttype_entry (&info, ar_filter);
// Null catch type is a catch-all handler. We can catch // Null catch type is a catch-all handler; we can catch foreign
// foreign exceptions with this. // exceptions with this. Otherwise we must match types.
if (! catch_type) if (! catch_type
{ || (throw_type
if (!(actions & _UA_FORCE_UNWIND)) && get_adjusted_ptr (catch_type, throw_type,
{ &thrown_ptr)))
saw_handler = true;
break;
}
}
else if (throw_type)
{
if (get_adjusted_ptr (catch_type, throw_type, &thrown_ptr))
{ {
saw_handler = true; saw_handler = true;
break; break;
} }
} }
}
else else
{ {
// Negative filter values are exception specifications. // Negative filter values are exception specifications.
// ??? How do foreign exceptions fit in? As far as I can // ??? How do foreign exceptions fit in? As far as I can
// see we can't match because there's no __cxa_exception // see we can't match because there's no __cxa_exception
// object to stuff bits in for __cxa_call_unexpected to use. // 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 if (throw_type
&& ! check_exception_spec (&info, throw_type, thrown_ptr, ? ! check_exception_spec (&info, throw_type, thrown_ptr,
ar_filter)) ar_filter)
: empty_exception_spec (&info, ar_filter))
{ {
saw_handler = true; saw_handler = true;
break; break;
...@@ -400,6 +410,24 @@ PERSONALITY_FUNCTION (int version, ...@@ -400,6 +410,24 @@ PERSONALITY_FUNCTION (int version,
} }
install_context: install_context:
// 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)
{
if (found_type == found_terminate)
std::terminate ();
else if (handler_switch_value < 0)
{
try
{ std::unexpected (); }
catch(...)
{ std::terminate (); }
}
}
else
{
if (found_type == found_terminate) if (found_type == found_terminate)
{ {
__cxa_begin_catch (&xh->unwindHeader); __cxa_begin_catch (&xh->unwindHeader);
...@@ -410,9 +438,9 @@ PERSONALITY_FUNCTION (int version, ...@@ -410,9 +438,9 @@ PERSONALITY_FUNCTION (int version,
// have an _Unwind_Context then. // have an _Unwind_Context then.
if (handler_switch_value < 0) if (handler_switch_value < 0)
{ {
parse_lsda_header (context, xh->languageSpecificData, &info); parse_lsda_header (context, language_specific_data, &info);
xh->catchTemp = base_of_encoded_value (info.ttype_encoding, xh->catchTemp = base_of_encoded_value (info.ttype_encoding, context);
context); }
} }
_Unwind_SetGR (context, __builtin_eh_return_data_regno (0), _Unwind_SetGR (context, __builtin_eh_return_data_regno (0),
...@@ -457,7 +485,6 @@ __cxa_call_unexpected (void *exc_obj_in) ...@@ -457,7 +485,6 @@ __cxa_call_unexpected (void *exc_obj_in)
catch(...) catch(...)
{ {
// Get the exception thrown from unexpected. // Get the exception thrown from unexpected.
// ??? Foreign exceptions can't be stacked this way.
__cxa_eh_globals *globals = __cxa_get_globals_fast (); __cxa_eh_globals *globals = __cxa_get_globals_fast ();
__cxa_exception *new_xh = globals->caughtExceptions; __cxa_exception *new_xh = globals->caughtExceptions;
...@@ -479,6 +506,7 @@ __cxa_call_unexpected (void *exc_obj_in) ...@@ -479,6 +506,7 @@ __cxa_call_unexpected (void *exc_obj_in)
if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value)) if (check_exception_spec (&info, &bad_exc, 0, xh_switch_value))
throw std::bad_exception(); throw std::bad_exception();
#endif #endif
// Otherwise, die. // Otherwise, die.
__terminate (xh_terminate_handler); __terminate (xh_terminate_handler);
} }
......
// -*- C++ -*- Exception handling routines for throwing. // -*- 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. // This file is part of GNU CC.
// //
...@@ -90,12 +90,15 @@ __cxa_rethrow () ...@@ -90,12 +90,15 @@ __cxa_rethrow ()
if (header) if (header)
{ {
// Tell __cxa_end_catch this is a rethrow. // Tell __cxa_end_catch this is a rethrow.
if (header->unwindHeader.exception_class != __gxx_exception_class)
globals->caughtExceptions = 0;
else
header->handlerCount = -header->handlerCount; header->handlerCount = -header->handlerCount;
#ifdef _GLIBCPP_SJLJ_EXCEPTIONS #ifdef _GLIBCPP_SJLJ_EXCEPTIONS
_Unwind_SjLj_RaiseException (&header->unwindHeader); _Unwind_SjLj_Resume_or_Rethrow (&header->unwindHeader);
#else #else
_Unwind_RaiseException (&header->unwindHeader); _Unwind_Resume_or_Rethrow (&header->unwindHeader);
#endif #endif
// Some sort of unwinding error. Note that terminate is a handler. // Some sort of unwinding error. Note that terminate is a handler.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment