except.c (expand_start_eh_spec): Use the try/catch code.

* except.c (expand_start_eh_spec): Use the try/catch code.
	(expand_end_eh_spec): Likewise.  Call __check_eh_spec instead of
	doing everything inline.
	(init_exception_processing): throw_type_match now takes
 	const void pointers.
	* exception.cc (__check_eh_spec): New fn.
	* inc/exception: Neither terminate nor unexpected return.
	* decl.c: Make const_ptr_type_node public.
	* tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly.

From-SVN: r16651
This commit is contained in:
Jason Merrill 1997-11-21 20:29:06 +00:00 committed by Jason Merrill
parent d32ecec207
commit 6c20b7e97e
6 changed files with 131 additions and 87 deletions

View file

@ -1,5 +1,15 @@
Fri Nov 21 12:22:07 1997 Jason Merrill <jason@yorick.cygnus.com>
* except.c (expand_start_eh_spec): Use the try/catch code.
(expand_end_eh_spec): Likewise. Call __check_eh_spec instead of
doing everything inline.
(init_exception_processing): throw_type_match now takes
const void pointers.
* exception.cc (__check_eh_spec): New fn.
* inc/exception: Neither terminate nor unexpected return.
* decl.c: Make const_ptr_type_node public.
* tinfo2.cc (__throw_type_match_rtti): Take the typeinfos constly.
* except.c (expand_start_catch_block): We only need the rethrow
region for non-sjlj exceptions.
(expand_end_catch_block): Likewise. Use outer_context_label_stack.

View file

@ -239,7 +239,7 @@ tree void_zero_node;
/* Nodes for types `void *' and `const void *'. */
tree ptr_type_node;
static tree const_ptr_type_node;
tree const_ptr_type_node;
/* Nodes for types `char *' and `const char *'. */

View file

@ -197,6 +197,7 @@ static tree saved_pc;
extern int throw_used;
extern rtx catch_clauses;
extern tree const_ptr_type_node;
/* ========================================================================= */
@ -263,8 +264,8 @@ init_exception_processing ()
? "__throw_type_match_rtti"
: "__throw_type_match",
build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, const_ptr_type_node,
tree_cons (NULL_TREE, const_ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
void_list_node)))),
NOT_BUILT_IN, NULL_PTR);
@ -1020,101 +1021,84 @@ expand_builtin_throw ()
#endif /* DWARF2_UNWIND_INFO */
}
/* An exception spec is implemented more or less like:
try {
function body;
} catch (...) {
void *p[] = { typeid(raises) };
__check_eh_spec (p, count);
}
__check_eh_spec in exception.cc handles all the details. */
void
expand_start_eh_spec ()
{
expand_eh_region_start ();
expand_start_try_stmts ();
}
static void
expand_end_eh_spec (raises)
tree raises;
{
tree expr, second_try;
rtx check = gen_label_rtx ();
rtx cont;
rtx ret = gen_reg_rtx (Pmode);
rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
rtx end = gen_label_rtx ();
tree tmp, fn, decl, types = NULL_TREE;
int count = 0;
expr = make_node (RTL_EXPR);
TREE_TYPE (expr) = void_type_node;
RTL_EXPR_RTL (expr) = const0_rtx;
TREE_SIDE_EFFECTS (expr) = 1;
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (expr);
cont = gen_label_rtx ();
emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
emit_jump (check);
emit_label (cont);
jumpif (make_tree (integer_type_node, flag), end);
do_function_call (Terminate, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Terminate, 0));
emit_barrier ();
do_pending_stack_adjust ();
RTL_EXPR_SEQUENCE (expr) = get_insns ();
end_sequence ();
second_try = expr;
expand_start_all_catch ();
expand_start_catch_block (NULL_TREE, NULL_TREE);
expr = make_node (RTL_EXPR);
TREE_TYPE (expr) = void_type_node;
RTL_EXPR_RTL (expr) = const0_rtx;
TREE_SIDE_EFFECTS (expr) = 1;
do_pending_stack_adjust ();
start_sequence_for_rtl_expr (expr);
cont = gen_label_rtx ();
emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
emit_jump (check);
emit_label (cont);
jumpif (make_tree (integer_type_node, flag), end);
expand_eh_region_start ();
do_function_call (Unexpected, NULL_TREE, NULL_TREE);
assemble_external (TREE_OPERAND (Unexpected, 0));
emit_barrier ();
expand_eh_region_end (second_try);
emit_label (check);
emit_move_insn (flag, const1_rtx);
cont = gen_label_rtx ();
push_eh_info ();
while (raises)
/* Build up an array of type_infos. */
for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
{
tree exp;
tree match_type = TREE_VALUE (raises);
if (match_type)
{
/* check TREE_VALUE (raises) here */
exp = get_eh_value ();
exp = expr_tree_cons (NULL_TREE,
build_eh_type_type (match_type),
expr_tree_cons (NULL_TREE,
get_eh_type (),
expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
exp = build_function_call (CatchMatch, exp);
assemble_external (TREE_OPERAND (CatchMatch, 0));
jumpif (exp, cont);
}
raises = TREE_CHAIN (raises);
types = expr_tree_cons
(NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
++count;
}
emit_move_insn (flag, const0_rtx);
emit_label (cont);
emit_indirect_jump (ret);
emit_label (end);
types = build_nt (CONSTRUCTOR, NULL_TREE, types);
TREE_HAS_CONSTRUCTOR (types) = 1;
/* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
tmp = build_array_type (const_ptr_type_node, NULL_TREE);
decl = build_decl (VAR_DECL, NULL_TREE, tmp);
DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = types;
cp_finish_decl (decl, types, NULL_TREE, 0, 0);
decl = decay_conversion (decl);
fn = get_identifier ("__check_eh_spec");
if (IDENTIFIER_GLOBAL_VALUE (fn))
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
push_obstacks_nochange ();
end_temporary_allocation ();
tmp = tree_cons
(NULL_TREE, integer_type_node, tree_cons
(NULL_TREE, TREE_TYPE (decl), void_list_node));
tmp = build_function_type (void_type_node, tmp);
do_pending_stack_adjust ();
RTL_EXPR_SEQUENCE (expr) = get_insns ();
end_sequence ();
expand_eh_region_end (expr);
fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
DECL_EXTERNAL (fn) = 1;
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
TREE_THIS_VOLATILE (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
assemble_external (fn);
pop_obstacks ();
}
tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
(NULL_TREE, decl, NULL_TREE));
tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
expand_end_catch_block ();
expand_end_all_catch ();
}
/* This is called to expand all the toplevel exception handling

View file

@ -47,7 +47,8 @@ __default_unexpected ()
terminate ();
}
static unexpected_handler __unexpected_func = __default_unexpected;
static unexpected_handler __unexpected_func __attribute__((__noreturn__))
= __default_unexpected;
terminate_handler
set_terminate (terminate_handler func)
@ -159,6 +160,54 @@ __uncatch_exception (void)
/* otherwise __throw will call terminate(); don't crash here. */
}
/* As per [except.unexpected]:
If an exception is thrown, we check it against the spec. If it doesn't
match, we call unexpected (). If unexpected () throws, we check that
exception against the spec. If it doesn't match, if the spec allows
bad_exception we throw that; otherwise we call terminate ().
The compiler treats an exception spec as a try block with a generic
handler that just calls this function with a list of the allowed
exception types, so we have an active exception that can be rethrown.
This function does not return. */
extern "C" void
__check_eh_spec (int n, const void **spec)
{
cp_eh_info *p = __cp_exception_info ();
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti (spec[i], p->type, p->value))
throw;
}
try
{
unexpected ();
}
catch (...)
{
// __exception_info is an artificial var pushed into each catch block.
p = __exception_info;
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti (spec[i], p->type, p->value))
throw;
}
const type_info &bad_exc = typeid (bad_exception);
for (int i = 0; i < n; ++i)
{
if (__throw_type_match_rtti (spec[i], &bad_exc, p->value))
throw bad_exception ();
}
terminate ();
}
}
extern "C" void
__throw_bad_cast (void)
{

View file

@ -29,9 +29,9 @@ typedef void (*terminate_handler) ();
typedef void (*unexpected_handler) ();
terminate_handler set_terminate (terminate_handler);
void terminate (void);
void terminate (void) __attribute__ ((__noreturn__));
unexpected_handler set_unexpected (unexpected_handler);
void unexpected (void);
void unexpected (void) __attribute__ ((__noreturn__));
bool uncaught_exception ();
} // extern "C++"

View file

@ -119,7 +119,8 @@ struct __array_type_info : public type_info {
variables and thrown objects. */
extern "C" void*
__throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr)
__throw_type_match_rtti (const void *catch_type_r, const void *throw_type_r,
void *objptr)
{
const type_info &catch_type = *(const type_info *)catch_type_r;
const type_info &throw_type = *(const type_info *)throw_type_r;