Richard Henderson
2003-04-30 17:53:35 UTC
The result of the original thread
http://gcc.gnu.org/ml/gcc-patches/2003-04/msg00008.html
endorsed different semantics than I assumed in my original
patch. Here I update things to match the consensus.
Mark, I know it's getting late, but is this ok for 3.3?
(There'll be a pr shortly; wanted to include a pointer to
this message in the description text though.)
r~
gcc/
* except.c (RNL_ALWAYS_CAUGHT): New.
(expand_eh_region_end_cleanup): Ignore flag_forced_unwind_exceptions.
(convert_from_eh_region_ranges_1): Likewise.
(build_post_landing_pads): Likewise.
(sjlj_find_directly_reachable_regions): Likewise.
(collect_one_action_chain): Likewise.
(reachable_next_level): Return RNL_ALWAYS_CAUGHT for empty filter
spec and must_not_throw shadowing other catch handlers.
(reachable_handlers): With forced unwinding, only mark cleanups
live after catch(...), not throw().
(can_throw_external): Similarly wrt exceptions escaping the function.
gcc/cp/
* Make-lang.in (cfns.h): Add -t to gperf invocation.
* cfns.gperf: Use a structure; mark POSIX cancellation points.
* except.c (nothrow_libfn_p): Return bool; return false for
cancellation points when forced unwinding in effect.
* cp-tree.h (nothrow_libfn_p): Update declaration.
gcc/testsuite/
* g++.dg/eh/forced2.C (force_unwind): Remove nothrow spec.
libstdc++-v3/
* libsupc++/eh_personality.cc (empty_exception_spec): New.
(PERSONALITY_FUNCTION): Ignore FORCE_UNWIND when considering
must_not_throw barriers; allow empty filter specs to signal
unexpected on FORCE and foreign exception types.
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 30 Apr 2003 17:34:44 -0000
@@ -1,6 +1,6 @@
/* Implements exception handling.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Mike Stump <***@cygnus.com>.
This file is part of GCC.
@@ -324,8 +324,12 @@ enum reachable_code
RNL_NOT_CAUGHT,
/* The given exception may need processing by the given region. */
RNL_MAYBE_CAUGHT,
- /* The given exception is completely processed by the given region. */
+ /* The given exception is completely processed by the given region,
+ via catch clauses. */
RNL_CAUGHT,
+ /* The given exception is completely processed by the given region,
+ via empty eh filter specs or must_not_throw clauses. */
+ RNL_ALWAYS_CAUGHT,
/* The given exception is completely processed by the runtime. */
RNL_BLOCKED
};
@@ -562,9 +566,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. */
@@ -1140,16 +1142,10 @@ convert_from_eh_region_ranges_1 (pinsns,
/* 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. */
+ of 0 means that "normal" exceptions are suppressed. */
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;
- }
+ break;
/* Calls can always potentially throw exceptions; if we wanted
exceptions for non-call insns, then any may_trap_p
@@ -1793,33 +1789,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:
@@ -2000,21 +1971,7 @@ sjlj_find_directly_reachable_regions (lp
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 || rc == RNL_ALWAYS_CAUGHT)
{
lp_info[region->region_number].directly_reachable = 1;
found_one = true;
@@ -2752,7 +2709,7 @@ reachable_next_level (region, type_throw
if (region->u.allowed.type_list == NULL_TREE)
{
add_reachable_handler (info, region, region);
- return RNL_CAUGHT;
+ return RNL_ALWAYS_CAUGHT;
}
/* Collect a list of lists of allowed types for use in detecting
@@ -2791,7 +2748,7 @@ reachable_next_level (region, type_throw
if (info && info->handlers)
{
add_reachable_handler (info, region, region);
- return RNL_CAUGHT;
+ return RNL_ALWAYS_CAUGHT;
}
else
return RNL_BLOCKED;
@@ -2851,10 +2808,11 @@ reachable_handlers (insn)
while (region)
{
- if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
+ /* Forced unwind exceptions may be BLOCKED but not CAUGHT.
+ Make sure the cleanup regions are reachable. */
+ switch (reachable_next_level (region, type_thrown, &info))
{
- /* Forced unwind exceptions are neither BLOCKED nor CAUGHT.
- Make sure the cleanup regions are reachable. */
+ case RNL_CAUGHT:
if (flag_forced_unwind_exceptions)
{
while ((region = region->outer) != NULL)
@@ -2864,6 +2822,13 @@ reachable_handlers (insn)
break;
}
}
+ goto fini;
+
+ case RNL_ALWAYS_CAUGHT:
+ case RNL_BLOCKED:
+ goto fini;
+
+ default:
break;
}
@@ -2876,6 +2841,7 @@ reachable_handlers (insn)
else
region = region->outer;
}
+ fini:
return info.handlers;
}
@@ -2988,10 +2954,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;
@@ -3004,8 +2966,18 @@ can_throw_external (insn)
/* If the exception is caught or blocked by any containing region,
then it is not seen by any calling function. */
for (; region ; region = region->outer)
- if (reachable_next_level (region, type_thrown, NULL) >= RNL_CAUGHT)
- return false;
+ switch (reachable_next_level (region, type_thrown, NULL))
+ {
+ case RNL_CAUGHT:
+ if (!flag_forced_unwind_exceptions)
+ break;
+ /* FALLTHRU */
+ case RNL_ALWAYS_CAUGHT:
+ case RNL_BLOCKED:
+ return false;
+ default:
+ break;
+ }
return true;
}
@@ -3410,13 +3382,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/cp/Make-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/Make-lang.in,v
retrieving revision 1.125.4.3
diff -c -p -d -u -r1.125.4.3 Make-lang.in
--- gcc/cp/Make-lang.in 13 Feb 2003 07:17:09 -0000 1.125.4.3
+++ gcc/cp/Make-lang.in 30 Apr 2003 17:34:45 -0000
@@ -98,7 +98,7 @@ cc1plus$(exeext): $(CXX_OBJS) $(CXX_C_OB
# Special build rules.
$(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf
- gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' \
+ gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' -t \
$(srcdir)/cp/cfns.gperf > $(srcdir)/cp/cfns.h
$(srcdir)/cp/parse.h: $(srcdir)/cp/parse.c
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 30 Apr 2003 17:34:45 -0000
@@ -1,4 +1,20 @@
%{
+/*
+ * The standard C library functions, for feeding to gperf; the result is used
+ * by nothrow_libfn_p.
+ *
+ * [lib.res.on.exception.handling]: None of the functions from the
+ * Standard C library shall report an error by throwing an
+ * exception, unless it calls a program-supplied function that
+ * throws an exception.
+ *
+ * bsearch and qsort are omitted because they can call such functions.
+ *
+ * Cancellation points are marked either 1 (primary cancellation point)
+ * or 2 (secondary cancellation point). Taken from Section 2.9.5.2 of
+ * IEEE 1003.1 (POSIX 1) TC1.
+ */
+
#ifdef __GNUC__
__inline
#endif
@@ -6,224 +22,215 @@ static unsigned int hash PARAMS ((const
#ifdef __GNUC__
__inline
#endif
-const char * libc_name_p PARAMS ((const char *, unsigned int));
+const struct libc_name_data *libc_name_p PARAMS ((const char *, unsigned int));
%}
-# The standard C library functions, for feeding to gperf; the result is used
-# by nothrow_libfn_p.
-#
-# [lib.res.on.exception.handling]: None of the functions from the
-# Standard C library shall report an error by throwing an
-# exception, unless it calls a program-supplied function that
-# throws an exception.
-#
-# bsearch and qsort are commented out because they can call such functions.
-#
-abort
-abs
-acos
-asctime
-asin
-atan
-atan2
-atexit
-atof
-atoi
-atol
-#bsearch
-btowc
-calloc
-ceil
-clearerr
-clock
-cos
-cosh
-ctime
-difftime
-div
-exit
-exp
-fabs
-fclose
-feof
-ferror
-fflush
-fgetc
-fgetpos
-fgets
-fgetwc
-fgetws
-floor
-fmod
-fopen
-fprintf
-fputc
-fputs
-fputwc
-fputws
-fread
-free
-freopen
-frexp
-fscanf
-fseek
-fsetpos
-ftell
-fwide
-fwprintf
-fwrite
-fwscanf
-getc
-getchar
-getenv
-gets
-getwc
-getwchar
-gmtime
-isalnum
-isalpha
-iscntrl
-isdigit
-isgraph
-islower
-isprint
-ispunct
-isspace
-isupper
-iswalnum
-iswalpha
-iswcntrl
-iswctype
-iswdigit
-iswgraph
-iswlower
-iswprint
-iswpunct
-iswspace
-iswupper
-iswxdigit
-isxdigit
-labs
-ldexp
-ldiv
-localeconv
-localtime
-log
-log10
-longjmp
-malloc
-mblen
-mbrlen
-mbrtowc
-mbsinit
-mbsrtowcs
-mbstowcs
-mbtowc
-memchr
-memcmp
-memcpy
-memmove
-memset
-mktime
-modf
-perror
-pow
-printf
-putc
-putchar
-puts
-putwc
-putwchar
-#qsort
-raise
-rand
-realloc
-remove
-rename
-rewind
-scanf
-setbuf
-setlocale
-setvbuf
-signal
-sin
-sinh
-sprintf
-sqrt
-srand
-sscanf
-strcat
-strchr
-strcmp
-strcoll
-strcpy
-strcspn
-strerror
-strftime
-strlen
-strncat
-strncmp
-strncpy
-strpbrk
-strrchr
-strspn
-strstr
-strtod
-strtok
-strtol
-strtoul
-strxfrm
-swprintf
-swscanf
-system
-tan
-tanh
-time
-tmpfile
-tmpnam
-tolower
-toupper
-towctrans
-towlower
-towupper
-ungetc
-ungetwc
-vfprintf
-vfwprintf
-vprintf
-vsprintf
-vswprintf
-vwprintf
-wcrtomb
-wcscat
-wcschr
-wcscmp
-wcscoll
-wcscpy
-wcscspn
-wcsftime
-wcslen
-wcsncat
-wcsncmp
-wcsncpy
-wcspbrk
-wcsrchr
-wcsrtombs
-wcsspn
-wcsstr
-wcstod
-wcstok
-wcstol
-wcstombs
-wcstoul
-wcsxfrm
-wctob
-wctomb
-wctrans
-wctype
-wmemchr
-wmemcmp
-wmemcpy
-wmemmove
-wmemset
-wprintf
-wscanf
+struct libc_name_data { const char *name; int cancelation_point; };
+%%
+abort, 0
+abs, 0
+acos, 0
+asctime, 0
+asin, 0
+atan, 0
+atan2, 0
+atexit, 0
+atof, 0
+atoi, 0
+atol, 0
+btowc, 0
+calloc, 0
+ceil, 0
+clearerr, 0
+clock, 0
+cos, 0
+cosh, 0
+ctime, 0
+difftime, 0
+div, 0
+exit, 0
+exp, 0
+fabs, 0
+fclose, 2
+feof, 0
+ferror, 0
+fflush, 2
+fgetc, 2
+fgetpos, 2
+fgets, 2
+fgetwc, 2
+fgetws, 2
+floor, 0
+fmod, 0
+fopen, 2
+fprintf, 2
+fputc, 2
+fputs, 2
+fputwc, 2
+fputws, 2
+fread, 2
+free, 0
+freopen, 2
+frexp, 0
+fscanf, 2
+fseek, 2
+fsetpos, 2
+ftell, 2
+fwide, 0
+fwprintf, 2
+fwrite, 2
+fwscanf, 2
+getc, 2
+getchar, 2
+getenv, 0
+gets, 2
+getwc, 2
+getwchar, 2
+gmtime, 0
+isalnum, 0
+isalpha, 0
+iscntrl, 0
+isdigit, 0
+isgraph, 0
+islower, 0
+isprint, 0
+ispunct, 0
+isspace, 0
+isupper, 0
+iswalnum, 0
+iswalpha, 0
+iswcntrl, 0
+iswctype, 0
+iswdigit, 0
+iswgraph, 0
+iswlower, 0
+iswprint, 0
+iswpunct, 0
+iswspace, 0
+iswupper, 0
+iswxdigit, 0
+isxdigit, 0
+labs, 0
+ldexp, 0
+ldiv, 0
+localeconv, 0
+localtime, 0
+log, 0
+log10, 0
+longjmp, 0
+malloc, 0
+mblen, 0
+mbrlen, 0
+mbrtowc, 0
+mbsinit, 0
+mbsrtowcs, 0
+mbstowcs, 0
+mbtowc, 0
+memchr, 0
+memcmp, 0
+memcpy, 0
+memmove, 0
+memset, 0
+mktime, 0
+modf, 0
+perror, 2
+pow, 0
+printf, 2
+putc, 2
+putchar, 2
+puts, 2
+putwc, 2
+putwchar, 2
+raise, 0
+rand, 0
+realloc, 0
+remove, 2
+rename, 2
+rewind, 2
+scanf, 2
+setbuf, 0
+setlocale, 0
+setvbuf, 0
+signal, 0
+sin, 0
+sinh, 0
+sprintf, 2
+sqrt, 0
+srand, 0
+sscanf, 0
+strcat, 0
+strchr, 0
+strcmp, 0
+strcoll, 0
+strcpy, 0
+strcspn, 0
+strerror, 2
+strftime, 0
+strlen, 0
+strncat, 0
+strncmp, 0
+strncpy, 0
+strpbrk, 0
+strrchr, 0
+strspn, 0
+strstr, 0
+strtod, 0
+strtok, 0
+strtol, 0
+strtoul, 0
+strxfrm, 0
+swprintf, 0
+swscanf, 0
+system, 1
+tan, 0
+tanh, 0
+time, 0
+tmpfile, 2
+tmpnam, 2
+tolower, 0
+toupper, 0
+towctrans, 0
+towlower, 0
+towupper, 0
+ungetc, 2
+ungetwc, 2
+vfprintf, 2
+vfwprintf, 2
+vprintf, 2
+vsprintf, 0
+vswprintf, 0
+vwprintf, 2
+wcrtomb, 0
+wcscat, 0
+wcschr, 0
+wcscmp, 0
+wcscoll, 0
+wcscpy, 0
+wcscspn, 0
+wcsftime, 0
+wcslen, 0
+wcsncat, 0
+wcsncmp, 0
+wcsncpy, 0
+wcspbrk, 0
+wcsrchr, 0
+wcsrtombs, 0
+wcsspn, 0
+wcsstr, 0
+wcstod, 0
+wcstok, 0
+wcstol, 0
+wcstombs, 0
+wcstoul, 0
+wcsxfrm, 0
+wctob, 0
+wctomb, 0
+wctrans, 0
+wctype, 0
+wmemchr, 0
+wmemcmp, 0
+wmemcpy, 0
+wmemmove, 0
+wmemset, 0
+wprintf, 2
+wscanf, 2
+%%
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.776.2.18
diff -c -p -d -u -r1.776.2.18 cp-tree.h
--- gcc/cp/cp-tree.h 29 Apr 2003 18:51:55 -0000 1.776.2.18
+++ gcc/cp/cp-tree.h 30 Apr 2003 17:34:46 -0000
@@ -3910,7 +3910,7 @@ extern void expand_exception_blocks PAR
extern tree build_exc_ptr PARAMS ((void));
extern tree build_throw PARAMS ((tree));
extern void mark_all_runtime_matches PARAMS ((void));
-extern int nothrow_libfn_p PARAMS ((tree));
+extern bool nothrow_libfn_p PARAMS ((tree));
extern void check_handlers PARAMS ((tree));
extern void choose_personality_routine PARAMS ((enum languages));
Index: gcc/cp/except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/except.c,v
retrieving revision 1.149
diff -c -p -d -u -r1.149 except.c
--- gcc/cp/except.c 4 Dec 2002 20:13:01 -0000 1.149
+++ gcc/cp/except.c 30 Apr 2003 17:34:47 -0000
@@ -870,10 +870,11 @@ is_admissible_throw_operand (expr)
#include "cfns.h"
-int
+bool
nothrow_libfn_p (fn)
tree fn;
{
+ const struct libc_name_data *entry;
tree id;
if (TREE_PUBLIC (fn)
@@ -883,10 +884,16 @@ nothrow_libfn_p (fn)
/* OK */;
else
/* Can't be a C library function. */
- return 0;
+ return false;
id = DECL_ASSEMBLER_NAME (fn);
- return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
+ entry = libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
+ if (!entry)
+ return false;
+ if (flag_forced_unwind_exceptions)
+ return !entry->cancelation_point;
+ else
+ return true;
}
/* Returns nonzero if an exception of type FROM will be caught by a
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 30 Apr 2003 17:34:47 -0000
@@ -25,11 +25,10 @@ force_unwind_stop (int version, _Unwind_
return _URC_NO_REASON;
}
-// Note that neither the noreturn nor the nothrow specification
-// affects forced unwinding.
+// Note that the noreturn specification doesn't affect forced unwinding.
static void __attribute__((noreturn))
-force_unwind () throw()
+force_unwind ()
{
_Unwind_Exception *exc = new _Unwind_Exception;
exc->exception_class = 0;
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 30 Apr 2003 17:34:49 -0000
@@ -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
@@ -275,7 +289,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:
@@ -352,9 +366,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;
http://gcc.gnu.org/ml/gcc-patches/2003-04/msg00008.html
endorsed different semantics than I assumed in my original
patch. Here I update things to match the consensus.
Mark, I know it's getting late, but is this ok for 3.3?
(There'll be a pr shortly; wanted to include a pointer to
this message in the description text though.)
r~
gcc/
* except.c (RNL_ALWAYS_CAUGHT): New.
(expand_eh_region_end_cleanup): Ignore flag_forced_unwind_exceptions.
(convert_from_eh_region_ranges_1): Likewise.
(build_post_landing_pads): Likewise.
(sjlj_find_directly_reachable_regions): Likewise.
(collect_one_action_chain): Likewise.
(reachable_next_level): Return RNL_ALWAYS_CAUGHT for empty filter
spec and must_not_throw shadowing other catch handlers.
(reachable_handlers): With forced unwinding, only mark cleanups
live after catch(...), not throw().
(can_throw_external): Similarly wrt exceptions escaping the function.
gcc/cp/
* Make-lang.in (cfns.h): Add -t to gperf invocation.
* cfns.gperf: Use a structure; mark POSIX cancellation points.
* except.c (nothrow_libfn_p): Return bool; return false for
cancellation points when forced unwinding in effect.
* cp-tree.h (nothrow_libfn_p): Update declaration.
gcc/testsuite/
* g++.dg/eh/forced2.C (force_unwind): Remove nothrow spec.
libstdc++-v3/
* libsupc++/eh_personality.cc (empty_exception_spec): New.
(PERSONALITY_FUNCTION): Ignore FORCE_UNWIND when considering
must_not_throw barriers; allow empty filter specs to signal
unexpected on FORCE and foreign exception types.
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 30 Apr 2003 17:34:44 -0000
@@ -1,6 +1,6 @@
/* Implements exception handling.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Mike Stump <***@cygnus.com>.
This file is part of GCC.
@@ -324,8 +324,12 @@ enum reachable_code
RNL_NOT_CAUGHT,
/* The given exception may need processing by the given region. */
RNL_MAYBE_CAUGHT,
- /* The given exception is completely processed by the given region. */
+ /* The given exception is completely processed by the given region,
+ via catch clauses. */
RNL_CAUGHT,
+ /* The given exception is completely processed by the given region,
+ via empty eh filter specs or must_not_throw clauses. */
+ RNL_ALWAYS_CAUGHT,
/* The given exception is completely processed by the runtime. */
RNL_BLOCKED
};
@@ -562,9 +566,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. */
@@ -1140,16 +1142,10 @@ convert_from_eh_region_ranges_1 (pinsns,
/* 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. */
+ of 0 means that "normal" exceptions are suppressed. */
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;
- }
+ break;
/* Calls can always potentially throw exceptions; if we wanted
exceptions for non-call insns, then any may_trap_p
@@ -1793,33 +1789,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:
@@ -2000,21 +1971,7 @@ sjlj_find_directly_reachable_regions (lp
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 || rc == RNL_ALWAYS_CAUGHT)
{
lp_info[region->region_number].directly_reachable = 1;
found_one = true;
@@ -2752,7 +2709,7 @@ reachable_next_level (region, type_throw
if (region->u.allowed.type_list == NULL_TREE)
{
add_reachable_handler (info, region, region);
- return RNL_CAUGHT;
+ return RNL_ALWAYS_CAUGHT;
}
/* Collect a list of lists of allowed types for use in detecting
@@ -2791,7 +2748,7 @@ reachable_next_level (region, type_throw
if (info && info->handlers)
{
add_reachable_handler (info, region, region);
- return RNL_CAUGHT;
+ return RNL_ALWAYS_CAUGHT;
}
else
return RNL_BLOCKED;
@@ -2851,10 +2808,11 @@ reachable_handlers (insn)
while (region)
{
- if (reachable_next_level (region, type_thrown, &info) >= RNL_CAUGHT)
+ /* Forced unwind exceptions may be BLOCKED but not CAUGHT.
+ Make sure the cleanup regions are reachable. */
+ switch (reachable_next_level (region, type_thrown, &info))
{
- /* Forced unwind exceptions are neither BLOCKED nor CAUGHT.
- Make sure the cleanup regions are reachable. */
+ case RNL_CAUGHT:
if (flag_forced_unwind_exceptions)
{
while ((region = region->outer) != NULL)
@@ -2864,6 +2822,13 @@ reachable_handlers (insn)
break;
}
}
+ goto fini;
+
+ case RNL_ALWAYS_CAUGHT:
+ case RNL_BLOCKED:
+ goto fini;
+
+ default:
break;
}
@@ -2876,6 +2841,7 @@ reachable_handlers (insn)
else
region = region->outer;
}
+ fini:
return info.handlers;
}
@@ -2988,10 +2954,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;
@@ -3004,8 +2966,18 @@ can_throw_external (insn)
/* If the exception is caught or blocked by any containing region,
then it is not seen by any calling function. */
for (; region ; region = region->outer)
- if (reachable_next_level (region, type_thrown, NULL) >= RNL_CAUGHT)
- return false;
+ switch (reachable_next_level (region, type_thrown, NULL))
+ {
+ case RNL_CAUGHT:
+ if (!flag_forced_unwind_exceptions)
+ break;
+ /* FALLTHRU */
+ case RNL_ALWAYS_CAUGHT:
+ case RNL_BLOCKED:
+ return false;
+ default:
+ break;
+ }
return true;
}
@@ -3410,13 +3382,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/cp/Make-lang.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/Make-lang.in,v
retrieving revision 1.125.4.3
diff -c -p -d -u -r1.125.4.3 Make-lang.in
--- gcc/cp/Make-lang.in 13 Feb 2003 07:17:09 -0000 1.125.4.3
+++ gcc/cp/Make-lang.in 30 Apr 2003 17:34:45 -0000
@@ -98,7 +98,7 @@ cc1plus$(exeext): $(CXX_OBJS) $(CXX_C_OB
# Special build rules.
$(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf
- gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' \
+ gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' -t \
$(srcdir)/cp/cfns.gperf > $(srcdir)/cp/cfns.h
$(srcdir)/cp/parse.h: $(srcdir)/cp/parse.c
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 30 Apr 2003 17:34:45 -0000
@@ -1,4 +1,20 @@
%{
+/*
+ * The standard C library functions, for feeding to gperf; the result is used
+ * by nothrow_libfn_p.
+ *
+ * [lib.res.on.exception.handling]: None of the functions from the
+ * Standard C library shall report an error by throwing an
+ * exception, unless it calls a program-supplied function that
+ * throws an exception.
+ *
+ * bsearch and qsort are omitted because they can call such functions.
+ *
+ * Cancellation points are marked either 1 (primary cancellation point)
+ * or 2 (secondary cancellation point). Taken from Section 2.9.5.2 of
+ * IEEE 1003.1 (POSIX 1) TC1.
+ */
+
#ifdef __GNUC__
__inline
#endif
@@ -6,224 +22,215 @@ static unsigned int hash PARAMS ((const
#ifdef __GNUC__
__inline
#endif
-const char * libc_name_p PARAMS ((const char *, unsigned int));
+const struct libc_name_data *libc_name_p PARAMS ((const char *, unsigned int));
%}
-# The standard C library functions, for feeding to gperf; the result is used
-# by nothrow_libfn_p.
-#
-# [lib.res.on.exception.handling]: None of the functions from the
-# Standard C library shall report an error by throwing an
-# exception, unless it calls a program-supplied function that
-# throws an exception.
-#
-# bsearch and qsort are commented out because they can call such functions.
-#
-abort
-abs
-acos
-asctime
-asin
-atan
-atan2
-atexit
-atof
-atoi
-atol
-#bsearch
-btowc
-calloc
-ceil
-clearerr
-clock
-cos
-cosh
-ctime
-difftime
-div
-exit
-exp
-fabs
-fclose
-feof
-ferror
-fflush
-fgetc
-fgetpos
-fgets
-fgetwc
-fgetws
-floor
-fmod
-fopen
-fprintf
-fputc
-fputs
-fputwc
-fputws
-fread
-free
-freopen
-frexp
-fscanf
-fseek
-fsetpos
-ftell
-fwide
-fwprintf
-fwrite
-fwscanf
-getc
-getchar
-getenv
-gets
-getwc
-getwchar
-gmtime
-isalnum
-isalpha
-iscntrl
-isdigit
-isgraph
-islower
-isprint
-ispunct
-isspace
-isupper
-iswalnum
-iswalpha
-iswcntrl
-iswctype
-iswdigit
-iswgraph
-iswlower
-iswprint
-iswpunct
-iswspace
-iswupper
-iswxdigit
-isxdigit
-labs
-ldexp
-ldiv
-localeconv
-localtime
-log
-log10
-longjmp
-malloc
-mblen
-mbrlen
-mbrtowc
-mbsinit
-mbsrtowcs
-mbstowcs
-mbtowc
-memchr
-memcmp
-memcpy
-memmove
-memset
-mktime
-modf
-perror
-pow
-printf
-putc
-putchar
-puts
-putwc
-putwchar
-#qsort
-raise
-rand
-realloc
-remove
-rename
-rewind
-scanf
-setbuf
-setlocale
-setvbuf
-signal
-sin
-sinh
-sprintf
-sqrt
-srand
-sscanf
-strcat
-strchr
-strcmp
-strcoll
-strcpy
-strcspn
-strerror
-strftime
-strlen
-strncat
-strncmp
-strncpy
-strpbrk
-strrchr
-strspn
-strstr
-strtod
-strtok
-strtol
-strtoul
-strxfrm
-swprintf
-swscanf
-system
-tan
-tanh
-time
-tmpfile
-tmpnam
-tolower
-toupper
-towctrans
-towlower
-towupper
-ungetc
-ungetwc
-vfprintf
-vfwprintf
-vprintf
-vsprintf
-vswprintf
-vwprintf
-wcrtomb
-wcscat
-wcschr
-wcscmp
-wcscoll
-wcscpy
-wcscspn
-wcsftime
-wcslen
-wcsncat
-wcsncmp
-wcsncpy
-wcspbrk
-wcsrchr
-wcsrtombs
-wcsspn
-wcsstr
-wcstod
-wcstok
-wcstol
-wcstombs
-wcstoul
-wcsxfrm
-wctob
-wctomb
-wctrans
-wctype
-wmemchr
-wmemcmp
-wmemcpy
-wmemmove
-wmemset
-wprintf
-wscanf
+struct libc_name_data { const char *name; int cancelation_point; };
+%%
+abort, 0
+abs, 0
+acos, 0
+asctime, 0
+asin, 0
+atan, 0
+atan2, 0
+atexit, 0
+atof, 0
+atoi, 0
+atol, 0
+btowc, 0
+calloc, 0
+ceil, 0
+clearerr, 0
+clock, 0
+cos, 0
+cosh, 0
+ctime, 0
+difftime, 0
+div, 0
+exit, 0
+exp, 0
+fabs, 0
+fclose, 2
+feof, 0
+ferror, 0
+fflush, 2
+fgetc, 2
+fgetpos, 2
+fgets, 2
+fgetwc, 2
+fgetws, 2
+floor, 0
+fmod, 0
+fopen, 2
+fprintf, 2
+fputc, 2
+fputs, 2
+fputwc, 2
+fputws, 2
+fread, 2
+free, 0
+freopen, 2
+frexp, 0
+fscanf, 2
+fseek, 2
+fsetpos, 2
+ftell, 2
+fwide, 0
+fwprintf, 2
+fwrite, 2
+fwscanf, 2
+getc, 2
+getchar, 2
+getenv, 0
+gets, 2
+getwc, 2
+getwchar, 2
+gmtime, 0
+isalnum, 0
+isalpha, 0
+iscntrl, 0
+isdigit, 0
+isgraph, 0
+islower, 0
+isprint, 0
+ispunct, 0
+isspace, 0
+isupper, 0
+iswalnum, 0
+iswalpha, 0
+iswcntrl, 0
+iswctype, 0
+iswdigit, 0
+iswgraph, 0
+iswlower, 0
+iswprint, 0
+iswpunct, 0
+iswspace, 0
+iswupper, 0
+iswxdigit, 0
+isxdigit, 0
+labs, 0
+ldexp, 0
+ldiv, 0
+localeconv, 0
+localtime, 0
+log, 0
+log10, 0
+longjmp, 0
+malloc, 0
+mblen, 0
+mbrlen, 0
+mbrtowc, 0
+mbsinit, 0
+mbsrtowcs, 0
+mbstowcs, 0
+mbtowc, 0
+memchr, 0
+memcmp, 0
+memcpy, 0
+memmove, 0
+memset, 0
+mktime, 0
+modf, 0
+perror, 2
+pow, 0
+printf, 2
+putc, 2
+putchar, 2
+puts, 2
+putwc, 2
+putwchar, 2
+raise, 0
+rand, 0
+realloc, 0
+remove, 2
+rename, 2
+rewind, 2
+scanf, 2
+setbuf, 0
+setlocale, 0
+setvbuf, 0
+signal, 0
+sin, 0
+sinh, 0
+sprintf, 2
+sqrt, 0
+srand, 0
+sscanf, 0
+strcat, 0
+strchr, 0
+strcmp, 0
+strcoll, 0
+strcpy, 0
+strcspn, 0
+strerror, 2
+strftime, 0
+strlen, 0
+strncat, 0
+strncmp, 0
+strncpy, 0
+strpbrk, 0
+strrchr, 0
+strspn, 0
+strstr, 0
+strtod, 0
+strtok, 0
+strtol, 0
+strtoul, 0
+strxfrm, 0
+swprintf, 0
+swscanf, 0
+system, 1
+tan, 0
+tanh, 0
+time, 0
+tmpfile, 2
+tmpnam, 2
+tolower, 0
+toupper, 0
+towctrans, 0
+towlower, 0
+towupper, 0
+ungetc, 2
+ungetwc, 2
+vfprintf, 2
+vfwprintf, 2
+vprintf, 2
+vsprintf, 0
+vswprintf, 0
+vwprintf, 2
+wcrtomb, 0
+wcscat, 0
+wcschr, 0
+wcscmp, 0
+wcscoll, 0
+wcscpy, 0
+wcscspn, 0
+wcsftime, 0
+wcslen, 0
+wcsncat, 0
+wcsncmp, 0
+wcsncpy, 0
+wcspbrk, 0
+wcsrchr, 0
+wcsrtombs, 0
+wcsspn, 0
+wcsstr, 0
+wcstod, 0
+wcstok, 0
+wcstol, 0
+wcstombs, 0
+wcstoul, 0
+wcsxfrm, 0
+wctob, 0
+wctomb, 0
+wctrans, 0
+wctype, 0
+wmemchr, 0
+wmemcmp, 0
+wmemcpy, 0
+wmemmove, 0
+wmemset, 0
+wprintf, 2
+wscanf, 2
+%%
Index: gcc/cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.776.2.18
diff -c -p -d -u -r1.776.2.18 cp-tree.h
--- gcc/cp/cp-tree.h 29 Apr 2003 18:51:55 -0000 1.776.2.18
+++ gcc/cp/cp-tree.h 30 Apr 2003 17:34:46 -0000
@@ -3910,7 +3910,7 @@ extern void expand_exception_blocks PAR
extern tree build_exc_ptr PARAMS ((void));
extern tree build_throw PARAMS ((tree));
extern void mark_all_runtime_matches PARAMS ((void));
-extern int nothrow_libfn_p PARAMS ((tree));
+extern bool nothrow_libfn_p PARAMS ((tree));
extern void check_handlers PARAMS ((tree));
extern void choose_personality_routine PARAMS ((enum languages));
Index: gcc/cp/except.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/except.c,v
retrieving revision 1.149
diff -c -p -d -u -r1.149 except.c
--- gcc/cp/except.c 4 Dec 2002 20:13:01 -0000 1.149
+++ gcc/cp/except.c 30 Apr 2003 17:34:47 -0000
@@ -870,10 +870,11 @@ is_admissible_throw_operand (expr)
#include "cfns.h"
-int
+bool
nothrow_libfn_p (fn)
tree fn;
{
+ const struct libc_name_data *entry;
tree id;
if (TREE_PUBLIC (fn)
@@ -883,10 +884,16 @@ nothrow_libfn_p (fn)
/* OK */;
else
/* Can't be a C library function. */
- return 0;
+ return false;
id = DECL_ASSEMBLER_NAME (fn);
- return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
+ entry = libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
+ if (!entry)
+ return false;
+ if (flag_forced_unwind_exceptions)
+ return !entry->cancelation_point;
+ else
+ return true;
}
/* Returns nonzero if an exception of type FROM will be caught by a
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 30 Apr 2003 17:34:47 -0000
@@ -25,11 +25,10 @@ force_unwind_stop (int version, _Unwind_
return _URC_NO_REASON;
}
-// Note that neither the noreturn nor the nothrow specification
-// affects forced unwinding.
+// Note that the noreturn specification doesn't affect forced unwinding.
static void __attribute__((noreturn))
-force_unwind () throw()
+force_unwind ()
{
_Unwind_Exception *exc = new _Unwind_Exception;
exc->exception_class = 0;
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 30 Apr 2003 17:34:49 -0000
@@ -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
@@ -275,7 +289,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:
@@ -352,9 +366,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;