From: Jason Merrill Date: Fri, 31 Oct 1997 09:52:55 +0000 (+0000) Subject: [multiple changes] X-Git-Tag: releases/egcs-1.0.0~198 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6874c2647b322a34cd25c74c2cf2d0b374683df7;p=thirdparty%2Fgcc.git [multiple changes] Fri Oct 31 01:45:31 1997 Jason Merrill * libgcc2.c (L_eh): Define __eh_pc. Replace __eh_type with generic pointer __eh_info. Fri Oct 31 01:47:57 1997 Jason Merrill Support for nested exceptions. * tinfo2.cc (__is_pointer): New fn. * exception.cc (struct cp_eh_info): Define. (__cp_exception_info, __uncatch_exception): New fns. (__cp_push_exception, __cp_pop_exception): New fns. * except.c: Lose saved_throw_{type,value,cleanup,in_catch}. Lose empty_fndecl. (init_exception_processing): Likewise. __eh_pc is now external. (push_eh_info): New fn. (get_eh_{info,value,type,caught}): New fns. (push_eh_cleanup): Just call __cp_pop_exception. (expand_start_catch_block): Use push_eh_info. Start the eh region sooner. (expand_end_eh_spec): Use push_eh_info. (expand_throw): Call __cp_push_exception to set up the exception info. Just pass the destructor or 0 as the cleanup. Call __uncatch_exception when we rethrow. (expand_builtin_throw): Don't refer to empty_fndecl. From-SVN: r16248 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a417d4d8c310..540f17f3a111 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Fri Oct 31 01:45:31 1997 Jason Merrill + + * libgcc2.c (L_eh): Define __eh_pc. + Replace __eh_type with generic pointer __eh_info. + Fri Oct 31 00:34:55 1996 J"orn Rennecke * expr.c (expand_increment): When enqueing a postincrement for a MEM, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a1bb4702659e..5ff066ab51bc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +Fri Oct 31 01:47:57 1997 Jason Merrill + + Support for nested exceptions. + * tinfo2.cc (__is_pointer): New fn. + * exception.cc (struct cp_eh_info): Define. + (__cp_exception_info, __uncatch_exception): New fns. + (__cp_push_exception, __cp_pop_exception): New fns. + * except.c: Lose saved_throw_{type,value,cleanup,in_catch}. + Lose empty_fndecl. + (init_exception_processing): Likewise. __eh_pc is now external. + (push_eh_info): New fn. + (get_eh_{info,value,type,caught}): New fns. + (push_eh_cleanup): Just call __cp_pop_exception. + (expand_start_catch_block): Use push_eh_info. Start the eh region + sooner. + (expand_end_eh_spec): Use push_eh_info. + (expand_throw): Call __cp_push_exception to set up the exception info. + Just pass the destructor or 0 as the cleanup. Call __uncatch_exception + when we rethrow. + (expand_builtin_throw): Don't refer to empty_fndecl. + Thu Oct 23 02:01:30 1997 Jason Merrill * pt.c (instantiate_decl): SET_DECL_IMPLICIT_INSTANTIATION on new decl. diff --git a/gcc/cp/except.c b/gcc/cp/except.c index fe0a1b5e0385..4d3622bde90f 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -180,8 +180,6 @@ static tree Unwind; /* Holds a ready to emit call to "terminate". */ static tree TerminateFunctionCall; -static tree empty_fndecl; - /* ====================================================================== */ @@ -196,14 +194,6 @@ static tree empty_fndecl; /* Holds the pc for doing "throw" */ static tree saved_pc; -/* Holds the type of the thing being thrown. */ -static tree saved_throw_type; -/* Holds the value being thrown. */ -static tree saved_throw_value; -/* Holds the cleanup for the value being thrown. */ -static tree saved_cleanup; -/* Indicates if we are in a catch clause. */ -static tree saved_in_catch; extern int throw_used; extern rtx catch_clauses; @@ -290,12 +280,6 @@ init_exception_processing () tree_cons (NULL_TREE, ptr_type_node, void_list_node)), NOT_BUILT_IN, NULL_PTR); - empty_fndecl - = builtin_function ("__empty", - vtype, - NOT_BUILT_IN, NULL_PTR); - DECL_EXTERNAL (empty_fndecl) = 1; - TREE_PUBLIC (empty_fndecl) = 1; Unexpected = default_conversion (unexpected_fndecl); Terminate = default_conversion (terminate_fndecl); @@ -310,47 +294,118 @@ init_exception_processing () pop_lang_context (); - declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE); - d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc")); - d = start_decl (d, declspecs, 0); - DECL_COMMON (d) = 1; - cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0); - saved_pc = lookup_name (get_identifier ("__eh_pc"), 0); - - declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE); - d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type")); - d = start_decl (d, declspecs, 0); - DECL_COMMON (d) = 1; - cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0); - saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0); - - declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE); - d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value")); - d = start_decl (d, declspecs, 0); - DECL_COMMON (d) = 1; - cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0); - saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0); - - declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE); - d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_cleanup")); - d = make_call_declarator (d, void_list_node, NULL_TREE, NULL_TREE); - d = start_decl (d, declspecs, 0); - DECL_COMMON (d) = 1; - cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0); - saved_cleanup = lookup_name (get_identifier ("__eh_cleanup"), 0); - - declspecs = tree_cons (NULL_TREE, get_identifier ("bool"), NULL_TREE); - d = get_identifier ("__eh_in_catch"); - d = start_decl (d, declspecs, 0); - DECL_COMMON (d) = 1; - cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0); - saved_in_catch = lookup_name (get_identifier ("__eh_in_catch"), 0); + d = build_decl (VAR_DECL, get_identifier ("__eh_pc"), ptr_type_node); + TREE_PUBLIC (d) = 1; + DECL_EXTERNAL (d) = 1; + DECL_ARTIFICIAL (d) = 1; + cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0); + saved_pc = d; /* If we use setjmp/longjmp EH, arrange for all cleanup actions to be protected with __terminate. */ protect_cleanup_actions_with_terminate = 1; } +/* Retrieve a pointer to the cp_eh_info node for the current exception + and save it in the current binding level. */ + +static void +push_eh_info () +{ + tree decl, fn; + + fn = get_identifier ("__cp_exception_info"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + tree t, fields[5]; + + /* Declare cp_eh_info * __cp_exception_info (void), + as defined in exception.cc. */ + push_obstacks_nochange (); + end_temporary_allocation (); + + /* struct cp_eh_info. This must match exception.cc. Note that this + type is not pushed anywhere. */ + t = make_lang_type (RECORD_TYPE); + fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"), + ptr_type_node); + fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"), + ptr_type_node); + fields[2] = build_lang_field_decl + (FIELD_DECL, get_identifier ("cleanup"), + build_pointer_type (build_function_type + (ptr_type_node, tree_cons + (NULL_TREE, ptr_type_node, void_list_node)))); + fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"), + boolean_type_node); + fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"), + build_pointer_type (t)); + finish_builtin_type (t, "cp_eh_info", fields, 5, ptr_type_node); + t = build_pointer_type (t); + + /* And now the function. */ + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (t, void_list_node)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + fn = build_function_call (fn, NULL_TREE); + + /* Remember the pointer to the current exception info; it won't change + during this catch block. */ + decl = build_decl (VAR_DECL, get_identifier ("__exception_info"), + TREE_TYPE (fn)); + DECL_ARTIFICIAL (decl) = 1; + DECL_INITIAL (decl) = fn; + decl = pushdecl (decl); + cp_finish_decl (decl, fn, NULL_TREE, 0, 0); +} + +/* Returns a reference to the cp_eh_info node for the current exception. */ + +static tree +get_eh_info () +{ + /* Look for the pointer pushed in push_eh_info. */ + tree t = lookup_name (get_identifier ("__exception_info"), 0); + return build_indirect_ref (t, NULL_PTR); +} + +/* Returns a reference to the current exception object. */ + +static tree +get_eh_value () +{ + return build_component_ref (get_eh_info (), get_identifier ("value"), + NULL_TREE, 0); +} + +/* Returns a reference to the current exception type. */ + +static tree +get_eh_type () +{ + return build_component_ref (get_eh_info (), get_identifier ("type"), + NULL_TREE, 0); +} + +/* Returns a reference to whether or not the current exception + has been caught. */ + +static tree +get_eh_caught () +{ + return build_component_ref (get_eh_info (), get_identifier ("caught"), + NULL_TREE, 0); +} + /* Build a type value for use at runtime for a type that is matched against by the exception handling system. */ @@ -396,19 +451,37 @@ build_eh_type (exp) return build_eh_type_type (TREE_TYPE (exp)); } -/* This routine creates the cleanup for the exception handling object. */ +/* This routine creates the cleanup for the current exception. */ static void push_eh_cleanup () { /* All cleanups must last longer than normal. */ int yes = suspend_momentary (); + tree fn, cleanup; + + fn = get_identifier ("__cp_pop_exception"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + /* Declare void __cp_pop_exception (void), as defined in exception.cc. */ + push_obstacks_nochange (); + end_temporary_allocation (); + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (void_type_node, + void_list_node)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } /* Arrange to do a dynamically scoped cleanup upon exit from this region. */ - tree cleanup = build_function_call (saved_cleanup, NULL_TREE); - cleanup = build (COMPOUND_EXPR, void_type_node, cleanup, - build_modify_expr (saved_in_catch, NOP_EXPR, - build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node))); + cleanup = build_function_call (fn, NULL_TREE); expand_decl_cleanup (NULL_TREE, cleanup); resume_momentary (yes); @@ -456,6 +529,23 @@ expand_start_catch_block (declspecs, declarator) emit_line_note (input_filename, lineno); + push_eh_info (); + + /* If we are not doing setjmp/longjmp EH, because we are reordered + out of line, we arrange to rethrow in the outer context so as to + skip through the terminate region we are nested in, should we + encounter an exception in the catch handler. + + If we are doing setjmp/longjmp EH, we need to skip through the EH + object cleanup region. This isn't quite right, as we really need + to clean the object up, but we cannot do that until we track + multiple EH objects. + + Matches the end in expand_end_catch_block. */ + expand_eh_region_start (); + + push_eh_cleanup (); + if (declspecs) { tree exp; @@ -467,12 +557,6 @@ expand_start_catch_block (declspecs, declarator) if (decl == NULL_TREE) { error ("invalid catch parameter"); - - /* This is cheap, but we want to maintain the data - structures. */ - - expand_eh_region_start (); - return; } @@ -486,11 +570,11 @@ expand_start_catch_block (declspecs, declarator) && TREE_CODE (init_type) != POINTER_TYPE) init_type = build_reference_type (init_type); - exp = saved_throw_value; + exp = get_eh_value (); exp = expr_tree_cons (NULL_TREE, build_eh_type_type (TREE_TYPE (decl)), expr_tree_cons (NULL_TREE, - saved_throw_type, + 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); @@ -505,8 +589,6 @@ expand_start_catch_block (declspecs, declarator) /* if it returned FALSE, jump over the catch block, else fall into it */ emit_jump_insn (gen_beq (false_label_rtx)); - push_eh_cleanup (); - init = convert_from_reference (save_expr (make_tree (init_type, call_rtx))); /* Do we need the below two lines? */ @@ -515,27 +597,9 @@ expand_start_catch_block (declspecs, declarator) decl = pushdecl (decl); cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); } - else - { - push_eh_cleanup (); - /* Fall into the catch all section. */ - } - - emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx); - - /* If we are not doing setjmp/longjmp EH, because we are reordered - out of line, we arrange to rethrow in the outer context so as to - skip through the terminate region we are nested in, should we - encounter an exception in the catch handler. - - If we are doing setjmp/longjmp EH, we need to skip through the EH - object cleanup region. This isn't quite right, as we really need - to clean the object up, but we cannot do that until we track - multiple EH objects. - - Matches the end in expand_end_catch_block. */ - expand_eh_region_start (); + 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); } @@ -845,7 +909,8 @@ expand_builtin_throw () #ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE if (DONT_ACCESS_GBLS_AFTER_EPILOGUE) { - t = make_tree (build_pointer_type (TREE_TYPE (empty_fndecl)), + t = build_function_type (void_type_node, void_list_node); + t = make_tree (build_pointer_type (t), hard_function_value (ptr_type_node, NULL_TREE)); t = build_function_call (t, NULL_TREE); @@ -965,6 +1030,9 @@ expand_end_eh_spec (raises) emit_label (check); emit_move_insn (flag, const1_rtx); cont = gen_label_rtx (); + + push_eh_info (); + while (raises) { tree exp; @@ -973,11 +1041,11 @@ expand_end_eh_spec (raises) if (match_type) { /* check TREE_VALUE (raises) here */ - exp = saved_throw_value; + exp = get_eh_value (); exp = expr_tree_cons (NULL_TREE, build_eh_type_type (match_type), expr_tree_cons (NULL_TREE, - saved_throw_type, + get_eh_type (), expr_tree_cons (NULL_TREE, exp, NULL_TREE))); exp = build_function_call (CatchMatch, exp); assemble_external (TREE_OPERAND (CatchMatch, 0)); @@ -1123,6 +1191,8 @@ expand_throw (exp) tree exp; { rtx label; + tree fn; + static tree cleanup_type; if (! doing_eh (1)) return; @@ -1130,12 +1200,26 @@ expand_throw (exp) if (exp) { tree throw_type; - tree cleanup = empty_fndecl, e; + tree cleanup = NULL_TREE, e; /* throw expression */ /* First, decay it. */ exp = decay_conversion (exp); + /* cleanup_type is void (*)(void *, int), + the internal type of a destructor. */ + if (cleanup_type == NULL_TREE) + { + push_obstacks_nochange (); + end_temporary_allocation (); + cleanup_type = build_pointer_type + (build_function_type + (void_type_node, tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, integer_type_node, void_list_node)))); + pop_obstacks (); + } + if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE) { throw_type = build_eh_type (exp); @@ -1156,33 +1240,83 @@ expand_throw (exp) object = build_indirect_ref (exp, NULL_PTR); throw_type = build_eh_type (object); - /* Build __tcf_ function. */ - cleanup = start_anon_func (); - object = build_delete (TREE_TYPE (exp), saved_throw_value, - integer_three_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0); - expand_expr (object, const0_rtx, VOIDmode, 0); - end_anon_func (); - mark_addressable (cleanup); + if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object))) + { + cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), + dtor_identifier, 0); + cleanup = TREE_VALUE (cleanup); + mark_addressable (cleanup); + /* Pretend it's a normal function. */ + cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup); + } } - if (cleanup == empty_fndecl) - assemble_external (empty_fndecl); - - e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type); - expand_expr (e, const0_rtx, VOIDmode, 0); + if (cleanup == NULL_TREE) + { + cleanup = build_int_2 (0, 0); + TREE_TYPE (cleanup) = cleanup_type; + } - e = build_modify_expr (saved_throw_value, NOP_EXPR, exp); - e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e); - expand_expr (e, const0_rtx, VOIDmode, 0); + fn = get_identifier ("__cp_push_exception"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)), + as defined in exception.cc. */ + tree tmp; + push_obstacks_nochange (); + end_temporary_allocation (); + tmp = tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, ptr_type_node, tree_cons + (NULL_TREE, cleanup_type, void_list_node))); + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (void_type_node, tmp)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } - cleanup = build_unary_op (ADDR_EXPR, cleanup, 0); - cleanup = build_modify_expr (saved_cleanup, NOP_EXPR, cleanup); - expand_expr (cleanup, const0_rtx, VOIDmode, 0); + /* The throw expression is a full-expression. */ + exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp); + e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons + (NULL_TREE, throw_type, expr_tree_cons + (NULL_TREE, cleanup, NULL_TREE))); + e = build_function_call (fn, e); + expand_expr (e, const0_rtx, VOIDmode, 0); } else { - /* rethrow current exception */ - /* This part is easy, as we don't have to do anything else. */ + /* rethrow current exception; note that it's no longer caught. */ + + tree fn = get_identifier ("__uncatch_exception"); + if (IDENTIFIER_GLOBAL_VALUE (fn)) + fn = IDENTIFIER_GLOBAL_VALUE (fn); + else + { + /* Declare void __uncatch_exception (void) + as defined in exception.cc. */ + push_obstacks_nochange (); + end_temporary_allocation (); + fn = build_lang_decl (FUNCTION_DECL, fn, + build_function_type (void_type_node, + void_list_node)); + DECL_EXTERNAL (fn) = 1; + TREE_PUBLIC (fn) = 1; + DECL_ARTIFICIAL (fn) = 1; + pushdecl_top_level (fn); + make_function_rtl (fn); + assemble_external (fn); + pop_obstacks (); + } + + exp = build_function_call (fn, NULL_TREE); + expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL); } if (exceptions_via_longjmp) diff --git a/gcc/cp/exception.cc b/gcc/cp/exception.cc index 839525faafe8..4099d4776203 100644 --- a/gcc/cp/exception.cc +++ b/gcc/cp/exception.cc @@ -73,6 +73,79 @@ unexpected () __unexpected_func (); } +/* C++-specific state about the current exception. + This must match init_exception_processing(). */ + +struct cp_eh_info +{ + void *value; + void *type; + void (*cleanup)(void *, int); + bool caught; + cp_eh_info *next; +}; + +/* Language-specific EH info pointer, defined in libgcc2. */ + +extern cp_eh_info *__eh_info; // actually void* + +/* Is P the type_info node for a pointer of some kind? */ + +extern bool __is_pointer (void *); + +/* Compiler hook to return a pointer to the info for the current exception. + Used by get_eh_info (). */ + +extern "C" cp_eh_info * +__cp_exception_info (void) +{ + return __eh_info; +} + +/* Compiler hook to push a new exception onto the stack. + Used by expand_throw(). */ + +extern "C" void +__cp_push_exception (void *value, void *type, void (*cleanup)(void *, int)) +{ + cp_eh_info *p = new cp_eh_info; + p->value = value; + p->type = type; + p->cleanup = cleanup; + p->caught = false; + p->next = __eh_info; + __eh_info = p; +} + +/* Compiler hook to pop an exception that has been finalized. Used by + push_eh_cleanup(). */ + +extern "C" void +__cp_pop_exception (void) +{ + cp_eh_info *p = __eh_info; + + if (p->cleanup) + /* 3 is a magic value for destructors; see build_delete(). */ + p->cleanup (p->value, 3); + else if (__is_pointer (p->type)) + /* do nothing; pointers are passed directly in p->value. */; + else + delete p->value; + + __eh_info = p->next; + delete p; +} + +extern "C" void +__uncatch_exception (void) +{ + cp_eh_info *p = __cp_exception_info (); + if (p) + p->caught = false; + /* otherwise __throw will call terminate(); don't crash here. */ +} + extern "C" void __throw_bad_cast (void) { @@ -91,12 +164,13 @@ __throw_bad_exception (void) throw bad_exception (); } +/* Has the current exception been caught? */ + bool uncaught_exception () { - extern void *__eh_type; - extern bool __eh_in_catch; - return __eh_type && ! __eh_in_catch; + cp_eh_info *p = __cp_exception_info (); + return p && ! p->caught; } const char * exception:: diff --git a/gcc/cp/tinfo2.cc b/gcc/cp/tinfo2.cc index 72870df95382..128661c1cd2e 100644 --- a/gcc/cp/tinfo2.cc +++ b/gcc/cp/tinfo2.cc @@ -258,6 +258,18 @@ __throw_type_match_rtti (void *catch_type_r, void *throw_type_r, void *objptr) return new_objptr; } +/* Called from __cp_pop_exception. Is P the type_info node for a pointer + of some kind? */ + +bool +__is_pointer (void *p) +{ + const type_info *t = reinterpret_cast (p); + const __pointer_type_info *pt = + dynamic_cast (t); + return pt != 0; +} + extern "C" void __rtti_ptr (void *addr, const char *n, const type_info *ti) { new (addr) __pointer_type_info (n, *ti); } diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index ae97c5313ae7..6c34da7acf52 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -3109,7 +3109,9 @@ int _exit_dummy_decl = 0; /* prevent compiler & linker warnings */ /* Shared exception handling support routines. */ -extern void *__eh_type; +/* Language-specific information about the active exception(s). If there + are no active exceptions, it is set to 0. */ +void *__eh_info; void __default_terminate () @@ -3224,7 +3226,7 @@ __sjthrow () /* We must call terminate if we try and rethrow an exception, when there is no exception currently active and when there are no handlers left. */ - if (! __eh_type || (*dhc) == top_elt) + if (! __eh_info || (*dhc) == top_elt) __terminate (); /* Find the jmpbuf associated with the top element of the dynamic @@ -3307,7 +3309,7 @@ __sjpopnthrow () /* This value identifies the place from which an exception is being thrown. */ -extern void *__eh_pc; +void *__eh_pc; #ifdef EH_TABLE_LOOKUP @@ -3652,7 +3654,7 @@ __throw () /* This is required for C++ semantics. We must call terminate if we try and rethrow an exception, when there is no exception currently active. */ - if (! __eh_type) + if (! __eh_info) __terminate (); /* Start at our stack frame. */