OSDN Git Service

36th Cygnus<->FSF merge
authormrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 May 1994 09:27:46 +0000 (09:27 +0000)
committermrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 6 May 1994 09:27:46 +0000 (09:27 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@7221 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/expr.c
gcc/cp/gxx.gperf
gcc/cp/gxxint.texi
gcc/cp/hash.h
gcc/cp/init.c
gcc/cp/lex.c
gcc/cp/parse.y
gcc/cp/tree.c
gcc/cp/typeck.c

index d544301..1cf6db3 100644 (file)
@@ -1,3 +1,55 @@
+Fri May  6 01:25:38 1994  Mike Stump  (mrs@cygnus.com)
+
+       Add alpha exception handling support to the compiler.
+       Quick and dirty backend in except.c.
+
+       * cp/*:  Remove most remnants of old exception handling support.
+       * decl.c (finish_function): Call expand_exception_blocks to put
+       the exception hanlding blocks at the end of the function.
+       * dec.c (hack_incomplete_structures): Make sure expand_decl_cleanup
+       comes after expand_decl_init.
+       * except.c: Reimplementation.
+       * expr.c (cplus_expand_expr): Handle THROW_EXPRs.
+       * lex.c (init_lex): Always have catch, try and throw be reserved
+       words, so that we may always parse exception handling.
+       * parse.y: Cleanup to support new interface into exception handling.
+       * tree.def (THROW_EXPR): Add.
+
+Thu May  5 17:35:37 1994  Jason Merrill  (jason@deneb.cygnus.com)
+
+       * parse.y (simple_stmt, for loops): Use implicitly_scoped_stmt.
+       (various): Lose .kindof_pushlevel and partially_scoped_stmt.
+
+Thu May  5 16:17:27 1994  Kung Hsu  (kung@mexican.cygnus.com)
+
+       * parse.y (already_scoped_stmt): move expand_end_binding() to
+       fix the unmatched LBB/LBE in stabs.
+
+Thu May  5 14:36:17 1994  Jason Merrill  (jason@deneb.cygnus.com)
+
+       * decl.c (set_nested_typename): Set TREE_MANGLED on the new
+       identifiers.
+       (pushdecl): Check TREE_MANGLED.
+       (xref_tag): Ditto.
+       * cp-tree.h (TREE_MANGLED): This identifier is a
+       DECL_NESTED_TYPENAME (named to allow for future use to denote
+       mangled function names as well).
+
+       Implement inconsistency checking specified in [class.scope0].
+       * decl.c (lookup_name_real): Don't set ICV here after all.
+       (finish_enum): Also set the type of the enumerators themselves.
+       (build_enumerator): Put the CONST_DECL in the list instead of its
+       initial value.
+       (pushdecl_class_level): Check inconsistent use of a name in the
+       class body.
+       * class.c (finish_struct): Check inconsistent use of a name in the
+       class body.  Don't set DECL_CONTEXT on types here anymore.
+       * parse.y (qualified_type_name): Note that the identifier has now
+       been used (as a type) in the class body.
+       * lex.c (do_identifier): Note that the identifier has now been used
+       (as a constant) in the class body.
+       * error.c (dump_decl): Print type and enum decls better.
+
 Thu May  5 09:35:35 1994  Brendan Kehoe  (brendan@lisa.cygnus.com)
 
        * typeck.c (build_modify_expr): Warn about assignment to `this'.
index bc3b731..8f8bac2 100644 (file)
@@ -2924,18 +2924,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
        need_vtbl = maybe_needed;
       instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (basetype), instance);
     }
-  else if (instance == current_exception_object)
-    {
-      instance_ptr = build1 (ADDR_EXPR, TYPE_POINTER_TO (current_exception_type),
-                           TREE_OPERAND (current_exception_object, 0));
-      mark_addressable (TREE_OPERAND (current_exception_object, 0));
-      result = build_field_call (TYPE_BINFO (current_exception_type),
-                                instance_ptr, name, parms);
-      if (result)
-       return result;
-      cp_error ("exception member `%D' cannot be invoked", name);
-      return error_mark_node;
-    }
   else
     {
       /* The MAIN_VARIANT of the type that `instance_ptr' winds up being.  */
index fe169ad..730d0ca 100644 (file)
@@ -2504,7 +2504,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
      int warn_anon;
 {
   extern int interface_only, interface_unknown;
-  extern tree EHS_type;
 
   int old;
   int round_up_size = 1;
@@ -2727,10 +2726,25 @@ finish_struct (t, list_of_fieldlists, warn_anon)
              if (! fields)
                fields = x;
              last_x = x;
-             DECL_CONTEXT (x) = t;
              continue;
            }
 
+         /* Check for inconsistent use of this name in the class body.
+             Enums, types and static vars have already been checked.  */
+         if (TREE_CODE (x) != CONST_DECL && TREE_CODE (x) != VAR_DECL)
+           {
+             tree name = DECL_NAME (x);
+             tree icv = name ? IDENTIFIER_CLASS_VALUE (name) : NULL_TREE;
+
+             /* Don't complain about constructors.  */
+             if (icv && name != constructor_name (current_class_type))
+               {
+                 cp_error_at ("declaration of identifier `%D' as `%+#D'",
+                              name, x);
+                 cp_error_at ("conflicts with other use in class as `%#D'",
+                              icv);
+               }
+           }
 
          if (TREE_CODE (x) == FUNCTION_DECL)
            {
@@ -3129,9 +3143,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
       fn_fields = default_fn;
     }
 
-  /* Create default copy constructor, if needed.  Don't do it for
-     the exception handler.  */
-  if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor && t != EHS_type)
+  /* Create default copy constructor, if needed.  */
+  if (! TYPE_HAS_INIT_REF (t) && ! cant_synth_copy_ctor)
     {
       /* ARM 12.18: You get either X(X&) or X(const X&), but
         not both.  --Chip  */
index 4f73664..4f33c9f 100644 (file)
@@ -55,10 +55,9 @@ DEFTREECODE (TYPE_EXPR, "type_expr", "e", 1)
 DEFTREECODE (NEW_EXPR, "nw_expr", "e", 3)
 DEFTREECODE (VEC_NEW_EXPR, "vec_nw_expr", "e", 3)
 
-/* Distinguish variables that are only used to identify exceptions
-   that were caught.  Only the DECL_NAME (and TREE_CHAIN)
-   is really used.  */
-DEFTREECODE (CPLUS_CATCH_DECL, "catch_decl", "d", 0)
+/* A throw expression.  operand 0 is the expression, if there was one,
+   else it is NULL_TREE.  */
+DEFTREECODE (THROW_EXPR, "throw_expr", "e", 1)
 
 /* Template definition.  The following fields have the specified uses,
    although there are other macros in cp-tree.h that should be used for
index 1a82e0b..54dc2b2 100644 (file)
@@ -271,10 +271,6 @@ extern int interface_only, interface_unknown;
 
 extern int flag_elide_constructors;
 
-/* Nonzero means recognize and handle exception handling constructs.  */
-
-extern int flag_handle_exceptions;
-
 /* Nonzero means handle things in ANSI, instead of GNU fashion.  */
 
 extern int flag_ansi;
@@ -282,7 +278,7 @@ extern int flag_ansi;
 /* Nonzero means recognize and handle ansi-style exception handling
    constructs.  */
 
-extern int flag_ansi_exceptions;
+extern int flag_handle_exceptions;
 
 /* Nonzero means do argument matching for overloading according to the
    ANSI rules, rather than what g++ used to believe to be correct.  */
@@ -1083,10 +1079,14 @@ struct lang_decl
    or virtual baseclasses.  */
 #define TYPE_USES_COMPLEX_INHERITANCE(NODE) (TREE_LANG_FLAG_1 (NODE))
 
+/* Nonzero in IDENTIFIER_NODE means that this name is not the name the user
+   gave; it's a DECL_NESTED_TYPENAME.  Someone may want to set this on
+   mangled function names, too, but it isn't currently.  */
+#define TREE_MANGLED(NODE) (TREE_LANG_FLAG_0 (NODE))
+
 #if 0                          /* UNUSED */
 /* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
    should be looked up in a non-standard way.  */
-#define TREE_OVERLOADED(NODE) (TREE_LANG_FLAG_0 (NODE))
 #define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
 #endif
 
@@ -1921,27 +1921,20 @@ extern tree lookup_name_nonclass                PROTO((tree));
 /* in edsel.c */
 
 /* in except.c */
-extern tree lookup_exception_cname             PROTO((tree, tree, tree));
-extern tree lookup_exception_tname             PROTO((tree));
-extern tree lookup_exception_object            PROTO((tree, tree, int));
-extern tree lookup_exception_type              PROTO((tree, tree, tree));
-extern tree finish_exception                   PROTO((tree, tree));
-extern void finish_exception_decl              PROTO((tree, tree));
-extern void end_exception_decls                        PROTO((void));
-extern void cplus_expand_start_try             PROTO((int));
-extern tree cplus_expand_end_try               PROTO((int));
-extern void cplus_expand_start_except          PROTO((tree, tree));
-extern void cplus_expand_end_except            PROTO((tree));
-extern void cplus_expand_raise                 PROTO((tree, tree, tree, int));
-extern tree ansi_exception_object_lookup       PROTO((tree));
-extern void cplus_expand_throw                 PROTO((tree));
-extern tree cplus_expand_start_catch           PROTO((tree));
-extern tree ansi_expand_start_catch            PROTO((tree));
-extern void cplus_expand_end_catch             PROTO((int));
-extern void cplus_expand_reraise               PROTO((tree));
-extern void setup_exception_throw_decl         PROTO((void));
+
+extern void start_protect                      PROTO((void));
+extern void end_protect                                PROTO((tree));
+extern void expand_exception_blocks            PROTO((void));
+extern void expand_start_try_stmts             PROTO((void));
+extern void expand_end_try_stmts               PROTO((void));
+extern void expand_start_all_catch             PROTO((void));
+extern void expand_end_all_catch               PROTO((void));
+extern void start_catch_block                  PROTO((tree, tree));
+extern void end_catch_block                    PROTO((void));
+extern void expand_throw                       PROTO((tree));
+extern void build_exception_table              PROTO((void));
+extern tree build_throw                                PROTO((tree));
 extern void init_exception_processing          PROTO((void));
-extern void init_exception_processing_1                PROTO((void));
 
 /* in expr.c */
 /* skip cplus_expand_expr */
@@ -2291,18 +2284,6 @@ extern void GNU_xref_assign                      PROTO((tree));
 extern void GNU_xref_hier                      PROTO((char *, char *, int, int, int));
 extern void GNU_xref_member                    PROTO((tree, tree));
 
-#define in_try_block(X) (0)
-#define in_exception_handler(X) (0)
-#define expand_raise(X) (0)
-#define expand_start_try(A,B,C) ((void)0)
-#define expand_end_try() ((void)0)
-#define expand_start_except(A,B) ((void)0)
-#define expand_escape_except() (0)
-#define expand_end_except() (NULL_TREE)
-#define expand_catch(X) (0)
-#define expand_catch_default() (0)
-#define expand_end_catch() (0)
-
 /* -- end of C++ */
 
 #endif /* not _CP_TREE_H */
index 1533f95..e33db79 100644 (file)
@@ -41,6 +41,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
 
+extern tree builtin_return_address_fndecl;
+
 extern struct obstack permanent_obstack;
 
 extern int current_class_depth;
@@ -122,7 +124,6 @@ static tree grokparms                               PROTO((tree, int));
 static tree lookup_nested_type                 PROTO((tree, tree));
 static char *redeclaration_error_message       PROTO((tree, tree));
 static void grok_op_properties                 PROTO((tree, int, int));
-static void deactivate_exception_cleanups      PROTO((void));
 
 tree define_function           
        PROTO((char *, tree, enum built_in_function, void (*)(), char *));
@@ -257,12 +258,6 @@ tree dtor_label;
 
 tree ctor_label;
 
-/* A FUNCTION_DECL which can call `unhandled_exception'.
-   Not necessarily the one that the user will declare,
-   but sufficient to be called by routines that want to abort the program.  */
-
-tree unhandled_exception_fndecl;
-
 /* A FUNCTION_DECL which can call `abort'.  Not necessarily the
    one that the user will declare, but sufficient to be called
    by routines that want to abort the program.  */
@@ -564,11 +559,6 @@ struct binding_level
     unsigned more_cleanups_ok : 1;
     unsigned have_cleanups : 1;
 
-    /* Nonzero if this level can safely have additional
-       exception-raising statements added to it.  */
-    unsigned more_exceptions_ok : 1;
-    unsigned have_exceptions : 1;
-
     /* Nonzero if we should accept any name as an identifier in
        this scope.  This happens in some template definitions.  */
     unsigned accept_any : 1;
@@ -657,7 +647,6 @@ push_binding_level (newlevel, tag_transparent, keep)
   current_binding_level = newlevel;
   newlevel->tag_transparent = tag_transparent;
   newlevel->more_cleanups_ok = 1;
-  newlevel->more_exceptions_ok = 1;
   newlevel->keep = keep;
 #if defined(DEBUG_CP_BINDING_LEVELS)
   newlevel->binding_depth = binding_depth;
@@ -751,23 +740,6 @@ declare_parm_level ()
   current_binding_level->parm_flag = 1;
 }
 
-/* Identify this binding level as a level of a default exception handler.  */
-
-void
-declare_implicit_exception ()
-{
-  current_binding_level->parm_flag = 3;
-}
-
-/* Nonzero if current binding contour contains expressions
-   that might raise exceptions.  */
-
-int
-have_exceptions_p ()
-{
-  return current_binding_level->have_exceptions;
-}
-
 void
 declare_uninstantiated_type_level ()
 {
@@ -1105,7 +1077,7 @@ poplevel (keep, reverse, functionbody)
     }
 
   /* Take care of compiler's internal binding structures.  */
-  if (tmp == 2 && !implicit_try_block)
+  if (tmp == 2 && class_binding_level)
     {
 #if 0
       /* We did not call push_momentary for this
@@ -1300,10 +1272,6 @@ print_binding_level (lvl)
     fprintf (stderr, " more-cleanups-ok");
   if (lvl->have_cleanups)
     fprintf (stderr, " have-cleanups");
-  if (lvl->more_exceptions_ok)
-    fprintf (stderr, " more-exceptions-ok");
-  if (lvl->have_exceptions)
-    fprintf (stderr, " have-exceptions");
   fprintf (stderr, "\n");
   if (lvl->names)
     {
@@ -1664,6 +1632,7 @@ set_nested_typename (decl, classname, name, type)
       sprintf (buf, "%s::%s", IDENTIFIER_POINTER (classname),
               IDENTIFIER_POINTER (name));
       DECL_NESTED_TYPENAME (decl) = get_identifier (buf);
+      TREE_MANGLED (DECL_NESTED_TYPENAME (decl)) = 1;
 
       /* This is a special usage of IDENTIFIER_TYPE_VALUE which have no
         correspondence in any binding_level.  This is ok since the
@@ -2988,7 +2957,6 @@ pushdecl (x)
 
       /* Keep count of variables in this level with incomplete type.  */
       if (TREE_CODE (x) != TEMPLATE_DECL
-         && TREE_CODE (x) != CPLUS_CATCH_DECL
          && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
          && PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
        {
@@ -3001,7 +2969,7 @@ pushdecl (x)
     {
       if (current_class_name)
        {
-         if (!DECL_NESTED_TYPENAME (TYPE_NAME (TREE_TYPE (x))))
+         if (! TREE_MANGLED (name))
            set_nested_typename (x, current_class_name, DECL_NAME (x),
                                 TREE_TYPE (x));
        }
@@ -3107,6 +3075,21 @@ pushdecl_class_level (x)
 
   if (name)
     {
+      if (TYPE_BEING_DEFINED (current_class_type))
+       {
+         /* Check for inconsistent use of this name in the class body.
+            Types, enums, and static vars are checked here; other
+            members are checked in finish_struct.  */
+         tree icv = IDENTIFIER_CLASS_VALUE (name);
+
+         if (icv)
+           {
+             cp_error ("declaration of identifier `%D' as `%#D'", name, x);
+             cp_error_at ("conflicts with previous use in class as `%#D'",
+                          icv);
+           }
+       }
+
       push_class_level_binding (name, x);
       if (TREE_CODE (x) == TYPE_DECL)
        {
@@ -3936,11 +3919,7 @@ lookup_name_real (name, prefer_type, nonclass)
        /* Try to find values from base classes if we are presently
           defining a type.  We are presently only interested in
           TYPE_DECLs.  */
-       {
-         val = lookup_field (current_class_type, name, 0, 1);
-         if (val)
-           pushdecl_class_level (val);
-       }
+       val = lookup_field (current_class_type, name, 0, 1);
 
       /* yylex() calls this with -2, since we should never start digging for
         the nested name at the point where we haven't even, for example,
@@ -4498,6 +4477,7 @@ init_decl_processing ()
   builtin_function ("__builtin_constant_p", int_ftype_int,
                    BUILT_IN_CONSTANT_P, NULL_PTR);
 
+  builtin_return_address_fndecl =
   builtin_function ("__builtin_return_address",
                    build_function_type (ptr_type_node, 
                                         tree_cons (NULL_TREE,
@@ -4911,23 +4891,13 @@ init_decl_processing ()
                       build_function_type (void_type_node, void_list_node),
                       NOT_BUILT_IN, 0, 0);
 
-  unhandled_exception_fndecl
-    = define_function ("__unhandled_exception",
-                      build_function_type (void_type_node, NULL_TREE),
-                      NOT_BUILT_IN, 0, 0);
-
   /* Perform other language dependent initializations.  */
   init_class_processing ();
   init_init_processing ();
   init_search_processing ();
 
   if (flag_handle_exceptions)
-    {
-      if (flag_handle_exceptions == 2)
-       /* Too much trouble to inline all the trys needed for this.  */
-       flag_this_is_variable = 2;
-      init_exception_processing ();
-    }
+    init_exception_processing ();
   if (flag_gc)
     init_gc_processing ();
   if (flag_no_inline)
@@ -5097,14 +5067,11 @@ shadow_tag (declspecs)
              push_obstacks (&permanent_obstack, &permanent_obstack);
 
              pushclass (t, 0);
-             finish_exception (t, NULL_TREE);
 
              ename = TYPE_NAME (t);
              if (TREE_CODE (ename) == TYPE_DECL)
                ename = DECL_NAME (ename);
              decl = build_lang_field_decl (VAR_DECL, ename, t);
-             finish_exception_decl (current_class_name, decl);
-             end_exception_decls ();
 
              pop_obstacks ();
            }
@@ -5779,7 +5746,6 @@ finish_decl (decl, init, asmspec_tree, need_pop)
   if (type != error_mark_node && IS_AGGR_TYPE (type)
       && CLASSTYPE_DECLARED_EXCEPTION (type))
     {
-      finish_exception_decl (NULL_TREE, decl);
       CLASSTYPE_GOT_SEMICOLON (type) = 1;
       goto finish_end;
     }
@@ -6111,7 +6077,6 @@ finish_decl (decl, init, asmspec_tree, need_pop)
              cleanup = TREE_OPERAND (init, 2);
              init = TREE_OPERAND (init, 0);
              current_binding_level->have_cleanups = 1;
-             current_binding_level->more_exceptions_ok = 0;
            }
          else
            cleanup = maybe_build_cleanup (decl);
@@ -6146,14 +6111,6 @@ finish_decl (decl, init, asmspec_tree, need_pop)
       if (was_temp)
        end_temporary_allocation ();
 
-      /* If we are in need of a cleanup, get out of any implicit
-        handlers that have been established so far.  */
-      if (cleanup && current_binding_level->parm_flag == 3)
-       {
-         pop_implicit_try_blocks (decl);
-         current_binding_level->more_exceptions_ok = 0;
-       }
-
       if (TREE_CODE (decl) == VAR_DECL
          && current_binding_level != global_binding_level
          && ! TREE_STATIC (decl)
@@ -6343,7 +6300,11 @@ finish_decl (decl, init, asmspec_tree, need_pop)
                expand_decl (decl);
              else if (cleanup)
                {
-                 expand_decl_cleanup (NULL_TREE, cleanup);
+                 /* XXX: Why don't we use decl here?  */
+                 /* Ans: Because it was already expanded? */
+                 if (! expand_decl_cleanup (NULL_TREE, cleanup))
+                   cp_error ("parser lost in parsing declaration of `%D'",
+                             decl);
                  /* Cleanup used up here.  */
                  cleanup = NULL_TREE;
                }
@@ -8849,8 +8810,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
            decl = build_lang_field_decl (VAR_DECL, declarator, type);
            if (ctype == NULL_TREE)
              ctype = current_class_type;
-           finish_exception_decl (TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
-                                  ? TYPE_IDENTIFIER (ctype) : TYPE_NAME (ctype), decl);
            return void_type_node;
          }
        else if (TYPE_SIZE (type) == NULL_TREE && !staticp
@@ -9869,10 +9828,8 @@ xref_tag (code_type_node, name, binfo, globalize)
        * and don't try to find it as a type. */
       xref_next_defn = 0;
       if (t && TYPE_CONTEXT(t))
-       { 
-         extern char *index();
-         char *p;
-         if ((p = index(IDENTIFIER_POINTER(name), ':')) && *(p+1) == ':')
+       {
+         if (TREE_MANGLED (name))
            ref = t;
          else
            ref = lookup_tag (code, name, b, 1);
@@ -10267,6 +10224,7 @@ finish_enum (enumtype, values)
 
       HOST_WIDE_INT value = TREE_INT_CST_LOW (TREE_VALUE (values));
       TREE_TYPE (TREE_VALUE (values)) = enumtype;
+      TREE_TYPE (DECL_INITIAL (TREE_VALUE (values))) = enumtype;
       minvalue = maxvalue = value;
       
       for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
@@ -10370,8 +10328,7 @@ build_enumerator (name, value)
        }
       else
        {
-         error ("enumerator value for `%s' not integer constant",
-                IDENTIFIER_POINTER (name));
+         cp_error ("enumerator value for `%D' not integer constant", name);
          value = NULL_TREE;
        }
     }
@@ -10404,8 +10361,6 @@ build_enumerator (name, value)
       TREE_TYPE (value) = integer_type_node;
     }
 
-  result = saveable_tree_cons (name, value, NULL_TREE);
-
   /* C++ associates enums with global, function, or class declarations.  */
 
   decl = current_scope ();
@@ -10439,6 +10394,7 @@ build_enumerator (name, value)
   if (enum_next_value == integer_one_node)
     enum_next_value = copy_node (enum_next_value);
 
+  result = saveable_tree_cons (name, decl, NULL_TREE);
   return result;
 }
 
@@ -10494,7 +10450,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
      tree declarator, declspecs, raises;
      int pre_parsed_p;
 {
-  extern tree EHS_decl;
   tree decl1, olddecl;
   tree ctype = NULL_TREE;
   tree fntype;
@@ -10503,9 +10458,6 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
   extern int used_extern_spec;
   int doing_friend = 0;
 
-  if (flag_handle_exceptions && EHS_decl == NULL_TREE)
-    init_exception_processing_1 ();
-
   /* Sanity check.  */
   my_friendly_assert (TREE_VALUE (void_list_node) == void_type_node, 160);
   my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
@@ -10829,7 +10781,6 @@ store_parm_decls ()
   register tree fndecl = current_function_decl;
   register tree parm;
   int parms_have_cleanups = 0;
-  tree eh_decl;
 
   /* This is either a chain of PARM_DECLs (when a prototype is used).  */
   tree specparms = current_function_parms;
@@ -10854,18 +10805,6 @@ store_parm_decls ()
   /* Create a binding level for the parms.  */
   expand_start_bindings (0);
 
-  /* Prepare to catch raises, if appropriate.  */
-  if (flag_handle_exceptions)
-    {
-      /* Get this cleanup to be run last, since it
-        is a call to `longjmp'.  */
-      setup_exception_throw_decl ();
-      eh_decl = current_binding_level->names;
-      current_binding_level->names = TREE_CHAIN (current_binding_level->names);
-    }
-  if (flag_handle_exceptions)
-    expand_start_try (integer_one_node, 0, 1);
-
   if (specparms != NULL_TREE)
     {
       /* This case is when the function was defined with an ANSI prototype.
@@ -10919,7 +10858,9 @@ store_parm_decls ()
              if (cleanup)
                {
                  expand_decl (parm);
-                 expand_decl_cleanup (parm, cleanup);
+                 if (! expand_decl_cleanup (parm, cleanup))
+                   cp_error ("parser lost in parsing declaration of `%D'",
+                             parm);
                  parms_have_cleanups = 1;
                }
            }
@@ -10953,14 +10894,6 @@ store_parm_decls ()
   DECL_SAVED_INSNS (fndecl) = NULL_RTX;
   expand_function_start (fndecl, parms_have_cleanups);
 
-  if (flag_handle_exceptions)
-    {
-      /* Make the throw decl visible at this level, just
-        not in the way of the parameters.  */
-      pushdecl (eh_decl);
-      expand_decl_init (eh_decl);
-    }
-
   /* Create a binding contour which can be used to catch
      cleanup-generated temporaries.  Also, if the return value needs or
      has initialization, deal with that now.  */
@@ -10975,7 +10908,8 @@ store_parm_decls ()
   if (flag_gc)
     {
       maybe_gc_cleanup = build_tree_list (NULL_TREE, error_mark_node);
-      expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup);
+      if (! expand_decl_cleanup (NULL_TREE, maybe_gc_cleanup))
+       cp_error ("parser lost in parsing declaration of `%D'", fndecl);
     }
 
   /* If this function is `main', emit a call to `__main'
@@ -11121,7 +11055,6 @@ finish_function (lineno, call_poplevel)
   register tree fndecl = current_function_decl;
   tree fntype, ctype = NULL_TREE;
   rtx head, last_parm_insn, mark;
-  extern int sets_exception_throw_decl;
   /* Label to use if this function is supposed to return a value.  */
   tree no_return_label = NULL_TREE;
   tree decls = NULL_TREE;
@@ -11344,8 +11277,6 @@ finish_function (lineno, call_poplevel)
          if (call_poplevel)
            {
              decls = getdecls ();
-             if (flag_handle_exceptions == 2)
-               deactivate_exception_cleanups ();
              expand_end_bindings (decls, decls != NULL_TREE, 0);
              poplevel (decls != NULL_TREE, 0, 0);
            }
@@ -11377,41 +11308,6 @@ finish_function (lineno, call_poplevel)
                                  current_class_decl, integer_zero_node, 1);
          thenclause = build_modify_expr (current_class_decl, NOP_EXPR,
                                          build_new (NULL_TREE, current_class_type, void_type_node, 0));
-         if (flag_handle_exceptions == 2)
-           {
-             tree cleanup, cleanup_deallocate;
-             tree virtual_size;
-
-             /* This is the size of the virtual object pointed to by
-                allocated_this.  In this case, it is simple.  */
-             virtual_size = c_sizeof (current_class_type);
-
-             allocated_this = build_decl (VAR_DECL, NULL_TREE, ptr_type_node);
-             DECL_REGISTER (allocated_this) = 1;
-             DECL_INITIAL (allocated_this) = error_mark_node;
-             expand_decl (allocated_this);
-             expand_decl_init (allocated_this);
-             /* How we cleanup `this' if an exception was raised before
-                we are ready to bail out.  */
-             cleanup = TYPE_GETS_REG_DELETE (current_class_type)
-               ? build_opfncall (DELETE_EXPR, LOOKUP_NORMAL, allocated_this, virtual_size, NULL_TREE)
-                 /* The size of allocated_this is wrong, and hence the
-                    second argument to operator delete will be wrong. */
-                 : build_delete (TREE_TYPE (allocated_this), allocated_this,
-                                 integer_three_node,
-                                 LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE, 1);
-             cleanup_deallocate
-               = build_modify_expr (current_class_decl, NOP_EXPR, integer_zero_node);
-             cleanup = tree_cons (NULL_TREE, cleanup,
-                                  build_tree_list (NULL_TREE, cleanup_deallocate));
-
-             expand_decl_cleanup (allocated_this,
-                                  build (COND_EXPR, integer_type_node,
-                                         build (NE_EXPR, integer_type_node,
-                                                allocated_this, integer_zero_node),
-                                         build_compound_expr (cleanup),
-                                         integer_zero_node));
-           }
        }
 
       CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
@@ -11426,8 +11322,6 @@ finish_function (lineno, call_poplevel)
        {
          expand_start_cond (cond, 0);
          expand_expr_stmt (thenclause);
-         if (flag_handle_exceptions == 2)
-           expand_assignment (allocated_this, current_class_decl, 0, 0);
          expand_end_cond ();
        }
 
@@ -11460,14 +11354,6 @@ finish_function (lineno, call_poplevel)
       /* This is where the body of the constructor ends.  */
       expand_label (ctor_label);
       ctor_label = NULL_TREE;
-      if (flag_handle_exceptions == 2)
-       {
-         expand_assignment (allocated_this, integer_zero_node, 0, 0);
-         if (call_poplevel)
-           deactivate_exception_cleanups ();
-       }
-
-      pop_implicit_try_blocks (NULL_TREE);
 
       if (call_poplevel)
        {
@@ -11545,19 +11431,6 @@ finish_function (lineno, call_poplevel)
     /* Emit label at beginning of cleanup code for parameters.  */
     emit_label (cleanup_label);
 
-#if 1
-  /* Cheap hack to get better code from GNU C++.  Remove when cse is fixed.  */
-  if (exception_throw_decl && sets_exception_throw_decl == 0)
-    expand_assignment (exception_throw_decl, integer_zero_node, 0, 0);
-#endif
-
-  if (flag_handle_exceptions)
-    {
-      expand_end_try ();
-      expand_start_except (0, 0);
-      expand_end_except ();
-    }
-
   /* Get return value into register if that's where it's supposed to be.  */
   if (original_result_rtx)
     fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
@@ -11590,6 +11463,9 @@ finish_function (lineno, call_poplevel)
   /* Generate rtl for function exit.  */
   expand_function_end (input_filename, lineno, 1);
 
+  if (flag_handle_exceptions)
+    expand_exception_blocks();
+
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
      this function's blocks.  */
@@ -11917,9 +11793,13 @@ hack_incomplete_structures (type)
            rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
            if (! toplevel)
              {
+               tree cleanup;
                expand_decl (decl);
-               expand_decl_cleanup (decl, maybe_build_cleanup (decl));
+               cleanup = maybe_build_cleanup (decl);
                expand_decl_init (decl);
+               if (! expand_decl_cleanup (decl, cleanup))
+                 cp_error ("parser lost in parsing declaration of `%D'",
+                           decl);
              }
          }
        my_friendly_assert (current_binding_level->n_incomplete > 0, 164);
@@ -11982,9 +11862,6 @@ maybe_build_cleanup (decl)
        rval = build_compound_expr (tree_cons (NULL_TREE, rval,
                                               build_tree_list (NULL_TREE, build_vbase_delete (type, decl))));
 
-      current_binding_level->have_cleanups = 1;
-      current_binding_level->more_exceptions_ok = 0;
-
       if (TREE_CODE (decl) != PARM_DECL)
        resume_momentary (temp);
 
@@ -12024,27 +11901,8 @@ cplus_expand_expr_stmt (exp)
          cp_warning ("reference, not call, to function `%D'", exp);
          warning ("at this point in file");
        }
-      if (TREE_RAISES (exp))
-       {
-         my_friendly_assert (flag_handle_exceptions, 165);
-         if (flag_handle_exceptions == 2)
-           {
-             if (! current_binding_level->more_exceptions_ok)
-               {
-                 extern struct nesting *nesting_stack, *block_stack;
-
-                 remove_implicit_immediately
-                   = (nesting_stack != block_stack);
-                 cplus_expand_start_try (1);
-               }
-             current_binding_level->have_exceptions = 1;
-           }
-       }
 
       expand_expr_stmt (break_out_cleanups (exp));
-
-      if (remove_implicit_immediately)
-       pop_implicit_try_blocks (NULL_TREE);
     }
 
   /* Clean up any pending cleanups.  This happens when a function call
@@ -12082,95 +11940,6 @@ finish_stmt ()
     cadillac_finish_stmt ();
 }
 
-void
-pop_implicit_try_blocks (decl)
-     tree decl;
-{
-  if (decl)
-    {
-      my_friendly_assert (current_binding_level->parm_flag == 3, 166);
-      current_binding_level->names = TREE_CHAIN (decl);
-    }
-
-  while (current_binding_level->parm_flag == 3)
-    {
-      tree name = get_identifier ("(compiler error)");
-      tree orig_ex_type = current_exception_type;
-      tree orig_ex_decl = current_exception_decl;
-      tree orig_ex_obj = current_exception_object;
-      tree decl = cplus_expand_end_try (2);
-
-      /* @@ It would be nice to make all these point
-        to exactly the same handler.  */
-      /* Start hidden EXCEPT.  */
-      cplus_expand_start_except (name, decl);
-      /* reraise ALL.  */
-      cplus_expand_reraise (NULL_TREE);
-      current_exception_type = orig_ex_type;
-      current_exception_decl = orig_ex_decl;
-      current_exception_object = orig_ex_obj;
-      /* This will reraise for us.  */
-      cplus_expand_end_except (error_mark_node);
-    }
-
-  if (decl)
-    {
-      TREE_CHAIN (decl) = current_binding_level->names;
-      current_binding_level->names = decl;
-    }
-}
-
-/* Push a cleanup onto the current binding contour that will cause
-   ADDR to be cleaned up, in the case that an exception propagates
-   through its binding contour.  */
-
-void
-push_exception_cleanup (addr)
-     tree addr;
-{
-  tree decl = build_decl (VAR_DECL, get_identifier (EXCEPTION_CLEANUP_NAME), ptr_type_node);
-  tree cleanup;
-
-  decl = pushdecl (decl);
-  DECL_REGISTER (decl) = 1;
-  store_init_value (decl, addr);
-  expand_decl (decl);
-  expand_decl_init (decl);
-
-  cleanup = build (COND_EXPR, integer_type_node,
-                  build (NE_EXPR, integer_type_node,
-                         decl, integer_zero_node),
-                  build_delete (TREE_TYPE (addr), decl,
-                                lookup_name (in_charge_identifier, 0),
-                                LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0),
-                  integer_zero_node);
-  expand_decl_cleanup (decl, cleanup);
-}
-
-/* For each binding contour, emit code that deactivates the
-   exception cleanups.  All other cleanups are left as they were.  */
-
-static void
-deactivate_exception_cleanups ()
-{
-  struct binding_level *b = current_binding_level;
-  tree xyzzy = get_identifier (EXCEPTION_CLEANUP_NAME);
-  while (b != class_binding_level)
-    {
-      if (b->parm_flag == 3)
-       {
-         tree decls = b->names;
-         while (decls)
-           {
-             if (DECL_NAME (decls) == xyzzy)
-               expand_assignment (decls, integer_zero_node, 0, 0);
-             decls = TREE_CHAIN (decls);
-           }
-       }
-      b = b->level_chain;
-    }
-}
-
 /* Change a static member function definition into a FUNCTION_TYPE, instead
    of the METHOD_TYPE that we create when it's originally parsed.
 
index 34b7499..d6eb5d9 100644 (file)
@@ -266,16 +266,10 @@ int write_virtuals;
 int flag_elide_constructors;
 
 /* Nonzero means recognize and handle exception handling constructs.
-   2 means handle exceptions the way Spring wants them handled.  */
+   Use ansi syntax and semantics.  WORK IN PROGRESS!  */
 
 int flag_handle_exceptions;
 
-/* Nonzero means recognize and handle exception handling constructs.
-   Use ansi syntax and semantics.  WORK IN PROGRESS!
-   2 means handle exceptions the way Spring wants them handled.  */
-
-int flag_ansi_exceptions;
-
 /* Nonzero means recognize and handle signature language constructs.  */
 
 int flag_handle_signatures;
@@ -354,9 +348,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"memoize-lookups", &flag_memoize_lookups, 1},
   {"elide-constructors", &flag_elide_constructors, 1},
   {"handle-exceptions", &flag_handle_exceptions, 1},
-  {"ansi-exceptions", &flag_ansi_exceptions, 1},
   {"handle-signatures", &flag_handle_signatures, 1},
-  {"spring-exceptions", &flag_handle_exceptions, 2},
   {"default-inline", &flag_default_inline, 1},
   {"dollars-in-identifiers", &dollars_in_ident, 1},
   {"enum-int-equiv", &flag_int_enum_equivalence, 1},
@@ -2493,6 +2485,8 @@ finish_file ()
   tree vars = static_aggregates;
   int needs_cleaning = 0, needs_messing_up = 0;
 
+  build_exception_table ();
+
   if (flag_detailed_statistics)
     dump_tree_statistics ();
 
index 66f1266..629c70b 100644 (file)
@@ -559,14 +559,19 @@ dump_decl (t, v)
       break;
 
     case TYPE_DECL:
-      if (TYPE_NAME (TREE_TYPE (t)) != t)
-       {
-         if (v > 0)
-           OB_PUTS ("typedef ");
-         goto general;
-       }
-
-      dump_type (TREE_TYPE (t), v);
+      {
+       /* Don't say 'typedef class A' */
+       tree type = TREE_TYPE (t);
+        if (IS_AGGR_TYPE (type) && ! TYPE_PTRMEMFUNC_P (type)
+           && type == TYPE_MAIN_VARIANT (type))
+         {
+           dump_type (type, v);
+           break;
+         }
+      }
+      if (v > 0)
+       OB_PUTS ("typedef ");
+      goto general;
       break;
       
     case VAR_DECL:
@@ -586,9 +591,8 @@ dump_decl (t, v)
          OB_PUTC (' ');
        }
       /* DECL_CLASS_CONTEXT isn't being set in some cases.  Hmm...  */
-      if (TREE_CODE (t) == FIELD_DECL
-         || (TREE_CODE (t) == VAR_DECL && DECL_CONTEXT (t)
-             && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'))
+      if (DECL_CONTEXT (t)
+         && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
        {
          dump_type (DECL_CONTEXT (t), 0);
          OB_PUTC2 (':', ':');
@@ -696,14 +700,7 @@ dump_decl (t, v)
 
     case CONST_DECL:
       if (NEXT_CODE (t) == ENUMERAL_TYPE)
-       {
-         if (DECL_CONTEXT (t))
-           {
-             dump_decl (DECL_CONTEXT (t), 0);
-             OB_PUTC2 (':', ':');
-           }
-         OB_PUTID (DECL_NAME (t));
-       }
+       goto general;
       else
        dump_expr (DECL_INITIAL (t), 0);
       break;
index 4a7d0f8..60fd392 100644 (file)
@@ -1,6 +1,8 @@
 /* Handle exceptional things in C++.
-   Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
-   Contributed by Michael Tiemann (tiemann@cygnus.com)
+   Copyright (C) 1989, 1992, 1993, 1994 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.
 
 This file is part of GNU CC.
 
@@ -26,1198 +28,1346 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "rtl.h"
 #include "cp-tree.h"
 #include "flags.h"
-/* On Suns this can get you to the right definition if you
-   set the right value for TARGET.  */
-#include <setjmp.h>
-#ifdef sequent
-/* Can you believe they forgot this?  */
-#define _JBLEN 11
-#endif
-
-#ifndef _JBLEN
-#define _JBLEN (sizeof(jmp_buf)/sizeof(int))
-#endif
+#include "obstack.h"
+#include "expr.h"
 
-#undef NULL
-#define NULL (char *)0
+/* holds the fndecl for __builtin_return_address () */
+tree builtin_return_address_fndecl;
 
-/* This should be part of `ansi_opname', or at least be defined by the std.  */
-#define EXCEPTION_NAME_PREFIX "__ex"
-#define EXCEPTION_NAME_LENGTH 4
+/* Define at your own risk!  */
+#ifdef sun
+#ifdef sparc
+#define TRY_NEW_EH
+#endif
+#endif
 
-void init_exception_processing ();
-void init_exception_processing_1 ();
+#ifndef TRY_NEW_EH
 
-/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
-   next exception handler.  Its value says whether to throw or not.
-   In the case of functions which do not issue a RAISE, it should be
-   possible to optimize away this VAR_DECL (and overhead associated
-   with it).  */
-tree exception_throw_decl;
-/* Use this to know that we did not set `exception_throw_decl',
-   until GCC optimizer is smart enough to figure it out for itself.  */
-int sets_exception_throw_decl;
+static void
+sorry_no_eh ()
+{
+  static int warned = 0;
+  if (! warned)
+    {
+      sorry ("exception handling not supported");
+      warned = 1;
+    }
+}
 
-/* The exception `type' currently in scope, or NULL_TREE if none.  */
-tree current_exception_type;
+void
+build_exception_table ()
+{
+}
 
-/* The exception handler object for the given scope.  */
-tree current_exception_decl;
-rtx current_exception_name_as_rtx;
-rtx current_exception_parms_as_rtx;
+void
+expand_exception_blocks ()
+{
+}
 
-/* The ``object'' view of the current exception parameters.
-   We cast up from the `parms' field to `current_exception_type'.  */
-tree current_exception_object;
+void
+start_protect ()
+{
+}
 
-/* Cache `setjmp', `longjmp', `raise_exception', and `unhandled_exception'
-   after default conversion.  Maybe later they will get built-in.  */
-static tree BISJ, BILJ, BIR, BIUE;
+void
+end_protect (finalization)
+     tree finalization;
+{
+}
 
-/* Local variables which give the appearance that exception
-   handling is part of the language and the execution model.  */
+void
+expand_start_try_stmts ()
+{
+  sorry_no_eh ();
+}
 
-/* The type of the exception handler stack.  */
-tree EHS_type;
+void
+expand_end_try_stmts ()
+{
+}
 
-/* The global handler stack.  */
-tree EHS_decl;
+void
+expand_start_all_catch ()
+{
+}
 
-/* Cached component refs to fields of `EHS_decl'.  */
-static tree EHS_prev, EHS_handler, EHS_parms, EHS_name;
-static rtx EHS_parms_as_rtx, EHS_name_as_rtx;
+void
+expand_end_all_catch ()
+{
+}
 
-/* The parameter names of this exception type.  */
+void
+expand_start_catch_block (typename, identifier)
+     tree typename, identifier;
+{
+}
 
-static tree last_exception_fields;
-static tree last_exception_field_types;
+void
+expand_end_catch_block ()
+{
+}
 
-/* When ID is VOID_TYPE_NODE, it means ``raise all''.
-   Cannot be inline, since it uses `alloca', and that
-   breaks code which pushes the result of this function
-   on the stack.  */
-static tree
-exception_object_name (prefix, id)
-     tree prefix;
-     tree id;
+void
+init_exception_processing ()
 {
-  /* First, cons up the `name' of this exception.  */
-  char *name;
-  int length = (id == void_type_node ? 3 : IDENTIFIER_LENGTH (id)) + EXCEPTION_NAME_LENGTH;
+}
 
-  if (prefix)
-    length += IDENTIFIER_LENGTH (prefix) + 2;
+void
+expand_throw (exp)
+     tree exp;
+{
+  sorry_no_eh ();
+}
 
-  name = (char *)alloca (length);
-  strcpy (name, EXCEPTION_NAME_PREFIX);
-  length = EXCEPTION_NAME_LENGTH;
-  if (prefix)
-    {
-      strcpy (name + length, IDENTIFIER_POINTER (prefix));
-#ifdef JOINER
-      name[length + IDENTIFIER_LENGTH (prefix)] = JOINER;
 #else
-      name[length + IDENTIFIER_LENGTH (prefix)] = '_';
-#endif
-      length += IDENTIFIER_LENGTH (prefix) + 1;
-    }
-  if (id == void_type_node)
-    strcpy (name + length, "all");
-  else
-    strcpy (name + length, IDENTIFIER_POINTER (id));
-  return get_identifier (name);
-}
 
-tree
-lookup_exception_cname (ctype, cname, raise_id)
-     tree ctype, cname;
-     tree raise_id;
+static int
+doing_eh (do_warn)
+     int do_warn;
 {
-  tree this_cname = TREE_PURPOSE (raise_id);
-  if (this_cname == NULL_TREE)
+  if (! flag_handle_exceptions)
     {
-      if (cname)
+      static int warned = 0;
+      if (! warned && do_warn)
        {
-         tree name = TREE_VALUE (raise_id);
-         if (purpose_member (name, CLASSTYPE_TAGS (ctype)))
-           this_cname = cname;
+         error ("exception handling disabled, use -fhandle-exceptions to enable.");
+         warned = 1;
        }
+      return 0;
     }
-  else if (this_cname == void_type_node)
-    this_cname = NULL_TREE;
-  else if (TREE_CODE (this_cname) != IDENTIFIER_NODE)
-    {
-      sorry ("multiple scope refs in `cplus_expand_raise_stmt'");
-      this_cname = error_mark_node;
-    }
-  return this_cname;
+  return 1;
 }
 
-tree
-lookup_exception_tname (oname)
-     tree oname;
-{
-  return get_identifier (IDENTIFIER_POINTER (oname) + EXCEPTION_NAME_LENGTH);
-}
 
-tree
-lookup_exception_object (cname, name, complain)
-     tree cname, name;
-     int complain;
+/*
+NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer
+to supporting exception handling as per Stroustrup's 2nd edition.
+It is a complete rewrite of all the EH stuff that was here before
+       Shortcomings:
+               1. The type of the throw and catch must still match
+                  exactly (no support yet for matching base classes)
+               2. Throw specifications of functions still doesnt't work.
+       Cool Things:
+               1. Destructors are called properly :-)
+               2. No overhead for the non-exception thrown case.
+               3. Fixing shortcomings 1 and 2 is simple.
+                       -Tad Hunt       (tad@mail.csh.rit.edu)
+
+*/
+
+/* A couple of backend routines from m88k.c */
+
+/* used to cache a call to __builtin_return_address () */
+static tree BuiltinReturnAddress;
+
+
+
+
+
+#include <stdio.h>
+
+/* XXX - Tad: for EH */
+/* output an exception table entry */
+
+static void
+output_exception_table_entry (file, start_label, end_label, eh_label)
+     FILE *file;
+     rtx start_label, end_label, eh_label;
 {
-  tree oname;
-  tree decl;
+  char label[100];
 
-  if (cname == void_type_node)
-    cname = NULL_TREE;
-  else if (cname && TREE_CODE (cname) != IDENTIFIER_NODE)
+  fprintf (file, "\t%s\t ", ASM_LONG); 
+  if (GET_CODE (start_label) == CODE_LABEL)
     {
-      sorry ("multiple scope refs in `lookup_exception_object'");
-      cname = NULL_TREE;
+      ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (start_label));
+      assemble_name (file, label);
     }
-  oname = exception_object_name (cname, name);
-  decl = IDENTIFIER_GLOBAL_VALUE (oname);
-  if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
+  else if (GET_CODE (start_label) == SYMBOL_REF)
     {
-      if (complain)
-       {
-         push_obstacks_nochange ();
-
-         if (cname)
-           error ("no exception name object for name `%s::%s'",
-                  IDENTIFIER_POINTER (cname),
-                  IDENTIFIER_POINTER (name));
-         else
-           error ("no exception name object for name `%s'",
-                  IDENTIFIER_POINTER (name));
-         end_temporary_allocation ();
-         /* Avoid further error messages.  */
-         pushdecl_top_level (build_lang_field_decl (VAR_DECL,
-                                                    exception_object_name (cname, name),
-                                                    error_mark_node));
-         pop_obstacks ();
-       }
-      return NULL_TREE;
+      fprintf (stderr, "YYYYYYYYYEEEEEEEESSSSSSSSSSSS!!!!!!!!!!\n");
+      assemble_name (file, XSTR (start_label, 0));
     }
-  return decl;
+  putc ('\n', file);
+
+  fprintf (file, "\t%s\t ", ASM_LONG);
+  ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (end_label));
+  assemble_name (file, label);
+  putc ('\n', file);
+
+  fprintf (file, "\t%s\t ", ASM_LONG);
+  ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (eh_label));
+  assemble_name (file, label);
+  putc ('\n', file);
+
+  putc ('\n', file);           /* blank line */
+}
+   
+static void
+easy_expand_asm (str)
+     char *str;
+{
+  expand_asm (build_string (strlen (str)+1, str));
 }
 
-tree
-lookup_exception_type (ctype, cname, raise_id)
-     tree ctype, cname;
-     tree raise_id;
+/* unwind the stack. */
+static void
+do_unwind (throw_label)
+     rtx throw_label;
 {
-  tree name = TREE_VALUE (raise_id);
-  tree purpose = TREE_PURPOSE (raise_id);
+#ifdef sparc
+  extern FILE *asm_out_file;
+  tree fcall;
+  tree params;
+  rtx return_val_rtx;
+
+  /* call to  __builtin_return_address () */
+  params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+  fcall = build_function_call (BuiltinReturnAddress, params);
+  return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
+  /* In the return, the new pc is pc+8, as the value comming in is
+     really the address of the call insn, not the next insn.  */
+  emit_move_insn (return_val_rtx, plus_constant(gen_rtx (LABEL_REF,
+                                                        Pmode,
+                                                        throw_label), -8));
+  easy_expand_asm ("st %l0,[%fp]");
+  easy_expand_asm ("st %l1,[%fp+4]");
+  easy_expand_asm ("ret");
+  easy_expand_asm ("restore");
+  emit_barrier ();
+#endif
+#if m88k
+  rtx temp_frame = frame_pointer_rtx;
 
-  if (cname && purpose == NULL_TREE)
-    purpose = cname;
+  temp_frame = memory_address (Pmode, temp_frame);
+  temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
 
-  if (purpose && purpose != void_type_node)
-    {
-      tree link = NULL_TREE;
+  /* hopefully this will successfully pop the frame! */
+  emit_move_insn (frame_pointer_rtx, temp_frame);
+  emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
+  emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
+  emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
+                                                    (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
 
-      if (TREE_CODE (purpose) != IDENTIFIER_NODE)
-       {
-         sorry ("multiple scope refs in `lookup_exception_type'");
-         TREE_PURPOSE (raise_id) = NULL_TREE;
-         return NULL_TREE;
-       }
-      if (! is_aggr_typedef (purpose, 1))
-       return NULL_TREE;
-      ctype = IDENTIFIER_TYPE_VALUE (purpose);
-      link = purpose_member (name, CLASSTYPE_TAGS (ctype));
-      if (link)
-       return TREE_VALUE (link);
-    }
+#if 0
+  emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
+                                                  -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
+
+  emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
 
-  ctype = lookup_name (name, 1);
-  if (ctype && TREE_CODE (ctype) == TYPE_DECL)
-    ctype = TREE_TYPE (ctype);
-  if (ctype && TREE_CODE (ctype) == RECORD_TYPE
-      && CLASSTYPE_DECLARED_EXCEPTION (ctype))
-    return ctype;
-  return NULL_TREE;
+  emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
+                                                    (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
+#endif
+#endif
 }
 
-tree
-finish_exception (e, list_of_fieldlists)
-     tree e;
-     tree list_of_fieldlists;
-{
-  tree parmtypes = NULL_TREE, name_field;
-  tree cname = TYPE_NAME (e);
 
-  if (TREE_CODE (cname) == TYPE_DECL)
-    cname = DECL_NAME (cname);
 
-  if (last_exception_fields)
-    error ("cannot declare exceptions within exceptions");
-  if (list_of_fieldlists && ! ANON_AGGRNAME_P (cname))
-    cp_error ("exception name `%T' must follow body declaration", e);
-  if (list_of_fieldlists)
-    {
-      tree prev, field;
-
-      /* Note: no public, private, or protected allowed.  */
-      if (TREE_CHAIN (list_of_fieldlists))
-       error ("access declarations invalid in exception declaration");
-      else if (TREE_PURPOSE (list_of_fieldlists) != (tree)access_default)
-       error ("access declarations invalid in exception declaration");
-      TREE_PURPOSE (list_of_fieldlists) = (tree)access_default;
-
-      /* Note also: no member function declarations allowed.  */
-      for (prev = 0, field = TREE_VALUE (list_of_fieldlists);
-          field; prev = field, field = TREE_CHAIN (field))
-       {
-         switch (TREE_CODE (field))
-           {
-           case FIELD_DECL:
-             /* ok.  */
-             parmtypes = tree_cons (NULL_TREE, TREE_TYPE (field), parmtypes);
-             continue;
-           case FUNCTION_DECL:
-             cp_error ("declaration of function `%D' in exception invalid",
-                         field);
-             break;
-           case VAR_DECL:
-             if (TREE_STATIC (field))
-               cp_error ("declaration of static variable `%D' in exception invalid", field);
-             else
-               cp_error ("declaration of constant field `%D' in exception invalid", field);
-             break;
-           case CONST_DECL:
-             cp_error ("declaration of enum value `%D' in exception invalid", field);
-             break;
-           case SCOPE_REF:
-             error ("use of `::' in exception context invalid");
-             break;
-           }
-         if (prev)
-           TREE_CHAIN (prev) = TREE_CHAIN (field);
-         else
-           TREE_VALUE (list_of_fieldlists) = TREE_CHAIN (field);
-       }
-    }
+#if 0
+/* This is the startup, and finish stuff per exception table. */
 
-  /* Now that we've cleaned up the fields, add a name identifier at front.  */
-  name_field = build_lang_field_decl (FIELD_DECL, get_identifier ("__name"),
-                                     ptr_type_node);
-  if (list_of_fieldlists)
-    {
-      TREE_CHAIN (name_field) = TREE_VALUE (list_of_fieldlists);
-      TREE_VALUE (list_of_fieldlists) = name_field;
-    }
-  else
-    list_of_fieldlists = build_tree_list (NULL_TREE, name_field);
+/* XXX - Tad: exception handling section */
+#ifndef EXCEPT_SECTION_ASM_OP
+#define EXCEPT_SECTION_ASM_OP  "section\t.gcc_except_table,\"a\",@progbits"
+#endif
 
-  last_exception_fields = TREE_VALUE (list_of_fieldlists);
-  if (parmtypes)
-    {
-      last_exception_field_types = nreverse (parmtypes);
-      /* Set the TREE_CHAIN of what is now at the end of the
-        list to `void_list_node'.  */
-      TREE_CHAIN (parmtypes) = void_list_node;
-    }
-  else
-    last_exception_field_types = void_list_node;
+#ifdef EXCEPT_SECTION_ASM_OP
+typedef struct {
+    void *start_protect;
+    void *end_protect;
+    void *exception_handler;
+ } exception_table;
+#endif /* EXCEPT_SECTION_ASM_OP */
 
-  popclass (0);
+#ifdef EXCEPT_SECTION_ASM_OP
 
-#if 0
-  /* Remove aggregate types from the list of tags,
-     since these appear at global scope.  */
-  while (x && IS_AGGR_TYPE (TREE_VALUE (x)))
-    x = TREE_CHAIN (x);
-  CLASSTYPE_TAGS (t) = x;
-  y = x;
-  while (x)
-    {
-      if (IS_AGGR_TYPE (TREE_VALUE (x)))
-       TREE_CHAIN (y) = TREE_CHAIN (x);
-      x = TREE_CHAIN (x);
-    }
-#endif
+ /* on machines which support it, the exception table lives in another section,
+       but it needs a label so we can reference it...  This sets up that
+    label! */
+asm (EXCEPT_SECTION_ASM_OP);
+exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
+asm (TEXT_SECTION_ASM_OP);
 
-  if (flag_cadillac)
-    cadillac_finish_exception (e);
+#endif /* EXCEPT_SECTION_ASM_OP */
 
-  return e;
-}
+#ifdef EXCEPT_SECTION_ASM_OP
+
+ /* we need to know where the end of the exception table is... so this
+    is how we do it! */
+
+asm (EXCEPT_SECTION_ASM_OP);
+exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
+asm (TEXT_SECTION_ASM_OP);
+
+#endif /* EXCEPT_SECTION_ASM_OP */
+
+#endif
 
 void
-finish_exception_decl (cname, decl)
-     tree cname, decl;
+exception_section ()
 {
-  /* In decl.h.  */
-  extern tree last_function_parms;
-
-  /* An exception declaration.  */
-  tree t, ctor;
-  tree parmdecls = NULL_TREE, fields;
-  tree list_of_fieldlists = temp_tree_cons (NULL_TREE,
-                                           copy_list (last_exception_fields),
-                                           NULL_TREE);
-  tree edecl = build_lang_field_decl (VAR_DECL,
-                                     exception_object_name (cname, DECL_NAME (decl)),
-                                     ptr_type_node);
-
-  DECL_LANGUAGE (edecl) = lang_c;
-  TREE_STATIC (edecl) = 1;
-  TREE_PUBLIC (edecl) = 1;
-  finish_decl (pushdecl (edecl), NULL_TREE, NULL_TREE, 0);
-
-  /* Now instantiate the exception decl.  */
-  t = xref_tag (exception_type_node, DECL_NAME (decl), NULL_TREE, 0);
-
-  /* finish_struct will pop this.  */
-  pushclass (t, 0);
-
-  /* Now add a constructor which takes as parameters all the types we
-     just defined.  */
-  ctor = build_lang_decl (FUNCTION_DECL, DECL_NAME (decl),
-                         build_cplus_method_type (t, TYPE_POINTER_TO (t),
-                                                  last_exception_field_types));
-  /* Don't take `name'.  The constructor handles that.  */
-  fields = TREE_CHAIN (TREE_VALUE (list_of_fieldlists));
-  while (fields)
-    {
-      tree parm = build_decl (PARM_DECL, DECL_NAME (fields), TREE_TYPE (fields));
-      /* Since there is a prototype, args are passed in their own types.  */
-      DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
-#ifdef PROMOTE_PROTOTYPES
-      if ((TREE_CODE (TREE_TYPE (fields)) == INTEGER_TYPE
-          || TREE_CODE (TREE_TYPE (fields)) == ENUMERAL_TYPE)
-         && TYPE_PRECISION (TREE_TYPE (fields)) < TYPE_PRECISION (integer_type_node))
-       DECL_ARG_TYPE (parm) = integer_type_node;
+#ifdef ASM_OUTPUT_SECTION_NAME
+  named_section (".gcc_except_table");
+#else
+  text_section ();
 #endif
-      TREE_CHAIN (parm) = parmdecls;
-      parmdecls = parm;
-      fields = TREE_CHAIN (fields);
-    }
-  fields = TREE_VALUE (list_of_fieldlists);
-  last_function_parms = nreverse (parmdecls);
-
-  DECL_CONSTRUCTOR_P (ctor) = 1;
-  TYPE_HAS_CONSTRUCTOR (t) = 1;
-  grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, NULL_TREE);
-  DECL_EXTERNAL (ctor) = 1;
-  TREE_STATIC (ctor) = 1;
-  TREE_PUBLIC (ctor) = 0;
-  DECL_INLINE (ctor) = 1;
-  make_decl_rtl (ctor, NULL_PTR, 1);
-  finish_decl (ctor, NULL_TREE, NULL_TREE, 0);
-  TREE_CHAIN (ctor) = TREE_VALUE (list_of_fieldlists);
-  TREE_VALUE (list_of_fieldlists) = ctor;
-
-  finish_struct (t, list_of_fieldlists, 0);
-
-  if (current_function_decl)
-    error ("cannot define exception inside function scope");
-  else
-    {
-      enum debug_info_type old_write_symbols = write_symbols;
-      write_symbols = NO_DEBUG;
-
-      /* Now build the constructor for this exception.  */
-      parmdecls = DECL_ARGUMENTS (ctor);
-      start_function (NULL_TREE, ctor, 0, 1);
-      store_parm_decls ();
-      pushlevel (0);
-      clear_last_expr ();
-      push_momentary ();
-      expand_start_bindings (0);
-
-      /* Move all the parameters to the fields, skipping `this'.  */
-      parmdecls = TREE_CHAIN (parmdecls);
-      /* Install `name' of this exception handler.  */
-      DECL_INITIAL (fields) = build_unary_op (ADDR_EXPR, edecl, 0);
-      fields = TREE_CHAIN (fields);
-      /* Install all the values.  */
-      while (fields)
-       {
-         /* Set up the initialization for this field.  */
-         DECL_INITIAL (fields) = parmdecls;
-         fields = TREE_CHAIN (fields);
-         parmdecls = TREE_CHAIN (parmdecls);
-       }
-      emit_base_init (t, 0);
-
-      finish_function (DECL_SOURCE_LINE (ctor), 1);
-      write_symbols = old_write_symbols;
-    }
 }
 
-void
-end_exception_decls ()
+
+
+
+/* from: my-cp-except.c */
+
+/* VI: ":set ts=4" */
+#if 0
+#include <stdio.h> */
+#include "config.h"
+#include "tree.h"
+#include "rtl.h"
+#include "cp-tree.h"
+#endif
+#include "decl.h"
+#if 0
+#include "flags.h"
+#endif
+#include "insn-flags.h"
+#include "obstack.h"
+#if 0
+#include "expr.h"
+#endif
+
+/* ======================================================================
+   Briefly the algorithm works like this:
+
+     When a constructor or start of a try block is encountered,
+     push_eh_entry (&eh_stack) is called.  Push_eh_entry () creates a
+     new entry in the unwind protection stack and returns a label to
+     output to start the protection for that block.
+
+     When a destructor or end try block is encountered, pop_eh_entry
+     (&eh_stack) is called.  Pop_eh_entry () returns the ehEntry it
+     created when push_eh_entry () was called.  The ehEntry structure
+     contains three things at this point.  The start protect label,
+     the end protect label, and the exception handler label.  The end
+     protect label should be output before the call to the destructor
+     (if any). If it was a destructor, then its parse tree is stored
+     in the finalization variable in the ehEntry structure.  Otherwise
+     the finalization variable is set to NULL to reflect the fact that
+     is the the end of a try block.  Next, this modified ehEntry node
+     is enqueued in the finalizations queue by calling
+     enqueue_eh_entry (&queue,entry).
+
+       +---------------------------------------------------------------+
+       |XXX: Will need modification to deal with partially             |
+       |                       constructed arrays of objects           |
+       |                                                               |
+       |       Basically, this consists of keeping track of how many   |
+       |       of the objects have been constructed already (this      |
+       |       should be in a register though, so that shouldn't be a  |
+       |       problem.                                                |
+       +---------------------------------------------------------------+
+
+     When a catch block is encountered, there is a lot of work to be
+     done.
+
+     Since we don't want to generate the catch block inline with the
+     regular flow of the function, we need to have some way of doing
+     so.  Luckily, we have a couple of routines "get_last_insn ()" and
+     "set_last_insn ()" provided.  When the start of a catch block is
+     encountered, we save a pointer to the last insn generated.  After
+     the catch block is generated, we save a pointer to the first
+     catch block insn and the last catch block insn with the routines
+     "NEXT_INSN ()" and "get_last_insn ()".  We then set the last insn
+     to be the last insn generated before the catch block, and set the
+     NEXT_INSN (last_insn) to zero.
+
+     Since catch blocks might be nested inside other catch blocks, and
+     we munge the chain of generated insns after the catch block is
+     generated, we need to store the pointers to the last insn
+     generated in a stack, so that when the end of a catch block is
+     encountered, the last insn before the current catch block can be
+     popped and set to be the last insn, and the first and last insns
+     of the catch block just generated can be enqueue'd for output at
+     a later time.
+               
+     Next we must insure that when the catch block is executed, all
+     finalizations for the matching try block have been completed.  If
+     any of those finalizations throw an exception, we must call
+     terminate according to the ARM (section r.15.6.1).  What this
+     means is that we need to dequeue and emit finalizations for each
+     entry in the ehQueue until we get to an entry with a NULL
+     finalization field.  For any of the finalization entries, if it
+     is not a call to terminate (), we must protect it by giving it
+     another start label, end label, and exception handler label,
+     setting its finalization tree to be a call to terminate (), and
+     enqueue'ing this new ehEntry to be output at an outer level.
+     Finally, after all that is done, we can get around to outputting
+     the catch block which basically wraps all the "catch (...) {...}"
+     statements in a big if/then/else construct that matches the
+     correct block to call.
+     
+     ===================================================================== */
+
+extern rtx emit_insn           PROTO((rtx));
+extern rtx gen_nop             PROTO(());
+extern void do_unwind          PROTO((rtx));
+
+/* local globals for function calls
+   ====================================================================== */
+
+/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
+   "set_unexpected ()" after default_conversion. (lib-except.c) */
+static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
+
+/* used to cache __find_first_exception_table_match ()
+   for throw (lib-except.c)  */
+static tree FirstExceptionMatch;
+
+/* used to cache a call to __unwind_function () (lib-except.c) */
+static tree Unwind;
+
+/* holds a ready to emit call to "terminate ()". */
+static tree TerminateFunctionCall;
+
+/* ====================================================================== */
+
+
+
+/* data structures for my various quick and dirty stacks and queues
+   Eventually, most of this should go away, because I think it can be
+   integrated with stuff already built into the compiler. */
+
+/* =================================================================== */
+
+struct labelNode {
+    rtx label;
+       struct labelNode *chain;
+ };
+
+
+/* this is the most important structure here.  Basically this is how I store
+   an exception table entry internally. */
+struct ehEntry {
+    rtx start_label;
+       rtx end_label;
+       rtx exception_handler_label;
+
+       tree finalization;
+ };
+
+struct ehNode {
+    struct ehEntry *entry;
+       struct ehNode *chain;
+ };
+
+struct ehStack {
+    struct ehNode *top;
+ };
+
+struct ehQueue {
+    struct ehNode *head;
+       struct ehNode *tail;
+ };
+
+struct exceptNode {
+    rtx catchstart;
+       rtx catchend;
+
+       struct exceptNode *chain;
+ };
+
+struct exceptStack {
+       struct exceptNode *top;
+ };
+/* ========================================================================= */
+
+
+
+/* local globals - these local globals are for storing data necessary for
+   generating the exception table and code in the correct order.
+
+   ========================================================================= */
+
+/* holds the pc for doing "throw" */
+rtx saved_pc;
+/* holds the type of the thing being thrown. */
+rtx saved_throw_type;
+
+rtx throw_label;
+
+static struct ehStack ehstack;
+static struct ehQueue ehqueue;
+static struct ehQueue eh_table_output_queue;
+static struct exceptStack exceptstack;
+static struct labelNode *false_label_stack = NULL;
+static struct labelNode *caught_return_label_stack = NULL;
+/* ========================================================================= */
+
+/* function prototypes */
+static struct ehEntry *pop_eh_entry    PROTO((struct ehStack *stack));
+static void enqueue_eh_entry           PROTO((struct ehQueue *queue, struct ehEntry *entry));
+static void push_except_stmts          PROTO((struct exceptStack *exceptstack,
+                                        rtx catchstart, rtx catchend));
+static int pop_except_stmts            PROTO((struct exceptStack *exceptstack,
+                                        rtx *catchstart, rtx *catchend));
+static rtx push_eh_entry               PROTO((struct ehStack *stack));
+static struct ehEntry *dequeue_eh_entry        PROTO((struct ehQueue *queue));
+static void new_eh_queue               PROTO((struct ehQueue *queue));
+static void new_eh_stack               PROTO((struct ehStack *stack));
+static void new_except_stack           PROTO((struct exceptStack *queue));
+static void push_last_insn             PROTO(());
+static rtx pop_last_insn               PROTO(());
+static void push_label_entry           PROTO((struct labelNode **labelstack, rtx label));
+static rtx pop_label_entry             PROTO((struct labelNode **labelstack));
+static rtx top_label_entry             PROTO((struct labelNode **labelstack));
+static struct ehEntry *copy_eh_entry   PROTO((struct ehEntry *entry));
+
+
+
+/* All my cheesy stack/queue/misc data structure handling routines
+
+   ========================================================================= */
+
+static void
+push_label_entry (labelstack, label)
+     struct labelNode **labelstack;
+     rtx label;
 {
-  last_exception_field_types = NULL_TREE;
-  last_exception_fields = NULL_TREE;
+  struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));
+
+  newnode->label = label;
+  newnode->chain = *labelstack;
+  *labelstack = newnode;
 }
-\f
-/* Statement-level exception semantics.  */
 
-void
-cplus_expand_start_try (implicit)
-     int implicit;
+static rtx
+pop_label_entry (labelstack)
+     struct labelNode **labelstack;
 {
-  tree call_to_setjmp;
-  tree handler, ref;
+  rtx label;
+  struct labelNode *tempnode;
 
-  /* Start a new block enclosing the whole handler.  */
-  if (implicit)
-    {
-      pushlevel_temporary (1);
-    }
-  else
-    {
-      pushlevel (0);
-      clear_last_expr ();
-      push_momentary ();
-
-      /* Encompass whole exception handler in one big binding contour.
-        If RAISE should throw out of the whole TRY/EXCEPT block, call
-        `expand_start_bindings' with argument of 1.  */
-      expand_start_bindings (0);
-    }
+  if (! *labelstack) return NULL_RTX;
 
-  /* Allocate handler in that block.  It's real name will come later.
-     Note that it will be the first name in this binding contour.  */
-  handler = get_temp_name (EHS_type, 0);
-  DECL_INITIAL (handler) = error_mark_node;
-  finish_decl (handler, NULL_TREE, NULL_TREE, 0);
+  tempnode = *labelstack;
+  label = tempnode->label;
+  *labelstack = (*labelstack)->chain;
+  free (tempnode);
 
-  /* Must come after call to `finish_decl', else the cleanup for the temp
-     for the handler will cause the contour we just created to be popped.  */
-  if (implicit)
-    declare_implicit_exception ();
+  return label;
+}
 
-  /* Catch via `setjmp'.  */
-  ref = build_component_ref (handler, get_identifier ("handler"), NULL_TREE, 0);
-  call_to_setjmp = build_function_call (BISJ, build_tree_list (NULL_TREE, ref));
+static rtx
+top_label_entry (labelstack)
+     struct labelNode **labelstack;
+{
+  if (! *labelstack) return NULL_RTX;
 
-  /* RAISE throws to EXCEPT part.  */
-  expand_start_try (build_binary_op (EQ_EXPR, call_to_setjmp, integer_zero_node, 1), 0, 1);
+  return (*labelstack)->label;
 }
 
-/* If KEEP is 1, then declarations in the TRY statement are worth keeping.
-   If KEEP is 2, then the TRY statement was generated by the compiler.
-   If KEEP is 0, the declarations in the TRY statement contain errors.  */
-
-tree
-cplus_expand_end_try (keep)
-     int keep;
+static void
+push_except_stmts (exceptstack, catchstart, catchend)
+     struct exceptStack *exceptstack;
+     rtx catchstart, catchend;
 {
-  tree decls, decl, block;
+  struct exceptNode *newnode = (struct exceptNode*)
+    xmalloc (sizeof (struct exceptNode));
 
-  if (keep < 2)
-    pop_implicit_try_blocks (NULL_TREE);
+  newnode->catchstart = catchstart;
+  newnode->catchend = catchend;
+  newnode->chain = exceptstack->top;
 
-  decls = getdecls ();
+  exceptstack->top = newnode;
+}
 
-  /* Emit code to avoid falling through into a default
-     handler that might come later.  */
-  expand_end_try ();
+static int
+pop_except_stmts (exceptstack, catchstart, catchend)
+     struct exceptStack *exceptstack;
+     rtx *catchstart, *catchend;
+{
+  struct exceptNode *tempnode;
 
-  /* Pops binding contour local to TRY, and get the exception handler
-     object built by `...start_try'.  */
-  switch (keep)
-    {
-    case 0:
-      expand_end_bindings (decls, 0, 1);
-      block = poplevel (0, 0, 0);
-      pop_momentary (); 
-      decl = getdecls ();
-      break;
-
-    case 1:
-      expand_end_bindings (decls, 1, 1);
-      block = poplevel (1, 1, 0);
-      pop_momentary ();
-      decl = getdecls ();
-      break;
-
-    default:
-      decl = tree_last (decls);
-      block = NULL_TREE;
-      break;
-    }
+  if (!exceptstack->top) {
+    *catchstart = *catchend = NULL_RTX;
+    return 0;
+  }
 
-  my_friendly_assert (TREE_CODE (decl) == VAR_DECL
-                     && TREE_TYPE (decl) == EHS_type, 203);
-  if (block)
-    {
-      BLOCK_HANDLER_BLOCK (block) = 1;
-      TREE_USED (block) = 1;
-    }
+  tempnode = exceptstack->top;
+  exceptstack->top = exceptstack->top->chain;
+
+  *catchstart = tempnode->catchstart;
+  *catchend = tempnode->catchend;
+  free (tempnode);
 
-  /* Pass it back so that its rtl can be bound to its name
-     (or vice versa).  */
-  return decl;
+  return 1;
 }
 
+/* Push to permanent obstack for rtl generation.
+   One level only!  */
+static struct obstack *saved_rtl_obstack;
 void
-cplus_expand_start_except (name, decl)
-     tree name, decl;
+push_rtl_perm ()
 {
-  int yes;
-  tree tmp, init;
+  extern struct obstack permanent_obstack;
+  extern struct obstack *rtl_obstack;
+  
+  saved_rtl_obstack = rtl_obstack;
+  rtl_obstack = &permanent_obstack;
+}
 
-  expand_start_except (0, 1);
+/* Pop back to normal rtl handling.  */
+static void
+pop_rtl_from_perm ()
+{
+  extern struct obstack permanent_obstack;
+  extern struct obstack *rtl_obstack;
+  
+  rtl_obstack = saved_rtl_obstack;
+}
 
-  /* This is internal `eh'.  */
-  current_exception_decl = decl;
-  current_exception_name_as_rtx
-    = expand_expr (build (COMPONENT_REF, ptr_type_node,
-                         current_exception_decl, TREE_OPERAND (EHS_name, 1)),
-                  0, 0, 0);
-  init = build (COMPONENT_REF, ptr_type_node, decl, TREE_OPERAND (EHS_parms, 1));
-  current_exception_parms_as_rtx = expand_expr (init, 0, 0, 0);
+static rtx
+push_eh_entry (stack)
+     struct ehStack *stack;
+{
+  struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
+  struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
 
-  if (name)
-    {
-      /* Get the exception object into scope (user declared `ex').  */
-      tmp = pushdecl (build_decl (VAR_DECL, name, ptr_type_node));
-      DECL_INITIAL (tmp) = error_mark_node;
-      finish_decl (tmp, init, 0, 0);
-    }
-  current_exception_type = NULL_TREE;
-  yes = suspend_momentary ();
-  if (name)
-    {
-      /* From now on, send the user to our faked-up object.  */
-      current_exception_object = build1 (INDIRECT_REF, void_type_node, tmp);
-      IDENTIFIER_LOCAL_VALUE (name) = current_exception_object;
-    }
-  resume_momentary (yes);
+  if (stack == NULL) {
+    free (node);
+    free (entry);
+    return NULL_RTX;
+  }
+
+  /* These are saved for the exception table.  */
+  push_rtl_perm ();
+  entry->start_label = gen_label_rtx ();
+  entry->end_label = gen_label_rtx ();
+  entry->exception_handler_label = gen_label_rtx ();
+  pop_rtl_from_perm ();
+
+  entry->finalization = NULL_TREE;
 
-  /* Pop exception handler stack.  */
-  expand_assignment (EHS_decl, EHS_prev, 0, 0);
+  node->entry = entry;
+  node->chain = stack->top;
+  stack->top = node;
+
+  enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
+
+  return entry->start_label;
 }
 
-/* Generate the call to `unhandled_exception' that is appropriate
-   for this particular unhandled exception.  */
-static tree
-call_to_unhandled_exception ()
+static struct ehEntry *
+pop_eh_entry (stack)
+     struct ehStack *stack;
 {
-  extern int lineno;
-  extern tree combine_strings ();
-  tree parms = tree_cons (NULL_TREE,
-                         combine_strings (build_string (strlen (input_filename + 1), input_filename)),
-                         build_tree_list (NULL_TREE, build_int_2 (lineno, 0)));
-  return build_function_call (BIUE, parms);
+  struct ehNode *tempnode;
+  struct ehEntry *tempentry;
+
+  if (stack && (tempnode = stack->top)) {
+    tempentry = tempnode->entry;
+    stack->top = stack->top->chain;
+    free (tempnode);
+
+    return tempentry;
+  }
+
+  return NULL;
 }
 
-/* Note that this must be mirror image of `...start_try'.
-   DFAULT is the default clause, if there was one.
-   DFAULT is ERROR_MARK_NODE when this ends an implicit handler.  */
-void
-cplus_expand_end_except (dfault)
-     tree dfault;
+static struct ehEntry *
+copy_eh_entry (entry)
+     struct ehEntry *entry;
 {
-  tree decls, raised;
+  struct ehEntry *newentry;
 
-  if (dfault == NULL_TREE)
-    {
-      /* Uncaught exception at outermost level.  If raised locally,
-        reraise the exception.  Otherwise, generate code to call `abort'.  */
-      if (in_try_block (1) == 0)
-       {
-         expand_start_cond (build (EQ_EXPR, integer_type_node,
-                                   exception_throw_decl, integer_zero_node), 0);
-         expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
-         expand_end_cond ();
-       }
-      /* Try the next handler.  */
-      if (! expand_escape_except ())
-       compiler_error ("except nesting botch");
-    }
+  newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
+  memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry));
 
-  raised = expand_end_except ();
+  return newentry;
+}
 
-  decls = getdecls ();
-  expand_end_bindings (decls, decls != 0, 1);
-  poplevel (decls != 0, 1, 0);
+static void
+enqueue_eh_entry (queue, entry)
+     struct ehQueue *queue;
+     struct ehEntry *entry;
+{
+  struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
 
-  /* Implicit handlers do not use the momentary obstack.  */
-  if (dfault != error_mark_node)
-    pop_momentary ();
+  node->entry = entry;
+  node->chain = NULL;
 
-  if (! in_try_block (1))
+  if (queue->head == NULL)
     {
-      /* Check that this function is not raising exceptions
-        it is not supposed to.  */
-      while (raised)
-       {
-         cp_error ("exception `%D' raised but not declared raisable",
-                     TREE_VALUE (raised));
-         raised = TREE_CHAIN (raised);
-       }
+      queue->head = node;
     }
-  else if (dfault == NULL_TREE || dfault == error_mark_node)
+  else
     {
-      expand_start_cond (build (NE_EXPR, integer_type_node,
-                               exception_throw_decl,
-                               integer_zero_node), 0);
-      /* We fell off the end of this try block.  Try going to the next.
-        The escape_label will be the beginning of the next try block.  */
-      if (! expand_escape_except ())
-       compiler_error ("except nesting botch");
-      expand_end_cond ();
+      queue->tail->chain = node;
     }
+  queue->tail = node;
 }
 
-/* Generate code to raise exception RAISE_ID.
-   If EXP is NULL_TREE, then PARMS is the list of parameters to use
-   for constructing this exception.
-   If EXP is non-NULL, then it is an already constructed object
-   of the kind that we want.
+static struct ehEntry *
+dequeue_eh_entry (queue)
+     struct ehQueue *queue;
+{
+  struct ehNode *tempnode;
+  struct ehEntry *tempentry;
+
+  if (queue->head == NULL)
+    return NULL;
+
+  tempnode = queue->head;
+  queue->head = queue->head->chain;
+
+  tempentry = tempnode->entry;
+  free (tempnode);
+
+  return tempentry;
+}
+
+static void
+new_eh_queue (queue)
+     struct ehQueue *queue;
+{
+  queue->head = queue->tail = NULL;
+}
+
+static void
+new_eh_stack (stack)
+     struct ehStack *stack;
+{
+  stack->top = NULL;
+}
+
+static void
+new_except_stack (stack)
+     struct exceptStack *stack;
+{
+  stack->top = NULL;
+}
+/* ========================================================================= */
+
+
+/* sets up all the global eh stuff that needs to be initialized at the
+   start of compilation.
+
+   This includes:
+               - Setting up all the function call trees
+               - Initializing the ehqueue
+               - Initializing the eh_table_output_queue
+               - Initializing the ehstack
+               - Initializing the exceptstack
+*/
 
-   FOR_RERAISE is non-zero if this raise is called by reraise.  In
-   this case we do not need to emit extra gotos to avoid warning messages;
-   the caller will do that once after all the exceptions it reraises
-   are handled and raised.  */
 void
-cplus_expand_raise (raise_id, parms, exp, for_reraise)
-     tree raise_id;
-     tree parms;
-     tree exp;
-     int for_reraise;
+init_exception_processing ()
 {
-  /* Allocate new exception of appropriate type, passing
-     PARMS to its constructor.  */
-  tree cname, name;
-  tree decl;
-  tree xexp = exp;
-
-  cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
-  if (cname == error_mark_node)
-    return;
-  name = TREE_VALUE (raise_id);
+  extern tree define_function ();
+  tree unexpected_fndecl, terminate_fndecl;
+  tree set_unexpected_fndecl, set_terminate_fndecl;
+  tree catch_match_fndecl;
+  tree find_first_exception_match_fndecl;
+  tree unwind_fndecl;
+  tree temp, PFV;
 
-  decl = lookup_exception_object (cname, name, 1);
-  if (decl == NULL_TREE)
-    return;
+  /* void (*)() */
+  PFV = build_pointer_type (build_function_type (void_type_node, void_list_node));
 
-  if (exp == NULL_TREE)
-    {
-      exp = build_method_call (NULL_TREE, name, parms, NULL_TREE, LOOKUP_COMPLAIN);
-      if (exp == error_mark_node)
-       return;
-    }
+  /* arg list for the build_function_type call for set_terminate () and
+     set_unexpected () */
+  temp = tree_cons (NULL_TREE, PFV, void_list_node);
 
-  if (in_try_block (1))
-    {
-      expand_raise (decl);
-    }
-  else if (! current_function_decl)
+  push_lang_context (lang_name_c);
+
+  set_terminate_fndecl =
+    define_function ("set_terminate",
+                    build_function_type (PFV, temp),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+  set_unexpected_fndecl =
+    define_function ("set_unexpected",
+                    build_function_type (PFV, temp),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+
+  unexpected_fndecl =
+    define_function ("unexpected",
+                    build_function_type (void_type_node, void_list_node),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+  terminate_fndecl =
+    define_function ("terminate",
+                    build_function_type (void_type_node, void_list_node),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+  catch_match_fndecl =
+    define_function ("__throw_type_match",
+                    build_function_type (integer_type_node,
+                                         tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, string_type_node, void_list_node))),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+  find_first_exception_match_fndecl =
+    define_function ("__find_first_exception_table_match",
+                    build_function_type (ptr_type_node,
+                                         tree_cons (NULL_TREE, ptr_type_node,
+                                                    void_list_node)),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+  unwind_fndecl =
+    define_function ("__unwind_function",
+                    build_function_type (void_type_node,
+                                         tree_cons (NULL_TREE, ptr_type_node, void_list_node)),
+                    NOT_BUILT_IN,
+                    pushdecl,
+                    0);
+
+  Unexpected = default_conversion (unexpected_fndecl);
+  Terminate = default_conversion (terminate_fndecl);
+  SetTerminate = default_conversion (set_terminate_fndecl);
+  SetUnexpected = default_conversion (set_unexpected_fndecl);
+  CatchMatch = default_conversion (catch_match_fndecl);
+  FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
+  Unwind = default_conversion (unwind_fndecl);
+  BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
+
+  TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
+
+  pop_lang_context ();
+  throw_label = gen_label_rtx ();
+  saved_pc = gen_rtx (REG, Pmode, 16);
+  saved_throw_type = gen_rtx (REG, Pmode, 17);
+
+  new_eh_queue (&ehqueue);
+  new_eh_queue (&eh_table_output_queue);
+  new_eh_stack (&ehstack);
+  new_except_stack (&exceptstack);
+}
+
+/* call this to begin a block of unwind protection (ie: when an object is
+   constructed) */
+void
+start_protect ()
+{
+  if (doing_eh (0))
     {
-      if (xexp == NULL_TREE)
-       cp_error ("invalid raise of `%D' outside of functions", decl);
-      else
-       cp_error ("invalid reraise of `%D' outside of functions", decl);
-    }
-  else
-    {
-      /* Test this raise against what this function permits.  */
-      tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
-      while (names)
-       {
-         if (decl == TREE_TYPE (names))
-           break;
-         names = TREE_CHAIN (names);
-       }
-      if (names == NULL_TREE)
-       {
-         error ("current function not declared to raise exception `%s'",
-                IDENTIFIER_POINTER (name));
-         return;
-       }
+      emit_label (push_eh_entry (&ehstack));
     }
+}
+   
+/* call this to end a block of unwind protection.  the finalization tree is
+   the finalization which needs to be run in order to cleanly unwind through
+   this level of protection. (ie: call this when a scope is exited)*/
+void
+end_protect (finalization)
+     tree finalization;
+{
+  struct ehEntry *entry = pop_eh_entry (&ehstack);
 
-  store_expr (exp, EHS_parms_as_rtx, 0);
+  if (! doing_eh (0))
+    return;
 
-  /* Set the global exception handler stack's NAME field
-     to the `name' of this exception.  The global exception
-     handler stack is the container for the exception object
-     we just built.
+  emit_label (entry->end_label);
 
-     We go through a function call to make life easier when debugging.  */
-#if 0
-  expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
-#else
-  parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),
-                    build_tree_list (NULL_TREE,
-                                     build_unary_op (ADDR_EXPR, decl, 0)));
-  expand_expr (build_function_call (BIR, parms), 0, 0, 0);
-#endif
+  entry->finalization = finalization;
+
+  enqueue_eh_entry (&ehqueue, entry);
+}
 
-  /* Activate thrower.  If we are inside a TRY statement,
-     we can cheat and not do this, saving a longjmp.  */
-  if (in_try_block (1) == 0)
+/* call this on start of a try block. */
+void
+expand_start_try_stmts ()
+{
+  if (doing_eh (1))
     {
-      sets_exception_throw_decl = 1;
-      emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
+      start_protect ();
     }
+}
 
-  if (xexp == NULL_TREE)
-    {    
-      /* Invoke destructors for current procedure or handler.  */
-      if (! expand_escape_except ())
-       compiler_error ("except nesting botch");
-      /* Throw via `longjmp'... Done as side-effect of goto.  */
-    }
-  /* To avoid spurious warning messages, we add a goto to the end
-     of the function.  This code is dead, and the compiler should
-     know how to delete it, but for now, we are stuck with it.  */
-  if (! for_reraise
-      && TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
-    expand_null_return ();
+void
+expand_end_try_stmts ()
+{
+  end_protect (integer_zero_node);
 }
 
-extern tree cplus_exception_name ();
+struct insn_save_node {
+       rtx last;
+       struct insn_save_node *chain;
+ };
 
-tree
-ansi_exception_object_lookup (type)
-     tree type;
+static struct insn_save_node *InsnSave = NULL;
+
+
+/* Used to keep track of where the catch blocks start.  */
+static void
+push_last_insn ()
 {
-  tree raise_id = cplus_exception_name (type);
-  tree decl;
+  struct insn_save_node *newnode = (struct insn_save_node*)
+    xmalloc (sizeof (struct insn_save_node));
 
-  decl = IDENTIFIER_GLOBAL_VALUE (raise_id);
-  if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
-    {
-      push_obstacks_nochange ();
-      end_temporary_allocation ();
-      decl = build_decl (VAR_DECL, raise_id, ptr_type_node);
-      TREE_PUBLIC (decl) = 1;
-      TREE_STATIC (decl) = 1;
-      pushdecl_top_level (decl);
-      make_decl_rtl (decl, (char*)0, 1);
-      pop_obstacks ();
-    }
-  return decl;
+  newnode->last = get_last_insn ();
+  newnode->chain = InsnSave;
+  InsnSave = newnode;
 }
 
-/* Generate code to throw an exception using EXP.
-   Usng ANSI syntax and semantics.
-   If EXP is NULL_TREE< re-raise instead. */
+/* Use to keep track of where the catch blocks start.  */
+static rtx
+pop_last_insn ()
+{
+  struct insn_save_node *tempnode;
+  rtx temprtx;
+
+  if (!InsnSave) return NULL_RTX;
+
+  tempnode = InsnSave;
+  temprtx = tempnode->last;
+  InsnSave = InsnSave->chain;
+
+  free (tempnode);
+
+  return temprtx;
+}
 
+/* call this to start processing of all the catch blocks. */
 void
-cplus_expand_throw (exp)
-     tree exp;
+expand_start_all_catch ()
 {
-  tree parms;
-  int for_reraise;
-  /* Allocate new exception of appropriate type, passing
-     PARMS to its constructor.  */
-  tree decl = ansi_exception_object_lookup (TREE_TYPE (exp));
-  tree xexp = exp;
-
-  if (in_try_block (1))
+  struct ehEntry *entry;
+  rtx label;
+
+  if (! doing_eh (1))
+    return;
+
+  emit_line_note (input_filename, lineno);
+  label = gen_label_rtx ();
+  /* The label for the exception handling block we will save.  */
+  emit_label (label);
+  push_label_entry (&caught_return_label_stack, label);
+
+  /* Remember where we started. */
+  push_last_insn ();
+
+  /* Will this help us not stomp on it? */
+  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+
+  while (1)
     {
+      entry = dequeue_eh_entry (&ehqueue);
+      emit_label (entry->exception_handler_label);
+
+      expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
+
+      /* When we get down to the matching entry, stop.  */
+      if (entry->finalization == integer_zero_node)
+       break;
+
+      free (entry);
+    }
+
+  /* This goes when the below moves out of our way.  */
 #if 1
-      my_friendly_abort (35);
-#else
-      expand_raise (decl);
+  label = gen_label_rtx ();
+  emit_jump (label);
 #endif
-    }
-  else if (! current_function_decl)
-    error ("invalid throw outside of functions");
-  else
-    {
-#if 0
-      /* Test this raise against what this function permits.  */
-      tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
-      while (names)
-       {
-         if (decl == TREE_TYPE (names))
-           break;
-         names = TREE_CHAIN (names);
-       }
-      if (names == NULL_TREE)
-       {
-         error ("current function not declared to raise exception `%s'",
-                IDENTIFIER_POINTER (name));
-         return;
-       }
+  
+  /* All this should be out of line, and saved back in the exception handler
+     block area.  */
+#if 1
+  entry->start_label = entry->exception_handler_label;
+  /* These are saved for the exception table.  */
+  push_rtl_perm ();
+  entry->end_label = gen_label_rtx ();
+  entry->exception_handler_label = gen_label_rtx ();
+  entry->finalization = TerminateFunctionCall;
+  pop_rtl_from_perm ();
+  emit_label (entry->end_label);
+
+
+  enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
+
+  /* After running the finalization, continue on out to the next
+     cleanup, if we have nothing better to do.  */
+  emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry->end_label));
+  /* Will this help us not stomp on it? */
+  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+  emit_jump (throw_label);
+  emit_label (entry->exception_handler_label);
+  expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
+  emit_barrier ();
 #endif
-    }
+  emit_label (label);
+}
 
-  store_expr (exp, EHS_parms_as_rtx, 0);
+/* call this to end processing of all the catch blocks. */
+void
+expand_end_all_catch ()
+{
+  rtx catchstart, catchend, last;
+  rtx label;
 
-  /* Set the global exception handler stack's NAME field
-     to the `name' of this exception.  The global exception
-     handler stack is the container for the exception object
-     we just built.
+  if (! doing_eh (1))
+    return;
 
-     We go through a function call to make life easier when debugging.  */
-#if 0
-  expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
-#else
-  parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),
-                    build_tree_list (NULL_TREE,
-                                     build_unary_op (ADDR_EXPR, decl, 0)));
-  expand_expr (build_function_call (BIR, parms), 0, 0, 0);
-#endif
+  /* Find the start of the catch block.  */
+  last = pop_last_insn ();
+  catchstart = NEXT_INSN (last);
+  catchend = get_last_insn ();
 
-  /* Activate thrower.  If we are inside a TRY statement,
-     we can cheat and not do this, saving a longjmp.  */
-  if (in_try_block (1) == 0)
-    {
-      sets_exception_throw_decl = 1;
-      emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
-    }
+  NEXT_INSN (last) = 0;
+  set_last_insn (last);
 
-  if (xexp == NULL_TREE)
-    {    
-      /* Invoke destructors for current procedure or handler.  */
-      if (! expand_escape_except ())
-       compiler_error ("except nesting botch");
-      /* Throw via `longjmp'... Done as side-effect of goto.  */
-    }
+  /* this level of catch blocks is done, so set up the successful catch jump
+     label for the next layer of catch blocks. */
+  pop_label_entry (&caught_return_label_stack);
 
-  /* XXX: for_reraise is never set above here.  */
-  /* To avoid spurious warning messages, we add a goto to the end
-     of the function.  This code is dead, and the compiler should
-     know how to delete it, but for now, we are stuck with it.  */
-  if (! for_reraise
-      && TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
-    expand_null_return ();
+  push_except_stmts (&exceptstack, catchstart, catchend);
+  
+  /* Here was fall through into the continuation code.  */
 }
 
-tree
-cplus_expand_start_catch (raise_id)
-     tree raise_id;
+
+/* this is called from expand_exception_blocks () to expand the toplevel
+   finalizations for a function. */
+void
+expand_leftover_cleanups ()
 {
-  tree cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
-  tree decl;
-  tree cond;
+  struct ehEntry *entry;
+  rtx first_label = NULL_RTX;
 
-  if (cname == error_mark_node)
-    {
-      decl = error_mark_node;
-      cond = error_mark_node;
-    }
-  else
+  if (! doing_eh (0))
+    return;
+
+  /* Will this help us not stomp on it? */
+  emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+
+  while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
     {
-      decl = lookup_exception_object (cname, TREE_VALUE (raise_id), 1);
-      if (decl == NULL_TREE)
-       cond = error_mark_node;
-      else
-       cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0),
-                               build (COMPONENT_REF, ptr_type_node,
-                                      current_exception_decl,
-                                      TREE_OPERAND (EHS_name, 1)),
-                               1);
-    }
-  expand_start_cond (cond, 0);
+      if (! first_label)
+       first_label = entry->exception_handler_label;
+      emit_label (entry->exception_handler_label);
+
+      expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
 
-  /* Does nothing right now.  */
-  expand_catch (decl);
-  if (current_exception_type
-      && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
+      /* leftover try block, opps.  */
+      if (entry->finalization == integer_zero_node)
+       abort ();
+
+      free (entry);
+    }
+  if (first_label)
     {
-      /* Make a cleanup for the name-specific exception object now in scope.  */
-      tree cleanup = maybe_build_cleanup (current_exception_object);
-      expand_start_bindings (0);
-      expand_decl_cleanup (NULL_TREE, cleanup);
+      rtx label;
+      struct ehEntry entry;
+      /* These are saved for the exception table.  */
+      push_rtl_perm ();
+      label = gen_label_rtx ();
+      entry.start_label = first_label;
+      entry.end_label = label;
+      entry.exception_handler_label = gen_label_rtx ();
+      entry.finalization = TerminateFunctionCall;
+      pop_rtl_from_perm ();
+      emit_label (label);
+
+      enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
+
+      /* After running the finalization, continue on out to the next
+        cleanup, if we have nothing better to do.  */
+      emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry.end_label));
+      /* Will this help us not stomp on it? */
+      emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
+      emit_jump (throw_label);
+      emit_label (entry.exception_handler_label);
+      expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
+      emit_barrier ();
     }
-  return decl;
 }
-tree
-ansi_expand_start_catch (raise_type)
-     tree raise_type;
-{
-  tree decl = ansi_exception_object_lookup (raise_type);
-  tree cond;
 
-  if (decl == NULL_TREE)
-      cond = error_mark_node;
-  else
-      cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0),
-                             build (COMPONENT_REF, ptr_type_node,
-                                    current_exception_decl,
-                                    TREE_OPERAND (EHS_name, 1)),
-                             1);
-  expand_start_cond (cond, 0);
-
-  /* Does nothing right now.  */
-  expand_catch (decl);
-  return decl;
-}
 
+/* call this to start a catch block. Typename is the typename, and identifier
+   is the variable to place the object in or NULL if the variable doesn't
+   matter.  If typename is NULL, that means its a "catch (...)" or catch
+   everything.  In that case we don't need to do any type checking.
+   (ie: it ends up as the "else" clause rather than an "else if" clause) */
 void
-cplus_expand_end_catch (for_reraise)
-     int for_reraise;
+expand_start_catch_block (typename, identifier)
+     tree typename, identifier;
 {
-  if (current_exception_type
-      && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
-    {
-      /* Destroy the specific exception object now in scope.  */
-      expand_end_bindings (getdecls (), 0, 1);
-    }
-  if (for_reraise)
+  rtx false_label_rtx;
+  tree type;
+
+  if (! doing_eh (1))
+    return;
+
+  if (typename)
+    type = groktypename (typename);
+  else
+    type = NULL_TREE;
+
+  false_label_rtx = gen_label_rtx ();
+  push_label_entry (&false_label_stack, false_label_rtx);
+
+  if (type)
     {
-      if (! expand_escape_except ())
-       my_friendly_abort (36);
+      tree params;
+      char *typestring;
+      rtx call_rtx, return_value_rtx;
+      tree catch_match_fcall;
+      tree catchmatch_arg, argval;
+
+      typestring = build_overload_name (type, 1, 1);
+
+      params = tree_cons (NULL_TREE,
+                        combine_strings (build_string (strlen (typestring)+1, typestring)),
+                        tree_cons (NULL_TREE,
+                                   make_tree (ptr_type_node, saved_throw_type),
+                                   NULL_TREE));
+      catch_match_fcall = build_function_call (CatchMatch, params);
+      call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
+
+      return_value_rtx =
+       hard_function_value (integer_type_node, catch_match_fcall);
+
+      /* did the throw type match function return TRUE? */
+      emit_cmp_insn (return_value_rtx, const0_rtx, NE, 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_bne (false_label_rtx));
     }
   else
     {
-      if (! expand_end_catch ())
-       my_friendly_abort (37);
+      /* Fall into the catch all section. */
     }
-  expand_end_cond ();
+  emit_line_note (input_filename, lineno);
 }
 
-/* Reraise an exception.
-   If EXCEPTIONS is NULL_TREE, it means reraise whatever exception was caught.
-   If EXCEPTIONS is an IDENTIFIER_NODE, it means reraise the exception
-   object named by EXCEPTIONS.  This must be a variable declared in
-   an `except' clause.
-   If EXCEPTIONS is a TREE_LIST, it is the list of exceptions we are
-   willing to reraise.  */
 
-void
-cplus_expand_reraise (exceptions)
-     tree exceptions;
+/* 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.  */
+void expand_end_catch_block ()
 {
-  tree ex_ptr;
-  tree ex_object = current_exception_object;
-  rtx ex_ptr_as_rtx;
-
-  if (exceptions && TREE_CODE (exceptions) == IDENTIFIER_NODE)
+  if (doing_eh (1))
     {
-      /* Don't get tripped up if its TREE_TYPE is `error_mark_node'.  */
-      ex_object = IDENTIFIER_LOCAL_VALUE (exceptions);
-      if (ex_object == NULL_TREE || TREE_CODE (ex_object) != INDIRECT_REF)
-       {
-         error ("`%s' is not an exception decl", IDENTIFIER_POINTER (exceptions));
-         return;
-       }
-      my_friendly_assert (TREE_CODE (TREE_OPERAND (ex_object, 0)) == VAR_DECL,
-                         204);
-      exceptions = NULL_TREE;
+      /* label we jump to if we caught the exception */
+      emit_jump (top_label_entry (&caught_return_label_stack));
+
+      /* label we emit to jump to if this catch block didn't match. */
+      emit_label (pop_label_entry (&false_label_stack));
     }
+}
 
-  ex_ptr = build1 (NOP_EXPR, ptr_type_node, TREE_OPERAND (ex_object, 0));
-  ex_ptr_as_rtx = expand_expr (ex_ptr, 0, 0, 0);
+/* cheesyness to save some typing. returns the return value rtx */
+rtx
+do_function_call (func, params, return_type)
+     tree func, params, return_type;
+{
+  tree func_call;
+  func_call = build_function_call (func, params);
+  expand_call (func_call, NULL_RTX, 0);
+  if (return_type != NULL_TREE)
+    return hard_function_value (return_type, func_call);
+  return NULL_RTX;
+}
 
-  /* reraise ALL, used by compiler.  */
-  if (exceptions == NULL_TREE)
-    {
-      /* Now treat reraise like catch/raise.  */
-      expand_catch (error_mark_node);
-      expand_raise (error_mark_node);
-      emit_move_insn (EHS_name_as_rtx, current_exception_name_as_rtx);
-      store_expr ((tree) EHS_parms_as_rtx, current_exception_parms_as_rtx, 0);
-      if (in_try_block (1) == 0)
-       {
-         sets_exception_throw_decl = 1;
-         emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
-       }
-      /* Set to zero so that destructor will not be called.  */
-      emit_move_insn (ex_ptr_as_rtx, const0_rtx);
-      if (! expand_escape_except ())
-       my_friendly_abort (38);
-
-      /* To avoid spurious warning messages, we add a goto to the end
-        of the function.  This code is dead, and the compiler should
-        know how to delete it, but for now, we are stuck with it.  */
-      if (TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
-       expand_null_return ();
-
-      return;
-    }
 
-  /* reraise from a list of exceptions.  */
-  while (exceptions)
-    {
-      tree type = lookup_exception_type (current_class_type, current_class_name,
-                                        exceptions);
-      if (type == NULL_TREE)
-       {
-         error ("`%s' is not an exception type",
-                IDENTIFIER_POINTER (TREE_VALUE (exceptions)));
-         current_exception_type = NULL_TREE;
-         TREE_TYPE (ex_object) = error_mark_node;
-         TREE_TYPE (ex_ptr) = error_mark_node;
-       }
-      else
-       {
-         current_exception_type = type;
-         /* In-place union.  */
-         TREE_TYPE (ex_object) = type;
-         TREE_TYPE (ex_ptr) = TYPE_POINTER_TO (type);
-       }
+/* is called from expand_excpetion_blocks () to generate the code in a function
+   to "throw" if anything in the function needs to preform a throw.
 
-      /* Now treat reraise like catch/raise.  */
-      cplus_expand_start_catch (exceptions);
-      cplus_expand_raise (exceptions, NULL_TREE, ex_ptr, 1);
-      /* Set to zero so that destructor will not be called.  */
-      if (TREE_TYPE (ex_ptr) != error_mark_node)
-       emit_move_insn (ex_ptr_as_rtx, const0_rtx);
-      cplus_expand_end_catch (1);
-      exceptions = TREE_CHAIN (exceptions);
-    }
-  /* Don't propagate any unhandled exceptions.  */
-  expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
-
-  /* To avoid spurious warning messages, we add a goto to the end
-     of the function.  This code is dead, and the compiler should
-     know how to delete it, but for now, we are stuck with it.  */
-  if (TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
-    expand_null_return ();
+   expands "throw" as the following psuedo code:
+
+       throw:
+               eh = find_first_exception_match (saved_pc);
+           if (!eh) goto gotta_rethrow_it;
+               goto eh;
+
+       gotta_rethrow_it:
+               saved_pc = __builtin_return_address (0);
+               pop_to_previous_level ();
+               goto throw;
+
+ */
+static void
+expand_builtin_throw ()
+{
+  tree fcall;
+  tree params;
+  rtx return_val_rtx;
+  rtx gotta_rethrow_it = gen_label_rtx ();
+  rtx gotta_call_terminate = gen_label_rtx ();
+  rtx unwind_and_throw = gen_label_rtx ();
+  rtx goto_unwind_and_throw = gen_label_rtx ();
+
+  emit_label (throw_label);
+
+  /* search for an exception handler for the saved_pc */
+  return_val_rtx = do_function_call (FirstExceptionMatch,
+                                    tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE),
+                                    ptr_type_node);
+
+  /* did we find one? */
+  emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
+                GET_MODE (return_val_rtx), 0, 0);
+
+  /* if not, jump to gotta_rethrow_it */
+  emit_jump_insn (gen_beq (gotta_rethrow_it));
+
+  /* we found it, so jump to it */
+  emit_indirect_jump (return_val_rtx);
+
+  /* code to deal with unwinding and looking for it again */
+  emit_label (gotta_rethrow_it);
+
+  /* call to  __builtin_return_address () */
+  params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
+  fcall = build_function_call (BuiltinReturnAddress, params);
+  return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
+
+  /* did __builtin_return_address () return a valid address? */
+  emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
+                GET_MODE (return_val_rtx), 0, 0);
+
+  emit_jump_insn (gen_beq (gotta_call_terminate));
+
+  /* yes it did */
+  emit_move_insn (saved_pc, return_val_rtx);
+  do_unwind (throw_label);
+  emit_jump (throw_label);
+
+  /* no it didn't --> therefore we need to call terminate */
+  emit_label (gotta_call_terminate);
+  do_function_call (Terminate, NULL_TREE, NULL_TREE);
 }
-\f
+
+
+/* This is called to expand all the toplevel exception handling
+   finalization for a function.  It should only be called once per
+   function.  */
 void
-setup_exception_throw_decl ()
+expand_exception_blocks ()
 {
-  tree call_to_longjmp, parms;
-
-  int old = suspend_momentary ();
-
-  exception_throw_decl = build_decl (VAR_DECL, get_identifier (THROW_NAME), integer_type_node);
-  pushdecl (exception_throw_decl);
-  parms = tree_cons (NULL_TREE, EHS_handler,
-                    build_tree_list (0, integer_one_node));
-  call_to_longjmp = build_function_call (BILJ, parms);
-
-  expand_decl (exception_throw_decl);
-  expand_decl_cleanup (exception_throw_decl,
-                      build (COND_EXPR, void_type_node,
-                             exception_throw_decl,
-                             call_to_longjmp, integer_zero_node));
-  DECL_INITIAL (exception_throw_decl) = integer_zero_node;
-  sets_exception_throw_decl = 0;
-  resume_momentary (old);
-
-  /* Cache these, since they won't change throughout the function.  */
-  EHS_parms_as_rtx = expand_expr (EHS_parms, 0, 0, 0);
-  EHS_name_as_rtx = expand_expr (EHS_name, 0, 0, 0);
+  rtx catchstart, catchend;
+  rtx last;
+  static rtx funcend;
+
+  funcend = gen_label_rtx ();
+  emit_jump (funcend);
+  /* expand_null_return (); */
+
+  while (pop_except_stmts (&exceptstack, &catchstart, &catchend)) {
+    last = get_last_insn ();
+    NEXT_INSN (last) = catchstart;
+    PREV_INSN (catchstart) = last;
+    NEXT_INSN (catchend) = 0;
+    set_last_insn (catchend);
+  }
+
+  expand_leftover_cleanups ();
+
+  {
+    static int have_done = 0;
+    if (! have_done && TREE_PUBLIC (current_function_decl)
+       && ! DECL_INLINE (current_function_decl))
+      {
+       have_done = 1;
+       expand_builtin_throw ();
+      }
+  }
+  emit_label (funcend);
 }
 
+
+/* call this to expand a throw statement.  This follows the following
+   algorithm:
+
+       1. Allocate space to save the current PC onto the stack.
+       2. Generate and emit a label and save its address into the
+               newly allocate stack space since we can't save the pc directly.
+       3. If this is the first call to throw in this function:
+               generate a label for the throw block
+       4. jump to the throw block label.  */
 void
-init_exception_processing ()
+expand_throw (exp)
+     tree exp;
 {
-  extern tree build_function_type (), define_function ();
-  extern tree unhandled_exception_fndecl;
-  tree cname = get_identifier ("ExceptionHandler");
-  tree field, chain;
-  tree ctor, dtor;
-  tree jmp_buf_type = build_array_type (integer_type_node,
-                                       build_index_type (build_int_2 (_JBLEN-1, 0)));
-  tree jmp_buf_arg_type = build_pointer_type (integer_type_node);
-
-  tree parmtypes = hash_tree_chain (jmp_buf_arg_type, void_list_node);
-  tree setjmp_fndecl, longjmp_fndecl, raise_fndecl;
-
-  int old_interface_only = interface_only;
-  int old_interface_unknown = interface_unknown;
-  interface_only = 1;
-  interface_unknown = 0;
-  EHS_type = xref_tag (record_type_node, cname, NULL_TREE, 0);
-  push_lang_context (lang_name_c);
-  setjmp_fndecl = define_function ("setjmp",
-                                  build_function_type (integer_type_node,
-                                                       parmtypes),
-                                  NOT_BUILT_IN, pushdecl, 0);
-  BISJ = default_conversion (setjmp_fndecl);
-  parmtypes = hash_tree_chain (jmp_buf_arg_type,
-                              hash_tree_chain (integer_type_node, void_list_node));
-  longjmp_fndecl = define_function ("longjmp",
-                                   build_function_type (void_type_node, parmtypes),
-                                   NOT_BUILT_IN, pushdecl, 0);
-  raise_fndecl = define_function ("__raise_exception",
-                                 build_function_type (void_type_node,
-                                                      hash_tree_chain (ptr_type_node,
-                                                                       hash_tree_chain (build_pointer_type (ptr_type_node), void_list_node))),
-                                 NOT_BUILT_IN, pushdecl, 0);
-  BILJ = default_conversion (longjmp_fndecl);
-  BIR = default_conversion (raise_fndecl);
-  BIUE = default_conversion (unhandled_exception_fndecl);
+  tree raiseid = NULL_TREE;
+  rtx temp_size;
+  rtx label;
+  tree type;
 
-  pop_lang_context ();
+  if (! doing_eh (1))
+    return;
 
-  /* finish_struct will pop this.  */
-  pushclass (EHS_type, 0);
-  field = build_lang_field_decl (FIELD_DECL, get_identifier ("parms"), ptr_type_node);
-  chain = field;
-  field = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
-                                build_pointer_type (default_function_type));
-  TREE_CHAIN (field) = chain;
-  chain = field;
-  field = build_lang_field_decl (FIELD_DECL, get_identifier ("handler"), jmp_buf_type);
-  TREE_CHAIN (field) = chain;
-  chain = field;
-  field = build_lang_field_decl (FIELD_DECL, get_identifier ("prev"),
-                                TYPE_POINTER_TO (EHS_type));
-  TREE_CHAIN (field) = chain;
-  chain = field;
-
-  ctor = build_lang_decl (FUNCTION_DECL, cname,
-                         build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
-  DECL_CONSTRUCTOR_P (ctor) = 1;
-  TREE_STATIC (ctor) = 1;
-  TREE_PUBLIC (ctor) = 1;
-  DECL_EXTERNAL (ctor) = 1;
-  grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0);
-  grok_ctor_properties (EHS_type, ctor);
-  finish_decl (pushdecl (ctor), NULL_TREE, NULL_TREE, 0);
-  /* Must copy the node here because the FUNCTION_DECL
-     used inside the struct ain't the same as the
-     FUNCTION_DECL we stick into the global binding
-     contour.  */
-  ctor = copy_node (ctor);
-  TREE_CHAIN (ctor) = chain;
-  chain = ctor;
-  dtor = build_lang_decl (FUNCTION_DECL, cname,
-                         build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
-  TREE_STATIC (dtor) = 1;
-  TREE_PUBLIC (dtor) = 1;
-  DECL_EXTERNAL (dtor) = 1;
-  grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0);
-  finish_decl (pushdecl (dtor), NULL_TREE, NULL_TREE, 0);
-  /* Copy for the same reason as copying ctor.  */
-  dtor = copy_node (dtor);
-  TREE_CHAIN (dtor) = chain;
-  chain = dtor;
-  TYPE_HAS_CONSTRUCTOR (EHS_type) = 1;
-  TYPE_HAS_DESTRUCTOR (EHS_type) = 1;
-  finish_struct (EHS_type, temp_tree_cons (NULL_TREE, chain, NULL_TREE), 0);
-  interface_only = old_interface_only;
-  interface_unknown = old_interface_unknown;
+  label = gen_label_rtx ();
+  emit_label (label);
+  emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label));
+
+  if (exp)
+    {
+      /* throw variable */
+      /* First, decay it. */
+      exp = default_conversion (exp);
+      type = TREE_TYPE (exp);
+    }
+  else
+    type = void_type_node;
+
+  {
+    char *typestring = build_overload_name (type, 1, 1);
+    tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
+    rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
+    emit_move_insn (saved_throw_type, throw_type_rtx);
+  }
+
+  emit_jump (throw_label);
 }
 
+
+/* output the exception table */
 void
-init_exception_processing_1 ()
+build_exception_table ()
 {
-  register tree EHS_id = get_identifier ("exceptionHandlerStack");
+  extern FILE *asm_out_file;
+  struct ehEntry *entry;
 
-  EHS_decl = IDENTIFIER_GLOBAL_VALUE (EHS_id);
+  if (! doing_eh (0))
+    return;
 
-  /* If we have no other definition, default to library implementation.  */
-  if (EHS_decl == NULL_TREE)
-    {
-      EHS_decl = build_decl (VAR_DECL, EHS_id, TYPE_POINTER_TO (EHS_type));
-      /* If we don't push this, its definition, should it be encountered,
-        will not be seen.  */
-      EHS_decl = pushdecl (EHS_decl);
-      DECL_EXTERNAL (EHS_decl) = 1;
-      TREE_STATIC (EHS_decl) = 1;
-      TREE_PUBLIC (EHS_decl) = 1;
-      finish_decl (EHS_decl, NULL_TREE, NULL_TREE, 0);
-    }
-  else if (TREE_CODE (EHS_decl) != VAR_DECL
-          || TREE_TYPE (EHS_decl) != TYPE_POINTER_TO (EHS_type))
-    fatal ("exception handling declarations conflict with compiler's internal model");
+  exception_section ();
 
-  if (EHS_prev == NULL_TREE)
-    {
-      register tree EHS_DECL = build1 (INDIRECT_REF, EHS_type, EHS_decl);
-      EHS_prev = build_component_ref (EHS_DECL, get_identifier ("prev"), 0, 0);
-      EHS_handler = build_component_ref (EHS_DECL, get_identifier ("handler"), 0, 0);
-      EHS_parms = build_component_ref (EHS_DECL, get_identifier ("parms"), 0, 0);
-      EHS_name = build_component_ref (EHS_DECL, get_identifier ("name"), 0, 0);
-    }
+  /* Beginning marker for table. */
+  fprintf (asm_out_file, "        .global ___EXCEPTION_TABLE__\n");
+  fprintf (asm_out_file, "        .align 4\n");
+  fprintf (asm_out_file, "___EXCEPTION_TABLE__:\n");
+  fprintf (asm_out_file, "        .word   0, 0, 0\n");
+
+ while (entry = dequeue_eh_entry (&eh_table_output_queue)) {
+     output_exception_table_entry (asm_out_file,
+            entry->start_label, entry->end_label, entry->exception_handler_label);
+  }
+
+  /* Ending marker for table. */
+  fprintf (asm_out_file, "        .global ___EXCEPTION_END__\n");
+  fprintf (asm_out_file, "___EXCEPTION_END__:\n");
+  fprintf (asm_out_file, "        .word   -1, -1, -1\n");
+}
+
+/* end of: my-cp-except.c */
+#endif
+
+
+/* Build a throw expression.  */
+tree
+build_throw (e)
+     tree e;
+{
+  e = build1 (THROW_EXPR, void_type_node, e);
+  TREE_SIDE_EFFECTS (e) = 1;
+  return e;
 }
index b59fefe..c2213d5 100644 (file)
@@ -214,6 +214,10 @@ cplus_expand_expr (exp, target, tmode, modifier)
     case THUNK_DECL:
       return DECL_RTL (exp);
 
+    case THROW_EXPR:
+      expand_throw (TREE_OPERAND (exp, 0));
+      return NULL;
+
     default:
       break;
     }
index 20eadb6..33f1d23 100644 (file)
@@ -26,14 +26,6 @@ __typeof__, TYPEOF, NORID
 __volatile, TYPE_QUAL, RID_VOLATILE
 __volatile__, TYPE_QUAL, RID_VOLATILE
 __wchar_t, TYPESPEC, RID_WCHAR  /* Unique to ANSI C++ */,
-all, ALL, NORID                        /* Extension */,
-except, EXCEPT, NORID          /* Extension */,
-exception, AGGR, RID_EXCEPTION /* Extension */,
-raise, RAISE, NORID            /* Extension */,
-raises, RAISES, NORID          /* Extension */,
-reraise, RERAISE, NORID                /* Extension */,
-throw, THROW, NORID            /* Extension */,
-try, TRY, NORID                        /* Extension */,
 asm, ASM_KEYWORD, NORID,
 auto, SCSPEC, RID_AUTO,
 break, BREAK, NORID,
@@ -79,7 +71,9 @@ static, SCSPEC, RID_STATIC,
 struct, AGGR, RID_RECORD,
 switch, SWITCH, NORID,
 this, THIS, NORID,
+throw, THROW, NORID,
 template, TEMPLATE, NORID,
+try, TRY, NORID,
 typedef, SCSPEC, RID_TYPEDEF,
 typeof, TYPEOF, NORID,
 typeid, TYPEID, NORID,
index d27fe70..d91a97e 100644 (file)
@@ -8,7 +8,7 @@
 @node Top, Limitations of g++, (dir), (dir)
 @chapter Internal Architecture of the Compiler
 
-This is meant to describe the C++ frontend for gcc in detail.
+This is meant to describe the C++ front-end for gcc in detail.
 Questions and comments to mrs@@cygnus.com.
 
 @menu
@@ -24,6 +24,7 @@ Questions and comments to mrs@@cygnus.com.
 * Error Reporting::             
 * Parser::                      
 * Copying Objects::             
+* Exception Handling::             
 * Concept Index::               
 @end menu
 
@@ -555,7 +556,7 @@ IDENTIFIER_NODEs for TYPE_DECLs
 
 @item DECL_IGNORED_P
 A bit that can be set to inform the debug information output routines in
-the backend that a certain _DECL node should be totally ignored.
+the back-end that a certain _DECL node should be totally ignored.
 
 Used in cases where it is known that the debugging information will be
 output in another file, or where a sub-type is known not to be needed
@@ -989,7 +990,7 @@ completely unrelated to access control!
 @node Error Reporting, Parser, Access Control, Top
 @section Error Reporting
 
-The C++ frontend uses a call-back mechanism to allow functions to print
+The C++ front-end uses a call-back mechanism to allow functions to print
 out reasonable strings for types and functions without putting extra
 logic in the functions where errors are found.  The interface is through
 the @code{cp_error} function (or @code{cp_warning}, etc.).  The
@@ -1115,7 +1116,7 @@ conflicts.
 
 Unlike the others, this ambiguity is not recognized by the Working Paper.
 
-@node  Copying Objects, Concept Index, Parser, Top
+@node  Copying Objects, Exception Handling, Parser, Top
 @section Copying Objects
 
 The generated copy assignment operator in g++ does not currently do the
@@ -1141,7 +1142,54 @@ them.
 This issue is currently under discussion in the core reflector
 (2/28/94).
 
-@node Concept Index,  , Copying Objects, Top
+@node  Copying Objects, Concept Index, Copying Objects, Top
+@section Exception Handling
+
+This section describes the mapping of C++ exceptions in the C++
+front-end, into the back-end exception handling framework.
+
+The basic mechanism of exception handling in the back-end is
+unwind-protect a la elisp.  This is a general, robust, and language
+independent representation for exceptions.
+
+The C++ front-end exceptions are mapping into the unwind-protect
+semantics by the C++ front-end.  The mapping is describe below.
+
+Objects with RTTI support, should use the RTTI information to do mapping
+and checking.  Objects without RTTI, like int and const char *, have to
+use another means of matching.  Currently we use the normal mangling used in
+building functions names.  Int's are "i", const char * is PCc, etc...
+
+Unfortunately, the standard allows standard type conversions on throw
+parameters so they can match catch handlers.  This means we need a
+mechanism to handle type conversion at run time, ICK.
+
+In C++, all cleanups should be protected by exception regions.  The
+region starts just after the reason why the cleanup is created has
+ended.  For example, with an automatic variable, that has a constructor,
+it would be right after the constructor is run.  The region ends just
+before the finalization is expanded.  Since the backend may expand the
+cleanup multiple times along different paths, once for normal end of the
+region, once for non-local gotos, once for returns, etc, the backend
+must take special care to protect the finalization expansion, if the
+expansion is for any other reason than normal region end, and it is
+`inline' (it is inside the exception region).  The backend can either
+choose to move them out of line, or it can created an exception region
+over the finalization to protect it, and in the handler associated with
+it, it would not run the finalization as it otherwise would have, but
+rather just rethrow to the outer handler, careful to skip the normal
+handler for the original region.
+
+In Ada, they will use the more runtime intensive approach of having
+fewer regions, but at the cost of additional work at run time, to keep a
+list of things that need cleanups.  When a variable has finished
+construction, they add the cleanup to the list, when the come to the end
+of the lifetime of the variable, the run the list down.  If the take a
+hit before the section finishes normally, they examine the list for
+actions to perform.  I hope they add this logic into the back-end, as it
+would be nice to get that alternative approach in C++.
+
+@node Concept Index,  , Exception Handling, Top
 @section Concept Index
 
 @printindex cp
index fceaa63..86bc4ca 100644 (file)
@@ -3,12 +3,12 @@
 /* Command-line: gperf -p -j1 -g -o -t -N is_reserved_word -k1,4,$,7 gplus.gperf  */
 struct resword { char *name; short token; enum rid rid;};
 
-#define TOTAL_KEYWORDS 86
+#define TOTAL_KEYWORDS 80
 #define MIN_WORD_LENGTH 2
 #define MAX_WORD_LENGTH 13
 #define MIN_HASH_VALUE 4
-#define MAX_HASH_VALUE 196
-/* maximum key range = 193, duplicates = 0 */
+#define MAX_HASH_VALUE 166
+/* maximum key range = 163, duplicates = 0 */
 
 #ifdef __GNUC__
 inline
@@ -20,19 +20,19 @@ hash (str, len)
 {
   static unsigned char asso_values[] =
     {
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
-     197, 197, 197, 197, 197,   0, 197,  93,   3,  35,
-       3,   0,  71,   8,   4,  78, 197,   3,  30,   6,
-      29,  18,  37, 197,  55,   0,   4,  11,   7,  20,
-       0,   8, 197, 197, 197, 197, 197, 197,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167, 167, 167, 167, 167, 167,
+     167, 167, 167, 167, 167,   0, 167,  36,   6,  60,
+      17,   0,  16,   5,  41,  38, 167,  11,  22,   7,
+      26,   0,   4, 167,  22,   0,   4,  44,  19,   8,
+       5,  18, 167, 167, 167, 167, 167, 167,
     };
   register int hval = len;
 
@@ -68,127 +68,103 @@ is_reserved_word (str, len)
       {"",}, {"",}, 
       {"__asm__",  GCC_ASM_KEYWORD, NORID},
       {"this",  THIS, NORID,},
-      {"delete",  DELETE, NORID,},
-      {"except",  EXCEPT, NORID                /* Extension */,},
-      {"__asm",  GCC_ASM_KEYWORD, NORID},
-      {"double",  TYPESPEC, RID_DOUBLE,},
-      {"typeid",  TYPEID, NORID,},
-      {"switch",  SWITCH, NORID,},
-      {"try",  TRY, NORID                      /* Extension */,},
-      {"enum",  ENUM, NORID,},
-      {"void",  TYPESPEC, RID_VOID,},
-      {"",}, {"",}, {"",}, 
-      {"struct",  AGGR, RID_RECORD,},
-      {"",}, 
-      {"do",  DO, NORID,},
-      {"",}, {"",}, {"",}, {"",}, 
+      {"goto",  GOTO, NORID,},
       {"__headof__",  HEADOF, NORID},
-      {"",}, {"",}, 
+      {"",}, 
+      {"__asm",  GCC_ASM_KEYWORD, NORID},
       {"__const__",  TYPE_QUAL, RID_CONST},
       {"__volatile",  TYPE_QUAL, RID_VOLATILE},
       {"__const",  TYPE_QUAL, RID_CONST},
       {"__volatile__",  TYPE_QUAL, RID_VOLATILE},
-      {"extern",  SCSPEC, RID_EXTERN,},
+      {"throw",  THROW, NORID,},
+      {"enum",  ENUM, NORID,},
+      {"do",  DO, NORID,},
+      {"template",  TEMPLATE, NORID,},
+      {"sigof",  SIGOF, NORID          /* Extension */,},
+      {"sizeof",  SIZEOF, NORID,},
+      {"delete",  DELETE, NORID,},
+      {"__headof",  HEADOF, NORID},
+      {"try",  TRY, NORID,},
+      {"typeof",  TYPEOF, NORID,},
+      {"typeid",  TYPEID, NORID,},
       {"__typeof__",  TYPEOF, NORID},
-      {"",}, 
-      {"signed",  TYPESPEC, RID_SIGNED,},
-      {"case",  CASE, NORID,},
-      {"class",  AGGR, RID_CLASS,},
+      {"double",  TYPESPEC, RID_DOUBLE,},
+      {"private",  VISSPEC, RID_PRIVATE,},
+      {"short",  TYPESPEC, RID_SHORT,},
+      {"extern",  SCSPEC, RID_EXTERN,},
       {"__classof__",  CLASSOF, NORID},
-      {"__extension__",  EXTENSION, NORID},
-      {"",}, 
-      {"const",  TYPE_QUAL, RID_CONST,},
-      {"static",  SCSPEC, RID_STATIC,},
       {"",}, 
-      {"throw",  THROW, NORID          /* Extension */,},
-      {"goto",  GOTO, NORID,},
-      {"signature",  AGGR, RID_SIGNATURE       /* Extension */,},
+      {"while",  WHILE, NORID,},
       {"long",  TYPESPEC, RID_LONG,},
-      {"private",  VISSPEC, RID_PRIVATE,},
       {"new",  NEW, NORID,},
-      {"template",  TEMPLATE, NORID,},
-      {"",}, 
-      {"while",  WHILE, NORID,},
-      {"",}, 
       {"protected",  VISSPEC, RID_PROTECTED,},
-      {"continue",  CONTINUE, NORID,},
-      {"",}, 
-      {"raise",  RAISE, NORID          /* Extension */,},
-      {"raises",  RAISES, NORID                /* Extension */,},
-      {"",}, 
-      {"union",  AGGR, RID_UNION,},
-      {"short",  TYPESPEC, RID_SHORT,},
-      {"",}, 
-      {"__inline",  SCSPEC, RID_INLINE},
-      {"",}, 
-      {"__inline__",  SCSPEC, RID_INLINE},
-      {"",}, 
-      {"__alignof__",  ALIGNOF, NORID},
-      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"sizeof",  SIZEOF, NORID,},
-      {"virtual",  SCSPEC, RID_VIRTUAL,},
-      {"catch",  CATCH, NORID,},
       {"friend",  SCSPEC, RID_FRIEND,},
-      {"typeof",  TYPEOF, NORID,},
-      {"",}, {"",}, 
-      {"headof",  HEADOF, NORID,},
+      {"auto",  SCSPEC, RID_AUTO,},
+      {"for",  FOR, NORID,},
+      {"__typeof",  TYPEOF, NORID},
+      {"typedef",  SCSPEC, RID_TYPEDEF,},
+      {"__extension__",  EXTENSION, NORID},
       {"int",  TYPESPEC, RID_INT,},
-      {"",}, {"",}, 
+      {"asm",  ASM_KEYWORD, NORID,},
+      {"__classof",  CLASSOF, NORID},
       {"__signed__",  TYPESPEC, RID_SIGNED},
-      {"__signed",  TYPESPEC, RID_SIGNED},
-      {"",}, {"",}, {"",}, 
+      {"signed",  TYPESPEC, RID_SIGNED,},
+      {"mutable",  SCSPEC, RID_MUTABLE,},
+      {"switch",  SWITCH, NORID,},
+      {"operator",  OPERATOR, NORID,},
       {"__attribute",  ATTRIBUTE, NORID},
-      {"sigof",  SIGOF, NORID          /* Extension */,},
+      {"struct",  AGGR, RID_RECORD,},
       {"__attribute__",  ATTRIBUTE, NORID},
+      {"if",  IF, NORID,},
+      {"void",  TYPESPEC, RID_VOID,},
+      {"break",  BREAK, NORID,},
+      {"__alignof__",  ALIGNOF, NORID},
+      {"__inline",  SCSPEC, RID_INLINE},
+      {"float",  TYPESPEC, RID_FLOAT,},
+      {"__inline__",  SCSPEC, RID_INLINE},
+      {"__signed",  TYPESPEC, RID_SIGNED},
+      {"case",  CASE, NORID,},
+      {"class",  AGGR, RID_CLASS,},
       {"",}, 
-      {"__headof",  HEADOF, NORID},
+      {"__label__",  LABEL, NORID},
+      {"default",  DEFAULT, NORID,},
+      {"const",  TYPE_QUAL, RID_CONST,},
+      {"static",  SCSPEC, RID_STATIC,},
       {"",}, {"",}, 
-      {"unsigned",  TYPESPEC, RID_UNSIGNED,},
-      {"return",  RETURN, NORID,},
-      {"asm",  ASM_KEYWORD, NORID,},
-      {"__wchar_t",  TYPESPEC, RID_WCHAR  /* Unique to ANSI C++ */,},
-      {"break",  BREAK, NORID,},
-      {"__typeof",  TYPEOF, NORID},
-      {"mutable",  SCSPEC, RID_MUTABLE,},
+      {"__alignof",  ALIGNOF, NORID},
+      {"virtual",  SCSPEC, RID_VIRTUAL,},
+      {"union",  AGGR, RID_UNION,},
+      {"",}, {"",}, {"",}, 
+      {"signature",  AGGR, RID_SIGNATURE       /* Extension */,},
+      {"headof",  HEADOF, NORID,},
       {"",}, 
-      {"public",  VISSPEC, RID_PUBLIC,},
+      {"inline",  SCSPEC, RID_INLINE,},
+      {"overload",  OVERLOAD, NORID,},
       {"",}, 
-      {"__classof",  CLASSOF, NORID},
-      {"default",  DEFAULT, NORID,},
+      {"volatile",  TYPE_QUAL, RID_VOLATILE,},
       {"",}, {"",}, {"",}, {"",}, 
-      {"exception",  AGGR, RID_EXCEPTION       /* Extension */,},
-      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"all",  ALL, NORID                      /* Extension */,},
+      {"register",  SCSPEC, RID_REGISTER,},
+      {"",}, 
+      {"public",  VISSPEC, RID_PUBLIC,},
       {"",}, {"",}, 
-      {"for",  FOR, NORID,},
+      {"__wchar_t",  TYPESPEC, RID_WCHAR  /* Unique to ANSI C++ */,},
       {"",}, {"",}, 
-      {"__label__",  LABEL, NORID},
-      {"auto",  SCSPEC, RID_AUTO,},
-      {"",}, {"",}, {"",}, {"",}, 
-      {"volatile",  TYPE_QUAL, RID_VOLATILE,},
-      {"__alignof",  ALIGNOF, NORID},
+      {"return",  RETURN, NORID,},
+      {"classof",  CLASSOF, NORID,},
       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"dynamic_cast",  DYNAMIC_CAST, NORID,},
-      {"",}, 
+      {"unsigned",  TYPESPEC, RID_UNSIGNED,},
       {"char",  TYPESPEC, RID_CHAR,},
-      {"",}, 
-      {"if",  IF, NORID,},
-      {"",}, 
-      {"typedef",  SCSPEC, RID_TYPEDEF,},
-      {"operator",  OPERATOR, NORID,},
-      {"reraise",  RERAISE, NORID              /* Extension */,},
-      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"inline",  SCSPEC, RID_INLINE,},
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"continue",  CONTINUE, NORID,},
       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"",}, 
-      {"float",  TYPESPEC, RID_FLOAT,},
       {"",}, {"",}, {"",}, 
-      {"overload",  OVERLOAD, NORID,},
-      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"classof",  CLASSOF, NORID,},
+      {"dynamic_cast",  DYNAMIC_CAST, NORID,},
       {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
-      {"",}, {"",}, 
-      {"register",  SCSPEC, RID_REGISTER,},
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, 
+      
+      {"catch",  CATCH, NORID,},
     };
 
   if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
index 8a81db9..8e70143 100644 (file)
@@ -217,12 +217,8 @@ perform_member_init (member, name, init, explicit)
          expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
        }
     }
-
-  if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type))
-    {
-      cplus_expand_start_try (1);
-      push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));
-    }
+  if (flag_handle_exceptions && TYPE_NEEDS_DESTRUCTOR (type))
+    cp_warning ("caution, member `%D' may not be destroyed in the presense of an exception during construction", member);
 }
 
 /* Subroutine of emit_member_init.  */
@@ -390,20 +386,6 @@ emit_base_init (t, immediately)
     emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),
                          DECL_SOURCE_LINE (current_function_decl));
 
-  /* In this case, we always need IN_CHARGE_NODE, because we have
-     to know whether to deallocate or not before exiting.  */
-  if (flag_handle_exceptions == 2
-      && lookup_name (in_charge_identifier, 0) == NULL_TREE)
-    {
-      tree in_charge_node = pushdecl (build_decl (VAR_DECL, in_charge_identifier,
-                                                 integer_type_node));
-      store_init_value (in_charge_node, build (EQ_EXPR, integer_type_node,
-                                              current_class_decl,
-                                              integer_zero_node));
-      expand_decl (in_charge_node);
-      expand_decl_init (in_charge_node);
-    }
-
   start = ! TYPE_USES_VIRTUAL_BASECLASSES (t);
   for (pass = start; pass < 2; pass++)
     {
@@ -521,11 +503,6 @@ emit_base_init (t, immediately)
          expand_aggr_init_1 (t_binfo, 0,
                              build_indirect_ref (member, NULL_PTR), init,
                              BINFO_OFFSET_ZEROP (binfo), LOOKUP_COMPLAIN);
-         if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
-           {
-             cplus_expand_start_try (1);
-             push_exception_cleanup (member);
-           }
        }
 
       if (pass == 0)
@@ -594,12 +571,6 @@ emit_base_init (t, immediately)
              expand_aggr_init_1 (t_binfo, 0, ref, NULL_TREE,
                                  BINFO_OFFSET_ZEROP (base_binfo),
                                  LOOKUP_COMPLAIN);
-             if (flag_handle_exceptions == 2
-                 && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))
-               {
-                 cplus_expand_start_try (1);
-                 push_exception_cleanup (base);
-               }
            }
        }
       CLEAR_BINFO_BASEINIT_MARKED (base_binfo);
index 51cb772..7c88ba5 100644 (file)
@@ -766,40 +766,16 @@ init_lex ()
   do { struct resword *s = is_reserved_word (STRING, sizeof (STRING) - 1); \
        if (s) s->name = ""; } while (0)
 
-  if (flag_ansi_exceptions)
-      flag_handle_exceptions = 2;
-
-  if (!flag_ansi_exceptions)
+#if 0
+  /* let's parse things, and if they use it, then give them an error.  */
+  if (!flag_handle_exceptions)
     {
+      UNSET_RESERVED_WORD ("throw");
+      UNSET_RESERVED_WORD ("try");
       UNSET_RESERVED_WORD ("catch");
     }
+#endif
 
-  if (! flag_handle_exceptions)
-    {
-      /* Easiest way to not recognize exception
-        handling extensions...  */
-      UNSET_RESERVED_WORD ("all");
-      UNSET_RESERVED_WORD ("except");
-      UNSET_RESERVED_WORD ("exception");
-      UNSET_RESERVED_WORD ("raise");
-      UNSET_RESERVED_WORD ("raises");
-      UNSET_RESERVED_WORD ("reraise");
-      UNSET_RESERVED_WORD ("try");
-      UNSET_RESERVED_WORD ("throw");
-    }
-  else if (flag_ansi_exceptions)
-    {
-      /* Easiest way to not recognize exception
-        handling extensions...  */
-      UNSET_RESERVED_WORD ("exception");
-      UNSET_RESERVED_WORD ("all");
-      UNSET_RESERVED_WORD ("except");
-      UNSET_RESERVED_WORD ("raise");
-      UNSET_RESERVED_WORD ("raises");
-      UNSET_RESERVED_WORD ("reraise");
-      is_reserved_word ("try", sizeof ("try") - 1)->token = ANSI_TRY;
-      is_reserved_word ("throw", sizeof ("throw") - 1)->token = ANSI_THROW;
-    }
   if (! (flag_gc || flag_dossier))
     {
       UNSET_RESERVED_WORD ("classof");
@@ -3171,6 +3147,13 @@ do_identifier (token)
        }
     }
 
+  /* Remember that this name has been used in the class definition, as per
+     [class.scope0] */
+  if (id && current_class_type
+      && TYPE_BEING_DEFINED (current_class_type)
+      && ! IDENTIFIER_CLASS_VALUE (token))
+    pushdecl_class_level (id);
+    
   if (!id || id == error_mark_node)
     {
       if (id == error_mark_node && current_class_type != NULL_TREE)
@@ -3496,7 +3479,14 @@ real_yylex ()
        if (strcmp ("catch", token_buffer) == 0
            || strcmp ("throw", token_buffer) == 0
            || strcmp ("try", token_buffer) == 0)
-         pedwarn ("`catch', `throw', and `try' are all C++ reserved words");
+         {
+           static int did_warn = 0;
+           if (! did_warn  && ! flag_handle_exceptions)
+             {
+               pedwarn ("`catch', `throw', and `try' are all C++ reserved words");
+               did_warn = 1;
+             }
+         }
 
        if (value == IDENTIFIER || value == TYPESPEC)
          GNU_xref_ref (current_function_decl, token_buffer);
index 32c5e52..f46f70a 100644 (file)
@@ -192,8 +192,7 @@ empty_parms ()
 %left <code> POINTSAT '.' '(' '['
 
 %right SCOPE                   /* C++ extension */
-%nonassoc NEW DELETE RAISE RAISES RERAISE TRY EXCEPT CATCH THROW
-%nonassoc ANSI_TRY ANSI_THROW
+%nonassoc NEW DELETE TRY CATCH THROW
 
 %type <code> unop
 
@@ -209,7 +208,7 @@ empty_parms ()
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attribute_list attrib
 
-%type <ttype> compstmt except_stmts ansi_except_stmts implicitly_scoped_stmt
+%type <ttype> compstmt implicitly_scoped_stmt
 
 %type <ttype> declarator notype_declarator after_type_declarator
 %type <ttype> direct_notype_declarator direct_after_type_declarator
@@ -251,15 +250,13 @@ empty_parms ()
 /* %type <ttype> primary_no_id */
 %type <ttype> nonmomentary_expr
 %type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list
-%type <itype> try ansi_try
 %type <ttype> template_header template_parm_list template_parm
 %type <ttype> template_type template_arg_list template_arg
 %type <ttype> template_instantiation template_type_name tmpl.2
 %type <ttype> template_instantiate_once template_instantiate_some
 %type <itype> fn_tmpl_end
 /* %type <itype> try_for_typename */
-%type <ttype> condition partially_scoped_stmt xcond paren_cond_or_null
-%type <strtype> .kindof_pushlevel
+%type <ttype> condition xcond paren_cond_or_null
 %type <ttype> type_name nested_name_specifier nested_type ptr_to_mem
 %type <ttype> qualified_type_name complete_type_name notype_identifier
 %type <ttype> complex_type_name nested_name_specifier_1
@@ -486,7 +483,6 @@ template_def:
                                  0, $<ttype>4);
                  cplus_decl_attributes (d, $6);
                  finish_decl (d, NULL_TREE, $5, 0);
-                 end_exception_decls ();
                  end_template_decl ($1, d, 0, def);
                  if (def)
                    {
@@ -530,7 +526,6 @@ datadef:
                }
        | typed_declspecs initdecls ';'
                {
-                 end_exception_decls ();
                  note_list_got_semicolon ($<ttype>$);
                }
        /* Normal case: make this fast.  */
@@ -538,7 +533,6 @@ datadef:
                { tree d;
                  d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE);
                  finish_decl (d, NULL_TREE, NULL_TREE, 0);
-                 end_exception_decls ();
                  note_list_got_semicolon ($<ttype>$);
                }
         | declmods ';'
@@ -959,56 +953,6 @@ condition:
        | expr
        ;
 
-/* Used for the blocks controlled by a condition, to add any DECLs in
-   the condition to the controlled block.  */
-.kindof_pushlevel: /* empty */
-               { tree d = getdecls ();
-                 emit_line_note (input_filename, lineno);
-                 pushlevel (0);
-                 clear_last_expr ();
-                 push_momentary ();
-                 expand_start_bindings (0);
-                 if (d) pushdecl (d);
-               }    
-       ;
-
-/* Like implicitly_scoped_stmt, but uses .kindof_pushlevel */
-partially_scoped_stmt:
-           '{' .kindof_pushlevel '}'
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p (), 1);
-                 $$ = poplevel (kept_level_p (), 1, 0);
-                 pop_momentary (); 
-                 finish_stmt (); }
-       | '{' .kindof_pushlevel maybe_label_decls stmts '}'
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p (), 1);
-                 $$ = poplevel (kept_level_p (), 1, 0);
-                 pop_momentary (); 
-                 finish_stmt (); }
-       | '{' .kindof_pushlevel maybe_label_decls error '}'
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p (), 1);
-                 $$ = poplevel (kept_level_p (), 0, 0);
-                 pop_momentary (); 
-                 finish_stmt (); }
-       | .kindof_pushlevel simple_stmt
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p (), 1);
-                 $$ = poplevel (kept_level_p (), 1, 0);
-                 pop_momentary (); }
-       ;
-
-already_scoped_stmt:
-          '{' '}'
-               { finish_stmt (); }
-       | '{' maybe_label_decls stmts '}'
-               { finish_stmt (); }
-       | '{' maybe_label_decls error '}'
-               { finish_stmt (); }
-       | simple_stmt
-       ;
-
 nontrivial_exprlist:
          expr_no_commas ',' expr_no_commas
                { $$ = tree_cons (NULL_TREE, $$, 
@@ -1262,6 +1206,10 @@ expr_no_commas:
                    $$ = rval;
                  else
                    $$ = build_modify_expr ($$, $2, $3); }
+       | THROW
+               { $$ = build_throw (NULL_TREE); }
+       | THROW expr_no_commas
+               { $$ = build_throw ($2); }
 /* These extensions are not defined.  The second arg to build_m_component_ref
    is old, build_m_component_ref now does an implicit
    build_indirect_ref (x, NULL_PTR) on the second argument.
@@ -1767,10 +1715,10 @@ typed_declspecs1:
                { $$ = decl_tree_cons (NULL_TREE, $$, $2); }
        | declmods typespec reserved_declspecs
                { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
-       | declmods typespec reserved_typespecquals
-               { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
-       | declmods typespec reserved_typespecquals reserved_declspecs
-               { $$ = decl_tree_cons (NULL_TREE, $2, 
+       | declmods typespec reserved_typespecquals
+               { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
+       | declmods typespec reserved_typespecquals reserved_declspecs
+               { $$ = decl_tree_cons (NULL_TREE, $2, 
                                       chainon ($3, chainon ($4, $$))); }
        ;
 
@@ -1873,7 +1821,7 @@ typespec: structsp
                    }
                  else
                    {
-                     error("`sigof' applied to non-aggregate type");
+                     error("`sigof' applied to non-aggregate type");
                      $$ = error_mark_node;
                    }
                }
@@ -2150,10 +2098,6 @@ structsp:
                    /* $$ = $1 from default rule.  */;
                  else if (CLASSTYPE_DECLARED_EXCEPTION ($$))
                    {
-                     if (! semi)
-                       $$ = finish_exception ($$, $3);
-                     else
-                       warning ("empty exception declaration\n");
                    }
                  else
                    {
@@ -2546,12 +2490,10 @@ component_decl_1:
          typed_declspecs components
                {
                  $$ = grok_x_components ($$, $2);
-                 end_exception_decls ();
                }
        | declmods notype_components
                { 
                  $$ = grok_x_components ($$, $2);
-                 end_exception_decls ();
                }
        | notype_declarator maybe_raises maybeasm maybe_attribute
                { $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, $3);
@@ -2764,6 +2706,18 @@ after_type_declarator:
 
 qualified_type_name:
          type_name %prec EMPTY
+               {
+                 /* Remember that this name has been used in the class
+                    definition, as per [class.scope0] */
+                 if (current_class_type
+                     && TYPE_BEING_DEFINED (current_class_type)
+                     && ! IDENTIFIER_CLASS_VALUE ($$))
+                   {
+                     tree t = lookup_name ($$, -2);
+                     if (t)
+                       pushdecl_class_level (t);
+                   }
+               }
        | nested_type
        ;
 
@@ -3072,18 +3026,15 @@ compstmt_or_error:
        ;
 
 compstmt: '{' .pushlevel '}'
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p(), 1);
+               { expand_end_bindings (getdecls (), kept_level_p(), 1);
                  $$ = poplevel (kept_level_p (), 1, 0);
                  pop_momentary (); }
        | '{' .pushlevel maybe_label_decls stmts '}'
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p(), 1);
+               { expand_end_bindings (getdecls (), kept_level_p(), 1);
                  $$ = poplevel (kept_level_p (), 1, 0);
                  pop_momentary (); }
        | '{' .pushlevel maybe_label_decls error '}'
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p(), 1);
+               { expand_end_bindings (getdecls (), kept_level_p(), 1);
                  $$ = poplevel (kept_level_p (), 0, 0);
                  pop_momentary (); }
        ;
@@ -3094,15 +3045,14 @@ simple_if:
          .pushlevel paren_cond_or_null
                { emit_line_note (input_filename, lineno);
                  expand_start_cond (truthvalue_conversion ($4), 0); }
-         partially_scoped_stmt
+         implicitly_scoped_stmt
        ;
 
 implicitly_scoped_stmt:
          compstmt
                { finish_stmt (); }
        | .pushlevel simple_stmt
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), getdecls() != NULL_TREE, 1);
+               { expand_end_bindings (getdecls (), getdecls() != NULL_TREE, 1);
                  $$ = poplevel (kept_level_p (), 1, 0);
                  pop_momentary (); }
        ;
@@ -3118,7 +3068,7 @@ simple_stmt:
                { finish_stmt (); }
        | expr ';'
                {
-                 tree expr = $1;
+                 tree expr = $1;
                  emit_line_note (input_filename, lineno);
                  /* Do default conversion if safe and possibly important,
                     in case within ({...}).  */
@@ -3131,16 +3081,14 @@ simple_stmt:
                  finish_stmt (); }
        | simple_if ELSE
                { expand_start_else (); }
-         partially_scoped_stmt
+         implicitly_scoped_stmt
                { expand_end_cond ();
-                 pop_implicit_try_blocks (NULL_TREE);
                  expand_end_bindings (getdecls (), kept_level_p (), 1);
                  poplevel (kept_level_p (), 1, 0);
                  pop_momentary ();
                  finish_stmt (); }
        | simple_if %prec IF
                { expand_end_cond ();
-                 pop_implicit_try_blocks (NULL_TREE);
                  expand_end_bindings (getdecls (), kept_level_p (), 1);
                  poplevel (kept_level_p (), 1, 0);
                  pop_momentary ();
@@ -3152,9 +3100,8 @@ simple_stmt:
                  cond_stmt_keyword = "while"; }
          .pushlevel paren_cond_or_null
                { expand_exit_loop_if_false (0, truthvalue_conversion ($4)); }
-         already_scoped_stmt
-               { pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p (), 1);
+         implicitly_scoped_stmt
+               { expand_end_bindings (getdecls (), kept_level_p (), 1);
                  poplevel (kept_level_p (), 1, 0);
                  pop_momentary ();
                  expand_end_loop ();
@@ -3184,13 +3131,12 @@ simple_stmt:
                /* Don't let the tree nodes for $7 be discarded
                   by clear_momentary during the parsing of the next stmt.  */
                { push_momentary (); }
-         already_scoped_stmt
+         implicitly_scoped_stmt
                { emit_line_note (input_filename, lineno);
-                 pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p (), 1);
                  expand_loop_continue_here ();
                  if ($7) cplus_expand_expr_stmt ($7);
                  pop_momentary ();
+                 expand_end_bindings (getdecls (), kept_level_p (), 1);
                  poplevel (kept_level_p (), 1, 0);
                  pop_momentary ();
                  expand_end_loop ();
@@ -3207,13 +3153,12 @@ simple_stmt:
                   by clear_momentary during the parsing of the next stmt.  */
                { push_momentary ();
                  $<itype>8 = lineno; }
-         already_scoped_stmt
+         implicitly_scoped_stmt
                { emit_line_note (input_filename, (int) $<itype>8);
-                 pop_implicit_try_blocks (NULL_TREE);
-                 expand_end_bindings (getdecls (), kept_level_p (), 1);
                  expand_loop_continue_here ();
                  if ($7) cplus_expand_expr_stmt ($7);
                  pop_momentary ();
+                 expand_end_bindings (getdecls (), kept_level_p (), 1);
                  poplevel (kept_level_p (), 1, 0);
                  pop_momentary ();
                  expand_end_loop ();
@@ -3225,10 +3170,9 @@ simple_stmt:
                  /* Don't let the tree nodes for $4 be discarded by
                     clear_momentary during the parsing of the next stmt.  */
                  push_momentary (); }
-         partially_scoped_stmt
+         implicitly_scoped_stmt
                { expand_end_case ($4);
                  pop_momentary ();
-                 pop_implicit_try_blocks (NULL_TREE);
                  expand_end_bindings (getdecls (), kept_level_p (), 1);
                  poplevel (kept_level_p (), 1, 0);
                  pop_momentary ();
@@ -3422,7 +3366,7 @@ simple_stmt:
                }
        /* This is the case with clobbered registers as well.  */
        | asm_keyword maybe_type_qual '(' string ':' asm_operands ':'
-         asm_operands ':' asm_clobbers ')' ';'
+         asm_operands ':' asm_clobbers ')' ';'
                { if (TREE_CHAIN ($4)) $4 = combine_strings ($4);
                  emit_line_note (input_filename, lineno);
                  c_expand_asm_operands ($4, $6, $8, $10,
@@ -3447,291 +3391,34 @@ simple_stmt:
                  finish_stmt (); }
        | ';'
                { finish_stmt (); }
-
-       /* Exception handling extensions.  */
-       | ANSI_THROW ';' { cplus_expand_throw (NULL_TREE); }
-       | ANSI_THROW expr ';' { cplus_expand_throw ($2); }
-       | THROW raise_identifier '(' nonnull_exprlist ')' ';'
-               { cplus_expand_raise ($2, $4, NULL_TREE, 0);
-                 finish_stmt (); }
-       | THROW raise_identifier LEFT_RIGHT ';'
-               { cplus_expand_raise ($2, NULL_TREE, NULL_TREE, 0);
-                 finish_stmt (); }
-       | RAISE raise_identifier '(' nonnull_exprlist ')' ';'
-               { cplus_expand_raise ($2, $4, NULL_TREE, 0);
-                 finish_stmt (); }
-       | RAISE raise_identifier LEFT_RIGHT ';'
-               { cplus_expand_raise ($2, NULL_TREE, NULL_TREE, 0);
-                 finish_stmt (); }
-       | RAISE identifier ';'
-               { cplus_expand_reraise ($2);
-                 finish_stmt (); }
-       | try EXCEPT identifier '{'
-               {
-                 tree decl = cplus_expand_end_try ($1);
-                 $<ttype>2 = current_exception_type;
-                 $<ttype>4 = current_exception_decl;
-                 $<ttype>$ = current_exception_object;
-                 cplus_expand_start_except ($3, decl);
-                 pushlevel (0);
-                 clear_last_expr ();
-                 push_momentary ();
-                 expand_start_bindings (0);
-               }
-         except_stmts '}'
-               {
-                 tree decls = getdecls ();
-                 /* If there is a default exception to handle,
-                    handle it here.  */
-                 if ($6)
-                   {
-                     tree decl = build_decl (CPLUS_CATCH_DECL, NULL_TREE, 0);
-                     tree block;
-
-                     pushlevel (1);
-                     expand_start_bindings (0);
-                     expand_expr ($6, 0, 0, 0);
-                     expand_end_bindings (0, 1, 0);
-                     block = poplevel (1, 0, 0);
-
-                     /* This is a catch block.  */
-                     TREE_LANG_FLAG_2 (block) = 1;
-                     BLOCK_VARS (block) = decl;
-                   }
-
-                 expand_end_bindings (decls, decls != 0, 1);
-                 poplevel (decls != 0, 1, 0);
-                 pop_momentary ();
-                 current_exception_type = $<ttype>2;
-                 current_exception_decl = $<ttype>4;
-                 current_exception_object = $<ttype>5;
-                 cplus_expand_end_except ($6);
-               }
-       | try error
-               {
-                 cplus_expand_end_try ($1);
-                 /* These are the important actions of
-                    `cplus_expand_end_except' which we must emulate.  */
-                 if (expand_escape_except ())
-                   expand_end_except ();
-                 expand_end_bindings (0, 0, 1);
-                 poplevel (0, 0, 0);
-               }
-       | ansi_try ansi_dummy ansi_dummy
-               {
-                 tree decl = cplus_expand_end_try ($1);
-                 $<ttype>2 = current_exception_type;
-                 $<ttype>3 = current_exception_decl;
-                 $<ttype>$ = current_exception_object;
-                 cplus_expand_start_except (NULL, decl);
-                 pushlevel (0);
-                 clear_last_expr ();
-                 push_momentary ();
-                 expand_start_bindings (0);
-               }
-         ansi_except_stmts
-               {
-                 tree decls = getdecls ();
-                 /* If there is a default exception to handle,
-                    handle it here.  */
-                 if ($5)
-                   {
-                     tree decl = build_decl (CPLUS_CATCH_DECL, NULL_TREE, 0);
-                     tree block;
-
-                     pushlevel (1);
-                     expand_start_bindings (0);
-                     expand_expr ($5, 0, 0, 0);
-                     expand_end_bindings (0, 1, 0);
-                     block = poplevel (1, 0, 0);
-
-                     /* This is a catch block.  */
-                     TREE_LANG_FLAG_2 (block) = 1;
-                     BLOCK_VARS (block) = decl;
-                   }
-
-                 expand_end_bindings (decls, decls != 0, 1);
-                 poplevel (decls != 0, 1, 0);
-                 pop_momentary ();
-                 current_exception_type = $<ttype>2;
-                 current_exception_decl = $<ttype>3;
-                 current_exception_object = $<ttype>4;
-                 cplus_expand_end_except ($5);
-               }
-       | try RERAISE raise_identifiers /* ';' checked for at bottom.  */
-               { tree name = get_identifier ("(compiler error)");
-                 tree orig_ex_type = current_exception_type;
-                 tree orig_ex_decl = current_exception_decl;
-                 tree orig_ex_obj = current_exception_object;
-                 tree decl = cplus_expand_end_try ($1), decls;
-
-                 /* Start hidden EXCEPT.  */
-                 cplus_expand_start_except (name, decl);
-                 pushlevel (0);
-                 clear_last_expr ();
-                 push_momentary ();
-                 expand_start_bindings (0);
-
-                 /* This sets up the reraise.  */
-                 cplus_expand_reraise ($3);
-
-                 decls = getdecls ();
-                 expand_end_bindings (decls, decls != 0, 1);
-                 poplevel (decls != 0, 1, 0);
-                 pop_momentary ();
-                 current_exception_type = orig_ex_type;
-                 current_exception_decl = orig_ex_decl;
-                 current_exception_object = orig_ex_obj;
-                 /* This will reraise for us.  */
-                 cplus_expand_end_except (error_mark_node);
-                 if (yychar == YYEMPTY)
-                   yychar = YYLEX;
-                 if (yychar != ';')
-                   error ("missing ';' after reraise statement");
-               }
-       | try  %prec EMPTY
-               { yyerror ("`except' missing after `try' statement");
-                 /* Terminate the binding contour started by special
-                    code in `.pushlevel'.  Automagically pops off
-                    the conditional we started for `try' stmt.  */
-                 cplus_expand_end_try ($1);
-                 expand_end_bindings (0, 0, 1);
-                 poplevel (0, 0, 0);
-                 pop_momentary ();
-                 YYERROR; }
-       ;
-
-try:     try_head '}'
-               /* An empty try block is degenerate, but it's better to
-                  do extra work here than to do all the special-case work
-                  everywhere else.  */
-               {
-                 $$ = 1;
-                 pop_implicit_try_blocks (NULL_TREE);
-               }
-       | try_head stmts '}'
-               {
-                 $$ = 1;
-                 pop_implicit_try_blocks (NULL_TREE);
-               }
-       | try_head error '}'
-               {
-                 $$ = 0;
-                 pop_implicit_try_blocks (NULL_TREE);
-               }
+       | try_block
        ;
 
-label_colon:
-         IDENTIFIER ':'
-               { tree label;
-               do_label:
-                 label = define_label (input_filename, lineno, $1);
-                 if (label)
-                   expand_label (label);
-               }
-       | PTYPENAME ':'
-               { goto do_label; }
+try_block:
+         TRY '{' .pushlevel
+               { expand_start_try_stmts (); }
+         ansi_try_stmts
+               { expand_end_try_stmts ();
+                 expand_start_all_catch (); }
+         handler_seq
+               { expand_end_all_catch (); }
        ;
 
-try_head: TRY '{' { cplus_expand_start_try (0); } .pushlevel
-
-ansi_try:        ansi_try_head '}'
+ansi_try_stmts:
+         '}'
                /* An empty try block is degenerate, but it's better to
                   do extra work here than to do all the special-case work
                   everywhere else.  */
-               {
-                 $$ = 1;
-                 pop_implicit_try_blocks (NULL_TREE);
-               }
-       | ansi_try_head stmts '}'
-               {
-                 $$ = 1;
-                 pop_implicit_try_blocks (NULL_TREE);
-               }
-       | ansi_try_head error '}'
-               {
-                 $$ = 0;
-                 pop_implicit_try_blocks (NULL_TREE);
-               }
-       ;
-
-ansi_dummy: ; /* Temporary place-holder. */
-ansi_try_head: ANSI_TRY '{' { cplus_expand_start_try (0); } .pushlevel
-
-except_stmts:
-         /* empty */
-               { $$ = NULL_TREE; }
-       | except_stmts raise_identifier
-               {
-                 tree type = lookup_exception_type (current_class_type, current_class_name, $2);
-                 if (type == NULL_TREE)
-                   {
-                     error ("`%s' is not an exception type",
-                            IDENTIFIER_POINTER (TREE_VALUE ($2)));
-                     current_exception_type = NULL_TREE;
-                     TREE_TYPE (current_exception_object) = error_mark_node;
-                   }
-                 else
-                   {
-                     current_exception_type = type;
-                     /* In-place union.  */
-                     TREE_TYPE (current_exception_object) = type;
-                   }
-                 $2 = cplus_expand_start_catch ($2);
-                 pushlevel (1);
-                 expand_start_bindings (0);
-               }
-         compstmt
-               {
-                 expand_end_bindings (0, 1, 0);
-                 $4 = poplevel (1, 0, 0);
-
-                 cplus_expand_end_catch (0);
-
-                 /* Mark this as a catch block.  */
-                 TREE_LANG_FLAG_2 ($4) = 1;
-                 if ($2 != error_mark_node)
-                   {
-                     tree decl = build_decl (CPLUS_CATCH_DECL, DECL_NAME ($2), 0);
-                     DECL_RTL (decl) = DECL_RTL ($2);
-                     TREE_CHAIN (decl) = BLOCK_VARS ($4);
-                     BLOCK_VARS ($4) = decl;
-                   }
+               { expand_end_bindings (0,1,1);
+                 poplevel (2,0,0);
                }
-       | except_stmts DEFAULT
-               {
-                 if ($1)
-                   error ("duplicate default in exception handler");
-                 current_exception_type = NULL_TREE;
-                 /* Takes it right out of scope.  */
-                 TREE_TYPE (current_exception_object) = error_mark_node;
-
-                 if (! expand_catch_default ())
-                   compiler_error ("default catch botch");
-
-                 /* The default exception is handled as the
-                    last in the chain of exceptions handled.  */
-                 do_pending_stack_adjust ();
-                 $1 = make_node (RTL_EXPR);
-                 TREE_TYPE ($1) = void_type_node;
-                 start_sequence_for_rtl_expr ($1);
+       | stmts '}'
+               { expand_end_bindings (0,1,1);
+                 poplevel (2,0,0);
                }
-         compstmt
-               {
-                 extern struct rtx_def *get_insns ();
-                 do_pending_stack_adjust ();
-                 if (! expand_catch (NULL_TREE))
-                   compiler_error ("except nesting botch");
-                 if (! expand_end_catch ())
-                   compiler_error ("except nesting botch");
-                 RTL_EXPR_SEQUENCE ($1) = get_insns ();
-                 if ($4)
-                   {
-                     /* Mark this block as the default catch block.  */
-                     TREE_LANG_FLAG_1 ($4) = 1;
-                     TREE_LANG_FLAG_2 ($4) = 1;
-                   }
-                 end_sequence ();
+       | error '}'
+               { expand_end_bindings (0,1,1);
+                 poplevel (2,0,0);
                }
        ;
 
@@ -3740,47 +3427,31 @@ optional_identifier:
                { $$ = NULL_TREE; }
        | identifier ;
 
-ansi_except_stmts:
+handler_seq:
          /* empty */
-               { $$ = NULL_TREE; }
-       | ansi_except_stmts CATCH '(' type_id optional_identifier ')'
-               {
-                 tree type = groktypename ($4);
-                 if (IS_SIGNATURE (type))
-                   {
-                     error ("exception cannot be of signature type");
-                     type = error_mark_node;
-                   }
-                 current_exception_type = type;
-                 /* In-place union.  */
-                 if ($5)
-                   {
-                     tree tmp;
-                     tmp = pushdecl (build_decl (VAR_DECL, $5, type));
-                     current_exception_object =
-                         build1 (INDIRECT_REF, type, tmp);
-                    }
-                 $4 = ansi_expand_start_catch(type);
-                 pushlevel (1);
-                 expand_start_bindings (0);
-               }
-         compstmt
-               {
-                 expand_end_bindings (0, 1, 0);
-                 $8 = poplevel (1, 0, 0);
+       | handler_seq CATCH
+               { emit_line_note (input_filename, lineno); }
+         handler_args compstmt
+               { expand_end_catch_block (); }
+       ;
 
-                 cplus_expand_end_catch (0);
+handler_args:
+         '(' ELLIPSIS ')'
+               { expand_start_catch_block (NULL_TREE, NULL_TREE); }
+       | '(' type_id optional_identifier ')'
+               { expand_start_catch_block ($2, $3); }
+       ;
 
-                 /* Mark this as a catch block.  */
-                 TREE_LANG_FLAG_2 ($8) = 1;
-                 if ($4 != error_mark_node)
-                   {
-                     tree decl = build_decl (CPLUS_CATCH_DECL, DECL_NAME ($4), 0);
-                     DECL_RTL (decl) = DECL_RTL ($4);
-                     TREE_CHAIN (decl) = BLOCK_VARS ($8);
-                     BLOCK_VARS ($8) = decl;
-                   }
+label_colon:
+         IDENTIFIER ':'
+               { tree label;
+               do_label:
+                 label = define_label (input_filename, lineno, $1);
+                 if (label)
+                   expand_label (label);
                }
+       | PTYPENAME ':'
+               { goto do_label; }
        ;
 
 forhead.1:
@@ -3869,7 +3540,7 @@ parmlist:  /* empty */
    as it is ambiguous and must be disambiguated elsewhere.  */
 complex_parmlist:
          parms
-               {
+               {
                  $$ = chainon ($$, void_list_node);
                  TREE_PARMLIST ($$) = 1;
                }
@@ -4029,16 +3700,14 @@ bad_parm:
 maybe_raises:
          %prec EMPTY /* empty */
                { $$ = NULL_TREE; }
-       | RAISES raise_identifiers  %prec EMPTY
-               { $$ = $2; }
-       | ANSI_THROW '(' ansi_raise_identifiers  ')' %prec EMPTY
+       | THROW '(' ansi_raise_identifiers  ')' %prec EMPTY
                { $$ = $3; }
        ;
 
 raise_identifier:
-         ALL
-               { $$ = void_list_node; }
-       | IDENTIFIER
+/*       ALL
+               { $$ = void_list_node; } */
+         IDENTIFIER
                { $$ = build_decl_list (NULL_TREE, $$); }
        | TYPENAME
                { $$ = build_decl_list (NULL_TREE, $$); }
@@ -4057,7 +3726,7 @@ raise_identifiers:
          raise_identifier
        | raise_identifiers ',' raise_identifier
                {
-                 TREE_CHAIN ($3) = $$;
+                 TREE_CHAIN ($3) = $$;
                  $$ = $3;
                }
        ;
@@ -4066,7 +3735,7 @@ ansi_raise_identifiers:
          ansi_raise_identifier
        | ansi_raise_identifiers ',' ansi_raise_identifier
                {
-                 TREE_CHAIN ($3) = $$;
+                 TREE_CHAIN ($3) = $$;
                  $$ = $3;
                }
        ;
index f035d6d..edb0b78 100644 (file)
@@ -1494,44 +1494,6 @@ build_exception_variant (ctype, type, raises)
   int constp = TYPE_READONLY (type);
   int volatilep = TYPE_VOLATILE (type);
 
-  if (raises && TREE_CHAIN (raises))
-    {
-      for (i = 0, t = raises; t; t = TREE_CHAIN (t), i++)
-       a[i] = t;
-      /* NULL terminator for list.  */
-      a[i] = NULL_TREE;
-      qsort (a, i, sizeof (tree), id_cmp);
-      while (i--)
-       TREE_CHAIN (a[i]) = a[i+1];
-      raises = a[0];
-    }
-  else if (raises)
-    /* do nothing.  */;
-  else
-    return build_type_variant (v, constp, volatilep);
-
-  if (ctype)
-    {
-      cname = TYPE_NAME (ctype);
-      if (TREE_CODE (cname) == TYPE_DECL)
-       cname = DECL_NAME (cname);
-    }
-  else
-    cname = NULL_TREE;
-
-  for (t = raises; t; t = TREE_CHAIN (t))
-    {
-      /* See that all the exceptions we are thinking about
-        raising have been declared.  */
-      tree this_cname = lookup_exception_cname (ctype, cname, t);
-      tree decl = lookup_exception_object (this_cname, TREE_VALUE (t), 1);
-
-      if (decl == NULL_TREE)
-       decl = lookup_exception_object (this_cname, TREE_VALUE (t), 0);
-      /* Place canonical exception decl into TREE_TYPE of RAISES list.  */
-      TREE_TYPE (t) = decl;
-    }
-
   for (v = TYPE_NEXT_VARIANT (v); v; v = TYPE_NEXT_VARIANT (v))
     {
       if (TYPE_READONLY (v) != constp
index 55f5f86..03ca722 100644 (file)
@@ -2280,6 +2280,7 @@ build_function_call_real (function, params, require_complete, flags)
             function, coerced_params, NULL_TREE);
 
     TREE_SIDE_EFFECTS (result) = 1;
+    /* Remove this sometime. */
     TREE_RAISES (result) |= !! TYPE_RAISES_EXCEPTIONS (fntype);
     if (! require_complete)
       return result;