|
|
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. */ 1.1.1.5 ! root 81: tree EHS_type; 1.1 root 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)) 1.1.1.5 ! root 257: cp_error ("exception name `%T' must follow body declaration", e); 1.1 root 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: 1.1.1.5 ! root 280: cp_error ("declaration of function `%D' in exception invalid", ! 281: field); 1.1 root 282: break; 283: case VAR_DECL: 284: if (TREE_STATIC (field)) 1.1.1.5 ! root 285: cp_error ("declaration of static variable `%D' in exception invalid", field); 1.1 root 286: else 1.1.1.5 ! root 287: cp_error ("declaration of constant field `%D' in exception invalid", field); 1.1 root 288: break; 289: case CONST_DECL: 1.1.1.5 ! root 290: cp_error ("declaration of enum value `%D' in exception invalid", field); 1.1 root 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; 1.1.1.4 root 368: finish_decl (pushdecl (edecl), NULL_TREE, NULL_TREE, 0); 1.1 root 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 1.1.1.5 ! root 389: if ((TREE_CODE (TREE_TYPE (fields)) == INTEGER_TYPE ! 390: || TREE_CODE (TREE_TYPE (fields)) == ENUMERAL_TYPE) 1.1 root 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); 1.1.1.3 root 404: DECL_EXTERNAL (ctor) = 1; 1.1 root 405: TREE_STATIC (ctor) = 1; 406: TREE_PUBLIC (ctor) = 0; 1.1.1.3 root 407: DECL_INLINE (ctor) = 1; 1.1.1.4 root 408: make_decl_rtl (ctor, NULL_PTR, 1); 409: finish_decl (ctor, NULL_TREE, NULL_TREE, 0); 1.1 root 410: TREE_CHAIN (ctor) = TREE_VALUE (list_of_fieldlists); 411: TREE_VALUE (list_of_fieldlists) = ctor; 412: 1.1.1.4 root 413: finish_struct (t, list_of_fieldlists, 0); 1.1 root 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; 1.1.1.4 root 488: finish_decl (handler, NULL_TREE, NULL_TREE, 0); 1.1 root 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. */ 1.1.1.4 root 500: expand_start_try (build_binary_op (EQ_EXPR, call_to_setjmp, integer_zero_node, 1), 0, 1); 1.1 root 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: 1.1.1.3 root 546: my_friendly_assert (TREE_CODE (decl) == VAR_DECL 547: && TREE_TYPE (decl) == EHS_type, 203); 1.1 root 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; 1.1.1.4 root 604: extern tree combine_strings (); 1.1 root 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: { 1.1.1.5 ! root 653: cp_error ("exception `%D' raised but not declared raisable", ! 654: TREE_VALUE (raised)); 1.1 root 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) 1.1.1.5 ! root 717: cp_error ("invalid raise of `%D' outside of functions", decl); 1.1 root 718: else 1.1.1.5 ! root 719: cp_error ("invalid reraise of `%D' outside of functions", decl); 1.1 root 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) 1.1.1.3 root 783: tree type; 1.1 root 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 1.1.1.2 root 821: my_friendly_abort (35); 1.1 root 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: } 1.1.1.4 root 880: 881: /* XXX: for_reraise is never set above here. */ 1.1 root 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, 1.1.1.4 root 911: current_exception_decl, 912: TREE_OPERAND (EHS_name, 1)), 913: 1); 1.1 root 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, 1.1.1.4 root 942: TREE_OPERAND (EHS_name, 1)), 943: 1); 1.1 root 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 ()) 1.1.1.2 root 964: my_friendly_abort (36); 1.1 root 965: } 966: else 967: { 968: if (! expand_end_catch ()) 1.1.1.2 root 969: my_friendly_abort (37); 1.1 root 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; 1.1.1.3 root 988: rtx ex_ptr_as_rtx; 1.1 root 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: } 1.1.1.3 root 999: my_friendly_assert (TREE_CODE (TREE_OPERAND (ex_object, 0)) == VAR_DECL, 1000: 204); 1.1 root 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); 1.1.1.3 root 1013: emit_move_insn (EHS_name_as_rtx, current_exception_name_as_rtx); 1.1.1.4 root 1014: store_expr ((tree) EHS_parms_as_rtx, current_exception_parms_as_rtx, 0); 1.1 root 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 ()) 1.1.1.2 root 1023: my_friendly_abort (38); 1.1 root 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: { 1.1.1.4 root 1104: extern tree build_function_type (), define_function (); 1.1 root 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; 1.1.1.3 root 1164: DECL_EXTERNAL (ctor) = 1; 1.1 root 1165: grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0); 1166: grok_ctor_properties (EHS_type, ctor); 1.1.1.4 root 1167: finish_decl (pushdecl (ctor), NULL_TREE, NULL_TREE, 0); 1.1 root 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; 1.1.1.3 root 1179: DECL_EXTERNAL (dtor) = 1; 1.1 root 1180: grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0); 1.1.1.4 root 1181: finish_decl (pushdecl (dtor), NULL_TREE, NULL_TREE, 0); 1.1 root 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; 1.1.1.4 root 1188: finish_struct (EHS_type, temp_tree_cons (NULL_TREE, chain, NULL_TREE), 0); 1.1 root 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); 1.1.1.3 root 1207: DECL_EXTERNAL (EHS_decl) = 1; 1.1 root 1208: TREE_STATIC (EHS_decl) = 1; 1209: TREE_PUBLIC (EHS_decl) = 1; 1.1.1.4 root 1210: finish_decl (EHS_decl, NULL_TREE, NULL_TREE, 0); 1.1 root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.