Annotation of gcc/cp-except.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com

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