Use the stock GCC 2.95.1 file here. Our previous (rev 1.2) changes are OBE.

This commit is contained in:
obrien 1999-10-16 07:53:19 +00:00
parent 7f3675d738
commit ad65a89b33

View File

@ -1,5 +1,5 @@
/* Handle exceptional things in C++.
Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
Copyright (C) 1989, 92-97, 1998, 1999 Free Software Foundation, Inc.
Contributed by Michael Tiemann <tiemann@cygnus.com>
Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
initial re-implementation courtesy Tad Hunt.
@ -21,6 +21,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* $FreeBSD$ */
#include "config.h"
#include "system.h"
@ -52,12 +54,13 @@ static tree call_eh_info PROTO((void));
static void push_eh_info PROTO((void));
static tree get_eh_info PROTO((void));
static tree get_eh_value PROTO((void));
#if 0
static tree get_eh_type PROTO((void));
static tree get_eh_caught PROTO((void));
static tree get_eh_handlers PROTO((void));
#endif
static tree do_pop_exception PROTO((void));
static void process_start_catch_block PROTO((tree, tree));
static void process_start_catch_block_old PROTO((tree, tree));
static tree build_eh_type_type_ref PROTO((tree));
static tree build_terminate_handler PROTO((void));
static tree alloc_eh_object PROTO((tree));
@ -248,14 +251,14 @@ call_eh_info ()
{
tree fn;
fn = get_identifier ("__cp_eh_info");
fn = get_identifier ("__start_cp_handler");
if (IDENTIFIER_GLOBAL_VALUE (fn))
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
tree t1, t, fields[7];
/* Declare cp_eh_info * __cp_eh_info (void),
/* Declare cp_eh_info * __start_cp_handler (void),
as defined in exception.cc. */
push_obstacks_nochange ();
end_temporary_allocation ();
@ -269,9 +272,11 @@ call_eh_info ()
get_identifier ("dynamic_handler_chain"), ptr_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL,
get_identifier ("info"), ptr_type_node);
fields[3] = build_lang_field_decl (FIELD_DECL,
get_identifier ("table_index"), ptr_type_node);
/* N.B.: The fourth field LEN is expected to be
the number of fields - 1, not the total number of fields. */
finish_builtin_type (t1, "eh_context", fields, 2, ptr_type_node);
finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
t1 = build_pointer_type (t1);
t1= make_lang_type (RECORD_TYPE);
@ -315,9 +320,9 @@ call_eh_info ()
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
assemble_external (fn);
pop_obstacks ();
}
mark_used (fn);
return build_function_call (fn, NULL_TREE);
}
@ -360,6 +365,7 @@ get_eh_value ()
/* Returns a reference to the current exception type. */
#if 0
static tree
get_eh_type ()
{
@ -386,6 +392,7 @@ get_eh_handlers ()
return build_component_ref (get_eh_info (), get_identifier ("handlers"),
NULL_TREE, 0);
}
#endif
/* Build a type value for use at runtime for a type that is matched
against by the exception handling system. */
@ -394,7 +401,7 @@ static tree
build_eh_type_type (type)
tree type;
{
char *typestring;
const char *typestring;
tree exp;
if (type == error_mark_node)
@ -408,9 +415,7 @@ build_eh_type_type (type)
type = TYPE_MAIN_VARIANT (type);
if (flag_rtti)
{
return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
}
return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
typestring = build_overload_name (type, 1, 1);
exp = combine_strings (build_string (strlen (typestring)+1, typestring));
@ -424,7 +429,7 @@ static tree
build_eh_type_type_ref (type)
tree type;
{
char *typestring;
const char *typestring;
tree exp;
if (type == error_mark_node)
@ -528,10 +533,10 @@ do_pop_exception ()
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
assemble_external (fn);
pop_obstacks ();
}
mark_used (fn);
/* Arrange to do a dynamically scoped cleanup upon exit from this region. */
cleanup = lookup_name (get_identifier ("__exception_info"), 0);
cleanup = build_function_call (fn, expr_tree_cons
@ -546,9 +551,6 @@ push_eh_cleanup ()
{
int yes;
expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
const0_rtx, VOIDmode, EXPAND_NORMAL);
yes = suspend_momentary ();
/* All cleanups must last longer than normal. */
expand_decl_cleanup (NULL_TREE, do_pop_exception ());
@ -597,135 +599,14 @@ expand_start_catch_block (declspecs, declarator)
if (! doing_eh (1))
return;
if (flag_new_exceptions)
process_start_catch_block (declspecs, declarator);
else
process_start_catch_block_old (declspecs, declarator);
process_start_catch_block (declspecs, declarator);
}
/* This function performs the expand_start_catch_block functionality for
exceptions implemented in the old style, where catch blocks were all
called, and had to check the runtime information themselves. */
static void
process_start_catch_block_old (declspecs, declarator)
tree declspecs, declarator;
{
rtx false_label_rtx;
tree decl = NULL_TREE;
tree init;
/* Create a binding level for the eh_info and the exception object
cleanup. */
pushlevel (0);
expand_start_bindings (0);
false_label_rtx = gen_label_rtx ();
push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
emit_line_note (input_filename, lineno);
push_eh_info ();
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
if (decl == NULL_TREE)
error ("invalid catch parameter");
}
if (decl)
{
tree exp;
rtx call_rtx, return_value_rtx;
tree init_type;
/* Make sure we mark the catch param as used, otherwise we'll get
a warning about an unused ((anonymous)). */
TREE_USED (decl) = 1;
/* Figure out the type that the initializer is. */
init_type = TREE_TYPE (decl);
if (TREE_CODE (init_type) != REFERENCE_TYPE
&& TREE_CODE (init_type) != POINTER_TYPE)
init_type = build_reference_type (init_type);
exp = get_eh_value ();
/* Since pointers are passed by value, initialize a reference to
pointer catch parm with the address of the value slot. */
if (TREE_CODE (init_type) == REFERENCE_TYPE
&& TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
exp = build_unary_op (ADDR_EXPR, exp, 1);
exp = expr_tree_cons (NULL_TREE,
build_eh_type_type (TREE_TYPE (decl)),
expr_tree_cons (NULL_TREE,
get_eh_type (),
expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
exp = build_function_call (CatchMatch, exp);
call_rtx = expand_call (exp, NULL_RTX, 0);
return_value_rtx = hard_function_value (ptr_type_node, exp);
/* did the throw type match function return TRUE? */
emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
GET_MODE (return_value_rtx), 0, 0);
/* if it returned FALSE, jump over the catch block, else fall into it */
emit_jump_insn (gen_beq (false_label_rtx));
push_eh_cleanup ();
/* Create a binding level for the parm. */
pushlevel (0);
expand_start_bindings (0);
init = convert_from_reference (make_tree (init_type, call_rtx));
/* If the constructor for the catch parm exits via an exception, we
must call terminate. See eh23.C. */
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
{
/* Generate the copy constructor call directly so we can wrap it.
See also expand_default_init. */
init = ocp_convert (TREE_TYPE (decl), init,
CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
build_terminate_handler ());
}
/* Let `cp_finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
decl = pushdecl (decl);
start_decl_1 (decl);
cp_finish_decl (decl, DECL_INITIAL (decl),
NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
}
else
{
push_eh_cleanup ();
/* Create a binding level for the parm. */
pushlevel (0);
expand_start_bindings (0);
/* Fall into the catch all section. */
}
init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
emit_line_note (input_filename, lineno);
}
/* This function performs the expand_start_catch_block functionality for
exceptions implemented in the new style. __throw determines whether
a handler needs to be called or not, so the handler itself has to do
nothing additionaal. */
nothing additional. */
static void
process_start_catch_block (declspecs, declarator)
@ -806,7 +687,9 @@ process_start_catch_block (declspecs, declarator)
DECL_INITIAL (decl) = init;
decl = pushdecl (decl);
cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
start_decl_1 (decl);
cp_finish_decl (decl, init, NULL_TREE, 0,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
else
{
@ -819,14 +702,10 @@ process_start_catch_block (declspecs, declarator)
/* Fall into the catch all section. */
}
init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
emit_line_note (input_filename, lineno);
}
/* Call this to end a catch block. Its responsible for emitting the
code to handle jumping back to the correct place, and for emitting
the label to jump to if this catch block didn't match. */
@ -850,10 +729,7 @@ expand_end_catch_block ()
documentation. */
expand_goto (top_label_entry (&caught_return_label_stack));
/* label we emit to jump to if this catch block didn't match. */
/* This the closing } in the `if (eq) {' of the documentation. */
if (! flag_new_exceptions)
emit_label (pop_label_entry (&false_label_stack));
end_catch_handler ();
}
/* An exception spec is implemented more or less like:
@ -895,7 +771,7 @@ expand_end_eh_spec (raises)
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);
tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
decl = build_decl (VAR_DECL, NULL_TREE, tmp);
DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = types;
@ -923,10 +799,10 @@ expand_end_eh_spec (raises)
TREE_THIS_VOLATILE (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
assemble_external (fn);
pop_obstacks ();
}
mark_used (fn);
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);
@ -1065,10 +941,10 @@ alloc_eh_object (type)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
assemble_external (fn);
pop_obstacks ();
}
mark_used (fn);
exp = build_function_call (fn, expr_tree_cons
(NULL_TREE, size_in_bytes (type), NULL_TREE));
exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
@ -1118,11 +994,8 @@ expand_throw (exp)
pop_obstacks ();
}
if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
{
throw_type = build_eh_type (exp);
exp = build_reinterpret_cast (ptr_type_node, exp);
}
if (TYPE_PTR_P (TREE_TYPE (exp)))
throw_type = build_eh_type (exp);
else
{
tree object, ptr;
@ -1153,13 +1026,11 @@ expand_throw (exp)
ourselves into expand_call. */
if (TREE_SIDE_EFFECTS (exp))
{
tree temp = build (VAR_DECL, TREE_TYPE (exp));
tree temp = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
DECL_ARTIFICIAL (temp) = 1;
layout_decl (temp, 0);
DECL_RTL (temp) = assign_temp (TREE_TYPE (exp), 2, 0, 1);
expand_expr (build (INIT_EXPR, TREE_TYPE (exp), temp, exp),
NULL_RTX, VOIDmode, 0);
expand_decl_cleanup (NULL_TREE, maybe_build_cleanup (temp));
DECL_INITIAL (temp) = exp;
cp_finish_decl (temp, exp, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
exp = temp;
}
#endif
@ -1196,6 +1067,10 @@ expand_throw (exp)
exp = ptr;
}
/* Cast EXP to `void *' so that it will match the prototype for
__cp_push_exception. */
exp = convert (ptr_type_node, exp);
if (cleanup == NULL_TREE)
{
cleanup = build_int_2 (0, 0);
@ -1223,10 +1098,10 @@ expand_throw (exp)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
assemble_external (fn);
pop_obstacks ();
}
mark_used (fn);
e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
(NULL_TREE, throw_type, expr_tree_cons
(NULL_TREE, cleanup, NULL_TREE)));
@ -1254,10 +1129,10 @@ expand_throw (exp)
DECL_ARTIFICIAL (fn) = 1;
pushdecl_top_level (fn);
make_function_rtl (fn);
assemble_external (fn);
pop_obstacks ();
}
mark_used (fn);
exp = build_function_call (fn, NULL_TREE);
expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
@ -1277,11 +1152,8 @@ build_throw (e)
if (processing_template_decl)
return build_min (THROW_EXPR, void_type_node, e);
if (! flag_ansi && e == null_node)
{
cp_warning ("throwing NULL");
e = integer_zero_node;
}
if (e == null_node)
cp_warning ("throwing NULL, which has integral, not pointer type");
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;