home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / cc / g++-dist / cplus-except.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-26  |  28.4 KB  |  961 lines

  1. /* Handle exceptional things in C++.
  2.    Copyright (C) 1989 Free Software Foundation, Inc.
  3.    Contributed by Michael Tiemann (tiemann@mcc.com)
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 1, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21.  
  22. /* High-level class interface. */
  23.  
  24. #define NULL 0
  25. #define EXCEPTION_NAME_PREFIX "__exception_"
  26. #define EXCEPTION_NAME_LENGTH 12
  27.  
  28. #include "config.h"
  29. #include "tree.h"
  30. #include "cplus-tree.h"
  31. #include "flags.h"
  32. #include "assert.h"
  33. /* On Suns this can get you to the right definition if you
  34.    set the right value for TARGET.  */
  35. #include <setjmp.h>
  36. #ifdef sequent
  37. /* Can you believe they forgot this?  */
  38. #define _JBLEN 11
  39. #endif
  40.  
  41. #ifndef _JBLEN
  42. #define _JBLEN (sizeof(jmp_buf)/sizeof(int))
  43. #endif
  44.  
  45. /* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
  46.    next exception handler.  Its value says whether to throw or not.
  47.    In the case of functions which do not issue a RAISE, it should be
  48.    possible to optimize away this VAR_DECL (and overhead associated
  49.    with it).  */
  50. tree exception_throw_decl;
  51. /* Use this to know that we did not set `exception_throw_decl',
  52.    until GCC optimizer is smart enough to figure it out for itself.  */
  53. int sets_exception_throw_decl;
  54.  
  55. /* The exception `type' currently in scope, or NULL_TREE if none.  */
  56. tree current_exception_type;
  57.  
  58. /* The exception handler object for the given scope.  */
  59. tree current_exception_decl;
  60.  
  61. /* The ``object'' view of the current exception parameters.
  62.    We cast up from the `parms' field to `current_exception_type'.  */
  63. tree current_exception_object;
  64.  
  65. /* Low-level rtl interface.  */
  66. #include "rtl.h"
  67.  
  68. /* Cache `setjmp', `longjmp', and `unhandled_exception' after
  69.    default conversion.  Maybe later they will get built-in.  */
  70. static tree BISJ, BILJ, BIUE;
  71.  
  72. /* Local variables which give the appearance that exception
  73.    handling is part of the language and the execution model.  */
  74.  
  75. /* The type of the exception handler stack.  */
  76. static tree EHS_type;
  77.  
  78. /* The global handler stack.  */
  79. static tree EHS_decl;
  80.  
  81. /* Cached component refs to fields of `EHS_decl'.  */
  82. static tree EHS_prev, EHS_handler, EHS_parms, EHS_name;
  83.  
  84. /* The parameter names of this exception type.  */
  85.  
  86. static tree last_exception_fields;
  87. static tree last_exception_field_types;
  88.  
  89. /* When ID is VOID_TYPE_NODE, it means ``raise all''.
  90.    Cannot be inline, since it uses `alloca', and that
  91.    breaks code which pushes the result of this function
  92.    on the stack.  */
  93. static tree
  94. exception_object_name (prefix, id)
  95.      tree prefix;
  96.      tree id;
  97. {
  98.   /* First, cons up the `name' of this exception.  */
  99.   char *name;
  100.   int length = (id == void_type_node ? 3 : IDENTIFIER_LENGTH (id)) + EXCEPTION_NAME_LENGTH;
  101.  
  102.   if (prefix)
  103.     length += IDENTIFIER_LENGTH (prefix) + 2;
  104.  
  105.   name = (char *)alloca (length);
  106.   strcpy (name, EXCEPTION_NAME_PREFIX);
  107.   length = EXCEPTION_NAME_LENGTH;
  108.   if (prefix)
  109.     {
  110.       strcpy (name + length, IDENTIFIER_POINTER (prefix));
  111.       name[length + IDENTIFIER_LENGTH (prefix)] = JOINER;
  112.       length += IDENTIFIER_LENGTH (prefix) + 1;
  113.     }
  114.   if (id == void_type_node)
  115.     strcpy (name + length, "all");
  116.   else
  117.     strcpy (name + length, IDENTIFIER_POINTER (id));
  118.   return get_identifier (name);
  119. }
  120.  
  121. tree
  122. lookup_exception_cname (ctype, cname, raise_id)
  123.      tree ctype, cname;
  124.      tree raise_id;
  125. {
  126.   tree this_cname = TREE_PURPOSE (raise_id);
  127.   if (this_cname == NULL_TREE)
  128.     {
  129.       if (cname)
  130.     {
  131.       tree name = TREE_VALUE (raise_id);
  132.       if (purpose_member (name, CLASSTYPE_TAGS (ctype)))
  133.         this_cname = cname;
  134.     }
  135.     }
  136.   else if (this_cname == void_type_node)
  137.     this_cname = NULL_TREE;
  138.   else if (TREE_CODE (this_cname) != IDENTIFIER_NODE)
  139.     {
  140.       sorry ("multiple scope refs in `expand_cplus_raise_stmt'");
  141.       this_cname = error_mark_node;
  142.     }
  143.   return this_cname;
  144. }
  145.  
  146. tree
  147. lookup_exception_tname (oname)
  148.      tree oname;
  149. {
  150.   return get_identifier (IDENTIFIER_POINTER (oname) + EXCEPTION_NAME_LENGTH);
  151. }
  152.  
  153. tree
  154. lookup_exception_object (cname, name, complain)
  155.      tree cname, name;
  156.      int complain;
  157. {
  158.   tree oname;
  159.   tree decl;
  160.  
  161.   if (cname == void_type_node)
  162.     cname = NULL_TREE;
  163.   else if (cname && TREE_CODE (cname) != IDENTIFIER_NODE)
  164.     {
  165.       sorry ("multiple scope refs in `lookup_exception_object'");
  166.       cname = NULL_TREE;
  167.     }
  168.   oname = exception_object_name (cname, name);
  169.   decl = IDENTIFIER_GLOBAL_VALUE (oname);
  170.   if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
  171.     {
  172.       if (complain)
  173.     {
  174.       int temp = allocation_temporary_p ();
  175.       if (cname)
  176.         error ("no exception name object for name `%s::%s'",
  177.            IDENTIFIER_POINTER (cname),
  178.            IDENTIFIER_POINTER (name));
  179.       else
  180.         error ("no exception name object for name `%s'",
  181.            IDENTIFIER_POINTER (name));
  182.       if (temp)
  183.         end_temporary_allocation ();
  184.       /* Avoid further error messages.  */
  185.       pushdecl_top_level (build_lang_field_decl (VAR_DECL,
  186.                              exception_object_name (cname, name),
  187.                              error_mark_node));
  188.       if (temp)
  189.         resume_temporary_allocation ();
  190.     }
  191.       return NULL_TREE;
  192.     }
  193.   return decl;
  194. }
  195.  
  196. tree
  197. lookup_exception_type (ctype, cname, raise_id)
  198.      tree ctype, cname;
  199.      tree raise_id;
  200. {
  201.   tree name = TREE_VALUE (raise_id);
  202.   tree purpose = TREE_PURPOSE (raise_id);
  203.  
  204.   if (cname && purpose == NULL_TREE)
  205.     purpose = cname;
  206.  
  207.   if (purpose && purpose != void_type_node)
  208.     {
  209.       tree assoc = NULL_TREE;
  210.  
  211.       if (TREE_CODE (purpose) != IDENTIFIER_NODE)
  212.     {
  213.       sorry ("multiple scope refs in `lookup_exception_type'");
  214.       TREE_PURPOSE (raise_id) = NULL_TREE;
  215.       return NULL_TREE;
  216.     }
  217.       if (! is_aggr_typedef (purpose, 1))
  218.     return NULL_TREE;
  219.       ctype = TREE_TYPE (TREE_TYPE (purpose));
  220.       assoc = purpose_member (name, CLASSTYPE_TAGS (ctype));
  221.       if (assoc)
  222.     return TREE_VALUE (assoc);
  223.     }
  224.  
  225.   ctype = lookup_name (name);
  226.   if (ctype && TREE_CODE (ctype) == TYPE_DECL)
  227.     ctype = TREE_TYPE (ctype);
  228.   if (ctype && TREE_CODE (ctype) == RECORD_TYPE
  229.       && CLASSTYPE_DECLARED_EXCEPTION (ctype))
  230.     return ctype;
  231.   return NULL_TREE;
  232. }
  233.  
  234. tree
  235. finish_exception (e, list_of_fieldlists)
  236.      tree e;
  237.      tree list_of_fieldlists;
  238. {
  239.   tree parmtypes = NULL_TREE, name_field;
  240.   tree cname = TYPE_NAME (e);
  241.  
  242.   if (TREE_CODE (cname) == TYPE_DECL)
  243.     cname = DECL_NAME (cname);
  244.  
  245.   if (last_exception_fields)
  246.     error ("cannot declare exceptions within exceptions");
  247.   if (list_of_fieldlists && ! ANON_AGGRNAME_P (cname))
  248.     error_with_aggr_type (e, "exception name `%s' must follow body declaration");
  249.   if (list_of_fieldlists)
  250.     {
  251.       tree prev, field;
  252.  
  253.       /* Note: no public, private, or protected allowed.  */
  254.       if (TREE_CHAIN (list_of_fieldlists))
  255.     error ("visibility declarations invalid in exception declaration");
  256.       else if (TREE_PURPOSE (list_of_fieldlists) != (tree)visibility_default)
  257.     error ("visibility declarations invalid in exception declaration");
  258.       TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_default;
  259.  
  260.       /* Note also: no member function declarations allowed.  */
  261.       for (prev = 0, field = TREE_VALUE (list_of_fieldlists);
  262.        field; prev = field, field = TREE_CHAIN (field))
  263.     {
  264.       switch (TREE_CODE (field))
  265.         {
  266.         case FIELD_DECL:
  267.           /* ok.  */
  268.           parmtypes = tree_cons (NULL_TREE, TREE_TYPE (field), parmtypes);
  269.           continue;
  270.         case FUNCTION_DECL:
  271.           error_with_decl (field, "declaration of function `%s' in exception invalid");
  272.           break;
  273.         case VAR_DECL:
  274.           if (TREE_STATIC (field))
  275.         error_with_decl (field, "declaration of static variable `%s' in exception invalid");
  276.           else
  277.         error_with_decl (field, "declaration of constant field `%s' in exception invalid");
  278.           break;
  279.         case CONST_DECL:
  280.           error_with_decl (field, "declaration of enum value `%s' in exception invalid");
  281.           break;
  282.         case SCOPE_REF:
  283.           error ("use of `::' in exception context invalid");
  284.           break;
  285.         }
  286.       if (prev)
  287.         TREE_CHAIN (prev) = TREE_CHAIN (field);
  288.       else
  289.         TREE_VALUE (list_of_fieldlists) = TREE_CHAIN (field);
  290.     }
  291.     }
  292.  
  293.   /* Now that we've cleaned up the fields, add a name identifier at front.  */
  294.   name_field = build_lang_field_decl (FIELD_DECL, get_identifier ("__name"),
  295.                       ptr_type_node);
  296.   if (list_of_fieldlists)
  297.     {
  298.       TREE_CHAIN (name_field) = TREE_VALUE (list_of_fieldlists);
  299.       TREE_VALUE (list_of_fieldlists) = name_field;
  300.     }
  301.   else
  302.     list_of_fieldlists = build_tree_list (NULL_TREE, name_field);
  303.  
  304.   last_exception_fields = TREE_VALUE (list_of_fieldlists);
  305.   if (parmtypes)
  306.     {
  307.       last_exception_field_types = nreverse (parmtypes);
  308.       /* Set the TREE_CHAIN of what is now at the end of the
  309.      list to `void_list_node'.  */
  310.       TREE_CHAIN (parmtypes) = void_list_node;
  311.     }
  312.   else
  313.     last_exception_field_types = void_list_node;
  314.  
  315.   popclass (0);
  316.  
  317. #if 0
  318.   /* Remove aggregate types from the list of tags,
  319.      since these appear at global scope.  */
  320.   while (x && IS_AGGR_TYPE (TREE_VALUE (x)))
  321.     x = TREE_CHAIN (x);
  322.   CLASSTYPE_TAGS (t) = x;
  323.   y = x;
  324.   while (x)
  325.     {
  326.       if (IS_AGGR_TYPE (TREE_VALUE (x)))
  327.     TREE_CHAIN (y) = TREE_CHAIN (x);
  328.       x = TREE_CHAIN (x);
  329.     }
  330. #endif
  331.  
  332.   return e;
  333. }
  334.  
  335. void
  336. finish_exception_decl (cname, decl)
  337.      tree cname, decl;
  338. {
  339.   /* In cplus-decl.h.  */
  340.   extern tree last_function_parms;
  341.  
  342.   /* An exception declaration.  */
  343.   tree t, ctor;
  344.   tree parmdecls = NULL_TREE, fields;
  345.   tree list_of_fieldlists = temp_tree_cons (NULL_TREE,
  346.                         copy_list (last_exception_fields),
  347.                         NULL_TREE);
  348.   tree edecl = build_lang_field_decl (VAR_DECL,
  349.                       exception_object_name (cname, DECL_NAME (decl)),
  350.                       ptr_type_node);
  351.  
  352.   DECL_LANGUAGE (edecl) = lang_c;
  353.   TREE_STATIC (edecl) = 1;
  354.   TREE_PUBLIC (edecl) = 1;
  355.   finish_decl (pushdecl (edecl), 0, 0);
  356.  
  357.   /* Now instantiate the exception decl.  */
  358.   t = xref_tag (exception_type_node, DECL_NAME (decl), NULL_TREE);
  359.  
  360.   /* finish_struct will pop this.  */
  361.   pushclass (t, 0);
  362.  
  363.   /* Now add a constructor which takes as parameters all the types we
  364.      just defined.  */
  365.   ctor = build_lang_decl (FUNCTION_DECL, DECL_NAME (decl),
  366.               build_cplus_method_type (t, TYPE_POINTER_TO (t),
  367.                            last_exception_field_types));
  368.   /* Don't take `name'.  The constructor handles that.  */
  369.   fields = TREE_CHAIN (TREE_VALUE (list_of_fieldlists));
  370.   while (fields)
  371.     {
  372.       tree parm = build_decl (PARM_DECL, DECL_NAME (fields), TREE_TYPE (fields));
  373.       /* Since there is a prototype, args are passed in their own types.  */
  374.       DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
  375. #ifdef PROMOTE_PROTOTYPES
  376.       if (TREE_CODE (TREE_TYPE (fields)) == INTEGER_TYPE
  377.       && TYPE_PRECISION (TREE_TYPE (fields)) < TYPE_PRECISION (integer_type_node))
  378.     DECL_ARG_TYPE (parm) = integer_type_node;
  379. #endif
  380.       TREE_CHAIN (parm) = parmdecls;
  381.       parmdecls = parm;
  382.       fields = TREE_CHAIN (fields);
  383.     }
  384.   fields = TREE_VALUE (list_of_fieldlists);
  385.   last_function_parms = nreverse (parmdecls);
  386.  
  387.   DECL_CONSTRUCTOR_P (ctor) = 1;
  388.   TYPE_HAS_CONSTRUCTOR (t) = 1;
  389.   grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, 0, NULL_TREE);
  390.   TREE_EXTERNAL (ctor) = 1;
  391.   TREE_STATIC (ctor) = 1;
  392.   TREE_PUBLIC (ctor) = 0;
  393.   TREE_INLINE (ctor) = 1;
  394.   make_decl_rtl (ctor, 0, 1);
  395.   finish_decl (ctor, NULL_TREE, 0);
  396.   TREE_CHAIN (ctor) = TREE_VALUE (list_of_fieldlists);
  397.   TREE_VALUE (list_of_fieldlists) = ctor;
  398.  
  399.   finish_struct (t, list_of_fieldlists, 0, 0);
  400.  
  401.   if (current_function_decl)
  402.     error ("cannot define exception inside function scope");
  403.   else
  404.     {
  405.       /* Now build the constructor for this exception.
  406.      Pretending that CTOR is not a constructor simplifies
  407.      things here.  */
  408.       DECL_CONSTRUCTOR_P (ctor) = 0;
  409.       parmdecls = DECL_ARGUMENTS (ctor);
  410.       start_function (NULL_TREE, ctor, 0, 1);
  411.       store_parm_decls ();
  412.       pushlevel (0);
  413.       clear_last_expr ();
  414.       push_momentary ();
  415.       expand_start_bindings (0);
  416.  
  417.       /* Move all the parameters to the fields, skipping `this'.  */
  418.       parmdecls = TREE_CHAIN (parmdecls);
  419.       /* Install `name' of this exception handler.  */
  420.       expand_assignment (build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields),
  421.              build_unary_op (ADDR_EXPR, edecl, 0), 0, 0);
  422.       fields = TREE_CHAIN (fields);
  423.       /* Install all the values.  */
  424.       while (fields)
  425.     {
  426.       expand_expr_stmt (build_modify_expr (build (COMPONENT_REF, TREE_TYPE (fields), C_C_D, fields),
  427.                            INIT_EXPR,
  428.                            parmdecls));
  429.       fields = TREE_CHAIN (fields);
  430.       parmdecls = TREE_CHAIN (parmdecls);
  431.     }
  432.       c_expand_return (current_class_decl);
  433.       expand_end_bindings (getdecls (), 1, 0);
  434.       poplevel (1, 0, 1);
  435.       pop_momentary ();
  436.  
  437.       finish_function (DECL_SOURCE_LINE (ctor), 0);
  438.       DECL_CONSTRUCTOR_P (ctor) = 1;
  439.     }
  440. }
  441.  
  442. void
  443. end_exception_decls ()
  444. {
  445.   last_exception_field_types = NULL_TREE;
  446.   last_exception_fields = NULL_TREE;
  447. }
  448.  
  449. /* Statement-level exception semantics.  */
  450.  
  451. void
  452. cplus_expand_start_try (implicit)
  453.      int implicit;
  454. {
  455.   tree call_to_setjmp;
  456.   tree handler, ref;
  457.  
  458.   /* Start a new block enclosing the whole handler.  */
  459.   if (implicit)
  460.     pushlevel_temporary (1);
  461.   else
  462.     {
  463.       pushlevel (0);
  464.       clear_last_expr ();
  465.       push_momentary ();
  466.  
  467.       /* Encompass whole exception handler in one big binding contour.
  468.      If RAISE should throw out of the whole TRY/EXCEPT block, call
  469.      `expand_start_bindings' with argument of 1.  */
  470.       expand_start_bindings (0);
  471.     }
  472.  
  473.   /* Allocate handler in that block.  It's real name will come later.
  474.      Note that it will be the first name in this binding contour.  */
  475.   handler = get_temp_name (EHS_type, 0);
  476.   DECL_INITIAL (handler) = error_mark_node;
  477.   finish_decl (handler, NULL_TREE, 0);
  478.  
  479.   /* Catch via `setjmp'.  */
  480.   ref = build_component_ref (handler, get_identifier ("handler"), NULL_TREE, 0);
  481.   call_to_setjmp = build_function_call (BISJ, build_tree_list (NULL_TREE, ref));
  482.  
  483.   /* RAISE throws to EXCEPT part.  */
  484.   expand_start_try (build_binary_op (EQ_EXPR, call_to_setjmp, integer_zero_node), 0, 1);
  485. }
  486.  
  487. /* If KEEP is 1, then declarations in the TRY statement are worth keeping.
  488.    If KEEP is 2, then the TRY statement was generated by the compiler.
  489.    If KEEP is 0, the declarations in the TRY statement contain errors.  */
  490.  
  491. tree
  492. cplus_expand_end_try (keep)
  493.      int keep;
  494. {
  495.   tree decls;
  496.   tree decl;
  497.  
  498.   if (keep < 2)
  499.     pop_implicit_try_blocks (NULL_TREE);
  500.  
  501.   decls = getdecls ();
  502.  
  503.   /* Emit code to avoid falling through into a default
  504.      handler that might come later.  */
  505.   expand_end_try ();
  506.  
  507.   /* Pops binding contour local to TRY, and get the exception handler
  508.      object built by `...start_try'.  */
  509.   switch (keep)
  510.     {
  511.     case 0:
  512.       expand_end_bindings (decls, 0, 1);
  513.       poplevel (0, 0, 0);
  514.       pop_momentary (); 
  515.       decl = getdecls ();
  516.       break;
  517.  
  518.     case 1:
  519.       expand_end_bindings (decls, decls != 0, 1);
  520.       poplevel (decls != 0, 1, 0);
  521.       pop_momentary ();
  522.       decl = getdecls ();
  523.       break;
  524.  
  525.     default:
  526.       decl = tree_last (decls);
  527.       break;
  528.     }
  529.  
  530.   assert (TREE_CODE (decl) == VAR_DECL && TREE_TYPE (decl) == EHS_type);
  531.  
  532.   /* Pass it back so that its rtl can be bound to its name
  533.      (or vice versa).  */
  534.   return decl;
  535. }
  536.  
  537. void
  538. cplus_expand_start_except (name, decl)
  539.      tree name, decl;
  540. {
  541.   int yes;
  542.   tree tmp;
  543.  
  544.   expand_start_except (0, 1);
  545.  
  546.   /* This is internal `eh'.  */
  547.   current_exception_decl = decl;
  548.   /* Get the exception object into scope (user declared `ex').  */
  549.   tmp = pushdecl (build_decl (VAR_DECL, name, ptr_type_node));
  550.   DECL_INITIAL (tmp) = error_mark_node;
  551.   finish_decl (tmp, build (COMPONENT_REF, ptr_type_node, decl, TREE_OPERAND (EHS_parms, 1)), 0);
  552.   current_exception_type = NULL_TREE;
  553.   yes = suspend_momentary ();
  554.   /* From now on, send the user to our faked-up object.  */
  555.   current_exception_object = build1 (INDIRECT_REF, void_type_node, tmp);
  556.   IDENTIFIER_LOCAL_VALUE (name) = current_exception_object;
  557.   resume_momentary (yes);
  558.  
  559.   /* Pop exception handler stack.  */
  560.   expand_assignment (EHS_decl, EHS_prev, 0, 0);
  561. }
  562.  
  563. /* Generate the call to `unhandled_exception' that is appropriate
  564.    for this particular unhandled exception.  */
  565. static tree
  566. call_to_unhandled_exception ()
  567. {
  568.   extern int lineno;
  569.   tree parms = tree_cons (NULL_TREE,
  570.               combine_strings (build_string (strlen (input_filename), input_filename)),
  571.               build_tree_list (NULL_TREE, build_int_2 (lineno, 0)));
  572.   return build_function_call (BIUE, parms);
  573. }
  574.  
  575. /* Note that this must be mirror image of `...start_try'.
  576.    DFAULT is the default clause, if there was one.
  577.    DFAULT is ERROR_MARK_NODE when this ends an implicit handler.  */
  578. void
  579. cplus_expand_end_except (dfault)
  580.      tree dfault;
  581. {
  582.   extern tree expand_end_except (); /* stmt.c.  */
  583.   tree decls, raised;
  584.  
  585.   if (dfault == NULL_TREE)
  586.     {
  587.       /* Uncaught exception at outermost level.  If raised locally,
  588.      reraise the exception.  Otherwise, generate code to call `abort'.  */
  589.       if (in_try_block (1) == 0)
  590.     {
  591.       expand_start_cond (build (EQ_EXPR, integer_type_node,
  592.                     exception_throw_decl, integer_zero_node), 0);
  593.       expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
  594.       expand_end_cond ();
  595.     }
  596.     }
  597.  
  598.   /* Try the next handler.  */
  599.   if (! expand_escape_except ())
  600.     compiler_error ("except nesting botch");
  601.  
  602.   raised = expand_end_except ();
  603.  
  604.   decls = getdecls ();
  605.   expand_end_bindings (decls, decls != 0, 1);
  606.   poplevel (decls != 0, 1, 0);
  607.  
  608.   /* Implicit handlers do not use the momentary obstack.  */
  609.   if (dfault != error_mark_node)
  610.     pop_momentary ();
  611.  
  612.   if (! in_try_block (1))
  613.     {
  614.       /* Check that this function is not raising exceptions
  615.      it is not supposed to.  */
  616.       while (raised)
  617.     {
  618.       error_with_decl (TREE_VALUE (raised), "exception `%s' raised but not declared raisable");
  619.       raised = TREE_CHAIN (raised);
  620.     }
  621.     }
  622.   else if (dfault == NULL_TREE || dfault == error_mark_node)
  623.     {
  624.       expand_start_cond (build (NE_EXPR, integer_type_node,
  625.                 exception_throw_decl,
  626.                 integer_zero_node), 0);
  627.       /* We fell off the end of this try block.  Try going to the next.
  628.      The escape_label will be the beginning of the next try block.  */
  629.       if (! expand_escape_except ())
  630.     compiler_error ("except nesting botch");
  631.       expand_end_cond ();
  632.     }
  633. }
  634.  
  635. /* Generate code to raise exception RAISE_ID.
  636.    If EXP is NULL_TREE, then PARMS is the list of parameters to use
  637.    for constructing this exception.
  638.    If EXP is non-NULL, then it is an already constructed object
  639.    of the kind that we want.  */
  640. void
  641. expand_cplus_raise (raise_id, parms, exp)
  642.      tree raise_id;
  643.      tree parms;
  644.      tree exp;
  645. {
  646.   /* Allocate new exception of appropriate type, passing
  647.      PARMS to its constructor.  */
  648.   tree cname, name;
  649.   tree decl;
  650.   tree xexp = exp;
  651.  
  652.   cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
  653.   if (cname == error_mark_node)
  654.     return;
  655.   name = TREE_VALUE (raise_id);
  656.  
  657.   decl = lookup_exception_object (cname, name, 1);
  658.   if (decl == NULL_TREE)
  659.     return;
  660.  
  661.   if (exp == NULL_TREE)
  662.     {
  663.       exp = build_method_call (NULL_TREE, name, parms, NULL_TREE, LOOKUP_COMPLAIN);
  664.       if (exp == error_mark_node)
  665.     return;
  666.     }
  667.  
  668.   if (in_try_block (1))
  669.     {
  670.       expand_raise (decl);
  671.     }
  672.   else if (! current_function_decl)
  673.     {
  674.       if (xexp == NULL_TREE)
  675.     error_with_decl (decl, "invalid raise of `%s' outside of functions");
  676.       else
  677.     error_with_decl (decl, "invalid reraise of `%s' outside of functions");
  678.     }
  679.   else
  680.     {
  681.       /* Test this raise against what this function permits.  */
  682.       tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
  683.       while (names)
  684.     {
  685.       if (decl == TREE_TYPE (names))
  686.         break;
  687.       names = TREE_CHAIN (names);
  688.     }
  689.       if (names == NULL_TREE)
  690.     {
  691.       error ("current function not declared to raise exception `%s'",
  692.          IDENTIFIER_POINTER (name));
  693.       return;
  694.     }
  695.     }
  696.  
  697.   expand_assignment (EHS_parms, exp, 0, 0);
  698.  
  699.   /* Set the global exception handler stack's NAME field
  700.      to the `name' of this exception.  The global exception
  701.      handler stack is the container for the exception object
  702.      we just built.  */
  703.   expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
  704.  
  705.   /* Activate thrower.  If we are inside a TRY statement,
  706.      we can cheat and not do this, saving a longjmp.  */
  707.   if (in_try_block (1) == 0)
  708.     {
  709.       sets_exception_throw_decl = 1;
  710.       expand_assignment (exception_throw_decl, integer_one_node, 0, 0);
  711.     }
  712.  
  713.   if (xexp == NULL_TREE)
  714.     {    
  715.       /* Invoke destructors for current procedure or handler.  */
  716.       if (! expand_escape_except ())
  717.     compiler_error ("except nesting botch");
  718.       /* Throw via `longjmp'... Done as side-effect of goto.  */
  719.     }
  720.   /* If we were re-raising, just let this fall through.
  721.      At the end of the reraises, the call to `expand_goto'
  722.      will take care of everybody.  */
  723. }
  724.  
  725. void
  726. expand_cplus_start_catch (raise_id)
  727.      tree raise_id;
  728. {
  729.   tree cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
  730.   tree decl;
  731.   tree ref, cond;
  732.  
  733.   if (cname == error_mark_node)
  734.     cond = error_mark_node;
  735.   else
  736.     {
  737.       decl = lookup_exception_object (cname, TREE_VALUE (raise_id), 1);
  738.       if (decl == NULL_TREE)
  739.     {
  740.       cond = error_mark_node;
  741.     }
  742.       else
  743.     {
  744.       ref = build (COMPONENT_REF, ptr_type_node,
  745.                current_exception_decl, TREE_OPERAND (EHS_name, 1));
  746.       cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0), ref);
  747.     }
  748.     }
  749.   expand_start_cond (cond, 0);
  750.   /* Does nothing right now.  */
  751.   expand_catch (decl);
  752.   if (current_exception_type
  753.       && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
  754.     {
  755.       /* Make a cleanup for the name-specific exception object now in scope.  */
  756.       tree cleanup = maybe_build_cleanup (current_exception_object);
  757.       expand_start_bindings (0);
  758.       expand_decl_cleanup (NULL_TREE, cleanup);
  759.     }
  760. }
  761.  
  762. void
  763. expand_cplus_end_catch (for_reraise)
  764.      int for_reraise;
  765. {
  766.   if (current_exception_type
  767.       && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
  768.     {
  769.       /* Destroy the specific exception object now in scope.  */
  770.       expand_end_bindings (getdecls (), 1, 1);
  771.     }
  772.   if (for_reraise)
  773.     {
  774.       if (! expand_escape_except ())
  775.     abort ();
  776.     }
  777.   else
  778.     {
  779.       if (! expand_end_catch ())
  780.     abort ();
  781.     }
  782.   expand_end_cond ();
  783. }
  784.  
  785. void
  786. expand_cplus_reraise (exceptions)
  787.      tree exceptions;
  788. {
  789.   tree current_exception_ptr;
  790.  
  791.   /* reraise ALL, used by compiler.  */
  792.   if (exceptions == NULL_TREE)
  793.     {
  794.       /* Now treat reraise like catch/raise.  */
  795.       expand_catch (error_mark_node);
  796.       expand_raise (error_mark_node);
  797.       expand_assignment (EHS_name,
  798.              build (COMPONENT_REF, ptr_type_node,
  799.                 current_exception_decl, TREE_OPERAND (EHS_name, 1)), 0, 0);
  800.       expand_assignment (EHS_parms,
  801.              build (COMPONENT_REF, ptr_type_node,
  802.                 current_exception_decl, TREE_OPERAND (EHS_parms, 1)), 0, 0);
  803.       if (in_try_block (1) == 0)
  804.     {
  805.       sets_exception_throw_decl = 1;
  806.       expand_assignment (exception_throw_decl, integer_one_node, 0, 0);
  807.     }
  808.       /* Set to zero so that destructor will not be called.  */
  809.       expand_assignment (build (NOP_EXPR, ptr_type_node,
  810.                 TREE_OPERAND (current_exception_object, 0)),
  811.              integer_zero_node, 0, 0);
  812.       if (! expand_escape_except ())
  813.     abort ();
  814.       return;
  815.     }
  816.  
  817.   current_exception_ptr = build (NOP_EXPR, NULL_TREE,
  818.                  TREE_OPERAND (current_exception_object, 0));
  819.  
  820.   /* reraise from a list of exceptions.  */
  821.   while (exceptions)
  822.     {
  823.       tree type = lookup_exception_type (current_class_type, current_class_name,
  824.                      exceptions);
  825.       if (type == NULL_TREE)
  826.     {
  827.       error ("`%s' is not an exception type",
  828.          IDENTIFIER_POINTER (TREE_VALUE (exceptions)));
  829.       current_exception_type = NULL_TREE;
  830.       TREE_TYPE (current_exception_object) = error_mark_node;
  831.       TREE_TYPE (current_exception_ptr) = error_mark_node;
  832.     }
  833.       else
  834.     {
  835.       current_exception_type = type;
  836.       /* In-place union.  */
  837.       TREE_TYPE (current_exception_object) = type;
  838.       TREE_TYPE (current_exception_ptr) = TYPE_POINTER_TO (type);
  839.     }
  840.  
  841.       /* Now treat reraise like catch/raise.  */
  842.       expand_cplus_start_catch (exceptions);
  843.       expand_cplus_raise (exceptions, NULL_TREE, current_exception_ptr);
  844.       /* Set to zero so that destructor will not be called.  */
  845.       if (TREE_TYPE (current_exception_ptr) != error_mark_node)
  846.     expand_assignment (current_exception_ptr, integer_zero_node, 0, 0);
  847.       expand_cplus_end_catch (1);
  848.       exceptions = TREE_CHAIN (exceptions);
  849.     }
  850.   /* Don't propagate any unhandled exceptions.  */
  851.   expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
  852. }
  853.  
  854. void
  855. setup_exception_throw_decl ()
  856. {
  857.   tree call_to_longjmp, parms;
  858.  
  859.   int old = suspend_momentary ();
  860.  
  861.   exception_throw_decl = build_decl (VAR_DECL, get_identifier (THROW_NAME), integer_type_node);
  862.   pushdecl (exception_throw_decl);
  863.   parms = tree_cons (NULL_TREE, EHS_handler,
  864.              build_tree_list (0, integer_one_node));
  865.   call_to_longjmp = build_function_call (BILJ, parms);
  866.  
  867.   expand_decl (exception_throw_decl);
  868.   expand_decl_cleanup (exception_throw_decl,
  869.                build (COND_EXPR, void_type_node,
  870.                   exception_throw_decl,
  871.                   call_to_longjmp, integer_zero_node));
  872.   DECL_INITIAL (exception_throw_decl) = integer_zero_node;
  873.   sets_exception_throw_decl = 0;
  874.   resume_momentary (old);
  875. }
  876.  
  877. void
  878. init_exception_processing ()
  879. {
  880.   extern tree unhandled_exception_fndecl;
  881.   tree cname = get_identifier ("ExceptionHandler");
  882.   tree field, chain;
  883.   tree ctor, dtor;
  884.   tree EHS_DECL;
  885.   tree jmp_buf_type = build_array_type (integer_type_node,
  886.                     build_index_type (build_int_2 (_JBLEN-1, 0)));
  887.   tree jmp_buf_arg_type = build_pointer_type (integer_type_node);
  888.  
  889.   tree parmtypes = hash_tree_chain (jmp_buf_arg_type, NULL_TREE);
  890.   tree setjmp_fndecl, longjmp_fndecl;
  891.  
  892.   EHS_type = xref_tag (record_type_node, cname, NULL_TREE);
  893.  
  894.   push_lang_context (lang_name_c);
  895.   setjmp_fndecl = define_function ("setjmp",
  896.                    build_function_type (integer_type_node,
  897.                             parmtypes),
  898.                    NOT_BUILT_IN, 0);
  899.   BISJ = default_conversion (setjmp_fndecl);
  900.   longjmp_fndecl = define_function ("longjmp",
  901.                     build_function_type (integer_type_node,
  902.                              hash_tree_chain (jmp_buf_arg_type,
  903.                                       hash_tree_chain (integer_type_node, NULL_TREE))),
  904.                     NOT_BUILT_IN, 0);
  905.   BILJ = default_conversion (longjmp_fndecl);
  906.   BIUE = default_conversion (unhandled_exception_fndecl);
  907.  
  908.   pop_lang_context ();
  909.  
  910.   /* finish_struct will pop this.  */
  911.   pushclass (EHS_type, 0);
  912.   field = build_lang_field_decl (FIELD_DECL, get_identifier ("parms"), ptr_type_node);
  913.   chain = field;
  914.   field = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
  915.                  build_pointer_type (default_function_type));
  916.   TREE_CHAIN (field) = chain;
  917.   chain = field;
  918.   field = build_lang_field_decl (FIELD_DECL, get_identifier ("handler"), jmp_buf_type);
  919.   TREE_CHAIN (field) = chain;
  920.   chain = field;
  921.   field = build_lang_field_decl (FIELD_DECL, get_identifier ("prev"),
  922.                  TYPE_POINTER_TO (EHS_type));
  923.   TREE_CHAIN (field) = chain;
  924.   chain = field;
  925.  
  926.   ctor = build_lang_decl (FUNCTION_DECL, cname,
  927.               build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
  928.   DECL_CONSTRUCTOR_P (ctor) = 1;
  929.   TREE_STATIC (ctor) = 1;
  930.   TREE_PUBLIC (ctor) = 1;
  931.   grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0, 0);
  932.   finish_decl (ctor, 0, 0);
  933.   TREE_CHAIN (ctor) = chain;
  934.   chain = ctor;
  935.   dtor = build_lang_decl (FUNCTION_DECL, cname,
  936.               build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
  937.   TREE_STATIC (dtor) = 1;
  938.   TREE_PUBLIC (dtor) = 1;
  939.   grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0, 0);
  940.   finish_decl (dtor, 0, 0);
  941.   TREE_CHAIN (dtor) = chain;
  942.   chain = dtor;
  943.   TYPE_HAS_CONSTRUCTOR (EHS_type) = 1;
  944.   TYPE_HAS_DESTRUCTOR (EHS_type) = 1;
  945.   finish_struct (EHS_type, temp_tree_cons (NULL_TREE, chain, NULL_TREE), 0, 0);
  946.   EHS_decl = build_decl (VAR_DECL, get_identifier ("exceptionHandlerStack"),
  947.              TYPE_POINTER_TO (EHS_type));
  948.   /* If we don't push this, its definition, should it be encountered,
  949.      will not be seen.  */
  950.   EHS_decl = pushdecl (EHS_decl);
  951.   EHS_DECL = build1 (INDIRECT_REF, EHS_type, EHS_decl);
  952.   TREE_EXTERNAL (EHS_decl) = 1;
  953.   TREE_STATIC (EHS_decl) = 1;
  954.   TREE_PUBLIC (EHS_decl) = 1;
  955.   finish_decl (EHS_decl, 0, 0);
  956.   EHS_prev = build_component_ref (EHS_DECL, get_identifier ("prev"), 0, 0);
  957.   EHS_handler = build_component_ref (EHS_DECL, get_identifier ("handler"), 0, 0);
  958.   EHS_parms = build_component_ref (EHS_DECL, get_identifier ("parms"), 0, 0);
  959.   EHS_name = build_component_ref (EHS_DECL, get_identifier ("name"), 0, 0);
  960. }
  961.