No empty .Rs/.Re
[netbsd-mini2440.git] / gnu / usr.bin / g++ / cc1plus / cplus-except.c
blobb9333c5129a83353bf66e29c6a70b93b9c1fe652
1 /* Handle exceptional things in C++.
2 Copyright (C) 1989 Free Software Foundation, Inc.
3 Contributed by Michael Tiemann (tiemann@mcc.com)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
10 any later version.
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.
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. */
22 /* High-level class interface. */
24 #define NULL 0
25 #define EXCEPTION_NAME_PREFIX "__exception_"
27 #include "config.h"
28 #include "tree.h"
29 #include "cplus-tree.h"
30 #include "flags.h"
31 #include "assert.h"
32 /* On Suns this can get you to the right definition if you
33 set the right value for TARGET. */
34 #include <setjmp.h>
35 #ifdef sequent
36 /* Can you believe they forgot this? */
37 #define _JBLEN 11
38 #endif
40 #ifndef _JBLEN
41 #define _JBLEN (sizeof(jmp_buf)/sizeof(int))
42 #endif
44 void init_exception_processing ();
45 void init_exception_processing_1 ();
47 /* If non-zero, a VAR_DECL whose cleanup will cause a throw to the
48 next exception handler. Its value says whether to throw or not.
49 In the case of functions which do not issue a RAISE, it should be
50 possible to optimize away this VAR_DECL (and overhead associated
51 with it). */
52 tree exception_throw_decl;
53 /* Use this to know that we did not set `exception_throw_decl',
54 until GCC optimizer is smart enough to figure it out for itself. */
55 int sets_exception_throw_decl;
57 /* The exception `type' currently in scope, or NULL_TREE if none. */
58 tree current_exception_type;
60 /* The exception handler object for the given scope. */
61 tree current_exception_decl;
63 /* The ``object'' view of the current exception parameters.
64 We cast up from the `parms' field to `current_exception_type'. */
65 tree current_exception_object;
67 /* Low-level rtl interface. */
68 #include "rtl.h"
70 /* Cache `setjmp', `longjmp', `raise_exception', and `unhandled_exception'
71 after default conversion. Maybe later they will get built-in. */
72 static tree BISJ, BILJ, BIR, BIUE;
74 /* Local variables which give the appearance that exception
75 handling is part of the language and the execution model. */
77 /* The type of the exception handler stack. */
78 static tree EHS_type;
80 /* The global handler stack. */
81 tree EHS_decl;
83 /* Cached component refs to fields of `EHS_decl'. */
84 static tree EHS_prev, EHS_handler, EHS_parms, EHS_name;
86 /* The parameter names of this exception type. */
88 static tree last_exception_fields;
89 static tree last_exception_field_types;
91 /* When ID is VOID_TYPE_NODE, it means ``raise all''.
92 Cannot be inline, since it uses `alloca', and that
93 breaks code which pushes the result of this function
94 on the stack. */
95 static tree
96 exception_object_name (prefix, id)
97 tree prefix;
98 tree id;
100 /* First, cons up the `name' of this exception. */
101 char *name;
102 int length = (id == void_type_node ? 3 : IDENTIFIER_LENGTH (id)) + EXCEPTION_NAME_LENGTH;
104 if (prefix)
105 length += IDENTIFIER_LENGTH (prefix) + 2;
107 name = (char *)alloca (length);
108 strcpy (name, EXCEPTION_NAME_PREFIX);
109 length = EXCEPTION_NAME_LENGTH;
110 if (prefix)
112 strcpy (name + length, IDENTIFIER_POINTER (prefix));
113 name[length + IDENTIFIER_LENGTH (prefix)] = JOINER;
114 length += IDENTIFIER_LENGTH (prefix) + 1;
116 if (id == void_type_node)
117 strcpy (name + length, "all");
118 else
119 strcpy (name + length, IDENTIFIER_POINTER (id));
120 return get_identifier (name);
123 tree
124 lookup_exception_cname (ctype, cname, raise_id)
125 tree ctype, cname;
126 tree raise_id;
128 tree this_cname = TREE_PURPOSE (raise_id);
129 if (this_cname == NULL_TREE)
131 if (cname)
133 tree name = TREE_VALUE (raise_id);
134 if (purpose_member (name, CLASSTYPE_TAGS (ctype)))
135 this_cname = cname;
138 else if (this_cname == void_type_node)
139 this_cname = NULL_TREE;
140 else if (TREE_CODE (this_cname) != IDENTIFIER_NODE)
142 sorry ("multiple scope refs in `cplus_expand_raise_stmt'");
143 this_cname = error_mark_node;
145 return this_cname;
148 tree
149 lookup_exception_tname (oname)
150 tree oname;
152 return get_identifier (IDENTIFIER_POINTER (oname) + EXCEPTION_NAME_LENGTH);
155 tree
156 lookup_exception_object (cname, name, complain)
157 tree cname, name;
158 int complain;
160 tree oname;
161 tree decl;
163 if (cname == void_type_node)
164 cname = NULL_TREE;
165 else if (cname && TREE_CODE (cname) != IDENTIFIER_NODE)
167 sorry ("multiple scope refs in `lookup_exception_object'");
168 cname = NULL_TREE;
170 oname = exception_object_name (cname, name);
171 decl = IDENTIFIER_GLOBAL_VALUE (oname);
172 if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)
174 if (complain)
176 int temp = allocation_temporary_p ();
177 if (cname)
178 error ("no exception name object for name `%s::%s'",
179 IDENTIFIER_POINTER (cname),
180 IDENTIFIER_POINTER (name));
181 else
182 error ("no exception name object for name `%s'",
183 IDENTIFIER_POINTER (name));
184 if (temp)
185 end_temporary_allocation ();
186 /* Avoid further error messages. */
187 pushdecl_top_level (build_lang_field_decl (VAR_DECL,
188 exception_object_name (cname, name),
189 error_mark_node));
190 if (temp)
191 resume_temporary_allocation ();
193 return NULL_TREE;
195 return decl;
198 tree
199 lookup_exception_type (ctype, cname, raise_id)
200 tree ctype, cname;
201 tree raise_id;
203 tree name = TREE_VALUE (raise_id);
204 tree purpose = TREE_PURPOSE (raise_id);
206 if (cname && purpose == NULL_TREE)
207 purpose = cname;
209 if (purpose && purpose != void_type_node)
211 tree assoc = NULL_TREE;
213 if (TREE_CODE (purpose) != IDENTIFIER_NODE)
215 sorry ("multiple scope refs in `lookup_exception_type'");
216 TREE_PURPOSE (raise_id) = NULL_TREE;
217 return NULL_TREE;
219 if (! is_aggr_typedef (purpose, 1))
220 return NULL_TREE;
221 ctype = TREE_TYPE (TREE_TYPE (purpose));
222 assoc = purpose_member (name, CLASSTYPE_TAGS (ctype));
223 if (assoc)
224 return TREE_VALUE (assoc);
227 ctype = lookup_name (name);
228 if (ctype && TREE_CODE (ctype) == TYPE_DECL)
229 ctype = TREE_TYPE (ctype);
230 if (ctype && TREE_CODE (ctype) == RECORD_TYPE
231 && CLASSTYPE_DECLARED_EXCEPTION (ctype))
232 return ctype;
233 return NULL_TREE;
236 tree
237 finish_exception (e, list_of_fieldlists)
238 tree e;
239 tree list_of_fieldlists;
241 tree parmtypes = NULL_TREE, name_field;
242 tree cname = TYPE_NAME (e);
244 if (TREE_CODE (cname) == TYPE_DECL)
245 cname = DECL_NAME (cname);
247 if (last_exception_fields)
248 error ("cannot declare exceptions within exceptions");
249 if (list_of_fieldlists && ! ANON_AGGRNAME_P (cname))
250 error_with_aggr_type (e, "exception name `%s' must follow body declaration");
251 if (list_of_fieldlists)
253 tree prev, field;
255 /* Note: no public, private, or protected allowed. */
256 if (TREE_CHAIN (list_of_fieldlists))
257 error ("visibility declarations invalid in exception declaration");
258 else if (TREE_PURPOSE (list_of_fieldlists) != (tree)visibility_default)
259 error ("visibility declarations invalid in exception declaration");
260 TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_default;
262 /* Note also: no member function declarations allowed. */
263 for (prev = 0, field = TREE_VALUE (list_of_fieldlists);
264 field; prev = field, field = TREE_CHAIN (field))
266 switch (TREE_CODE (field))
268 case FIELD_DECL:
269 /* ok. */
270 parmtypes = tree_cons (NULL_TREE, TREE_TYPE (field), parmtypes);
271 continue;
272 case FUNCTION_DECL:
273 error_with_decl (field, "declaration of function `%s' in exception invalid");
274 break;
275 case VAR_DECL:
276 if (TREE_STATIC (field))
277 error_with_decl (field, "declaration of static variable `%s' in exception invalid");
278 else
279 error_with_decl (field, "declaration of constant field `%s' in exception invalid");
280 break;
281 case CONST_DECL:
282 error_with_decl (field, "declaration of enum value `%s' in exception invalid");
283 break;
284 case SCOPE_REF:
285 error ("use of `::' in exception context invalid");
286 break;
288 if (prev)
289 TREE_CHAIN (prev) = TREE_CHAIN (field);
290 else
291 TREE_VALUE (list_of_fieldlists) = TREE_CHAIN (field);
295 /* Now that we've cleaned up the fields, add a name identifier at front. */
296 name_field = build_lang_field_decl (FIELD_DECL, get_identifier ("__name"),
297 ptr_type_node);
298 if (list_of_fieldlists)
300 TREE_CHAIN (name_field) = TREE_VALUE (list_of_fieldlists);
301 TREE_VALUE (list_of_fieldlists) = name_field;
303 else
304 list_of_fieldlists = build_tree_list (NULL_TREE, name_field);
306 last_exception_fields = TREE_VALUE (list_of_fieldlists);
307 if (parmtypes)
309 last_exception_field_types = nreverse (parmtypes);
310 /* Set the TREE_CHAIN of what is now at the end of the
311 list to `void_list_node'. */
312 TREE_CHAIN (parmtypes) = void_list_node;
314 else
315 last_exception_field_types = void_list_node;
317 popclass (0);
319 #if 0
320 /* Remove aggregate types from the list of tags,
321 since these appear at global scope. */
322 while (x && IS_AGGR_TYPE (TREE_VALUE (x)))
323 x = TREE_CHAIN (x);
324 CLASSTYPE_TAGS (t) = x;
325 y = x;
326 while (x)
328 if (IS_AGGR_TYPE (TREE_VALUE (x)))
329 TREE_CHAIN (y) = TREE_CHAIN (x);
330 x = TREE_CHAIN (x);
332 #endif
334 if (flag_cadillac)
335 cadillac_finish_exception (e);
337 return e;
340 void
341 finish_exception_decl (cname, decl)
342 tree cname, decl;
344 /* In cplus-decl.h. */
345 extern tree last_function_parms;
347 /* An exception declaration. */
348 tree t, ctor;
349 tree parmdecls = NULL_TREE, fields;
350 tree list_of_fieldlists = temp_tree_cons (NULL_TREE,
351 copy_list (last_exception_fields),
352 NULL_TREE);
353 tree edecl = build_lang_field_decl (VAR_DECL,
354 exception_object_name (cname, DECL_NAME (decl)),
355 ptr_type_node);
357 DECL_LANGUAGE (edecl) = lang_c;
358 TREE_STATIC (edecl) = 1;
359 TREE_PUBLIC (edecl) = 1;
360 finish_decl (pushdecl (edecl), 0, 0);
362 /* Now instantiate the exception decl. */
363 t = xref_tag (exception_type_node, DECL_NAME (decl), NULL_TREE);
365 /* finish_struct will pop this. */
366 pushclass (t, 0);
368 /* Now add a constructor which takes as parameters all the types we
369 just defined. */
370 ctor = build_lang_decl (FUNCTION_DECL, DECL_NAME (decl),
371 build_cplus_method_type (t, TYPE_POINTER_TO (t),
372 last_exception_field_types));
373 /* Don't take `name'. The constructor handles that. */
374 fields = TREE_CHAIN (TREE_VALUE (list_of_fieldlists));
375 while (fields)
377 tree parm = build_decl (PARM_DECL, DECL_NAME (fields), TREE_TYPE (fields));
378 /* Since there is a prototype, args are passed in their own types. */
379 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
380 #ifdef PROMOTE_PROTOTYPES
381 if (TREE_CODE (TREE_TYPE (fields)) == INTEGER_TYPE
382 && TYPE_PRECISION (TREE_TYPE (fields)) < TYPE_PRECISION (integer_type_node))
383 DECL_ARG_TYPE (parm) = integer_type_node;
384 #endif
385 TREE_CHAIN (parm) = parmdecls;
386 parmdecls = parm;
387 fields = TREE_CHAIN (fields);
389 fields = TREE_VALUE (list_of_fieldlists);
390 last_function_parms = nreverse (parmdecls);
392 DECL_CONSTRUCTOR_P (ctor) = 1;
393 TYPE_HAS_CONSTRUCTOR (t) = 1;
394 grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, 0, NULL_TREE);
395 TREE_EXTERNAL (ctor) = 1;
396 TREE_STATIC (ctor) = 1;
397 TREE_PUBLIC (ctor) = 0;
398 TREE_INLINE (ctor) = 1;
399 make_decl_rtl (ctor, 0, 1);
400 finish_decl (ctor, NULL_TREE, 0);
401 TREE_CHAIN (ctor) = TREE_VALUE (list_of_fieldlists);
402 TREE_VALUE (list_of_fieldlists) = ctor;
404 finish_struct (t, list_of_fieldlists, 0, 0);
406 if (current_function_decl)
407 error ("cannot define exception inside function scope");
408 else
410 /* Now build the constructor for this exception. */
411 parmdecls = DECL_ARGUMENTS (ctor);
412 start_function (NULL_TREE, ctor, 0, 1);
413 store_parm_decls ();
414 pushlevel (0);
415 clear_last_expr ();
416 push_momentary ();
417 expand_start_bindings (0);
419 /* Move all the parameters to the fields, skipping `this'. */
420 parmdecls = TREE_CHAIN (parmdecls);
421 /* Install `name' of this exception handler. */
422 DECL_INITIAL (fields) = build_unary_op (ADDR_EXPR, edecl, 0);
423 fields = TREE_CHAIN (fields);
424 /* Install all the values. */
425 while (fields)
427 /* Set up the initialization for this field. */
428 DECL_INITIAL (fields) = parmdecls;
429 fields = TREE_CHAIN (fields);
430 parmdecls = TREE_CHAIN (parmdecls);
432 emit_base_init (t, 0);
434 finish_function (DECL_SOURCE_LINE (ctor), 1);
438 void
439 end_exception_decls ()
441 last_exception_field_types = NULL_TREE;
442 last_exception_fields = NULL_TREE;
445 /* Statement-level exception semantics. */
447 void
448 cplus_expand_start_try (implicit)
449 int implicit;
451 tree call_to_setjmp;
452 tree handler, ref;
454 /* Start a new block enclosing the whole handler. */
455 if (implicit)
457 pushlevel_temporary (1);
459 else
461 pushlevel (0);
462 clear_last_expr ();
463 push_momentary ();
465 /* Encompass whole exception handler in one big binding contour.
466 If RAISE should throw out of the whole TRY/EXCEPT block, call
467 `expand_start_bindings' with argument of 1. */
468 expand_start_bindings (0);
471 /* Allocate handler in that block. It's real name will come later.
472 Note that it will be the first name in this binding contour. */
473 handler = get_temp_name (EHS_type, 0);
474 DECL_INITIAL (handler) = error_mark_node;
475 finish_decl (handler, NULL_TREE, 0);
477 /* Must come after call to `finish_decl', else the cleanup for the temp
478 for the handler will cause the contour we just created to be popped. */
479 if (implicit)
480 declare_implicit_exception ();
482 /* Catch via `setjmp'. */
483 ref = build_component_ref (handler, get_identifier ("handler"), NULL_TREE, 0);
484 call_to_setjmp = build_function_call (BISJ, build_tree_list (NULL_TREE, ref));
486 /* RAISE throws to EXCEPT part. */
487 expand_start_try (build_binary_op (EQ_EXPR, call_to_setjmp, integer_zero_node), 0, 1);
490 /* If KEEP is 1, then declarations in the TRY statement are worth keeping.
491 If KEEP is 2, then the TRY statement was generated by the compiler.
492 If KEEP is 0, the declarations in the TRY statement contain errors. */
494 tree
495 cplus_expand_end_try (keep)
496 int keep;
498 tree decls, decl, block;
500 if (keep < 2)
501 pop_implicit_try_blocks (NULL_TREE);
503 decls = getdecls ();
505 /* Emit code to avoid falling through into a default
506 handler that might come later. */
507 expand_end_try ();
509 /* Pops binding contour local to TRY, and get the exception handler
510 object built by `...start_try'. */
511 switch (keep)
513 case 0:
514 expand_end_bindings (decls, 0, 1);
515 block = poplevel (0, 0, 0);
516 pop_momentary ();
517 decl = getdecls ();
518 break;
520 case 1:
521 expand_end_bindings (decls, 1, 1);
522 block = poplevel (1, 1, 0);
523 pop_momentary ();
524 decl = getdecls ();
525 break;
527 default:
528 decl = tree_last (decls);
529 block = NULL_TREE;
530 break;
533 assert (TREE_CODE (decl) == VAR_DECL && TREE_TYPE (decl) == EHS_type);
534 if (block)
536 TREE_LANG_FLAG_1 (block) = 1;
537 TREE_USED (block) = 1;
540 /* Pass it back so that its rtl can be bound to its name
541 (or vice versa). */
542 return decl;
545 void
546 cplus_expand_start_except (name, decl)
547 tree name, decl;
549 int yes;
550 tree tmp;
552 expand_start_except (0, 1);
554 /* This is internal `eh'. */
555 current_exception_decl = decl;
556 /* Get the exception object into scope (user declared `ex'). */
557 tmp = pushdecl (build_decl (VAR_DECL, name, ptr_type_node));
558 DECL_INITIAL (tmp) = error_mark_node;
559 finish_decl (tmp, build (COMPONENT_REF, ptr_type_node, decl, TREE_OPERAND (EHS_parms, 1)), 0);
560 current_exception_type = NULL_TREE;
561 yes = suspend_momentary ();
562 /* From now on, send the user to our faked-up object. */
563 current_exception_object = build1 (INDIRECT_REF, void_type_node, tmp);
564 IDENTIFIER_LOCAL_VALUE (name) = current_exception_object;
565 resume_momentary (yes);
567 /* Pop exception handler stack. */
568 expand_assignment (EHS_decl, EHS_prev, 0, 0);
571 /* Generate the call to `unhandled_exception' that is appropriate
572 for this particular unhandled exception. */
573 static tree
574 call_to_unhandled_exception ()
576 extern int lineno;
577 tree parms = tree_cons (NULL_TREE,
578 combine_strings (build_string (strlen (input_filename + 1), input_filename)),
579 build_tree_list (NULL_TREE, build_int_2 (lineno, 0)));
580 return build_function_call (BIUE, parms);
583 /* Note that this must be mirror image of `...start_try'.
584 DFAULT is the default clause, if there was one.
585 DFAULT is ERROR_MARK_NODE when this ends an implicit handler. */
586 void
587 cplus_expand_end_except (dfault)
588 tree dfault;
590 extern tree expand_end_except (); /* stmt.c. */
591 tree decls, raised;
593 if (dfault == NULL_TREE)
595 /* Uncaught exception at outermost level. If raised locally,
596 reraise the exception. Otherwise, generate code to call `abort'. */
597 if (in_try_block (1) == 0)
599 expand_start_cond (build (EQ_EXPR, integer_type_node,
600 exception_throw_decl, integer_zero_node), 0);
601 expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
602 expand_end_cond ();
604 /* Try the next handler. */
605 if (! expand_escape_except ())
606 compiler_error ("except nesting botch");
609 raised = expand_end_except ();
611 decls = getdecls ();
612 expand_end_bindings (decls, decls != 0, 1);
613 poplevel (decls != 0, 1, 0);
615 /* Implicit handlers do not use the momentary obstack. */
616 if (dfault != error_mark_node)
617 pop_momentary ();
619 if (! in_try_block (1))
621 /* Check that this function is not raising exceptions
622 it is not supposed to. */
623 while (raised)
625 error_with_decl (TREE_VALUE (raised), "exception `%s' raised but not declared raisable");
626 raised = TREE_CHAIN (raised);
629 else if (dfault == NULL_TREE || dfault == error_mark_node)
631 expand_start_cond (build (NE_EXPR, integer_type_node,
632 exception_throw_decl,
633 integer_zero_node), 0);
634 /* We fell off the end of this try block. Try going to the next.
635 The escape_label will be the beginning of the next try block. */
636 if (! expand_escape_except ())
637 compiler_error ("except nesting botch");
638 expand_end_cond ();
642 /* Generate code to raise exception RAISE_ID.
643 If EXP is NULL_TREE, then PARMS is the list of parameters to use
644 for constructing this exception.
645 If EXP is non-NULL, then it is an already constructed object
646 of the kind that we want. */
647 void
648 cplus_expand_raise (raise_id, parms, exp)
649 tree raise_id;
650 tree parms;
651 tree exp;
653 /* Allocate new exception of appropriate type, passing
654 PARMS to its constructor. */
655 tree cname, name;
656 tree decl;
657 tree xexp = exp;
659 cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
660 if (cname == error_mark_node)
661 return;
662 name = TREE_VALUE (raise_id);
664 decl = lookup_exception_object (cname, name, 1);
665 if (decl == NULL_TREE)
666 return;
668 if (exp == NULL_TREE)
670 exp = build_method_call (NULL_TREE, name, parms, NULL_TREE, LOOKUP_COMPLAIN);
671 if (exp == error_mark_node)
672 return;
675 if (in_try_block (1))
677 expand_raise (decl);
679 else if (! current_function_decl)
681 if (xexp == NULL_TREE)
682 error_with_decl (decl, "invalid raise of `%s' outside of functions");
683 else
684 error_with_decl (decl, "invalid reraise of `%s' outside of functions");
686 else
688 /* Test this raise against what this function permits. */
689 tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));
690 while (names)
692 if (decl == TREE_TYPE (names))
693 break;
694 names = TREE_CHAIN (names);
696 if (names == NULL_TREE)
698 error ("current function not declared to raise exception `%s'",
699 IDENTIFIER_POINTER (name));
700 return;
704 expand_assignment (EHS_parms, exp, 0, 0);
706 /* Set the global exception handler stack's NAME field
707 to the `name' of this exception. The global exception
708 handler stack is the container for the exception object
709 we just built.
711 We go through a function call to make life easier when debugging. */
712 #if 0
713 expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);
714 #else
715 parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),
716 build_tree_list (NULL_TREE,
717 build_unary_op (ADDR_EXPR, decl, 0)));
718 expand_expr (build_function_call (BIR, parms));
719 #endif
721 /* Activate thrower. If we are inside a TRY statement,
722 we can cheat and not do this, saving a longjmp. */
723 if (in_try_block (1) == 0)
725 sets_exception_throw_decl = 1;
726 expand_assignment (exception_throw_decl, integer_one_node, 0, 0);
729 if (xexp == NULL_TREE)
731 /* Invoke destructors for current procedure or handler. */
732 if (! expand_escape_except ())
733 compiler_error ("except nesting botch");
734 /* Throw via `longjmp'... Done as side-effect of goto. */
736 /* If we were re-raising, just let this fall through.
737 At the end of the reraises, the call to `expand_goto'
738 will take care of everybody. */
741 tree
742 cplus_expand_start_catch (raise_id)
743 tree raise_id;
745 tree cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);
746 tree decl;
747 tree ref, cond;
749 if (cname == error_mark_node)
751 decl = error_mark_node;
752 cond = error_mark_node;
754 else
756 decl = lookup_exception_object (cname, TREE_VALUE (raise_id), 1);
757 if (decl == NULL_TREE)
759 cond = error_mark_node;
761 else
763 ref = build (COMPONENT_REF, ptr_type_node,
764 current_exception_decl, TREE_OPERAND (EHS_name, 1));
765 cond = build_binary_op (EQ_EXPR, build_unary_op (ADDR_EXPR, decl, 0), ref);
768 expand_start_cond (cond, 0);
770 /* Does nothing right now. */
771 expand_catch (decl);
772 if (current_exception_type
773 && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
775 /* Make a cleanup for the name-specific exception object now in scope. */
776 tree cleanup = maybe_build_cleanup (current_exception_object);
777 expand_start_bindings (0);
778 expand_decl_cleanup (NULL_TREE, cleanup);
780 return decl;
783 void
784 cplus_expand_end_catch (for_reraise)
785 int for_reraise;
787 if (current_exception_type
788 && TYPE_NEEDS_DESTRUCTOR (current_exception_type))
790 /* Destroy the specific exception object now in scope. */
791 expand_end_bindings (getdecls (), 0, 1);
793 if (for_reraise)
795 if (! expand_escape_except ())
796 abort ();
798 else
800 if (! expand_end_catch ())
801 abort ();
803 expand_end_cond ();
806 /* Reraise an exception.
807 If EXCEPTIONS is NULL_TREE, it means reraise whatever exception was caught.
808 If EXCEPTIONS is an IDENTIFIER_NODE, it means reraise the exception
809 object named by EXCEPTIONS. This must be a variable declared in
810 an `except' clause.
811 If EXCEPTIONS is a TREE_LIST, it is the list of exceptions we are
812 willing to reraise. */
814 void
815 cplus_expand_reraise (exceptions)
816 tree exceptions;
818 tree ex_ptr;
819 tree ex_object = current_exception_object;
821 if (exceptions && TREE_CODE (exceptions) == IDENTIFIER_NODE)
823 /* Don't get tripped up if its TREE_TYPE is `error_mark_node'. */
824 ex_object = IDENTIFIER_LOCAL_VALUE (exceptions);
825 if (ex_object == NULL_TREE || TREE_CODE (ex_object) != INDIRECT_REF)
827 error ("`%s' is not an exception decl", IDENTIFIER_POINTER (exceptions));
828 return;
830 assert (TREE_CODE (TREE_OPERAND (ex_object, 0)) == VAR_DECL);
831 exceptions = NULL_TREE;
834 /* reraise ALL, used by compiler. */
835 if (exceptions == NULL_TREE)
837 /* Now treat reraise like catch/raise. */
838 expand_catch (error_mark_node);
839 expand_raise (error_mark_node);
840 expand_assignment (EHS_name,
841 build (COMPONENT_REF, ptr_type_node,
842 current_exception_decl, TREE_OPERAND (EHS_name, 1)), 0, 0);
843 expand_assignment (EHS_parms,
844 build (COMPONENT_REF, ptr_type_node,
845 current_exception_decl, TREE_OPERAND (EHS_parms, 1)), 0, 0);
846 if (in_try_block (1) == 0)
848 sets_exception_throw_decl = 1;
849 expand_assignment (exception_throw_decl, integer_one_node, 0, 0);
851 /* Set to zero so that destructor will not be called. */
852 expand_assignment (build1 (NOP_EXPR, ptr_type_node, TREE_OPERAND (ex_object, 0)),
853 integer_zero_node, 0, 0);
854 if (! expand_escape_except ())
855 abort ();
856 return;
859 ex_ptr = build1 (NOP_EXPR, NULL_TREE, TREE_OPERAND (ex_object, 0));
861 /* reraise from a list of exceptions. */
862 while (exceptions)
864 tree type = lookup_exception_type (current_class_type, current_class_name,
865 exceptions);
866 if (type == NULL_TREE)
868 error ("`%s' is not an exception type",
869 IDENTIFIER_POINTER (TREE_VALUE (exceptions)));
870 current_exception_type = NULL_TREE;
871 TREE_TYPE (ex_object) = error_mark_node;
872 TREE_TYPE (ex_ptr) = error_mark_node;
874 else
876 current_exception_type = type;
877 /* In-place union. */
878 TREE_TYPE (ex_object) = type;
879 TREE_TYPE (ex_ptr) = TYPE_POINTER_TO (type);
882 /* Now treat reraise like catch/raise. */
883 cplus_expand_start_catch (exceptions);
884 cplus_expand_raise (exceptions, NULL_TREE, ex_ptr);
885 /* Set to zero so that destructor will not be called. */
886 if (TREE_TYPE (ex_ptr) != error_mark_node)
887 expand_assignment (ex_ptr, integer_zero_node, 0, 0);
888 cplus_expand_end_catch (1);
889 exceptions = TREE_CHAIN (exceptions);
891 /* Don't propagate any unhandled exceptions. */
892 expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);
895 void
896 setup_exception_throw_decl ()
898 tree call_to_longjmp, parms;
900 int old = suspend_momentary ();
902 exception_throw_decl = build_decl (VAR_DECL, get_identifier (THROW_NAME), integer_type_node);
903 pushdecl (exception_throw_decl);
904 parms = tree_cons (NULL_TREE, EHS_handler,
905 build_tree_list (0, integer_one_node));
906 call_to_longjmp = build_function_call (BILJ, parms);
908 expand_decl (exception_throw_decl);
909 expand_decl_cleanup (exception_throw_decl,
910 build (COND_EXPR, void_type_node,
911 exception_throw_decl,
912 call_to_longjmp, integer_zero_node));
913 DECL_INITIAL (exception_throw_decl) = integer_zero_node;
914 sets_exception_throw_decl = 0;
915 resume_momentary (old);
918 void
919 init_exception_processing ()
921 extern tree unhandled_exception_fndecl;
922 tree cname = get_identifier ("ExceptionHandler");
923 tree field, chain;
924 tree ctor, dtor;
925 tree jmp_buf_type = build_array_type (integer_type_node,
926 build_index_type (build_int_2 (_JBLEN-1, 0)));
927 tree jmp_buf_arg_type = build_pointer_type (integer_type_node);
929 tree parmtypes = hash_tree_chain (jmp_buf_arg_type, NULL_TREE);
930 tree setjmp_fndecl, longjmp_fndecl, raise_fndecl;
932 EHS_type = xref_tag (record_type_node, cname, NULL_TREE);
934 push_lang_context (lang_name_c);
935 setjmp_fndecl = define_function ("setjmp",
936 build_function_type (integer_type_node,
937 parmtypes),
938 NOT_BUILT_IN, 0);
939 BISJ = default_conversion (setjmp_fndecl);
940 longjmp_fndecl = define_function ("longjmp",
941 build_function_type (integer_type_node,
942 hash_tree_chain (jmp_buf_arg_type,
943 hash_tree_chain (integer_type_node, NULL_TREE))),
944 NOT_BUILT_IN, 0);
945 raise_fndecl = define_function ("__raise_exception",
946 build_function_type (void_type_node,
947 hash_tree_chain (ptr_type_node,
948 hash_tree_chain (build_pointer_type (ptr_type_node), NULL_TREE))));
949 BILJ = default_conversion (longjmp_fndecl);
950 BIR = default_conversion (raise_fndecl);
951 BIUE = default_conversion (unhandled_exception_fndecl);
953 pop_lang_context ();
955 /* finish_struct will pop this. */
956 pushclass (EHS_type, 0);
957 field = build_lang_field_decl (FIELD_DECL, get_identifier ("parms"), ptr_type_node);
958 chain = field;
959 field = build_lang_field_decl (FIELD_DECL, get_identifier ("name"),
960 build_pointer_type (default_function_type));
961 TREE_CHAIN (field) = chain;
962 chain = field;
963 field = build_lang_field_decl (FIELD_DECL, get_identifier ("handler"), jmp_buf_type);
964 TREE_CHAIN (field) = chain;
965 chain = field;
966 field = build_lang_field_decl (FIELD_DECL, get_identifier ("prev"),
967 TYPE_POINTER_TO (EHS_type));
968 TREE_CHAIN (field) = chain;
969 chain = field;
971 ctor = build_lang_decl (FUNCTION_DECL, cname,
972 build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
973 DECL_CONSTRUCTOR_P (ctor) = 1;
974 TREE_STATIC (ctor) = 1;
975 TREE_PUBLIC (ctor) = 1;
976 grokclassfn (EHS_type, cname, ctor, NO_SPECIAL, 0, 0);
977 finish_decl (ctor, 0, 0);
978 TREE_CHAIN (ctor) = chain;
979 chain = ctor;
980 dtor = build_lang_decl (FUNCTION_DECL, cname,
981 build_cplus_method_type (EHS_type, TYPE_POINTER_TO (EHS_type), void_list_node));
982 TREE_STATIC (dtor) = 1;
983 TREE_PUBLIC (dtor) = 1;
984 grokclassfn (EHS_type, cname, dtor, DTOR_FLAG, 0, 0);
985 finish_decl (dtor, 0, 0);
986 TREE_CHAIN (dtor) = chain;
987 chain = dtor;
988 TYPE_HAS_CONSTRUCTOR (EHS_type) = 1;
989 TYPE_HAS_DESTRUCTOR (EHS_type) = 1;
990 finish_struct (EHS_type, temp_tree_cons (NULL_TREE, chain, NULL_TREE), 0, 0);
993 void
994 init_exception_processing_1 ()
996 register tree EHS_id = get_identifier ("exceptionHandlerStack");
998 EHS_decl = IDENTIFIER_GLOBAL_VALUE (EHS_id);
1000 /* If we have no other definition, default to library implementation. */
1001 if (EHS_decl == NULL_TREE)
1003 EHS_decl = build_decl (VAR_DECL, EHS_id, TYPE_POINTER_TO (EHS_type));
1004 /* If we don't push this, its definition, should it be encountered,
1005 will not be seen. */
1006 EHS_decl = pushdecl (EHS_decl);
1007 TREE_EXTERNAL (EHS_decl) = 1;
1008 TREE_STATIC (EHS_decl) = 1;
1009 TREE_PUBLIC (EHS_decl) = 1;
1010 finish_decl (EHS_decl, 0, 0);
1012 else if (TREE_CODE (EHS_decl) != VAR_DECL
1013 || TREE_TYPE (EHS_decl) != TYPE_POINTER_TO (EHS_type))
1014 fatal ("exception handling declarations conflict with compiler's internal model");
1016 if (EHS_prev == NULL_TREE)
1018 register tree EHS_DECL = build1 (INDIRECT_REF, EHS_type, EHS_decl);
1019 EHS_prev = build_component_ref (EHS_DECL, get_identifier ("prev"), 0, 0);
1020 EHS_handler = build_component_ref (EHS_DECL, get_identifier ("handler"), 0, 0);
1021 EHS_parms = build_component_ref (EHS_DECL, get_identifier ("parms"), 0, 0);
1022 EHS_name = build_component_ref (EHS_DECL, get_identifier ("name"), 0, 0);
1025 if (use_gdb_dbx_extensions)
1026 dbxout_eh_init (EHS_type, EHS_decl);