Annotation of GNUtools/cc/cp-except.c, revision 1.1

1.1     ! root        1: /* Handle exceptional things in C++.
        !             2:    Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc.
        !             3:    Contributed by Michael Tiemann ([email protected])
        !             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 2, 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: #include "config.h"
        !            25: #include "tree.h"
        !            26: #include "rtl.h"
        !            27: #include "cp-tree.h"
        !            28: #include "flags.h"
        !            29: /* On Suns this can get you to the right definition if you
        !            30:    set the right value for TARGET.  */
        !            31: #include <setjmp.h>
        !            32: #ifdef sequent
        !            33: /* Can you believe they forgot this?  */
        !            34: #define _JBLEN 11
        !            35: #endif
        !            36: 
        !            37: #ifndef _JBLEN
        !            38: #define _JBLEN (sizeof(jmp_buf)/sizeof(int))
        !            39: #endif
        !            40: 
        !            41: #undef NULL
        !            42: #define NULL (char *)0
        !            43: 
        !            44: /* This should be part of `ansi_opname', or at least be defined by the std.  */
        !            45: #define EXCEPTION_NAME_PREFIX "__ex"
        !            46: #define EXCEPTION_NAME_LENGTH 4
        !            47: 
        !            48: void init_exception_processing ();
        !            49: void init_exception_processing_1 ();
        !            50: 
        !            51: /* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
        !            52:    next exception handler.  Its value says whether to throw or not.
        !            53:    In the case of functions which do not issue a RAISE, it should be
        !            54:    possible to optimize away this VAR_DECL (and overhead associated
        !            55:    with it).  */
        !            56: tree exception_throw_decl;
        !            57: /* Use this to know that we did not set `exception_throw_decl',
        !            58:    until GCC optimizer is smart enough to figure it out for itself.  */
        !            59: int sets_exception_throw_decl;
        !            60: 
        !            61: /* The exception `type' currently in scope, or NULL_TREE if none.  */
        !            62: tree current_exception_type;
        !            63: 
        !            64: /* The exception handler object for the given scope.  */
        !            65: tree current_exception_decl;
        !            66: rtx current_exception_name_as_rtx;
        !            67: rtx current_exception_parms_as_rtx;
        !            68: 
        !            69: /* The ``object'' view of the current exception parameters.
        !            70:    We cast up from the `parms' field to `current_exception_type'.  */
        !            71: tree current_exception_object;
        !            72: 
        !            73: /* Cache `setjmp', `longjmp', `raise_exception', and `unhandled_exception'
        !            74:    after default conversion.  Maybe later they will get built-in.  */
        !            75: static tree BISJ, BILJ, BIR, BIUE;
        !            76: 
        !            77: /* Local variables which give the appearance that exception
        !            78:    handling is part of the language and the execution model.  */
        !            79: 
        !            80: /* The type of the exception handler stack.  */
        !            81: tree EHS_type;
        !            82: 
        !            83: /* The global handler stack.  */
        !            84: tree EHS_decl;
        !            85: 
        !            86: /* Cached component refs to fields of `EHS_decl'.  */
        !            87: static tree EHS_prev, EHS_handler, EHS_parms, EHS_name;
        !            88: static rtx EHS_parms_as_rtx, EHS_name_as_rtx;
        !            89: 
        !            90: /* The parameter names of this exception type.  */
        !            91: 
        !            92: static tree last_exception_fields;
        !            93: static tree last_exception_field_types;
        !            94: 
        !            95: /* When ID is VOID_TYPE_NODE, it means ``raise all''.
        !            96:    Cannot be inline, since it uses `alloca', and that
        !            97:    breaks code which pushes the result of this function
        !            98:    on the stack.  */
        !            99: static tree
        !           100: exception_object_name (prefix, id)
        !           101:      tree prefix;
        !           102:      tree id;
        !           103: {
        !           104:   /* First, cons up the `name' of this exception.  */
        !           105:   char *name;
        !           106:   int length = (id == void_type_node ? 3 : IDENTIFIER_LENGTH (id)) + EXCEPTION_NAME_LENGTH;
        !           107: 
        !           108:   if (prefix)
        !           109:     length += IDENTIFIER_LENGTH (prefix) + 2;
        !           110: 
        !           111:   name = (char *)alloca (length);
        !           112:   strcpy (name, EXCEPTION_NAME_PREFIX);
        !           113:   length = EXCEPTION_NAME_LENGTH;
        !           114:   if (prefix)
        !           115:     {
        !           116:       strcpy (name + length, IDENTIFIER_POINTER (prefix));
        !           117: #ifdef JOINER
        !           118:       name[length + IDENTIFIER_LENGTH (prefix)] = JOINER;
        !           119: #else
        !           120:       name[length + IDENTIFIER_LENGTH (prefix)] = '_';
        !           121: #endif
        !           122:       length += IDENTIFIER_LENGTH (prefix) + 1;
        !           123:     }
        !           124:   if (id == void_type_node)
        !           125:     strcpy (name + length, "all");
        !           126:   else
        !           127:     strcpy (name + length, IDENTIFIER_POINTER (id));
        !           128:   return get_identifier (name);
        !           129: }
        !           130: 
        !           131: tree
        !           132: lookup_exception_cname (ctype, cname, raise_id)
        !           133:      tree ctype, cname;
        !           134:      tree raise_id;
        !           135: {
        !           136:   tree this_cname = TREE_PURPOSE (raise_id);
        !           137:   if (this_cname == NULL_TREE)
        !           138:     {
        !           139:       if (cname)
        !           140:        {
        !           141:          tree name = TREE_VALUE (raise_id);
        !           142:          if (purpose_member (name, CLASSTYPE_TAGS (ctype)))
        !           143:            this_cname = cname;
        !           144:        }
        !           145:     }
        !           146:   else if (this_cname == void_type_node)
        !           147:     this_cname = NULL_TREE;
        !           148:   else if (TREE_CODE (this_cname) != IDENTIFIER_NODE)
        !           149:     {
        !           150:       sorry ("multiple scope refs in `cplus_expand_raise_stmt'");
        !           151:       this_cname = error_mark_node;
        !           152:     }
        !           153:   return this_cname;
        !           154: }
        !           155: 
        !           156: tree
        !           157: lookup_exception_tname (oname)
        !           158:      tree oname;
        !           159: {
        !           160:   return get_identifier (IDENTIFIER_POINTER (oname) + EXCEPTION_NAME_LENGTH);
        !           161: }
        !           162: 
        !           163: tree
        !           164: lookup_exception_object (cname, name, complain)
        !           165:      tree cname, name;
        !           166:      int complain;
        !           167: {
        !           168:   tree oname;
        !           169:   tree decl;
        !           170: 
        !           171:   if (cname == void_type_node)
        !           172:     cname = NULL_TREE;
        !           173:   else if (cname && TREE_CODE (cname) != IDENTIFIER_NODE)
        !           174:     {
        !           175:       sorry ("multiple scope refs in `lookup_exception_object'");
        !           176:       cname = NULL_TREE;
        !           177:     }
        !           178:   oname = exception_object_name (cname, name);
        !           179:   decl = IDENTIFIER_GLOBAL_VALUE (oname);
        !           180:   if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
        !           181:     {
        !           182:       if (complain)
        !           183:        {
        !           184:          push_obstacks_nochange ();
        !           185: 
        !           186:          if (cname)
        !           187:            error ("no exception name object for name `%s::%s'",
        !           188:                   IDENTIFIER_POINTER (cname),
        !           189:                   IDENTIFIER_POINTER (name));
        !           190:          else
        !           191:            error ("no exception name object for name `%s'",
        !           192:                   IDENTIFIER_POINTER (name));
        !           193:          end_temporary_allocation ();
        !           194:          /* Avoid further error messages.  */
        !           195:          pushdecl_top_level (build_lang_field_decl (VAR_DECL,
        !           196:                                                     exception_object_name (cname, name),
        !           197:                                                     error_mark_node));
        !           198:          pop_obstacks ();
        !           199:        }
        !           200:       return NULL_TREE;
        !           201:     }
        !           202:   return decl;
        !           203: }
        !           204: 
        !           205: tree
        !           206: lookup_exception_type (ctype, cname, raise_id)
        !           207:      tree ctype, cname;
        !           208:      tree raise_id;
        !           209: {
        !           210:   tree name = TREE_VALUE (raise_id);
        !           211:   tree purpose = TREE_PURPOSE (raise_id);
        !           212: 
        !           213:   if (cname && purpose == NULL_TREE)
        !           214:     purpose = cname;
        !           215: 
        !           216:   if (purpose && purpose != void_type_node)
        !           217:     {
        !           218:       tree link = NULL_TREE;
        !           219: 
        !           220:       if (TREE_CODE (purpose) != IDENTIFIER_NODE)
        !           221:        {
        !           222:          sorry ("multiple scope refs in `lookup_exception_type'");
        !           223:          TREE_PURPOSE (raise_id) = NULL_TREE;
        !           224:          return NULL_TREE;
        !           225:        }
        !           226:       if (! is_aggr_typedef (purpose, 1))
        !           227:        return NULL_TREE;
        !           228:       ctype = IDENTIFIER_TYPE_VALUE (purpose);
        !           229:       link = purpose_member (name, CLASSTYPE_TAGS (ctype));
        !           230:       if (link)
        !           231:        return TREE_VALUE (link);
        !           232:     }
        !           233: 
        !           234:   ctype = lookup_name (name, 1);
        !           235:   if (ctype && TREE_CODE (ctype) == TYPE_DECL)
        !           236:     ctype = TREE_TYPE (ctype);
        !           237:   if (ctype && TREE_CODE (ctype) == RECORD_TYPE
        !           238:       && CLASSTYPE_DECLARED_EXCEPTION (ctype))
        !           239:     return ctype;
        !           240:   return NULL_TREE;
        !           241: }
        !           242: 
        !           243: tree
        !           244: finish_exception (e, list_of_fieldlists)
        !           245:      tree e;
        !           246:      tree list_of_fieldlists;
        !           247: {
        !           248:   tree parmtypes = NULL_TREE, name_field;
        !           249:   tree cname = TYPE_NAME (e);
        !           250: 
        !           251:   if (TREE_CODE (cname) == TYPE_DECL)
        !           252:     cname = DECL_NAME (cname);
        !           253: 
        !           254:   if (last_exception_fields)
        !           255:     error ("cannot declare exceptions within exceptions");
        !           256:   if (list_of_fieldlists && ! ANON_AGGRNAME_P (cname))
        !           257:     cp_error ("exception name `%T' must follow body declaration", e);
        !           258:   if (list_of_fieldlists)
        !           259:     {
        !           260:       tree prev, field;
        !           261: 
        !           262:       /* Note: no public, private, or protected allowed.  */
        !           263:       if (TREE_CHAIN (list_of_fieldlists))
        !           264:        error ("visibility declarations invalid in exception declaration");
        !           265:       else if (TREE_PURPOSE (list_of_fieldlists) != (tree)visibility_default)
        !           266:        error ("visibility declarations invalid in exception declaration");
        !           267:       TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_default;
        !           268: 
        !           269:       /* Note also: no member function declarations allowed.  */
        !           270:       for (prev = 0, field = TREE_VALUE (list_of_fieldlists);
        !           271:           field; prev = field, field = TREE_CHAIN (field))
        !           272:        {
        !           273:          switch (TREE_CODE (field))
        !           274:            {
        !           275:            case FIELD_DECL:
        !           276:              /* ok.  */
        !           277:              parmtypes = tree_cons (NULL_TREE, TREE_TYPE (field), parmtypes);
        !           278:              continue;
        !           279:            case FUNCTION_DECL:
        !           280:              cp_error ("declaration of function `%D' in exception invalid",
        !           281:                          field);
        !           282:              break;
        !           283:            case VAR_DECL:
        !           284:              if (TREE_STATIC (field))
        !           285:                cp_error ("declaration of static variable `%D' in exception invalid", field);
        !           286:              else
        !           287:                cp_error ("declaration of constant field `%D' in exception invalid", field);
        !           288:              break;
        !           289:            case CONST_DECL:
        !           290:              cp_error ("declaration of enum value `%D' in exception invalid", field);
        !           291:              break;
        !           292:            case SCOPE_REF:
        !           293:              error ("use of `::' in exception context invalid");
        !           294:              break;
        !           295:            }
        !           296:          if (prev)
        !           297:            TREE_CHAIN (prev) = TREE_CHAIN (field);
        !           298:          else
        !           299:            TREE_VALUE (list_of_fieldlists) = TREE_CHAIN (field);
        !           300:        }
        !           301:     }
        !           302: 
        !           303:   /* Now that we've cleaned up the fields, add a name identifier at front.  */
        !           304:   name_field = build_lang_field_decl (FIELD_DECL, get_identifier ("__name"),
        !           305:                                      ptr_type_node);
        !           306:   if (list_of_fieldlists)
        !           307:     {
        !           308:       TREE_CHAIN (name_field) = TREE_VALUE (list_of_fieldlists);
        !           309:       TREE_VALUE (list_of_fieldlists) = name_field;
        !           310:     }
        !           311:   else
        !           312:     list_of_fieldlists = build_tree_list (NULL_TREE, name_field);
        !           313: 
        !           314:   last_exception_fields = TREE_VALUE (list_of_fieldlists);
        !           315:   if (parmtypes)
        !           316:     {
        !           317:       last_exception_field_types = nreverse (parmtypes);
        !           318:       /* Set the TREE_CHAIN of what is now at the end of the
        !           319:         list to `void_list_node'.  */
        !           320:       TREE_CHAIN (parmtypes) = void_list_node;
        !           321:     }
        !           322:   else
        !           323:     last_exception_field_types = void_list_node;
        !           324: 
        !           325:   popclass (0);
        !           326: 
        !           327: #if 0
        !           328:   /* Remove aggregate types from the list of tags,
        !           329:      since these appear at global scope.  */
        !           330:   while (x && IS_AGGR_TYPE (TREE_VALUE (x)))
        !           331:     x = TREE_CHAIN (x);
        !           332:   CLASSTYPE_TAGS (t) = x;
        !           333:   y = x;
        !           334:   while (x)
        !           335:     {
        !           336:       if (IS_AGGR_TYPE (TREE_VALUE (x)))
        !           337:        TREE_CHAIN (y) = TREE_CHAIN (x);
        !           338:       x = TREE_CHAIN (x);
        !           339:     }
        !           340: #endif
        !           341: 
        !           342:   if (flag_cadillac)
        !           343:     cadillac_finish_exception (e);
        !           344: 
        !           345:   return e;
        !           346: }
        !           347: 
        !           348: void
        !           349: finish_exception_decl (cname, decl)
        !           350:      tree cname, decl;
        !           351: {
        !           352:   /* In cp-decl.h.  */
        !           353:   extern tree last_function_parms;
        !           354: 
        !           355:   /* An exception declaration.  */
        !           356:   tree t, ctor;
        !           357:   tree parmdecls = NULL_TREE, fields;
        !           358:   tree list_of_fieldlists = temp_tree_cons (NULL_TREE,
        !           359:                                            copy_list (last_exception_fields),
        !           360:                                            NULL_TREE);
        !           361:   tree edecl = build_lang_field_decl (VAR_DECL,
        !           362:                                      exception_object_name (cname, DECL_NAME (decl)),
        !           363:                                      ptr_type_node);
        !           364: 
        !           365:   DECL_LANGUAGE (edecl) = lang_c;
        !           366:   TREE_STATIC (edecl) = 1;
        !           367:   TREE_PUBLIC (edecl) = 1;
        !           368:   finish_decl (pushdecl (edecl), NULL_TREE, NULL_TREE, 0);
        !           369: 
        !           370:   /* Now instantiate the exception decl.  */
        !           371:   t = xref_tag (exception_type_node, DECL_NAME (decl), NULL_TREE);
        !           372: 
        !           373:   /* finish_struct will pop this.  */
        !           374:   pushclass (t, 0);
        !           375: 
        !           376:   /* Now add a constructor which takes as parameters all the types we
        !           377:      just defined.  */
        !           378:   ctor = build_lang_decl (FUNCTION_DECL, DECL_NAME (decl),
        !           379:                          build_cplus_method_type (t, TYPE_POINTER_TO (t),
        !           380:                                                   last_exception_field_types));
        !           381:   /* Don't take `name'.  The constructor handles that.  */
        !           382:   fields = TREE_CHAIN (TREE_VALUE (list_of_fieldlists));
        !           383:   while (fields)
        !           384:     {
        !           385:       tree parm = build_decl (PARM_DECL, DECL_NAME (fields), TREE_TYPE (fields));
        !           386:       /* Since there is a prototype, args are passed in their own types.  */
        !           387:       DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
        !           388: #ifdef PROMOTE_PROTOTYPES
        !           389:       if ((TREE_CODE (TREE_TYPE (fields)) == INTEGER_TYPE
        !           390:           || TREE_CODE (TREE_TYPE (fields)) == ENUMERAL_TYPE)
        !           391:          && TYPE_PRECISION (TREE_TYPE (fields)) < TYPE_PRECISION (integer_type_node))
        !           392:        DECL_ARG_TYPE (parm) = integer_type_node;
        !           393: #endif
        !           394:       TREE_CHAIN (parm) = parmdecls;
        !           395:       parmdecls = parm;
        !           396:       fields = TREE_CHAIN (fields);
        !           397:     }
        !           398:   fields = TREE_VALUE (list_of_fieldlists);
        !           399:   last_function_parms = nreverse (parmdecls);
        !           400: 
        !           401:   DECL_CONSTRUCTOR_P (ctor) = 1;
        !           402:   TYPE_HAS_CONSTRUCTOR (t) = 1;
        !           403:   grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, NULL_TREE);
        !           404:   DECL_EXTERNAL (ctor) = 1;
        !           405:   TREE_STATIC (ctor) = 1;
        !           406:   TREE_PUBLIC (ctor) = 0;
        !           407:   DECL_INLINE (ctor) = 1;
        !           408:   make_decl_rtl (ctor, NULL_PTR, 1);
        !           409:   finish_decl (ctor, NULL_TREE, NULL_TREE, 0);
        !           410:   TREE_CHAIN (ctor) = TREE_VALUE (list_of_fieldlists);
        !           411:   TREE_VALUE (list_of_fieldlists) = ctor;
        !           412: 
        !           413:   finish_struct (t, list_of_fieldlists, 0);
        !           414: 
        !           415:   if (current_function_decl)
        !           416:     error ("cannot define exception inside function scope");
        !           417:   else
        !           418:     {
        !           419:       enum debug_info_type old_write_symbols = write_symbols;
        !           420:       write_symbols = NO_DEBUG;
        !           421: 
        !           422:       /* Now build the constructor for this exception.  */
        !           423:       parmdecls = DECL_ARGUMENTS (ctor);
        !           424:       start_function (NULL_TREE, ctor, 0, 1);
        !           425:       store_parm_decls ();
        !           426:       pushlevel (0);
        !           427:       clear_last_expr ();
        !           428:       push_momentary ();
        !           429:       expand_start_bindings (0);
        !           430: 
        !           431:       /* Move all the parameters to the fields, skipping `this'.  */
        !           432:       parmdecls = TREE_CHAIN (parmdecls);
        !           433:       /* Install `name' of this exception handler.  */
        !           434:       DECL_INITIAL (fields) = build_unary_op (ADDR_EXPR, edecl, 0);
        !           435:       fields = TREE_CHAIN (fields);
        !           436:       /* Install all the values.  */
        !           437:       while (fields)
        !           438:        {
        !           439:          /* Set up the initialization for this field.  */
        !           440:          DECL_INITIAL (fields) = parmdecls;
        !           441:          fields = TREE_CHAIN (fields);
        !           442:          parmdecls = TREE_CHAIN (parmdecls);
        !           443:        }
        !           444:       emit_base_init (t, 0);
        !           445: 
        !           446:       finish_function (DECL_SOURCE_LINE (ctor), 1);
        !           447:       write_symbols = old_write_symbols;
        !           448:     }
        !           449: }
        !           450: 
        !           451: void
        !           452: end_exception_decls ()
        !           453: {
        !           454:   last_exception_field_types = NULL_TREE;
        !           455:   last_exception_fields = NULL_TREE;
        !           456: }
        !           457: 
        !           458: /* Statement-level exception semantics.  */
        !           459: 
        !           460: void
        !           461: cplus_expand_start_try (implicit)
        !           462:      int implicit;
        !           463: {
        !           464:   tree call_to_setjmp;
        !           465:   tree handler, ref;
        !           466: 
        !           467:   /* Start a new block enclosing the whole handler.  */
        !           468:   if (implicit)
        !           469:     {
        !           470:       pushlevel_temporary (1);
        !           471:     }
        !           472:   else
        !           473:     {
        !           474:       pushlevel (0);
        !           475:       clear_last_expr ();
        !           476:       push_momentary ();
        !           477: 
        !           478:       /* Encompass whole exception handler in one big binding contour.
        !           479:         If RAISE should throw out of the whole TRY/EXCEPT block, call
        !           480:         `expand_start_bindings' with argument of 1.  */
        !           481:       expand_start_bindings (0);
        !           482:     }
        !           483: 
        !           484:   /* Allocate handler in that block.  It's real name will come later.
        !           485:      Note that it will be the first name in this binding contour.  */
        !           486:   handler = get_temp_name (EHS_type, 0);
        !           487:   DECL_INITIAL (handler) = error_mark_node;
        !           488:   finish_decl (handler, NULL_TREE, NULL_TREE, 0);
        !           489: 
        !           490:   /* Must come after call to `finish_decl', else the cleanup for the temp
        !           491:      for the handler will cause the contour we just created to be popped.  */
        !           492:   if (implicit)
        !           493:     declare_implicit_exception ();
        !           494: 
        !           495:   /* Catch via `setjmp'.  */
        !           496:   ref = build_component_ref (handler, get_identifier ("handler"), NULL_TREE, 0);
        !           497:   call_to_setjmp = build_function_call (BISJ, build_tree_list (NULL_TREE, ref));
        !           498: 
        !           499:   /* RAISE throws to EXCEPT part.  */
        !           500:   expand_start_try (build_binary_op (EQ_EXPR, call_to_setjmp, integer_zero_node, 1), 0, 1);
        !           501: }
        !           502: 
        !           503: /* If KEEP is 1, then declarations in the TRY statement are worth keeping.
        !           504:    If KEEP is 2, then the TRY statement was generated by the compiler.
        !           505:    If KEEP is 0, the declarations in the TRY statement contain errors.  */
        !           506: 
        !           507: tree
        !           508: cplus_expand_end_try (keep)
        !           509:      int keep;
        !           510: {
        !           511:   tree decls, decl, block;
        !           512: 
        !           513:   if (keep < 2)
        !           514:     pop_implicit_try_blocks (NULL_TREE);
        !           515: 
        !           516:   decls = getdecls ();
        !           517: 
        !           518:   /* Emit code to avoid falling through into a default
        !           519:      handler that might come later.  */
        !           520:   expand_end_try ();
        !           521: 
        !           522:   /* Pops binding contour local to TRY, and get the exception handler
        !           523:      object built by `...start_try'.  */
        !           524:   switch (keep)
        !           525:     {
        !           526:     case 0:
        !           527:       expand_end_bindings (decls, 0, 1);
        !           528:       block = poplevel (0, 0, 0);
        !           529:       pop_momentary (); 
        !           530:       decl = getdecls ();
        !           531:       break;
        !           532: 
        !           533:     case 1:
        !           534:       expand_end_bindings (decls, 1, 1);
        !           535:       block = poplevel (1, 1, 0);
        !           536:       pop_momentary ();
        !           537:       decl = getdecls ();
        !           538:       break;
        !           539: 
        !           540:     default:
        !           541:       decl = tree_last (decls);
        !           542:       block = NULL_TREE;
        !           543:       break;
        !           544:     }
        !           545: 
        !           546:   my_friendly_assert (TREE_CODE (decl) == VAR_DECL
        !           547:                      && TREE_TYPE (decl) == EHS_type, 203);
        !           548:   if (block)
        !           549:     {
        !           550:       BLOCK_HANDLER_BLOCK (block) = 1;
        !           551:       TREE_USED (block) = 1;
        !           552:     }
        !           553: 
        !           554:   /* Pass it back so that its rtl can be bound to its name
        !           555:      (or vice versa).  */
        !           556:   return decl;
        !           557: }
        !           558: 
        !           559: void
        !           560: cplus_expand_start_except (name, decl)
        !           561:      tree name, decl;
        !           562: {
        !           563:   int yes;
        !           564:   tree tmp, init;
        !           565: 
        !           566:   expand_start_except (0, 1);
        !           567: 
        !           568:   /* This is internal `eh'.  */
        !           569:   current_exception_decl = decl;
        !           570:   current_exception_name_as_rtx
        !           571:     = expand_expr (build (COMPONENT_REF, ptr_type_node,
        !           572:                          current_exception_decl, TREE_OPERAND (EHS_name, 1)),
        !           573:                   0, 0, 0);
        !           574:   init = build (COMPONENT_REF, ptr_type_node, decl, TREE_OPERAND (EHS_parms, 1));
        !           575:   current_exception_parms_as_rtx = expand_expr (init, 0, 0, 0);
        !           576: 
        !           577:   if (name)
        !           578:     {
        !           579:       /* Get the exception object into scope (user declared `ex').  */
        !           580:       tmp = pushdecl (build_decl (VAR_DECL, name, ptr_type_node));
        !           581:       DECL_INITIAL (tmp) = error_mark_node;
        !           582:       finish_decl (tmp, init, 0, 0);
        !           583:     }
        !           584:   current_exception_type = NULL_TREE;
        !           585:   yes = suspend_momentary ();
        !           586:   if (name)
        !           587:     {
        !           588:       /* From now on, send the user to our faked-up object.  */
        !           589:       current_exception_object = build1 (INDIRECT_REF, void_type_node, tmp);
        !           590:       IDENTIFIER_LOCAL_VALUE (name) = current_exception_object;
        !           591:     }
        !           592:   resume_momentary (yes);
        !           593: 
        !           594:   /* Pop exception handler stack.  */
        !           595:   expand_assignment (EHS_decl, EHS_prev, 0, 0);
        !           596: }
        !           597: 
        !           598: /* Generate the call to `unhandled_exception' that is appropriate
        !           599:    for this particular unhandled exception.  */
        !           600: static tree
        !           601: call_to_unhandled_exception ()
        !           602: {
        !           603:   extern int lineno;
        !           604:   extern tree combine_strings ();
        !           605:   tree parms = tree_cons (NULL_TREE,
        !           606:                          combine_strings (build_string (strlen (input_filename + 1), input_filename)),
        !           607:                          build_tree_list (NULL_TREE, build_int_2 (lineno, 0)));
        !           608:   return build_function_call (BIUE, parms);
        !           609: }
        !           610: 
        !           611: /* Note that this must be mirror image of `...start_try'.
        !           612:    DFAULT is the default clause, if there was one.
        !           613:    DFAULT is ERROR_MARK_NODE when this ends an implicit handler.  */
        !           614: void
        !           615: cplus_expand_end_except (dfault)
        !           616:      tree dfault;
        !           617: {
        !           618:   extern tree expand_end_except (); /* stmt.c.  */
        !           619:   tree decls, raised;
        !           620: 
        !           621:   if (dfault == NULL_TREE)
        !           622:     {
        !           623:       /* Uncaught exception at outermost level.  If raised locally,
        !           624:         reraise the exception.  Otherwise, generate code to call `abort'.  */
        !           625:       if (in_try_block (1) == 0)
        !           626:        {
        !           627:          expand_start_cond (build (EQ_EXPR, integer_type_node,
        !           628:                                    exception_throw_decl, integer_zero_node), 0);
        !           629:          expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
        !           630:          expand_end_cond ();
        !           631:        }
        !           632:       /* Try the next handler.  */
        !           633:       if (! expand_escape_except ())
        !           634:        compiler_error ("except nesting botch");
        !           635:     }
        !           636: 
        !           637:   raised = expand_end_except ();
        !           638: 
        !           639:   decls = getdecls ();
        !           640:   expand_end_bindings (decls, decls != 0, 1);
        !           641:   poplevel (decls != 0, 1, 0);
        !           642: 
        !           643:   /* Implicit handlers do not use the momentary obstack.  */
        !           644:   if (dfault != error_mark_node)
        !           645:     pop_momentary ();
        !           646: 
        !           647:   if (! in_try_block (1))
        !           648:     {
        !           649:       /* Check that this function is not raising exceptions
        !           650:         it is not supposed to.  */
        !           651:       while (raised)
        !           652:        {
        !           653:          cp_error ("exception `%D' raised but not declared raisable",
        !           654:                      TREE_VALUE (raised));
        !           655:          raised = TREE_CHAIN (raised);
        !           656:        }
        !           657:     }
        !           658:   else if (dfault == NULL_TREE || dfault == error_mark_node)
        !           659:     {
        !           660:       expand_start_cond (build (NE_EXPR, integer_type_node,
        !           661:                                exception_throw_decl,
        !           662:                                integer_zero_node), 0);
        !           663:       /* We fell off the end of this try block.  Try going to the next.
        !           664:         The escape_label will be the beginning of the next try block.  */
        !           665:       if (! expand_escape_except ())
        !           666:        compiler_error ("except nesting botch");
        !           667:       expand_end_cond ();
        !           668:     }
        !           669: }
        !           670: 
        !           671: /* Generate code to raise exception RAISE_ID.
        !           672:    If EXP is NULL_TREE, then PARMS is the list of parameters to use
        !           673:    for constructing this exception.
        !           674:    If EXP is non-NULL, then it is an already constructed object
        !           675:    of the kind that we want.
        !           676: 
        !           677:    FOR_RERAISE is non-zero if this raise is called by reraise.  In
        !           678:    this case we do not need to emit extra gotos to avoid warning messages;
        !           679:    the caller will do that once after all the exceptions it reraises
        !           680:    are handled and raised.  */
        !           681: void
        !           682: cplus_expand_raise (raise_id, parms, exp, for_reraise)
        !           683:      tree raise_id;
        !           684:      tree parms;
        !           685:      tree exp;
        !           686:      int for_reraise;
        !           687: {
        !           688:   /* Allocate new exception of appropriate type, passing
        !           689:      PARMS to its constructor.  */
        !           690:   tree cname, name;
        !           691:   tree decl;
        !           692:   tree xexp = exp;
        !           693: 
        !           694:   cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
        !           695:   if (cname == error_mark_node)
        !           696:     return;
        !           697:   name = TREE_VALUE (raise_id);
        !           698: 
        !           699:   decl = lookup_exception_object (cname, name, 1);
        !           700:   if (decl == NULL_TREE)
        !           701:     return;
        !           702: 
        !           703:   if (exp == NULL_TREE)
        !           704:     {
        !           705:       exp = build_method_call (NULL_TREE, name, parms, NULL_TREE, LOOKUP_COMPLAIN);
        !           706:       if (exp == error_mark_node)
        !           707:        return;
        !           708:     }
        !           709: 
        !           710:   if (in_try_block (1))
        !           711:     {
        !           712:       expand_raise (decl);
        !           713:     }
        !           714:   else if (! current_function_decl)
        !           715:     {
        !           716:       if (xexp == NULL_TREE)
        !           717:        cp_error ("invalid raise of `%D' outside of functions", decl);
        !           718:       else
        !           719:        cp_error ("invalid reraise of `%D' outside of functions", decl);
        !           720:     }
        !           721:   else
        !           722:     {
        !           723:       /* Test this raise against what this function permits.  */
        !           724:       tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
        !           725:       while (names)
        !           726:        {
        !           727:          if (decl == TREE_TYPE (names))
        !           728:            break;
        !           729:          names = TREE_CHAIN (names);
        !           730:        }
        !           731:       if (names == NULL_TREE)
        !           732:        {
        !           733:          error ("current function not declared to raise exception `%s'",
        !           734:                 IDENTIFIER_POINTER (name));
        !           735:          return;
        !           736:        }
        !           737:     }
        !           738: 
        !           739:   store_expr (exp, EHS_parms_as_rtx, 0);
        !           740: 
        !           741:   /* Set the global exception handler stack's NAME field
        !           742:      to the `name' of this exception.  The global exception
        !           743:      handler stack is the container for the exception object
        !           744:      we just built.
        !           745: 
        !           746:      We go through a function call to make life easier when debugging.  */
        !           747: #if 0
        !           748:   expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
        !           749: #else
        !           750:   parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),
        !           751:                     build_tree_list (NULL_TREE,
        !           752:                                      build_unary_op (ADDR_EXPR, decl, 0)));
        !           753:   expand_expr (build_function_call (BIR, parms), 0, 0, 0);
        !           754: #endif
        !           755: 
        !           756:   /* Activate thrower.  If we are inside a TRY statement,
        !           757:      we can cheat and not do this, saving a longjmp.  */
        !           758:   if (in_try_block (1) == 0)
        !           759:     {
        !           760:       sets_exception_throw_decl = 1;
        !           761:       emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
        !           762:     }
        !           763: 
        !           764:   if (xexp == NULL_TREE)
        !           765:     {    
        !           766:       /* Invoke destructors for current procedure or handler.  */
        !           767:       if (! expand_escape_except ())
        !           768:        compiler_error ("except nesting botch");
        !           769:       /* Throw via `longjmp'... Done as side-effect of goto.  */
        !           770:     }
        !           771:   /* To avoid spurious warning messages, we add a goto to the end
        !           772:      of the function.  This code is dead, and the compiler should
        !           773:      know how to delete it, but for now, we are stuck with it.  */
        !           774:   if (! for_reraise
        !           775:       && TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
        !           776:     expand_null_return ();
        !           777: }
        !           778: 
        !           779: extern tree cplus_exception_name ();
        !           780: 
        !           781: tree
        !           782: ansi_exception_object_lookup (type)
        !           783:      tree type;
        !           784: {
        !           785:   tree raise_id = cplus_exception_name (type);
        !           786:   tree decl;
        !           787: 
        !           788:   decl = IDENTIFIER_GLOBAL_VALUE (raise_id);
        !           789:   if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
        !           790:     {
        !           791:       push_obstacks_nochange ();
        !           792:       end_temporary_allocation ();
        !           793:       decl = build_decl (VAR_DECL, raise_id, ptr_type_node);
        !           794:       TREE_PUBLIC (decl) = 1;
        !           795:       TREE_STATIC (decl) = 1;
        !           796:       pushdecl_top_level (decl);
        !           797:       make_decl_rtl (decl, (char*)0, 1);
        !           798:       pop_obstacks ();
        !           799:     }
        !           800:   return decl;
        !           801: }
        !           802: 
        !           803: /* Generate code to throw an exception using EXP.
        !           804:    Usng ANSI syntax and semantics.
        !           805:    If EXP is NULL_TREE< re-raise instead. */
        !           806: 
        !           807: void
        !           808: cplus_expand_throw (exp)
        !           809:      tree exp;
        !           810: {
        !           811:   tree parms;
        !           812:   int for_reraise;
        !           813:   /* Allocate new exception of appropriate type, passing
        !           814:      PARMS to its constructor.  */
        !           815:   tree decl = ansi_exception_object_lookup (TREE_TYPE (exp));
        !           816:   tree xexp = exp;
        !           817: 
        !           818:   if (in_try_block (1))
        !           819:     {
        !           820: #if 1
        !           821:       my_friendly_abort (35);
        !           822: #else
        !           823:       expand_raise (decl);
        !           824: #endif
        !           825:     }
        !           826:   else if (! current_function_decl)
        !           827:     error ("invalid throw outside of functions");
        !           828:   else
        !           829:     {
        !           830: #if 0
        !           831:       /* Test this raise against what this function permits.  */
        !           832:       tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
        !           833:       while (names)
        !           834:        {
        !           835:          if (decl == TREE_TYPE (names))
        !           836:            break;
        !           837:          names = TREE_CHAIN (names);
        !           838:        }
        !           839:       if (names == NULL_TREE)
        !           840:        {
        !           841:          error ("current function not declared to raise exception `%s'",
        !           842:                 IDENTIFIER_POINTER (name));
        !           843:          return;
        !           844:        }
        !           845: #endif
        !           846:     }
        !           847: 
        !           848:   store_expr (exp, EHS_parms_as_rtx, 0);
        !           849: 
        !           850:   /* Set the global exception handler stack's NAME field
        !           851:      to the `name' of this exception.  The global exception
        !           852:      handler stack is the container for the exception object
        !           853:      we just built.
        !           854: 
        !           855:      We go through a function call to make life easier when debugging.  */
        !           856: #if 0
        !           857:   expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
        !           858: #else
        !           859:   parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),
        !           860:                     build_tree_list (NULL_TREE,
        !           861:                                      build_unary_op (ADDR_EXPR, decl, 0)));
        !           862:   expand_expr (build_function_call (BIR, parms), 0, 0, 0);
        !           863: #endif
        !           864: 
        !           865:   /* Activate thrower.  If we are inside a TRY statement,
        !           866:      we can cheat and not do this, saving a longjmp.  */
        !           867:   if (in_try_block (1) == 0)
        !           868:     {
        !           869:       sets_exception_throw_decl = 1;
        !           870:       emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
        !           871:     }
        !           872: 
        !           873:   if (xexp == NULL_TREE)
        !           874:     {    
        !           875:       /* Invoke destructors for current procedure or handler.  */
        !           876:       if (! expand_escape_except ())
        !           877:        compiler_error ("except nesting botch");
        !           878:       /* Throw via `longjmp'... Done as side-effect of goto.  */
        !           879:     }
        !           880: 
        !           881:   /* XXX: for_reraise is never set above here.  */
        !           882:   /* To avoid spurious warning messages, we add a goto to the end
        !           883:      of the function.  This code is dead, and the compiler should
        !           884:      know how to delete it, but for now, we are stuck with it.  */
        !           885:   if (! for_reraise
        !           886:       && TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
        !           887:     expand_null_return ();
        !           888: }
        !           889: 
        !           890: tree
        !           891: cplus_expand_start_catch (raise_id)
        !           892:      tree raise_id;
        !           893: {
        !           894:   tree cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
        !           895:   tree decl;
        !           896:   tree cond;
        !           897: 
        !           898:   if (cname == error_mark_node)
        !           899:     {
        !           900:       decl = error_mark_node;
        !           901:       cond = error_mark_node;
        !           902:     }
        !           903:   else
        !           904:     {
        !           905:       decl = lookup_exception_object (cname, TREE_VALUE (raise_id), 1);
        !           906:       if (decl == NULL_TREE)
        !           907:        cond = error_mark_node;
        !           908:       else
        !           909:        cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0),
        !           910:                                build (COMPONENT_REF, ptr_type_node,
        !           911:                                       current_exception_decl,
        !           912:                                       TREE_OPERAND (EHS_name, 1)),
        !           913:                                1);
        !           914:     }
        !           915:   expand_start_cond (cond, 0);
        !           916: 
        !           917:   /* Does nothing right now.  */
        !           918:   expand_catch (decl);
        !           919:   if (current_exception_type
        !           920:       && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
        !           921:     {
        !           922:       /* Make a cleanup for the name-specific exception object now in scope.  */
        !           923:       tree cleanup = maybe_build_cleanup (current_exception_object);
        !           924:       expand_start_bindings (0);
        !           925:       expand_decl_cleanup (NULL_TREE, cleanup);
        !           926:     }
        !           927:   return decl;
        !           928: }
        !           929: tree
        !           930: ansi_expand_start_catch (raise_type)
        !           931:      tree raise_type;
        !           932: {
        !           933:   tree decl = ansi_exception_object_lookup (raise_type);
        !           934:   tree cond;
        !           935: 
        !           936:   if (decl == NULL_TREE)
        !           937:       cond = error_mark_node;
        !           938:   else
        !           939:       cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0),
        !           940:                              build (COMPONENT_REF, ptr_type_node,
        !           941:                                     current_exception_decl,
        !           942:                                     TREE_OPERAND (EHS_name, 1)),
        !           943:                              1);
        !           944:   expand_start_cond (cond, 0);
        !           945: 
        !           946:   /* Does nothing right now.  */
        !           947:   expand_catch (decl);
        !           948:   return decl;
        !           949: }
        !           950: 
        !           951: void
        !           952: cplus_expand_end_catch (for_reraise)
        !           953:      int for_reraise;
        !           954: {
        !           955:   if (current_exception_type
        !           956:       && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
        !           957:     {
        !           958:       /* Destroy the specific exception object now in scope.  */
        !           959:       expand_end_bindings (getdecls (), 0, 1);
        !           960:     }
        !           961:   if (for_reraise)
        !           962:     {
        !           963:       if (! expand_escape_except ())
        !           964:        my_friendly_abort (36);
        !           965:     }
        !           966:   else
        !           967:     {
        !           968:       if (! expand_end_catch ())
        !           969:        my_friendly_abort (37);
        !           970:     }
        !           971:   expand_end_cond ();
        !           972: }
        !           973: 
        !           974: /* Reraise an exception.
        !           975:    If EXCEPTIONS is NULL_TREE, it means reraise whatever exception was caught.
        !           976:    If EXCEPTIONS is an IDENTIFIER_NODE, it means reraise the exception
        !           977:    object named by EXCEPTIONS.  This must be a variable declared in
        !           978:    an `except' clause.
        !           979:    If EXCEPTIONS is a TREE_LIST, it is the list of exceptions we are
        !           980:    willing to reraise.  */
        !           981: 
        !           982: void
        !           983: cplus_expand_reraise (exceptions)
        !           984:      tree exceptions;
        !           985: {
        !           986:   tree ex_ptr;
        !           987:   tree ex_object = current_exception_object;
        !           988:   rtx ex_ptr_as_rtx;
        !           989: 
        !           990:   if (exceptions && TREE_CODE (exceptions) == IDENTIFIER_NODE)
        !           991:     {
        !           992:       /* Don't get tripped up if its TREE_TYPE is `error_mark_node'.  */
        !           993:       ex_object = IDENTIFIER_LOCAL_VALUE (exceptions);
        !           994:       if (ex_object == NULL_TREE || TREE_CODE (ex_object) != INDIRECT_REF)
        !           995:        {
        !           996:          error ("`%s' is not an exception decl", IDENTIFIER_POINTER (exceptions));
        !           997:          return;
        !           998:        }
        !           999:       my_friendly_assert (TREE_CODE (TREE_OPERAND (ex_object, 0)) == VAR_DECL,
        !          1000:                          204);
        !          1001:       exceptions = NULL_TREE;
        !          1002:     }
        !          1003: 
        !          1004:   ex_ptr = build1 (NOP_EXPR, ptr_type_node, TREE_OPERAND (ex_object, 0));
        !          1005:   ex_ptr_as_rtx = expand_expr (ex_ptr, 0, 0, 0);
        !          1006: 
        !          1007:   /* reraise ALL, used by compiler.  */
        !          1008:   if (exceptions == NULL_TREE)
        !          1009:     {
        !          1010:       /* Now treat reraise like catch/raise.  */
        !          1011:       expand_catch (error_mark_node);
        !          1012:       expand_raise (error_mark_node);
        !          1013:       emit_move_insn (EHS_name_as_rtx, current_exception_name_as_rtx);
        !          1014:       store_expr ((tree) EHS_parms_as_rtx, current_exception_parms_as_rtx, 0);
        !          1015:       if (in_try_block (1) == 0)
        !          1016:        {
        !          1017:          sets_exception_throw_decl = 1;
        !          1018:          emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);
        !          1019:        }
        !          1020:       /* Set to zero so that destructor will not be called.  */
        !          1021:       emit_move_insn (ex_ptr_as_rtx, const0_rtx);
        !          1022:       if (! expand_escape_except ())
        !          1023:        my_friendly_abort (38);
        !          1024: 
        !          1025:       /* To avoid spurious warning messages, we add a goto to the end
        !          1026:         of the function.  This code is dead, and the compiler should
        !          1027:         know how to delete it, but for now, we are stuck with it.  */
        !          1028:       if (TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
        !          1029:        expand_null_return ();
        !          1030: 
        !          1031:       return;
        !          1032:     }
        !          1033: 
        !          1034:   /* reraise from a list of exceptions.  */
        !          1035:   while (exceptions)
        !          1036:     {
        !          1037:       tree type = lookup_exception_type (current_class_type, current_class_name,
        !          1038:                                         exceptions);
        !          1039:       if (type == NULL_TREE)
        !          1040:        {
        !          1041:          error ("`%s' is not an exception type",
        !          1042:                 IDENTIFIER_POINTER (TREE_VALUE (exceptions)));
        !          1043:          current_exception_type = NULL_TREE;
        !          1044:          TREE_TYPE (ex_object) = error_mark_node;
        !          1045:          TREE_TYPE (ex_ptr) = error_mark_node;
        !          1046:        }
        !          1047:       else
        !          1048:        {
        !          1049:          current_exception_type = type;
        !          1050:          /* In-place union.  */
        !          1051:          TREE_TYPE (ex_object) = type;
        !          1052:          TREE_TYPE (ex_ptr) = TYPE_POINTER_TO (type);
        !          1053:        }
        !          1054: 
        !          1055:       /* Now treat reraise like catch/raise.  */
        !          1056:       cplus_expand_start_catch (exceptions);
        !          1057:       cplus_expand_raise (exceptions, NULL_TREE, ex_ptr, 1);
        !          1058:       /* Set to zero so that destructor will not be called.  */
        !          1059:       if (TREE_TYPE (ex_ptr) != error_mark_node)
        !          1060:        emit_move_insn (ex_ptr_as_rtx, const0_rtx);
        !          1061:       cplus_expand_end_catch (1);
        !          1062:       exceptions = TREE_CHAIN (exceptions);
        !          1063:     }
        !          1064:   /* Don't propagate any unhandled exceptions.  */
        !          1065:   expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
        !          1066: 
        !          1067:   /* To avoid spurious warning messages, we add a goto to the end
        !          1068:      of the function.  This code is dead, and the compiler should
        !          1069:      know how to delete it, but for now, we are stuck with it.  */
        !          1070:   if (TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)
        !          1071:     expand_null_return ();
        !          1072: }
        !          1073: 
        !          1074: void
        !          1075: setup_exception_throw_decl ()
        !          1076: {
        !          1077:   tree call_to_longjmp, parms;
        !          1078: 
        !          1079:   int old = suspend_momentary ();
        !          1080: 
        !          1081:   exception_throw_decl = build_decl (VAR_DECL, get_identifier (THROW_NAME), integer_type_node);
        !          1082:   pushdecl (exception_throw_decl);
        !          1083:   parms = tree_cons (NULL_TREE, EHS_handler,
        !          1084:                     build_tree_list (0, integer_one_node));
        !          1085:   call_to_longjmp = build_function_call (BILJ, parms);
        !          1086: 
        !          1087:   expand_decl (exception_throw_decl);
        !          1088:   expand_decl_cleanup (exception_throw_decl,
        !          1089:                       build (COND_EXPR, void_type_node,
        !          1090:                              exception_throw_decl,
        !          1091:                              call_to_longjmp, integer_zero_node));
        !          1092:   DECL_INITIAL (exception_throw_decl) = integer_zero_node;
        !          1093:   sets_exception_throw_decl = 0;
        !          1094:   resume_momentary (old);
        !          1095: 
        !          1096:   /* Cache these, since they won't change throughout the function.  */
        !          1097:   EHS_parms_as_rtx = expand_expr (EHS_parms, 0, 0, 0);
        !          1098:   EHS_name_as_rtx = expand_expr (EHS_name, 0, 0, 0);
        !          1099: }
        !          1100: 
        !          1101: void
        !          1102: init_exception_processing ()
        !          1103: {
        !          1104:   extern tree build_function_type (), define_function ();
        !          1105:   extern tree unhandled_exception_fndecl;
        !          1106:   tree cname = get_identifier ("ExceptionHandler");
        !          1107:   tree field, chain;
        !          1108:   tree ctor, dtor;
        !          1109:   tree jmp_buf_type = build_array_type (integer_type_node,
        !          1110:                                        build_index_type (build_int_2 (_JBLEN-1, 0)));
        !          1111:   tree jmp_buf_arg_type = build_pointer_type (integer_type_node);
        !          1112: 
        !          1113:   tree parmtypes = hash_tree_chain (jmp_buf_arg_type, void_list_node);
        !          1114:   tree setjmp_fndecl, longjmp_fndecl, raise_fndecl;
        !          1115: 
        !          1116:   int old_interface_only = interface_only;
        !          1117:   int old_interface_unknown = interface_unknown;
        !          1118:   interface_only = 1;
        !          1119:   interface_unknown = 0;
        !          1120:   EHS_type = xref_tag (record_type_node, cname, NULL_TREE);
        !          1121:   push_lang_context (lang_name_c);
        !          1122:   setjmp_fndecl = define_function ("setjmp",
        !          1123:                                   build_function_type (integer_type_node,
        !          1124:                                                        parmtypes),
        !          1125:                                   NOT_BUILT_IN, pushdecl, 0);
        !          1126:   BISJ = default_conversion (setjmp_fndecl);
        !          1127:   parmtypes = hash_tree_chain (jmp_buf_arg_type,
        !          1128:                               hash_tree_chain (integer_type_node, void_list_node));
        !          1129:   longjmp_fndecl = define_function ("longjmp",
        !          1130:                                    build_function_type (void_type_node, parmtypes),
        !          1131:                                    NOT_BUILT_IN, pushdecl, 0);
        !          1132:   raise_fndecl = define_function ("__raise_exception",
        !          1133:                                  build_function_type (void_type_node,
        !          1134:                                                       hash_tree_chain (ptr_type_node,
        !          1135:                                                                        hash_tree_chain (build_pointer_type (ptr_type_node), void_list_node))),
        !          1136:                                  NOT_BUILT_IN, pushdecl, 0);
        !          1137:   BILJ = default_conversion (longjmp_fndecl);
        !          1138:   BIR = default_conversion (raise_fndecl);
        !          1139:   BIUE = default_conversion (unhandled_exception_fndecl);
        !          1140: 
        !          1141:   pop_lang_context ();
        !          1142: 
        !          1143:   /* finish_struct will pop this.  */
        !          1144:   pushclass (EHS_type, 0);
        !          1145:   field = build_lang_field_decl (FIELD_DECL, get_identifier ("parms"), ptr_type_node);
        !          1146:   chain = field;
        !          1147:   field = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
        !          1148:                                 build_pointer_type (default_function_type));
        !          1149:   TREE_CHAIN (field) = chain;
        !          1150:   chain = field;
        !          1151:   field = build_lang_field_decl (FIELD_DECL, get_identifier ("handler"), jmp_buf_type);
        !          1152:   TREE_CHAIN (field) = chain;
        !          1153:   chain = field;
        !          1154:   field = build_lang_field_decl (FIELD_DECL, get_identifier ("prev"),
        !          1155:                                 TYPE_POINTER_TO (EHS_type));
        !          1156:   TREE_CHAIN (field) = chain;
        !          1157:   chain = field;
        !          1158: 
        !          1159:   ctor = build_lang_decl (FUNCTION_DECL, cname,
        !          1160:                          build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
        !          1161:   DECL_CONSTRUCTOR_P (ctor) = 1;
        !          1162:   TREE_STATIC (ctor) = 1;
        !          1163:   TREE_PUBLIC (ctor) = 1;
        !          1164:   DECL_EXTERNAL (ctor) = 1;
        !          1165:   grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0);
        !          1166:   grok_ctor_properties (EHS_type, ctor);
        !          1167:   finish_decl (pushdecl (ctor), NULL_TREE, NULL_TREE, 0);
        !          1168:   /* Must copy the node here because the FUNCTION_DECL
        !          1169:      used inside the struct ain't the same as the
        !          1170:      FUNCTION_DECL we stick into the global binding
        !          1171:      contour.  */
        !          1172:   ctor = copy_node (ctor);
        !          1173:   TREE_CHAIN (ctor) = chain;
        !          1174:   chain = ctor;
        !          1175:   dtor = build_lang_decl (FUNCTION_DECL, cname,
        !          1176:                          build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
        !          1177:   TREE_STATIC (dtor) = 1;
        !          1178:   TREE_PUBLIC (dtor) = 1;
        !          1179:   DECL_EXTERNAL (dtor) = 1;
        !          1180:   grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0);
        !          1181:   finish_decl (pushdecl (dtor), NULL_TREE, NULL_TREE, 0);
        !          1182:   /* Copy for the same reason as copying ctor.  */
        !          1183:   dtor = copy_node (dtor);
        !          1184:   TREE_CHAIN (dtor) = chain;
        !          1185:   chain = dtor;
        !          1186:   TYPE_HAS_CONSTRUCTOR (EHS_type) = 1;
        !          1187:   TYPE_HAS_DESTRUCTOR (EHS_type) = 1;
        !          1188:   finish_struct (EHS_type, temp_tree_cons (NULL_TREE, chain, NULL_TREE), 0);
        !          1189:   interface_only = old_interface_only;
        !          1190:   interface_unknown = old_interface_unknown;
        !          1191: }
        !          1192: 
        !          1193: void
        !          1194: init_exception_processing_1 ()
        !          1195: {
        !          1196:   register tree EHS_id = get_identifier ("exceptionHandlerStack");
        !          1197: 
        !          1198:   EHS_decl = IDENTIFIER_GLOBAL_VALUE (EHS_id);
        !          1199: 
        !          1200:   /* If we have no other definition, default to library implementation.  */
        !          1201:   if (EHS_decl == NULL_TREE)
        !          1202:     {
        !          1203:       EHS_decl = build_decl (VAR_DECL, EHS_id, TYPE_POINTER_TO (EHS_type));
        !          1204:       /* If we don't push this, its definition, should it be encountered,
        !          1205:         will not be seen.  */
        !          1206:       EHS_decl = pushdecl (EHS_decl);
        !          1207:       DECL_EXTERNAL (EHS_decl) = 1;
        !          1208:       TREE_STATIC (EHS_decl) = 1;
        !          1209:       TREE_PUBLIC (EHS_decl) = 1;
        !          1210:       finish_decl (EHS_decl, NULL_TREE, NULL_TREE, 0);
        !          1211:     }
        !          1212:   else if (TREE_CODE (EHS_decl) != VAR_DECL
        !          1213:           || TREE_TYPE (EHS_decl) != TYPE_POINTER_TO (EHS_type))
        !          1214:     fatal ("exception handling declarations conflict with compiler's internal model");
        !          1215: 
        !          1216:   if (EHS_prev == NULL_TREE)
        !          1217:     {
        !          1218:       register tree EHS_DECL = build1 (INDIRECT_REF, EHS_type, EHS_decl);
        !          1219:       EHS_prev = build_component_ref (EHS_DECL, get_identifier ("prev"), 0, 0);
        !          1220:       EHS_handler = build_component_ref (EHS_DECL, get_identifier ("handler"), 0, 0);
        !          1221:       EHS_parms = build_component_ref (EHS_DECL, get_identifier ("parms"), 0, 0);
        !          1222:       EHS_name = build_component_ref (EHS_DECL, get_identifier ("name"), 0, 0);
        !          1223:     }
        !          1224: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.