+Mon Nov 24 12:15:55 1997 Jason Merrill <jason@yorick.cygnus.com>
+
+ * exception.cc (struct cp_eh_info): Add handlers field.
+ (__cp_push_exception): Initialize it.
+ (__cp_pop_exception): Decrement it. Don't pop unless it's 0.
+ (__throw_bad_exception): Remove.
+ * except.c (call_eh_info): Add handlers field.
+ (get_eh_handlers): New fn.
+ (push_eh_cleanup): Increment handlers.
+
Fri Nov 21 12:22:07 1997 Jason Merrill <jason@yorick.cygnus.com>
* except.c (expand_start_eh_spec): Use the try/catch code.
fn = IDENTIFIER_GLOBAL_VALUE (fn);
else
{
- tree t, fields[5];
+ tree t, fields[6];
/* Declare cp_eh_info * __cp_exception_info (void),
as defined in exception.cc. */
boolean_type_node);
fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
build_pointer_type (t));
+ fields[5] = build_lang_field_decl
+ (FIELD_DECL, get_identifier ("handlers"), long_integer_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 (t, "cp_eh_info", fields, 4, ptr_type_node);
+ finish_builtin_type (t, "cp_eh_info", fields, 5, ptr_type_node);
t = build_pointer_type (t);
/* And now the function. */
NULL_TREE, 0);
}
+/* Returns a reference to whether or not the current exception
+ has been caught. */
+
+static tree
+get_eh_handlers ()
+{
+ return build_component_ref (get_eh_info (), get_identifier ("handlers"),
+ NULL_TREE, 0);
+}
+
/* Build a type value for use at runtime for a type that is matched
against by the exception handling system. */
expand_decl_cleanup_no_eh (NULL_TREE, do_pop_exception (boolean_false_node));
resume_momentary (yes);
+ expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
+ const0_rtx, VOIDmode, EXPAND_NORMAL);
+
/* We don't destroy the exception object on rethrow, so we can't use
the normal cleanup mechanism for it. */
expand_eh_region_start ();
}
/* C++-specific state about the current exception.
- This must match init_exception_processing(). */
+ This must match init_exception_processing().
+
+ Note that handlers and caught are not redundant; when rethrown, an
+ exception can have multiple active handlers and still be considered
+ uncaught. */
struct cp_eh_info
{
void (*cleanup)(void *, int);
bool caught;
cp_eh_info *next;
+ long handlers;
};
/* Language-specific EH info pointer, defined in libgcc2. */
p->value = value;
p->type = type;
p->cleanup = cleanup;
+ p->handlers = 0;
p->caught = false;
p->next = __eh_info;
__eh_info = p;
{
cp_eh_info **q = &__eh_info;
- if (handler && p == *q)
+ --p->handlers;
+
+ if (p->handlers > 0 || (handler && p == *q))
return;
for (; *q; q = &((*q)->next))
throw bad_typeid ();
}
-extern "C" void
-__throw_bad_exception (void)
-{
- throw bad_exception ();
-}
-
/* Has the current exception been caught? */
bool