]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
toplev.h: New file.
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
e5e809f4 2 Copyright (C) 1989, 92-97, 1998 Free Software Foundation, Inc.
8d2733ca
MS
3 Contributed by Michael Tiemann <tiemann@cygnus.com>
4 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
5 initial re-implementation courtesy Tad Hunt.
8d08fdba
MS
6
7This file is part of GNU CC.
8
9GNU CC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU CC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU CC; see the file COPYING. If not, write to
e9fa0c7c
RK
21the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
8d08fdba
MS
23
24
8d08fdba 25#include "config.h"
8d052bc7 26#include "system.h"
8d08fdba
MS
27#include "tree.h"
28#include "rtl.h"
29#include "cp-tree.h"
30#include "flags.h"
8d2733ca
MS
31#include "obstack.h"
32#include "expr.h"
21451173 33#include "output.h"
6467930b
MS
34#include "except.h"
35#include "function.h"
0021b564 36#include "defaults.h"
8d08fdba 37
f30432d7 38rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
a3b49ccd 39
eb66be0e 40/* Holds the fndecl for __builtin_return_address. */
8d2733ca 41tree builtin_return_address_fndecl;
8d2733ca
MS
42
43/* A couple of backend routines from m88k.c */
44
49c249e1 45static void push_eh_cleanup PROTO((void));
49c249e1
JM
46static rtx do_function_call PROTO((tree, tree, tree));
47static tree build_eh_type_type PROTO((tree));
48static tree build_eh_type PROTO((tree));
49static void expand_end_eh_spec PROTO((tree));
69ac77ce
JL
50static tree call_eh_info PROTO((void));
51static void push_eh_info PROTO((void));
52static tree get_eh_info PROTO((void));
53static tree get_eh_value PROTO((void));
54static tree get_eh_type PROTO((void));
55static tree get_eh_caught PROTO((void));
56static tree get_eh_handlers PROTO((void));
57static tree do_pop_exception PROTO((void));
8d2733ca 58
8d2733ca 59#if 0
e92cc029 60/* This is the startup, and finish stuff per exception table. */
8d08fdba 61
8d2733ca
MS
62/* XXX - Tad: exception handling section */
63#ifndef EXCEPT_SECTION_ASM_OP
64#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
65#endif
8d08fdba 66
8d2733ca
MS
67#ifdef EXCEPT_SECTION_ASM_OP
68typedef struct {
6467930b
MS
69 void *start_region;
70 void *end_region;
8d2733ca
MS
71 void *exception_handler;
72 } exception_table;
73#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 74
8d2733ca 75#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 76
8d2733ca
MS
77 /* on machines which support it, the exception table lives in another section,
78 but it needs a label so we can reference it... This sets up that
79 label! */
80asm (EXCEPT_SECTION_ASM_OP);
81exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
82asm (TEXT_SECTION_ASM_OP);
8d08fdba 83
8d2733ca 84#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 85
8d2733ca
MS
86#ifdef EXCEPT_SECTION_ASM_OP
87
88 /* we need to know where the end of the exception table is... so this
89 is how we do it! */
90
91asm (EXCEPT_SECTION_ASM_OP);
92exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
93asm (TEXT_SECTION_ASM_OP);
94
95#endif /* EXCEPT_SECTION_ASM_OP */
96
97#endif
8d08fdba 98
8d2733ca 99#include "decl.h"
8d2733ca
MS
100#include "insn-flags.h"
101#include "obstack.h"
8d2733ca
MS
102
103/* ======================================================================
104 Briefly the algorithm works like this:
105
106 When a constructor or start of a try block is encountered,
107 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
108 new entry in the unwind protection stack and returns a label to
109 output to start the protection for that block.
110
111 When a destructor or end try block is encountered, pop_eh_entry
6467930b
MS
112 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
113 created when push_eh_entry () was called. The eh_entry structure
8d2733ca
MS
114 contains three things at this point. The start protect label,
115 the end protect label, and the exception handler label. The end
116 protect label should be output before the call to the destructor
117 (if any). If it was a destructor, then its parse tree is stored
6467930b 118 in the finalization variable in the eh_entry structure. Otherwise
8d2733ca 119 the finalization variable is set to NULL to reflect the fact that
6467930b 120 is the the end of a try block. Next, this modified eh_entry node
8d2733ca
MS
121 is enqueued in the finalizations queue by calling
122 enqueue_eh_entry (&queue,entry).
123
124 +---------------------------------------------------------------+
125 |XXX: Will need modification to deal with partially |
126 | constructed arrays of objects |
127 | |
128 | Basically, this consists of keeping track of how many |
129 | of the objects have been constructed already (this |
130 | should be in a register though, so that shouldn't be a |
131 | problem. |
132 +---------------------------------------------------------------+
133
134 When a catch block is encountered, there is a lot of work to be
135 done.
136
137 Since we don't want to generate the catch block inline with the
138 regular flow of the function, we need to have some way of doing
f30432d7
MS
139 so. Luckily, we can use sequences to defer the catch sections.
140 When the start of a catch block is encountered, we start the
141 sequence. After the catch block is generated, we end the
142 sequence.
143
8d2733ca
MS
144 Next we must insure that when the catch block is executed, all
145 finalizations for the matching try block have been completed. If
146 any of those finalizations throw an exception, we must call
147 terminate according to the ARM (section r.15.6.1). What this
148 means is that we need to dequeue and emit finalizations for each
6467930b 149 entry in the eh_queue until we get to an entry with a NULL
8d2733ca
MS
150 finalization field. For any of the finalization entries, if it
151 is not a call to terminate (), we must protect it by giving it
152 another start label, end label, and exception handler label,
153 setting its finalization tree to be a call to terminate (), and
6467930b 154 enqueue'ing this new eh_entry to be output at an outer level.
8d2733ca
MS
155 Finally, after all that is done, we can get around to outputting
156 the catch block which basically wraps all the "catch (...) {...}"
157 statements in a big if/then/else construct that matches the
158 correct block to call.
159
160 ===================================================================== */
161
8d2733ca
MS
162/* local globals for function calls
163 ====================================================================== */
164
fb98cff6
JM
165/* Used to cache "terminate" and "__throw_type_match*". */
166static tree Terminate, CatchMatch;
8d2733ca 167
eb66be0e 168/* Used to cache __find_first_exception_table_match for throw. */
8d2733ca
MS
169static tree FirstExceptionMatch;
170
eb66be0e 171/* Used to cache a call to __unwind_function. */
8d2733ca
MS
172static tree Unwind;
173
8d2733ca
MS
174/* ====================================================================== */
175
176
8d2733ca
MS
177/* ========================================================================= */
178
179
180
181/* local globals - these local globals are for storing data necessary for
182 generating the exception table and code in the correct order.
183
184 ========================================================================= */
185
6467930b 186extern rtx catch_clauses;
6c20b7e9 187extern tree const_ptr_type_node;
8d2733ca 188
8d2733ca
MS
189/* ========================================================================= */
190
6467930b 191/* Cheesyness to save some typing. Returns the return value rtx. */
8d2733ca 192
5566b478 193static rtx
f30432d7
MS
194do_function_call (func, params, return_type)
195 tree func, params, return_type;
196{
197 tree func_call;
198 func_call = build_function_call (func, params);
199 expand_call (func_call, NULL_RTX, 0);
200 if (return_type != NULL_TREE)
201 return hard_function_value (return_type, func_call);
202 return NULL_RTX;
203}
204
8d2733ca
MS
205/* ========================================================================= */
206
8d2733ca
MS
207/* sets up all the global eh stuff that needs to be initialized at the
208 start of compilation.
209
210 This includes:
6467930b 211 - Setting up all the function call trees. */
8d08fdba 212
8d08fdba 213void
8d2733ca 214init_exception_processing ()
8d08fdba 215{
6633d636
MS
216 /* void vtype () */
217 tree vtype = build_function_type (void_type_node, void_list_node);
218
fb98cff6
JM
219 Terminate = auto_function (get_identifier ("terminate"),
220 vtype, NOT_BUILT_IN);
221 TREE_THIS_VOLATILE (Terminate) = 1;
8ccc31eb 222
8ccc31eb 223 push_lang_context (lang_name_c);
8d2733ca 224
fb98cff6 225 CatchMatch
beb53fb8
JM
226 = builtin_function (flag_rtti
227 ? "__throw_type_match_rtti"
228 : "__throw_type_match",
229 build_function_type (ptr_type_node,
6c20b7e9
JM
230 tree_cons (NULL_TREE, const_ptr_type_node,
231 tree_cons (NULL_TREE, const_ptr_type_node,
beb53fb8
JM
232 tree_cons (NULL_TREE, ptr_type_node,
233 void_list_node)))),
234 NOT_BUILT_IN, NULL_PTR);
fb98cff6 235 FirstExceptionMatch
beb53fb8
JM
236 = builtin_function ("__find_first_exception_table_match",
237 build_function_type (ptr_type_node,
238 tree_cons (NULL_TREE, ptr_type_node,
239 void_list_node)),
240 NOT_BUILT_IN, NULL_PTR);
fb98cff6 241 Unwind
beb53fb8
JM
242 = builtin_function ("__unwind_function",
243 build_function_type (void_type_node,
244 tree_cons (NULL_TREE, ptr_type_node,
245 void_list_node)),
246 NOT_BUILT_IN, NULL_PTR);
8d2733ca 247
8d2733ca 248 pop_lang_context ();
f30432d7 249
eb66be0e
MS
250 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
251 be protected with __terminate. */
252 protect_cleanup_actions_with_terminate = 1;
8d2733ca
MS
253}
254
95e8dcba 255/* Retrieve a pointer to the cp_eh_info node for the current exception. */
6874c264 256
95e8dcba
JM
257static tree
258call_eh_info ()
6874c264 259{
95e8dcba 260 tree fn;
6874c264
JM
261
262 fn = get_identifier ("__cp_exception_info");
263 if (IDENTIFIER_GLOBAL_VALUE (fn))
264 fn = IDENTIFIER_GLOBAL_VALUE (fn);
265 else
266 {
20b90169 267 tree t, fields[6];
6874c264
JM
268
269 /* Declare cp_eh_info * __cp_exception_info (void),
270 as defined in exception.cc. */
271 push_obstacks_nochange ();
272 end_temporary_allocation ();
273
274 /* struct cp_eh_info. This must match exception.cc. Note that this
275 type is not pushed anywhere. */
276 t = make_lang_type (RECORD_TYPE);
277 fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"),
278 ptr_type_node);
279 fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
280 ptr_type_node);
281 fields[2] = build_lang_field_decl
282 (FIELD_DECL, get_identifier ("cleanup"),
283 build_pointer_type (build_function_type
284 (ptr_type_node, tree_cons
285 (NULL_TREE, ptr_type_node, void_list_node))));
286 fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"),
287 boolean_type_node);
288 fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
289 build_pointer_type (t));
20b90169
JM
290 fields[5] = build_lang_field_decl
291 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
cf9d67e3
BK
292 /* N.B.: The fourth field LEN is expected to be
293 the number of fields - 1, not the total number of fields. */
20b90169 294 finish_builtin_type (t, "cp_eh_info", fields, 5, ptr_type_node);
6874c264
JM
295 t = build_pointer_type (t);
296
297 /* And now the function. */
298 fn = build_lang_decl (FUNCTION_DECL, fn,
299 build_function_type (t, void_list_node));
300 DECL_EXTERNAL (fn) = 1;
301 TREE_PUBLIC (fn) = 1;
302 DECL_ARTIFICIAL (fn) = 1;
303 pushdecl_top_level (fn);
304 make_function_rtl (fn);
305 assemble_external (fn);
306 pop_obstacks ();
307 }
95e8dcba
JM
308 return build_function_call (fn, NULL_TREE);
309}
310
311/* Retrieve a pointer to the cp_eh_info node for the current exception
312 and save it in the current binding level. */
313
314static void
315push_eh_info ()
316{
317 tree decl, fn = call_eh_info ();
6874c264
JM
318
319 /* Remember the pointer to the current exception info; it won't change
320 during this catch block. */
321 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
322 TREE_TYPE (fn));
323 DECL_ARTIFICIAL (decl) = 1;
324 DECL_INITIAL (decl) = fn;
325 decl = pushdecl (decl);
326 cp_finish_decl (decl, fn, NULL_TREE, 0, 0);
327}
328
329/* Returns a reference to the cp_eh_info node for the current exception. */
330
331static tree
332get_eh_info ()
333{
334 /* Look for the pointer pushed in push_eh_info. */
335 tree t = lookup_name (get_identifier ("__exception_info"), 0);
336 return build_indirect_ref (t, NULL_PTR);
337}
338
339/* Returns a reference to the current exception object. */
340
341static tree
342get_eh_value ()
343{
344 return build_component_ref (get_eh_info (), get_identifier ("value"),
345 NULL_TREE, 0);
346}
347
348/* Returns a reference to the current exception type. */
349
350static tree
351get_eh_type ()
352{
353 return build_component_ref (get_eh_info (), get_identifier ("type"),
354 NULL_TREE, 0);
355}
356
357/* Returns a reference to whether or not the current exception
358 has been caught. */
359
360static tree
361get_eh_caught ()
362{
363 return build_component_ref (get_eh_info (), get_identifier ("caught"),
364 NULL_TREE, 0);
365}
366
20b90169
JM
367/* Returns a reference to whether or not the current exception
368 has been caught. */
369
370static tree
371get_eh_handlers ()
372{
373 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
374 NULL_TREE, 0);
375}
376
f30432d7
MS
377/* Build a type value for use at runtime for a type that is matched
378 against by the exception handling system. */
6467930b 379
f30432d7
MS
380static tree
381build_eh_type_type (type)
382 tree type;
8d08fdba 383{
f30432d7
MS
384 char *typestring;
385 tree exp;
8d2733ca 386
f30432d7
MS
387 if (type == error_mark_node)
388 return error_mark_node;
8d2733ca 389
e92cc029 390 /* peel back references, so they match. */
f30432d7
MS
391 if (TREE_CODE (type) == REFERENCE_TYPE)
392 type = TREE_TYPE (type);
8d08fdba 393
e92cc029 394 /* Peel off cv qualifiers. */
f30432d7 395 type = TYPE_MAIN_VARIANT (type);
8d2733ca 396
f30432d7 397 if (flag_rtti)
8d08fdba 398 {
f30432d7 399 return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
8d08fdba 400 }
f30432d7
MS
401
402 typestring = build_overload_name (type, 1, 1);
403 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
404 return build1 (ADDR_EXPR, ptr_type_node, exp);
8d08fdba 405}
8d08fdba 406
faae18ab
MS
407/* Build a type value for use at runtime for a exp that is thrown or
408 matched against by the exception handling system. */
6467930b 409
faae18ab
MS
410static tree
411build_eh_type (exp)
412 tree exp;
413{
faae18ab
MS
414 if (flag_rtti)
415 {
416 exp = build_typeid (exp);
417 return build1 (ADDR_EXPR, ptr_type_node, exp);
418 }
f30432d7 419 return build_eh_type_type (TREE_TYPE (exp));
faae18ab
MS
420}
421
c7ae64f2
JM
422/* Build up a call to __cp_pop_exception, to destroy the exception object
423 for the current catch block. HANDLER is either true or false, telling
424 the library whether or not it is being called from an exception handler;
425 if it is, it avoids destroying the object on rethrow. */
6467930b 426
c7ae64f2 427static tree
de35891e 428do_pop_exception ()
72b7eeff 429{
6874c264 430 tree fn, cleanup;
6874c264
JM
431 fn = get_identifier ("__cp_pop_exception");
432 if (IDENTIFIER_GLOBAL_VALUE (fn))
433 fn = IDENTIFIER_GLOBAL_VALUE (fn);
434 else
435 {
c7ae64f2
JM
436 /* Declare void __cp_pop_exception (void *),
437 as defined in exception.cc. */
6874c264
JM
438 push_obstacks_nochange ();
439 end_temporary_allocation ();
c7ae64f2
JM
440 fn = build_lang_decl
441 (FUNCTION_DECL, fn,
442 build_function_type (void_type_node, tree_cons
de35891e 443 (NULL_TREE, ptr_type_node, void_list_node)));
6874c264
JM
444 DECL_EXTERNAL (fn) = 1;
445 TREE_PUBLIC (fn) = 1;
446 DECL_ARTIFICIAL (fn) = 1;
447 pushdecl_top_level (fn);
448 make_function_rtl (fn);
449 assemble_external (fn);
450 pop_obstacks ();
451 }
72b7eeff
MS
452
453 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
c7ae64f2
JM
454 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
455 cleanup = build_function_call (fn, expr_tree_cons
de35891e 456 (NULL_TREE, cleanup, NULL_TREE));
c0700ea5 457 return cleanup;
c7ae64f2
JM
458}
459
460/* This routine creates the cleanup for the current exception. */
72b7eeff 461
c7ae64f2
JM
462static void
463push_eh_cleanup ()
464{
de35891e 465 int yes;
72b7eeff 466
20b90169
JM
467 expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
468 const0_rtx, VOIDmode, EXPAND_NORMAL);
469
de35891e
JM
470 yes = suspend_momentary ();
471 /* All cleanups must last longer than normal. */
472 expand_decl_cleanup (NULL_TREE, do_pop_exception ());
473 resume_momentary (yes);
c7ae64f2 474}
72b7eeff 475
f4a23343
JM
476/* Build up a call to terminate on the function obstack, for use as an
477 exception handler. */
478
479tree
480build_terminate_handler ()
481{
482 int yes = suspend_momentary ();
483 tree term = build_function_call (Terminate, NULL_TREE);
484 resume_momentary (yes);
485 return term;
486}
487
8d2733ca
MS
488/* call this to start a catch block. Typename is the typename, and identifier
489 is the variable to place the object in or NULL if the variable doesn't
490 matter. If typename is NULL, that means its a "catch (...)" or catch
491 everything. In that case we don't need to do any type checking.
492 (ie: it ends up as the "else" clause rather than an "else if" clause) */
6467930b 493
8d08fdba 494void
a4443a08
MS
495expand_start_catch_block (declspecs, declarator)
496 tree declspecs, declarator;
8d08fdba 497{
8d2733ca 498 rtx false_label_rtx;
faae18ab 499 tree decl = NULL_TREE;
a3b49ccd 500 tree init;
8d2733ca 501
faf5394a
MS
502 if (processing_template_decl)
503 {
504 if (declspecs)
505 {
506 decl = grokdeclarator (declarator, declspecs, CATCHPARM,
507 1, NULL_TREE);
508 pushdecl (decl);
509 decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
510 copy_to_permanent (declspecs),
511 NULL_TREE);
512 add_tree (decl);
513 }
514 return;
515 }
516
8d2733ca
MS
517 if (! doing_eh (1))
518 return;
519
c7ae64f2
JM
520 /* Create a binding level for the eh_info and the exception object
521 cleanup. */
c11b6f21 522 pushlevel (0);
a3b49ccd
MS
523 expand_start_bindings (0);
524
f675499c 525 false_label_rtx = gen_label_rtx ();
72b7eeff 526 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
a3b49ccd 527
eb66be0e
MS
528 emit_line_note (input_filename, lineno);
529
6874c264
JM
530 push_eh_info ();
531
faae18ab 532 if (declspecs)
8d08fdba 533 {
c11b6f21 534 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
faae18ab
MS
535
536 if (decl == NULL_TREE)
c7ae64f2
JM
537 error ("invalid catch parameter");
538 }
95e8dcba 539
c7ae64f2
JM
540 if (decl)
541 {
542 tree exp;
543 rtx call_rtx, return_value_rtx;
544 tree init_type;
faae18ab 545
be99da77
MS
546 /* Make sure we mark the catch param as used, otherwise we'll get
547 a warning about an unused ((anonymous)). */
548 TREE_USED (decl) = 1;
549
e92cc029 550 /* Figure out the type that the initializer is. */
faae18ab 551 init_type = TREE_TYPE (decl);
f30432d7
MS
552 if (TREE_CODE (init_type) != REFERENCE_TYPE
553 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
554 init_type = build_reference_type (init_type);
555
6874c264 556 exp = get_eh_value ();
92f5c135
JM
557
558 /* Since pointers are passed by value, initialize a reference to
559 pointer catch parm with the address of the value slot. */
560 if (TREE_CODE (init_type) == REFERENCE_TYPE
561 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
562 exp = build_unary_op (ADDR_EXPR, exp, 1);
563
e66d884e 564 exp = expr_tree_cons (NULL_TREE,
f30432d7 565 build_eh_type_type (TREE_TYPE (decl)),
e66d884e 566 expr_tree_cons (NULL_TREE,
6874c264 567 get_eh_type (),
e66d884e 568 expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
faae18ab
MS
569 exp = build_function_call (CatchMatch, exp);
570 call_rtx = expand_call (exp, NULL_RTX, 0);
8d2733ca 571
faae18ab 572 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
573
574 /* did the throw type match function return TRUE? */
faae18ab 575 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
576 GET_MODE (return_value_rtx), 0, 0);
577
578 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
579 emit_jump_insn (gen_beq (false_label_rtx));
580
95e8dcba
JM
581 push_eh_cleanup ();
582
c7ae64f2
JM
583 /* Create a binding level for the parm. */
584 pushlevel (0);
585 expand_start_bindings (0);
586
587 init = convert_from_reference (make_tree (init_type, call_rtx));
588
589 /* If the constructor for the catch parm exits via an exception, we
590 must call terminate. See eh23.C. */
591 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
592 {
593 /* Generate the copy constructor call directly so we can wrap it.
594 See also expand_default_init. */
595 init = ocp_convert (TREE_TYPE (decl), init,
596 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
f4a23343
JM
597 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
598 build_terminate_handler ());
c7ae64f2 599 }
faae18ab 600
b3417a04 601 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
602 DECL_INITIAL (decl) = init;
603 decl = pushdecl (decl);
c7ae64f2 604
b3417a04 605 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba 606 }
95e8dcba
JM
607 else
608 {
609 push_eh_cleanup ();
610
c7ae64f2
JM
611 /* Create a binding level for the parm. */
612 pushlevel (0);
613 expand_start_bindings (0);
614
95e8dcba
JM
615 /* Fall into the catch all section. */
616 }
72b7eeff 617
6874c264
JM
618 init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
619 expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
f30432d7 620
6467930b
MS
621 emit_line_note (input_filename, lineno);
622}
f30432d7 623
f30432d7 624
f30432d7 625
8d2733ca
MS
626/* Call this to end a catch block. Its responsible for emitting the
627 code to handle jumping back to the correct place, and for emitting
628 the label to jump to if this catch block didn't match. */
6467930b 629
824b9a4c
MS
630void
631expand_end_catch_block ()
8d08fdba 632{
f30432d7
MS
633 if (! doing_eh (1))
634 return;
8d2733ca 635
c7ae64f2
JM
636 /* Cleanup the EH parameter. */
637 expand_end_bindings (getdecls (), kept_level_p (), 0);
638 poplevel (kept_level_p (), 1, 0);
639
c7ae64f2
JM
640 /* Cleanup the EH object. */
641 expand_end_bindings (getdecls (), kept_level_p (), 0);
642 poplevel (kept_level_p (), 1, 0);
eb66be0e 643
eb66be0e
MS
644 /* Fall to outside the try statement when done executing handler and
645 we fall off end of handler. This is jump Lresume in the
646 documentation. */
647 expand_goto (top_label_entry (&caught_return_label_stack));
648
6467930b 649 /* label we emit to jump to if this catch block didn't match. */
f30432d7
MS
650 /* This the closing } in the `if (eq) {' of the documentation. */
651 emit_label (pop_label_entry (&false_label_stack));
8d2733ca 652}
8d08fdba 653
6c20b7e9
JM
654/* An exception spec is implemented more or less like:
655
656 try {
657 function body;
658 } catch (...) {
659 void *p[] = { typeid(raises) };
660 __check_eh_spec (p, count);
661 }
662
663 __check_eh_spec in exception.cc handles all the details. */
8d2733ca 664
f30432d7
MS
665void
666expand_start_eh_spec ()
667{
6c20b7e9 668 expand_start_try_stmts ();
f30432d7
MS
669}
670
5566b478 671static void
f30432d7
MS
672expand_end_eh_spec (raises)
673 tree raises;
674{
6c20b7e9
JM
675 tree tmp, fn, decl, types = NULL_TREE;
676 int count = 0;
f30432d7 677
6c20b7e9
JM
678 expand_start_all_catch ();
679 expand_start_catch_block (NULL_TREE, NULL_TREE);
f30432d7 680
6c20b7e9
JM
681 /* Build up an array of type_infos. */
682 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
683 {
684 types = expr_tree_cons
685 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
686 ++count;
687 }
eb66be0e 688
6c20b7e9
JM
689 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
690 TREE_HAS_CONSTRUCTOR (types) = 1;
6874c264 691
6c20b7e9
JM
692 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
693 tmp = build_array_type (const_ptr_type_node, NULL_TREE);
694 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
695 DECL_ARTIFICIAL (decl) = 1;
696 DECL_INITIAL (decl) = types;
697 cp_finish_decl (decl, types, NULL_TREE, 0, 0);
698
699 decl = decay_conversion (decl);
6874c264 700
6c20b7e9
JM
701 fn = get_identifier ("__check_eh_spec");
702 if (IDENTIFIER_GLOBAL_VALUE (fn))
703 fn = IDENTIFIER_GLOBAL_VALUE (fn);
704 else
f30432d7 705 {
6c20b7e9
JM
706 push_obstacks_nochange ();
707 end_temporary_allocation ();
f30432d7 708
6c20b7e9
JM
709 tmp = tree_cons
710 (NULL_TREE, integer_type_node, tree_cons
711 (NULL_TREE, TREE_TYPE (decl), void_list_node));
712 tmp = build_function_type (void_type_node, tmp);
f30432d7 713
6c20b7e9
JM
714 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
715 DECL_EXTERNAL (fn) = 1;
716 TREE_PUBLIC (fn) = 1;
717 DECL_ARTIFICIAL (fn) = 1;
718 TREE_THIS_VOLATILE (fn) = 1;
719 pushdecl_top_level (fn);
720 make_function_rtl (fn);
721 assemble_external (fn);
722 pop_obstacks ();
723 }
724
725 tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
726 (NULL_TREE, decl, NULL_TREE));
727 tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
728 expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
729
730 expand_end_catch_block ();
731 expand_end_all_catch ();
f30432d7
MS
732}
733
8d2733ca
MS
734/* This is called to expand all the toplevel exception handling
735 finalization for a function. It should only be called once per
736 function. */
6467930b 737
8d08fdba 738void
8d2733ca 739expand_exception_blocks ()
8d08fdba 740{
92b96838 741 do_pending_stack_adjust ();
e00737d2 742 push_to_sequence (catch_clauses);
8d2733ca 743 expand_leftover_cleanups ();
92b96838 744 do_pending_stack_adjust ();
e00737d2 745 catch_clauses = get_insns ();
f30432d7 746 end_sequence ();
eb448459 747
eb448459
MS
748 /* Do this after we expand leftover cleanups, so that the
749 expand_eh_region_end that expand_end_eh_spec does will match the
750 right expand_eh_region_start, and make sure it comes out before
751 the terminate protected region. */
f30432d7
MS
752 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
753 {
eb448459 754 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
92b96838 755 do_pending_stack_adjust ();
e00737d2 756 push_to_sequence (catch_clauses);
eb448459 757 expand_leftover_cleanups ();
92b96838 758 do_pending_stack_adjust ();
e00737d2 759 catch_clauses = get_insns ();
eb448459 760 end_sequence ();
f30432d7
MS
761 }
762
e00737d2 763 if (catch_clauses)
f30432d7 764 {
e00737d2
MS
765 rtx funcend = gen_label_rtx ();
766 emit_jump (funcend);
767
eb66be0e
MS
768 /* We cannot protect n regions this way if we must flow into the
769 EH region through the top of the region, as we have to with
770 the setjmp/longjmp approach. */
771 if (exceptions_via_longjmp == 0)
fb98cff6 772 expand_eh_region_start ();
f30432d7 773
e00737d2
MS
774 emit_insns (catch_clauses);
775 catch_clauses = NULL_RTX;
eb66be0e
MS
776
777 if (exceptions_via_longjmp == 0)
f4a23343 778 expand_eh_region_end (build_terminate_handler ());
eb66be0e 779
6467930b 780 expand_leftover_cleanups ();
f30432d7 781
e00737d2
MS
782 emit_label (funcend);
783 }
8d08fdba
MS
784}
785
72b7eeff
MS
786tree
787start_anon_func ()
788{
789 static int counter = 0;
e92cc029 790 int old_interface_unknown = interface_unknown;
72b7eeff
MS
791 char name[32];
792 tree params;
793 tree t;
794
795 push_cp_function_context (NULL_TREE);
796 push_to_top_level ();
797
798 /* No need to mangle this. */
799 push_lang_context (lang_name_c);
800
e92cc029
MS
801 interface_unknown = 1;
802
72b7eeff 803 params = void_list_node;
956d6950 804 /* tcf stands for throw clean function. */
72b7eeff 805 sprintf (name, "__tcf_%d", counter++);
c11b6f21
MS
806 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
807 NULL_TREE);
72b7eeff
MS
808 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
809 void_list_node),
c11b6f21 810 t, NULL_TREE, 0);
72b7eeff
MS
811 store_parm_decls ();
812 pushlevel (0);
813 clear_last_expr ();
814 push_momentary ();
815 expand_start_bindings (0);
816 emit_line_note (input_filename, lineno);
817
e92cc029
MS
818 interface_unknown = old_interface_unknown;
819
72b7eeff
MS
820 pop_lang_context ();
821
822 return current_function_decl;
823}
824
825void
826end_anon_func ()
827{
fc378698 828 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
829 poplevel (1, 0, 0);
830 pop_momentary ();
831
832 finish_function (lineno, 0, 0);
833
834 pop_from_top_level ();
835 pop_cp_function_context (NULL_TREE);
836}
8d2733ca 837
f4a23343
JM
838/* Return a pointer to a buffer for an exception object of type TYPE. */
839
840tree
841alloc_eh_object (type)
842 tree type;
843{
844 tree fn, exp;
845
846 fn = get_identifier ("__eh_alloc");
847 if (IDENTIFIER_GLOBAL_VALUE (fn))
848 fn = IDENTIFIER_GLOBAL_VALUE (fn);
849 else
850 {
851 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
852 tree tmp;
853 push_obstacks_nochange ();
854 end_temporary_allocation ();
855 tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
856 fn = build_lang_decl (FUNCTION_DECL, fn,
857 build_function_type (ptr_type_node, tmp));
858 DECL_EXTERNAL (fn) = 1;
859 TREE_PUBLIC (fn) = 1;
860 DECL_ARTIFICIAL (fn) = 1;
861 pushdecl_top_level (fn);
862 make_function_rtl (fn);
863 assemble_external (fn);
864 pop_obstacks ();
865 }
866
867 exp = build_function_call (fn, expr_tree_cons
868 (NULL_TREE, size_in_bytes (type), NULL_TREE));
869 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
870 return exp;
871}
872
6467930b 873/* Expand a throw statement. This follows the following
8d2733ca
MS
874 algorithm:
875
876 1. Allocate space to save the current PC onto the stack.
877 2. Generate and emit a label and save its address into the
e1cd6e56 878 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
879 3. If this is the first call to throw in this function:
880 generate a label for the throw block
881 4. jump to the throw block label. */
6467930b 882
8d08fdba 883void
8d2733ca
MS
884expand_throw (exp)
885 tree exp;
8d08fdba 886{
6874c264
JM
887 tree fn;
888 static tree cleanup_type;
8d08fdba 889
8d2733ca
MS
890 if (! doing_eh (1))
891 return;
8d08fdba 892
8d2733ca
MS
893 if (exp)
894 {
faae18ab 895 tree throw_type;
6874c264 896 tree cleanup = NULL_TREE, e;
faae18ab 897
a3b49ccd 898 /* throw expression */
e92cc029 899 /* First, decay it. */
f30432d7 900 exp = decay_conversion (exp);
a3b49ccd 901
6874c264
JM
902 /* cleanup_type is void (*)(void *, int),
903 the internal type of a destructor. */
904 if (cleanup_type == NULL_TREE)
905 {
906 push_obstacks_nochange ();
907 end_temporary_allocation ();
908 cleanup_type = build_pointer_type
909 (build_function_type
910 (void_type_node, tree_cons
911 (NULL_TREE, ptr_type_node, tree_cons
912 (NULL_TREE, integer_type_node, void_list_node))));
913 pop_obstacks ();
914 }
915
f30432d7
MS
916 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
917 {
918 throw_type = build_eh_type (exp);
919 exp = build_reinterpret_cast (ptr_type_node, exp);
920 }
921 else
922 {
f4a23343
JM
923 tree object, ptr;
924
925 /* OK, this is kind of wacky. The WP says that we call
926 terminate
927
928 when the exception handling mechanism, after completing
929 evaluation of the expression to be thrown but before the
930 exception is caught (_except.throw_), calls a user function
931 that exits via an uncaught exception.
932
933 So we have to protect the actual initialization of the
934 exception object with terminate(), but evaluate the expression
935 first. We also expand the call to __eh_alloc
936 first. Since there could be temps in the expression, we need
937 to handle that, too. */
a50f0918 938
f4a23343
JM
939 expand_start_target_temps ();
940
941#if 0
942 /* Unfortunately, this doesn't work. */
943 preexpand_calls (exp);
944#else
945 /* Store the throw expression into a temp. This can be less
946 efficient than storing it into the allocated space directly, but
947 oh well. To do this efficiently we would need to insinuate
948 ourselves into expand_call. */
949 if (TREE_SIDE_EFFECTS (exp))
950 {
951 tree temp = build (VAR_DECL, TREE_TYPE (exp));
952 DECL_ARTIFICIAL (temp) = 1;
953 layout_decl (temp, 0);
954 DECL_RTL (temp) = assign_temp (TREE_TYPE (exp), 2, 0, 1);
955 expand_expr (build (INIT_EXPR, TREE_TYPE (exp), temp, exp),
956 NULL_RTX, VOIDmode, 0);
957 expand_decl_cleanup (NULL_TREE, maybe_build_cleanup (temp));
958 exp = temp;
959 }
960#endif
961
962 /* Allocate the space for the exception. */
963 ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
964 expand_expr (ptr, const0_rtx, VOIDmode, 0);
965
966 expand_eh_region_start ();
967
968 object = build_indirect_ref (ptr, NULL_PTR);
969 exp = build_modify_expr (object, INIT_EXPR, exp);
faae18ab 970
f30432d7
MS
971 if (exp == error_mark_node)
972 error (" in thrown expression");
faae18ab 973
f4a23343
JM
974 expand_expr (exp, const0_rtx, VOIDmode, 0);
975 expand_eh_region_end (build_terminate_handler ());
976 expand_end_target_temps ();
977
72b7eeff
MS
978 throw_type = build_eh_type (object);
979
6874c264
JM
980 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
981 {
982 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
983 dtor_identifier, 0);
984 cleanup = TREE_VALUE (cleanup);
e872bb7a 985 mark_used (cleanup);
6874c264
JM
986 mark_addressable (cleanup);
987 /* Pretend it's a normal function. */
988 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
989 }
f4a23343
JM
990
991 exp = ptr;
f30432d7 992 }
faae18ab 993
6874c264
JM
994 if (cleanup == NULL_TREE)
995 {
996 cleanup = build_int_2 (0, 0);
997 TREE_TYPE (cleanup) = cleanup_type;
998 }
72b7eeff 999
6874c264
JM
1000 fn = get_identifier ("__cp_push_exception");
1001 if (IDENTIFIER_GLOBAL_VALUE (fn))
1002 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1003 else
1004 {
1005 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
1006 as defined in exception.cc. */
1007 tree tmp;
1008 push_obstacks_nochange ();
1009 end_temporary_allocation ();
1010 tmp = tree_cons
1011 (NULL_TREE, ptr_type_node, tree_cons
1012 (NULL_TREE, ptr_type_node, tree_cons
1013 (NULL_TREE, cleanup_type, void_list_node)));
1014 fn = build_lang_decl (FUNCTION_DECL, fn,
1015 build_function_type (void_type_node, tmp));
1016 DECL_EXTERNAL (fn) = 1;
1017 TREE_PUBLIC (fn) = 1;
1018 DECL_ARTIFICIAL (fn) = 1;
1019 pushdecl_top_level (fn);
1020 make_function_rtl (fn);
1021 assemble_external (fn);
1022 pop_obstacks ();
1023 }
72b7eeff 1024
6874c264
JM
1025 e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
1026 (NULL_TREE, throw_type, expr_tree_cons
1027 (NULL_TREE, cleanup, NULL_TREE)));
1028 e = build_function_call (fn, e);
1029 expand_expr (e, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1030 }
1031 else
a3b49ccd 1032 {
6874c264
JM
1033 /* rethrow current exception; note that it's no longer caught. */
1034
1035 tree fn = get_identifier ("__uncatch_exception");
1036 if (IDENTIFIER_GLOBAL_VALUE (fn))
1037 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1038 else
1039 {
1040 /* Declare void __uncatch_exception (void)
1041 as defined in exception.cc. */
1042 push_obstacks_nochange ();
1043 end_temporary_allocation ();
1044 fn = build_lang_decl (FUNCTION_DECL, fn,
1045 build_function_type (void_type_node,
1046 void_list_node));
1047 DECL_EXTERNAL (fn) = 1;
1048 TREE_PUBLIC (fn) = 1;
1049 DECL_ARTIFICIAL (fn) = 1;
1050 pushdecl_top_level (fn);
1051 make_function_rtl (fn);
1052 assemble_external (fn);
1053 pop_obstacks ();
1054 }
1055
1056 exp = build_function_call (fn, NULL_TREE);
1057 expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
a3b49ccd 1058 }
8d2733ca 1059
e701eb4d 1060 expand_internal_throw ();
f376e137 1061}
8d2733ca
MS
1062
1063/* Build a throw expression. */
6467930b 1064
8d2733ca
MS
1065tree
1066build_throw (e)
1067 tree e;
1068{
db5ae43f
MS
1069 if (e != error_mark_node)
1070 {
5156628f 1071 if (processing_template_decl)
fc378698 1072 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1073 e = build1 (THROW_EXPR, void_type_node, e);
1074 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1075 TREE_USED (e) = 1;
db5ae43f 1076 }
8d2733ca 1077 return e;
8d08fdba 1078}
This page took 0.413894 seconds and 5 git commands to generate.