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