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)
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. */
25 #define EXCEPTION_NAME_PREFIX "__exception_"
29 #include "cplus-tree.h"
32 /* On Suns this can get you to the right definition if you
33 set the right value for TARGET. */
36 /* Can you believe they forgot this? */
41 #define _JBLEN (sizeof(jmp_buf)/sizeof(int))
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
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. */
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. */
80 /* The global handler stack. */
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
96 exception_object_name (prefix
, id
)
100 /* First, cons up the `name' of this exception. */
102 int length
= (id
== void_type_node
? 3 : IDENTIFIER_LENGTH (id
)) + EXCEPTION_NAME_LENGTH
;
105 length
+= IDENTIFIER_LENGTH (prefix
) + 2;
107 name
= (char *)alloca (length
);
108 strcpy (name
, EXCEPTION_NAME_PREFIX
);
109 length
= EXCEPTION_NAME_LENGTH
;
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");
119 strcpy (name
+ length
, IDENTIFIER_POINTER (id
));
120 return get_identifier (name
);
124 lookup_exception_cname (ctype
, cname
, raise_id
)
128 tree this_cname
= TREE_PURPOSE (raise_id
);
129 if (this_cname
== NULL_TREE
)
133 tree name
= TREE_VALUE (raise_id
);
134 if (purpose_member (name
, CLASSTYPE_TAGS (ctype
)))
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
;
149 lookup_exception_tname (oname
)
152 return get_identifier (IDENTIFIER_POINTER (oname
) + EXCEPTION_NAME_LENGTH
);
156 lookup_exception_object (cname
, name
, complain
)
163 if (cname
== void_type_node
)
165 else if (cname
&& TREE_CODE (cname
) != IDENTIFIER_NODE
)
167 sorry ("multiple scope refs in `lookup_exception_object'");
170 oname
= exception_object_name (cname
, name
);
171 decl
= IDENTIFIER_GLOBAL_VALUE (oname
);
172 if (decl
== NULL_TREE
|| TREE_CODE (decl
) != VAR_DECL
)
176 int temp
= allocation_temporary_p ();
178 error ("no exception name object for name `%s::%s'",
179 IDENTIFIER_POINTER (cname
),
180 IDENTIFIER_POINTER (name
));
182 error ("no exception name object for name `%s'",
183 IDENTIFIER_POINTER (name
));
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
),
191 resume_temporary_allocation ();
199 lookup_exception_type (ctype
, cname
, raise_id
)
203 tree name
= TREE_VALUE (raise_id
);
204 tree purpose
= TREE_PURPOSE (raise_id
);
206 if (cname
&& purpose
== NULL_TREE
)
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
;
219 if (! is_aggr_typedef (purpose
, 1))
221 ctype
= TREE_TYPE (TREE_TYPE (purpose
));
222 assoc
= purpose_member (name
, CLASSTYPE_TAGS (ctype
));
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
))
237 finish_exception (e
, list_of_fieldlists
)
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
)
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
))
270 parmtypes
= tree_cons (NULL_TREE
, TREE_TYPE (field
), parmtypes
);
273 error_with_decl (field
, "declaration of function `%s' in exception invalid");
276 if (TREE_STATIC (field
))
277 error_with_decl (field
, "declaration of static variable `%s' in exception invalid");
279 error_with_decl (field
, "declaration of constant field `%s' in exception invalid");
282 error_with_decl (field
, "declaration of enum value `%s' in exception invalid");
285 error ("use of `::' in exception context invalid");
289 TREE_CHAIN (prev
) = TREE_CHAIN (field
);
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"),
298 if (list_of_fieldlists
)
300 TREE_CHAIN (name_field
) = TREE_VALUE (list_of_fieldlists
);
301 TREE_VALUE (list_of_fieldlists
) = name_field
;
304 list_of_fieldlists
= build_tree_list (NULL_TREE
, name_field
);
306 last_exception_fields
= TREE_VALUE (list_of_fieldlists
);
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
;
315 last_exception_field_types
= void_list_node
;
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
)))
324 CLASSTYPE_TAGS (t
) = x
;
328 if (IS_AGGR_TYPE (TREE_VALUE (x
)))
329 TREE_CHAIN (y
) = TREE_CHAIN (x
);
335 cadillac_finish_exception (e
);
341 finish_exception_decl (cname
, decl
)
344 /* In cplus-decl.h. */
345 extern tree last_function_parms
;
347 /* An exception declaration. */
349 tree parmdecls
= NULL_TREE
, fields
;
350 tree list_of_fieldlists
= temp_tree_cons (NULL_TREE
,
351 copy_list (last_exception_fields
),
353 tree edecl
= build_lang_field_decl (VAR_DECL
,
354 exception_object_name (cname
, DECL_NAME (decl
)),
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. */
368 /* Now add a constructor which takes as parameters all the types we
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
));
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
;
385 TREE_CHAIN (parm
) = parmdecls
;
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");
410 /* Now build the constructor for this exception. */
411 parmdecls
= DECL_ARGUMENTS (ctor
);
412 start_function (NULL_TREE
, ctor
, 0, 1);
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. */
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);
439 end_exception_decls ()
441 last_exception_field_types
= NULL_TREE
;
442 last_exception_fields
= NULL_TREE
;
445 /* Statement-level exception semantics. */
448 cplus_expand_start_try (implicit
)
454 /* Start a new block enclosing the whole handler. */
457 pushlevel_temporary (1);
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. */
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. */
495 cplus_expand_end_try (keep
)
498 tree decls
, decl
, block
;
501 pop_implicit_try_blocks (NULL_TREE
);
505 /* Emit code to avoid falling through into a default
506 handler that might come later. */
509 /* Pops binding contour local to TRY, and get the exception handler
510 object built by `...start_try'. */
514 expand_end_bindings (decls
, 0, 1);
515 block
= poplevel (0, 0, 0);
521 expand_end_bindings (decls
, 1, 1);
522 block
= poplevel (1, 1, 0);
528 decl
= tree_last (decls
);
533 assert (TREE_CODE (decl
) == VAR_DECL
&& TREE_TYPE (decl
) == EHS_type
);
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
546 cplus_expand_start_except (name
, decl
)
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. */
574 call_to_unhandled_exception ()
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. */
587 cplus_expand_end_except (dfault
)
590 extern tree
expand_end_except (); /* stmt.c. */
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);
604 /* Try the next handler. */
605 if (! expand_escape_except ())
606 compiler_error ("except nesting botch");
609 raised
= expand_end_except ();
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
)
619 if (! in_try_block (1))
621 /* Check that this function is not raising exceptions
622 it is not supposed to. */
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");
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. */
648 cplus_expand_raise (raise_id
, parms
, exp
)
653 /* Allocate new exception of appropriate type, passing
654 PARMS to its constructor. */
659 cname
= lookup_exception_cname (current_class_type
, current_class_name
, raise_id
);
660 if (cname
== error_mark_node
)
662 name
= TREE_VALUE (raise_id
);
664 decl
= lookup_exception_object (cname
, name
, 1);
665 if (decl
== NULL_TREE
)
668 if (exp
== NULL_TREE
)
670 exp
= build_method_call (NULL_TREE
, name
, parms
, NULL_TREE
, LOOKUP_COMPLAIN
);
671 if (exp
== error_mark_node
)
675 if (in_try_block (1))
679 else if (! current_function_decl
)
681 if (xexp
== NULL_TREE
)
682 error_with_decl (decl
, "invalid raise of `%s' outside of functions");
684 error_with_decl (decl
, "invalid reraise of `%s' outside of functions");
688 /* Test this raise against what this function permits. */
689 tree names
= TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl
));
692 if (decl
== TREE_TYPE (names
))
694 names
= TREE_CHAIN (names
);
696 if (names
== NULL_TREE
)
698 error ("current function not declared to raise exception `%s'",
699 IDENTIFIER_POINTER (name
));
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
711 We go through a function call to make life easier when debugging. */
713 expand_assignment (EHS_name
, build_unary_op (ADDR_EXPR
, decl
, 0), 0, 0);
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
));
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. */
742 cplus_expand_start_catch (raise_id
)
745 tree cname
= lookup_exception_cname (current_class_type
, current_class_name
, raise_id
);
749 if (cname
== error_mark_node
)
751 decl
= error_mark_node
;
752 cond
= error_mark_node
;
756 decl
= lookup_exception_object (cname
, TREE_VALUE (raise_id
), 1);
757 if (decl
== NULL_TREE
)
759 cond
= error_mark_node
;
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. */
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
);
784 cplus_expand_end_catch (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);
795 if (! expand_escape_except ())
800 if (! expand_end_catch ())
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
811 If EXCEPTIONS is a TREE_LIST, it is the list of exceptions we are
812 willing to reraise. */
815 cplus_expand_reraise (exceptions
)
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
));
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 ())
859 ex_ptr
= build1 (NOP_EXPR
, NULL_TREE
, TREE_OPERAND (ex_object
, 0));
861 /* reraise from a list of exceptions. */
864 tree type
= lookup_exception_type (current_class_type
, current_class_name
,
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
;
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);
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
);
919 init_exception_processing ()
921 extern tree unhandled_exception_fndecl
;
922 tree cname
= get_identifier ("ExceptionHandler");
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
,
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
))),
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
);
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
);
959 field
= build_lang_field_decl (FIELD_DECL
, get_identifier ("name"),
960 build_pointer_type (default_function_type
));
961 TREE_CHAIN (field
) = chain
;
963 field
= build_lang_field_decl (FIELD_DECL
, get_identifier ("handler"), jmp_buf_type
);
964 TREE_CHAIN (field
) = chain
;
966 field
= build_lang_field_decl (FIELD_DECL
, get_identifier ("prev"),
967 TYPE_POINTER_TO (EHS_type
));
968 TREE_CHAIN (field
) = chain
;
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
;
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
;
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);
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
);