]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
integrate.c (output_inline_function): Just unset DECL_INLINE.
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
6467930b 2 Copyright (C) 1989, 92-95, 1996 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
eb66be0e 45/* Used to cache a call to __builtin_return_address. */
8d2733ca 46static tree BuiltinReturnAddress;
f30432d7 47
49c249e1
JM
48static void easy_expand_asm PROTO((char *));
49static void push_eh_cleanup PROTO((void));
50static void do_unwind PROTO((rtx));
51static rtx do_function_call PROTO((tree, tree, tree));
52static tree build_eh_type_type PROTO((tree));
53static tree build_eh_type PROTO((tree));
54static void expand_end_eh_spec PROTO((tree));
8d2733ca 55
8d2733ca
MS
56static void
57easy_expand_asm (str)
58 char *str;
59{
60 expand_asm (build_string (strlen (str)+1, str));
8d08fdba
MS
61}
62
8d08fdba 63
8d2733ca 64#if 0
e92cc029 65/* This is the startup, and finish stuff per exception table. */
8d08fdba 66
8d2733ca
MS
67/* XXX - Tad: exception handling section */
68#ifndef EXCEPT_SECTION_ASM_OP
69#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
70#endif
8d08fdba 71
8d2733ca
MS
72#ifdef EXCEPT_SECTION_ASM_OP
73typedef struct {
6467930b
MS
74 void *start_region;
75 void *end_region;
8d2733ca
MS
76 void *exception_handler;
77 } exception_table;
78#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 79
8d2733ca 80#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 81
8d2733ca
MS
82 /* on machines which support it, the exception table lives in another section,
83 but it needs a label so we can reference it... This sets up that
84 label! */
85asm (EXCEPT_SECTION_ASM_OP);
86exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
87asm (TEXT_SECTION_ASM_OP);
8d08fdba 88
8d2733ca 89#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 90
8d2733ca
MS
91#ifdef EXCEPT_SECTION_ASM_OP
92
93 /* we need to know where the end of the exception table is... so this
94 is how we do it! */
95
96asm (EXCEPT_SECTION_ASM_OP);
97exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
98asm (TEXT_SECTION_ASM_OP);
99
100#endif /* EXCEPT_SECTION_ASM_OP */
101
102#endif
8d08fdba 103
8d2733ca 104#include "decl.h"
8d2733ca
MS
105#include "insn-flags.h"
106#include "obstack.h"
8d2733ca
MS
107
108/* ======================================================================
109 Briefly the algorithm works like this:
110
111 When a constructor or start of a try block is encountered,
112 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
113 new entry in the unwind protection stack and returns a label to
114 output to start the protection for that block.
115
116 When a destructor or end try block is encountered, pop_eh_entry
6467930b
MS
117 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
118 created when push_eh_entry () was called. The eh_entry structure
8d2733ca
MS
119 contains three things at this point. The start protect label,
120 the end protect label, and the exception handler label. The end
121 protect label should be output before the call to the destructor
122 (if any). If it was a destructor, then its parse tree is stored
6467930b 123 in the finalization variable in the eh_entry structure. Otherwise
8d2733ca 124 the finalization variable is set to NULL to reflect the fact that
6467930b 125 is the the end of a try block. Next, this modified eh_entry node
8d2733ca
MS
126 is enqueued in the finalizations queue by calling
127 enqueue_eh_entry (&queue,entry).
128
129 +---------------------------------------------------------------+
130 |XXX: Will need modification to deal with partially |
131 | constructed arrays of objects |
132 | |
133 | Basically, this consists of keeping track of how many |
134 | of the objects have been constructed already (this |
135 | should be in a register though, so that shouldn't be a |
136 | problem. |
137 +---------------------------------------------------------------+
138
139 When a catch block is encountered, there is a lot of work to be
140 done.
141
142 Since we don't want to generate the catch block inline with the
143 regular flow of the function, we need to have some way of doing
f30432d7
MS
144 so. Luckily, we can use sequences to defer the catch sections.
145 When the start of a catch block is encountered, we start the
146 sequence. After the catch block is generated, we end the
147 sequence.
148
8d2733ca
MS
149 Next we must insure that when the catch block is executed, all
150 finalizations for the matching try block have been completed. If
151 any of those finalizations throw an exception, we must call
152 terminate according to the ARM (section r.15.6.1). What this
153 means is that we need to dequeue and emit finalizations for each
6467930b 154 entry in the eh_queue until we get to an entry with a NULL
8d2733ca
MS
155 finalization field. For any of the finalization entries, if it
156 is not a call to terminate (), we must protect it by giving it
157 another start label, end label, and exception handler label,
158 setting its finalization tree to be a call to terminate (), and
6467930b 159 enqueue'ing this new eh_entry to be output at an outer level.
8d2733ca
MS
160 Finally, after all that is done, we can get around to outputting
161 the catch block which basically wraps all the "catch (...) {...}"
162 statements in a big if/then/else construct that matches the
163 correct block to call.
164
165 ===================================================================== */
166
8d2733ca
MS
167/* local globals for function calls
168 ====================================================================== */
169
eb66be0e
MS
170/* Used to cache "terminate", "unexpected", "set_terminate", and
171 "set_unexpected" after default_conversion. (lib-except.c) */
6467930b 172static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
8d2733ca 173
eb66be0e 174/* Used to cache __find_first_exception_table_match for throw. */
8d2733ca
MS
175static tree FirstExceptionMatch;
176
eb66be0e 177/* Used to cache a call to __unwind_function. */
8d2733ca
MS
178static tree Unwind;
179
eb66be0e 180/* Holds a ready to emit call to "terminate". */
8d2733ca
MS
181static tree TerminateFunctionCall;
182
183/* ====================================================================== */
184
185
8d2733ca
MS
186/* ========================================================================= */
187
188
189
190/* local globals - these local globals are for storing data necessary for
191 generating the exception table and code in the correct order.
192
193 ========================================================================= */
194
a3b49ccd 195/* Holds the pc for doing "throw" */
5566b478 196static tree saved_pc;
f30432d7 197
6467930b
MS
198extern int throw_used;
199extern rtx catch_clauses;
6c20b7e9 200extern tree const_ptr_type_node;
8d2733ca 201
8d2733ca
MS
202/* ========================================================================= */
203
6467930b 204/* Cheesyness to save some typing. Returns the return value rtx. */
8d2733ca 205
5566b478 206static rtx
f30432d7
MS
207do_function_call (func, params, return_type)
208 tree func, params, return_type;
209{
210 tree func_call;
211 func_call = build_function_call (func, params);
212 expand_call (func_call, NULL_RTX, 0);
213 if (return_type != NULL_TREE)
214 return hard_function_value (return_type, func_call);
215 return NULL_RTX;
216}
217
8d2733ca
MS
218/* ========================================================================= */
219
8d2733ca
MS
220/* sets up all the global eh stuff that needs to be initialized at the
221 start of compilation.
222
223 This includes:
6467930b 224 - Setting up all the function call trees. */
8d08fdba 225
8d08fdba 226void
8d2733ca 227init_exception_processing ()
8d08fdba 228{
8d2733ca
MS
229 tree unexpected_fndecl, terminate_fndecl;
230 tree set_unexpected_fndecl, set_terminate_fndecl;
231 tree catch_match_fndecl;
232 tree find_first_exception_match_fndecl;
233 tree unwind_fndecl;
f30432d7
MS
234 tree declspecs;
235 tree d;
a3b49ccd 236
6633d636
MS
237 /* void vtype () */
238 tree vtype = build_function_type (void_type_node, void_list_node);
239
8d2733ca 240 /* void (*)() */
6633d636 241 tree PFV = build_pointer_type (vtype);
8d08fdba 242
eb66be0e
MS
243 /* Arg list for the build_function_type call for set_terminate and
244 set_unexpected. */
8ccc31eb 245 tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
8d08fdba 246
8ccc31eb
MS
247 /* void (*pfvtype (void (*) ()))() */
248 tree pfvtype = build_function_type (PFV, pfvlist);
8d2733ca 249
8ccc31eb
MS
250 set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
251 pfvtype, NOT_BUILT_IN);
252 set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
253 pfvtype, NOT_BUILT_IN);
254 unexpected_fndecl = auto_function (get_identifier ("unexpected"),
255 vtype, NOT_BUILT_IN);
256 terminate_fndecl = auto_function (get_identifier ("terminate"),
257 vtype, NOT_BUILT_IN);
e00737d2 258 TREE_THIS_VOLATILE (terminate_fndecl) = 1;
8ccc31eb 259
8ccc31eb 260 push_lang_context (lang_name_c);
8d2733ca 261
beb53fb8
JM
262 catch_match_fndecl
263 = builtin_function (flag_rtti
264 ? "__throw_type_match_rtti"
265 : "__throw_type_match",
266 build_function_type (ptr_type_node,
6c20b7e9
JM
267 tree_cons (NULL_TREE, const_ptr_type_node,
268 tree_cons (NULL_TREE, const_ptr_type_node,
beb53fb8
JM
269 tree_cons (NULL_TREE, ptr_type_node,
270 void_list_node)))),
271 NOT_BUILT_IN, NULL_PTR);
272 find_first_exception_match_fndecl
273 = builtin_function ("__find_first_exception_table_match",
274 build_function_type (ptr_type_node,
275 tree_cons (NULL_TREE, ptr_type_node,
276 void_list_node)),
277 NOT_BUILT_IN, NULL_PTR);
278 unwind_fndecl
279 = builtin_function ("__unwind_function",
280 build_function_type (void_type_node,
281 tree_cons (NULL_TREE, ptr_type_node,
282 void_list_node)),
283 NOT_BUILT_IN, NULL_PTR);
8d2733ca
MS
284
285 Unexpected = default_conversion (unexpected_fndecl);
286 Terminate = default_conversion (terminate_fndecl);
287 SetTerminate = default_conversion (set_terminate_fndecl);
288 SetUnexpected = default_conversion (set_unexpected_fndecl);
289 CatchMatch = default_conversion (catch_match_fndecl);
290 FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
291 Unwind = default_conversion (unwind_fndecl);
292 BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
293
294 TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
295
296 pop_lang_context ();
f30432d7 297
6874c264
JM
298 d = build_decl (VAR_DECL, get_identifier ("__eh_pc"), ptr_type_node);
299 TREE_PUBLIC (d) = 1;
300 DECL_EXTERNAL (d) = 1;
301 DECL_ARTIFICIAL (d) = 1;
302 cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
303 saved_pc = d;
eb66be0e
MS
304
305 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
306 be protected with __terminate. */
307 protect_cleanup_actions_with_terminate = 1;
8d2733ca
MS
308}
309
95e8dcba 310/* Retrieve a pointer to the cp_eh_info node for the current exception. */
6874c264 311
95e8dcba
JM
312static tree
313call_eh_info ()
6874c264 314{
95e8dcba 315 tree fn;
6874c264
JM
316
317 fn = get_identifier ("__cp_exception_info");
318 if (IDENTIFIER_GLOBAL_VALUE (fn))
319 fn = IDENTIFIER_GLOBAL_VALUE (fn);
320 else
321 {
20b90169 322 tree t, fields[6];
6874c264
JM
323
324 /* Declare cp_eh_info * __cp_exception_info (void),
325 as defined in exception.cc. */
326 push_obstacks_nochange ();
327 end_temporary_allocation ();
328
329 /* struct cp_eh_info. This must match exception.cc. Note that this
330 type is not pushed anywhere. */
331 t = make_lang_type (RECORD_TYPE);
332 fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"),
333 ptr_type_node);
334 fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
335 ptr_type_node);
336 fields[2] = build_lang_field_decl
337 (FIELD_DECL, get_identifier ("cleanup"),
338 build_pointer_type (build_function_type
339 (ptr_type_node, tree_cons
340 (NULL_TREE, ptr_type_node, void_list_node))));
341 fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"),
342 boolean_type_node);
343 fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
344 build_pointer_type (t));
20b90169
JM
345 fields[5] = build_lang_field_decl
346 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
cf9d67e3
BK
347 /* N.B.: The fourth field LEN is expected to be
348 the number of fields - 1, not the total number of fields. */
20b90169 349 finish_builtin_type (t, "cp_eh_info", fields, 5, ptr_type_node);
6874c264
JM
350 t = build_pointer_type (t);
351
352 /* And now the function. */
353 fn = build_lang_decl (FUNCTION_DECL, fn,
354 build_function_type (t, void_list_node));
355 DECL_EXTERNAL (fn) = 1;
356 TREE_PUBLIC (fn) = 1;
357 DECL_ARTIFICIAL (fn) = 1;
358 pushdecl_top_level (fn);
359 make_function_rtl (fn);
360 assemble_external (fn);
361 pop_obstacks ();
362 }
95e8dcba
JM
363 return build_function_call (fn, NULL_TREE);
364}
365
366/* Retrieve a pointer to the cp_eh_info node for the current exception
367 and save it in the current binding level. */
368
369static void
370push_eh_info ()
371{
372 tree decl, fn = call_eh_info ();
6874c264
JM
373
374 /* Remember the pointer to the current exception info; it won't change
375 during this catch block. */
376 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
377 TREE_TYPE (fn));
378 DECL_ARTIFICIAL (decl) = 1;
379 DECL_INITIAL (decl) = fn;
380 decl = pushdecl (decl);
381 cp_finish_decl (decl, fn, NULL_TREE, 0, 0);
382}
383
384/* Returns a reference to the cp_eh_info node for the current exception. */
385
386static tree
387get_eh_info ()
388{
389 /* Look for the pointer pushed in push_eh_info. */
390 tree t = lookup_name (get_identifier ("__exception_info"), 0);
391 return build_indirect_ref (t, NULL_PTR);
392}
393
394/* Returns a reference to the current exception object. */
395
396static tree
397get_eh_value ()
398{
399 return build_component_ref (get_eh_info (), get_identifier ("value"),
400 NULL_TREE, 0);
401}
402
403/* Returns a reference to the current exception type. */
404
405static tree
406get_eh_type ()
407{
408 return build_component_ref (get_eh_info (), get_identifier ("type"),
409 NULL_TREE, 0);
410}
411
412/* Returns a reference to whether or not the current exception
413 has been caught. */
414
415static tree
416get_eh_caught ()
417{
418 return build_component_ref (get_eh_info (), get_identifier ("caught"),
419 NULL_TREE, 0);
420}
421
20b90169
JM
422/* Returns a reference to whether or not the current exception
423 has been caught. */
424
425static tree
426get_eh_handlers ()
427{
428 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
429 NULL_TREE, 0);
430}
431
f30432d7
MS
432/* Build a type value for use at runtime for a type that is matched
433 against by the exception handling system. */
6467930b 434
f30432d7
MS
435static tree
436build_eh_type_type (type)
437 tree type;
8d08fdba 438{
f30432d7
MS
439 char *typestring;
440 tree exp;
8d2733ca 441
f30432d7
MS
442 if (type == error_mark_node)
443 return error_mark_node;
8d2733ca 444
e92cc029 445 /* peel back references, so they match. */
f30432d7
MS
446 if (TREE_CODE (type) == REFERENCE_TYPE)
447 type = TREE_TYPE (type);
8d08fdba 448
e92cc029 449 /* Peel off cv qualifiers. */
f30432d7 450 type = TYPE_MAIN_VARIANT (type);
8d2733ca 451
f30432d7 452 if (flag_rtti)
8d08fdba 453 {
f30432d7 454 return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
8d08fdba 455 }
f30432d7
MS
456
457 typestring = build_overload_name (type, 1, 1);
458 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
459 return build1 (ADDR_EXPR, ptr_type_node, exp);
8d08fdba 460}
8d08fdba 461
faae18ab
MS
462/* Build a type value for use at runtime for a exp that is thrown or
463 matched against by the exception handling system. */
6467930b 464
faae18ab
MS
465static tree
466build_eh_type (exp)
467 tree exp;
468{
faae18ab
MS
469 if (flag_rtti)
470 {
471 exp = build_typeid (exp);
472 return build1 (ADDR_EXPR, ptr_type_node, exp);
473 }
f30432d7 474 return build_eh_type_type (TREE_TYPE (exp));
faae18ab
MS
475}
476
c7ae64f2
JM
477/* Build up a call to __cp_pop_exception, to destroy the exception object
478 for the current catch block. HANDLER is either true or false, telling
479 the library whether or not it is being called from an exception handler;
480 if it is, it avoids destroying the object on rethrow. */
6467930b 481
c7ae64f2
JM
482static tree
483do_pop_exception (handler)
484 tree handler;
72b7eeff 485{
6874c264 486 tree fn, cleanup;
6874c264
JM
487 fn = get_identifier ("__cp_pop_exception");
488 if (IDENTIFIER_GLOBAL_VALUE (fn))
489 fn = IDENTIFIER_GLOBAL_VALUE (fn);
490 else
491 {
c7ae64f2
JM
492 /* Declare void __cp_pop_exception (void *),
493 as defined in exception.cc. */
6874c264
JM
494 push_obstacks_nochange ();
495 end_temporary_allocation ();
c7ae64f2
JM
496 fn = build_lang_decl
497 (FUNCTION_DECL, fn,
498 build_function_type (void_type_node, tree_cons
499 (NULL_TREE, ptr_type_node, tree_cons
500 (NULL_TREE, boolean_type_node,
501 void_list_node))));
6874c264
JM
502 DECL_EXTERNAL (fn) = 1;
503 TREE_PUBLIC (fn) = 1;
504 DECL_ARTIFICIAL (fn) = 1;
505 pushdecl_top_level (fn);
506 make_function_rtl (fn);
507 assemble_external (fn);
508 pop_obstacks ();
509 }
72b7eeff
MS
510
511 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
c7ae64f2
JM
512 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
513 cleanup = build_function_call (fn, expr_tree_cons
514 (NULL_TREE, cleanup, expr_tree_cons
515 (NULL_TREE, handler, NULL_TREE)));
c0700ea5 516 return cleanup;
c7ae64f2
JM
517}
518
519/* This routine creates the cleanup for the current exception. */
72b7eeff 520
c7ae64f2
JM
521static void
522push_eh_cleanup ()
523{
524 /* All cleanups must last longer than normal. */
525 int yes = suspend_momentary ();
526 expand_decl_cleanup_no_eh (NULL_TREE, do_pop_exception (boolean_false_node));
72b7eeff 527 resume_momentary (yes);
72b7eeff 528
20b90169
JM
529 expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
530 const0_rtx, VOIDmode, EXPAND_NORMAL);
531
c7ae64f2
JM
532 /* We don't destroy the exception object on rethrow, so we can't use
533 the normal cleanup mechanism for it. */
534 expand_eh_region_start ();
535}
72b7eeff 536
8d2733ca
MS
537/* call this to start a catch block. Typename is the typename, and identifier
538 is the variable to place the object in or NULL if the variable doesn't
539 matter. If typename is NULL, that means its a "catch (...)" or catch
540 everything. In that case we don't need to do any type checking.
541 (ie: it ends up as the "else" clause rather than an "else if" clause) */
6467930b 542
8d08fdba 543void
a4443a08
MS
544expand_start_catch_block (declspecs, declarator)
545 tree declspecs, declarator;
8d08fdba 546{
8d2733ca 547 rtx false_label_rtx;
faae18ab 548 tree decl = NULL_TREE;
a3b49ccd 549 tree init;
8d2733ca 550
faf5394a
MS
551 if (processing_template_decl)
552 {
553 if (declspecs)
554 {
555 decl = grokdeclarator (declarator, declspecs, CATCHPARM,
556 1, NULL_TREE);
557 pushdecl (decl);
558 decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
559 copy_to_permanent (declspecs),
560 NULL_TREE);
561 add_tree (decl);
562 }
563 return;
564 }
565
8d2733ca
MS
566 if (! doing_eh (1))
567 return;
568
c7ae64f2
JM
569 /* If we are not doing setjmp/longjmp EH, because we are reordered
570 out of line, we arrange to rethrow in the outer context so as to
571 skip through the terminate region we are nested in, should we
572 encounter an exception in the catch handler. We also need to do
573 this because we are not physically within the try block, if any,
574 that contains this catch block.
575
576 Matches the end in expand_end_catch_block. */
25d5eb3f
JM
577 if (! exceptions_via_longjmp)
578 expand_eh_region_start ();
c7ae64f2
JM
579
580 /* Create a binding level for the eh_info and the exception object
581 cleanup. */
c11b6f21 582 pushlevel (0);
a3b49ccd
MS
583 expand_start_bindings (0);
584
f675499c 585 false_label_rtx = gen_label_rtx ();
72b7eeff 586 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
a3b49ccd 587
eb66be0e
MS
588 emit_line_note (input_filename, lineno);
589
6874c264
JM
590 push_eh_info ();
591
faae18ab 592 if (declspecs)
8d08fdba 593 {
c11b6f21 594 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
faae18ab
MS
595
596 if (decl == NULL_TREE)
c7ae64f2
JM
597 error ("invalid catch parameter");
598 }
95e8dcba 599
c7ae64f2
JM
600 if (decl)
601 {
602 tree exp;
603 rtx call_rtx, return_value_rtx;
604 tree init_type;
faae18ab 605
be99da77
MS
606 /* Make sure we mark the catch param as used, otherwise we'll get
607 a warning about an unused ((anonymous)). */
608 TREE_USED (decl) = 1;
609
e92cc029 610 /* Figure out the type that the initializer is. */
faae18ab 611 init_type = TREE_TYPE (decl);
f30432d7
MS
612 if (TREE_CODE (init_type) != REFERENCE_TYPE
613 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
614 init_type = build_reference_type (init_type);
615
6874c264 616 exp = get_eh_value ();
e66d884e 617 exp = expr_tree_cons (NULL_TREE,
f30432d7 618 build_eh_type_type (TREE_TYPE (decl)),
e66d884e 619 expr_tree_cons (NULL_TREE,
6874c264 620 get_eh_type (),
e66d884e 621 expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
faae18ab
MS
622 exp = build_function_call (CatchMatch, exp);
623 call_rtx = expand_call (exp, NULL_RTX, 0);
e1cd6e56 624 assemble_external (TREE_OPERAND (CatchMatch, 0));
8d2733ca 625
faae18ab 626 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
627
628 /* did the throw type match function return TRUE? */
faae18ab 629 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
630 GET_MODE (return_value_rtx), 0, 0);
631
632 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
633 emit_jump_insn (gen_beq (false_label_rtx));
634
95e8dcba
JM
635 push_eh_cleanup ();
636
c7ae64f2
JM
637 /* Create a binding level for the parm. */
638 pushlevel (0);
639 expand_start_bindings (0);
640
641 init = convert_from_reference (make_tree (init_type, call_rtx));
642
643 /* If the constructor for the catch parm exits via an exception, we
644 must call terminate. See eh23.C. */
645 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
646 {
647 /* Generate the copy constructor call directly so we can wrap it.
648 See also expand_default_init. */
649 init = ocp_convert (TREE_TYPE (decl), init,
650 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
651 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
652 TerminateFunctionCall);
653 }
faae18ab 654
b3417a04 655 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
656 DECL_INITIAL (decl) = init;
657 decl = pushdecl (decl);
c7ae64f2 658
b3417a04 659 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba 660 }
95e8dcba
JM
661 else
662 {
663 push_eh_cleanup ();
664
c7ae64f2
JM
665 /* Create a binding level for the parm. */
666 pushlevel (0);
667 expand_start_bindings (0);
668
95e8dcba
JM
669 /* Fall into the catch all section. */
670 }
72b7eeff 671
6874c264
JM
672 init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
673 expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
f30432d7 674
6467930b
MS
675 emit_line_note (input_filename, lineno);
676}
f30432d7 677
f30432d7 678
f30432d7 679
8d2733ca
MS
680/* Call this to end a catch block. Its responsible for emitting the
681 code to handle jumping back to the correct place, and for emitting
682 the label to jump to if this catch block didn't match. */
6467930b 683
824b9a4c
MS
684void
685expand_end_catch_block ()
8d08fdba 686{
f30432d7
MS
687 if (! doing_eh (1))
688 return;
8d2733ca 689
c7ae64f2
JM
690 /* Cleanup the EH parameter. */
691 expand_end_bindings (getdecls (), kept_level_p (), 0);
692 poplevel (kept_level_p (), 1, 0);
693
694 /* Matches push_eh_cleanup. */
695 expand_eh_region_end (do_pop_exception (boolean_true_node));
696
697 /* Cleanup the EH object. */
698 expand_end_bindings (getdecls (), kept_level_p (), 0);
699 poplevel (kept_level_p (), 1, 0);
eb66be0e 700
0b3ca5ee 701 if (! exceptions_via_longjmp)
eb66be0e
MS
702 {
703 /* If we are not doing setjmp/longjmp EH, we need an extra
704 region around the whole catch block to skip through the
705 terminate region we are nested in. */
706
25d5eb3f
JM
707 tree t = make_node (RTL_EXPR);
708 TREE_TYPE (t) = void_type_node;
709 RTL_EXPR_RTL (t) = const0_rtx;
710 TREE_SIDE_EFFECTS (t) = 1;
711 do_pending_stack_adjust ();
712 start_sequence_for_rtl_expr (t);
713
714 expand_internal_throw (outer_context_label_stack->u.rlabel);
eb66be0e 715
25d5eb3f
JM
716 do_pending_stack_adjust ();
717 RTL_EXPR_SEQUENCE (t) = get_insns ();
718 end_sequence ();
f30432d7 719
25d5eb3f
JM
720 /* For the rethrow region. */
721 expand_eh_region_end (t);
722 }
f30432d7 723
eb66be0e
MS
724 /* Fall to outside the try statement when done executing handler and
725 we fall off end of handler. This is jump Lresume in the
726 documentation. */
727 expand_goto (top_label_entry (&caught_return_label_stack));
728
6467930b 729 expand_leftover_cleanups ();
f30432d7 730
6467930b 731 /* label we emit to jump to if this catch block didn't match. */
f30432d7
MS
732 /* This the closing } in the `if (eq) {' of the documentation. */
733 emit_label (pop_label_entry (&false_label_stack));
8d2733ca 734}
8d08fdba 735
6467930b
MS
736/* unwind the stack. */
737
db5ae43f 738static void
f30432d7
MS
739do_unwind (inner_throw_label)
740 rtx inner_throw_label;
db5ae43f 741{
be99da77 742#if defined (SPARC_STACK_ALIGN) /* was sparc */
0021b564
JM
743 /* This doesn't work for the flat model sparc, nor does it need to
744 as the default unwinder is only used to unwind non-flat frames. */
db5ae43f
MS
745 tree fcall;
746 tree params;
6633d636 747 rtx next_pc;
f30432d7 748 rtx temp;
db5ae43f 749
eb66be0e 750 /* Call to __builtin_return_address. */
e66d884e 751 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
db5ae43f 752 fcall = build_function_call (BuiltinReturnAddress, params);
6633d636 753 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
ddd5a7c1 754 /* In the return, the new pc is pc+8, as the value coming in is
db5ae43f 755 really the address of the call insn, not the next insn. */
f30432d7
MS
756 temp = gen_reg_rtx (Pmode);
757 emit_move_insn (temp, inner_throw_label);
6633d636 758 emit_move_insn (next_pc, plus_constant (temp, -8));
d11ad92e 759 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
db5ae43f
MS
760 easy_expand_asm ("ret");
761 easy_expand_asm ("restore");
762 emit_barrier ();
763#endif
be99da77 764#if defined (ARM_FRAME_RTX) /* was __arm */
f30432d7
MS
765 if (flag_omit_frame_pointer)
766 sorry ("this implementation of exception handling requires a frame pointer");
db5ae43f 767
f30432d7
MS
768 emit_move_insn (stack_pointer_rtx,
769 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
770 emit_move_insn (hard_frame_pointer_rtx,
771 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
db5ae43f 772#endif
be99da77 773#if defined (TARGET_88000) /* was m88k */
db5ae43f
MS
774 rtx temp_frame = frame_pointer_rtx;
775
776 temp_frame = memory_address (Pmode, temp_frame);
777 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
778
779 /* hopefully this will successfully pop the frame! */
780 emit_move_insn (frame_pointer_rtx, temp_frame);
781 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
782 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
783 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
784 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
785
786#if 0
787 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
788 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
789
790 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
791
792 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
793 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
794#endif
795#endif
be99da77 796#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
f30432d7
MS
797 tree fcall;
798 tree params;
6633d636 799 rtx next_pc;
e1cd6e56 800
be99da77 801#if 0
e92cc029 802 /* I would like to do this here, but the move below doesn't seem to work. */
eb66be0e 803 /* Call to __builtin_return_address. */
e66d884e 804 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
f30432d7 805 fcall = build_function_call (BuiltinReturnAddress, params);
6633d636 806 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 807
6633d636 808 emit_move_insn (next_pc, inner_throw_label);
e92cc029 809 /* So, for now, just pass throw label to stack unwinder. */
f30432d7 810#endif
e66d884e 811 params = expr_tree_cons (NULL_TREE, make_tree (ptr_type_node,
f30432d7
MS
812 inner_throw_label), NULL_TREE);
813
814 do_function_call (Unwind, params, NULL_TREE);
815 assemble_external (TREE_OPERAND (Unwind, 0));
816 emit_barrier ();
e1cd6e56 817#endif
db5ae43f 818}
8d08fdba 819
f30432d7 820
eb66be0e 821/* Is called from expand_exception_blocks to generate the code in a function
ddd5a7c1 822 to "throw" if anything in the function needs to perform a throw.
8d08fdba 823
ddd5a7c1 824 expands "throw" as the following pseudo code:
8d2733ca
MS
825
826 throw:
827 eh = find_first_exception_match (saved_pc);
828 if (!eh) goto gotta_rethrow_it;
829 goto eh;
830
831 gotta_rethrow_it:
832 saved_pc = __builtin_return_address (0);
833 pop_to_previous_level ();
6467930b 834 goto throw; */
8d2733ca 835
f30432d7 836void
8d2733ca
MS
837expand_builtin_throw ()
838{
0021b564 839#ifndef DWARF2_UNWIND_INFO
8d2733ca
MS
840 tree fcall;
841 tree params;
6633d636
MS
842 rtx handler;
843 rtx saved_pcnthrow;
844 rtx next_pc;
f30432d7
MS
845 rtx gotta_rethrow_it;
846 rtx gotta_call_terminate;
6633d636 847 rtx after_unwind;
f30432d7 848 rtx top_of_loop;
f30432d7 849 tree t;
6633d636 850 rtx x;
f30432d7
MS
851
852 if (! doing_eh (0))
853 return;
854
855 if (! throw_used)
856 return;
8d2733ca 857
f30432d7 858 params = void_list_node;
c11b6f21
MS
859 t = make_call_declarator (get_identifier ("__throw"), params, NULL_TREE,
860 NULL_TREE);
6633d636
MS
861 start_function (decl_tree_cons (NULL_TREE,
862 get_identifier ("void"),
863 decl_tree_cons (NULL_TREE,
864 get_identifier ("static"),
865 NULL_TREE)),
c11b6f21 866 t, NULL_TREE, 0);
f30432d7
MS
867 store_parm_decls ();
868 pushlevel (0);
869 clear_last_expr ();
870 push_momentary ();
871 expand_start_bindings (0);
872
873 gotta_rethrow_it = gen_label_rtx ();
874 gotta_call_terminate = gen_label_rtx ();
f30432d7 875
a50f0918 876 /* These two can be frontend specific. If wanted, they can go in
e92cc029 877 expand_throw. */
a50f0918 878 /* Do we have a valid object we are throwing? */
95e8dcba
JM
879 t = call_eh_info ();
880 emit_cmp_insn (expand_expr (t, NULL_RTX, Pmode, 0),
881 const0_rtx, EQ, NULL_RTX,
5a0fa1de 882 GET_MODE (DECL_RTL (t)), 0, 0);
a50f0918
MS
883 emit_jump_insn (gen_beq (gotta_call_terminate));
884
8d2733ca 885 /* search for an exception handler for the saved_pc */
6633d636 886 handler = do_function_call (FirstExceptionMatch,
e66d884e 887 expr_tree_cons (NULL_TREE, saved_pc,
6633d636
MS
888 NULL_TREE),
889 ptr_type_node);
e1cd6e56 890 assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
8d2733ca
MS
891
892 /* did we find one? */
6633d636
MS
893 emit_cmp_insn (handler, const0_rtx, EQ, NULL_RTX,
894 GET_MODE (handler), 0, 0);
8d2733ca
MS
895
896 /* if not, jump to gotta_rethrow_it */
897 emit_jump_insn (gen_beq (gotta_rethrow_it));
898
6633d636
MS
899 {
900 rtx ret_val, x;
901 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
902 0, hard_frame_pointer_rtx);
8d2733ca 903
6633d636
MS
904 /* Set it up so that we continue at the handler. */
905 emit_move_insn (ret_val, handler);
906#ifdef RETURN_ADDR_OFFSET
907 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
908 if (x != ret_val)
909 emit_move_insn (ret_val, x);
910#endif
8d2733ca 911
6633d636
MS
912 expand_null_return ();
913 }
914
915 top_of_loop = gen_label_rtx ();
916 emit_label (top_of_loop);
917
918#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
919 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
920 {
921 saved_pcnthrow = gen_reg_rtx (Pmode);
922 emit_move_insn (saved_pcnthrow, hard_function_value (ptr_type_node,
923 NULL_TREE));
924 }
925#endif
926
eb66be0e 927 /* Call to __builtin_return_address. */
be99da77
MS
928#if defined (ARM_FRAME_RTX) /* was __arm */
929 /* This should be moved into arm.h:RETURN_ADDR_RTX */
930 /* This replaces a 'call' to __builtin_return_address */
6633d636
MS
931 next_pc = gen_reg_rtx (Pmode);
932 emit_move_insn (next_pc,
933 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 934#else
e66d884e 935 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
8d2733ca 936 fcall = build_function_call (BuiltinReturnAddress, params);
6633d636 937 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 938#endif
8d2733ca 939
eb66be0e 940 /* Did __builtin_return_address return a valid address? */
6633d636
MS
941 emit_cmp_insn (next_pc, const0_rtx, EQ, NULL_RTX,
942 GET_MODE (next_pc), 0, 0);
8d2733ca
MS
943
944 emit_jump_insn (gen_beq (gotta_call_terminate));
945
6633d636 946 next_pc = eh_outer_context (next_pc);
e1cd6e56 947
be99da77 948 /* Yes it did. */
6633d636
MS
949#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
950 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
951 {
952 rtx x;
953
954 x = validize_mem (gen_rtx (MEM, Pmode, saved_pcnthrow));
955 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode, x)),
956 next_pc);
957#ifdef FUNCTION_OUTGOING_VALUE
958 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
959 validize_mem (gen_rtx (MEM, Pmode,
960 plus_constant (saved_pcnthrow,
961 GET_MODE_SIZE (Pmode)))));
962 emit_insn (gen_rtx (USE, VOIDmode,
963 FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
964#endif
965 }
966 else
967#endif
968 emit_move_insn (eh_saved_pc_rtx, next_pc);
f30432d7 969
6633d636
MS
970 after_unwind = gen_label_rtx ();
971 do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
972
973 emit_label (after_unwind);
974
975#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
976 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
977 {
6874c264
JM
978 t = build_function_type (void_type_node, void_list_node);
979 t = make_tree (build_pointer_type (t),
6633d636
MS
980 hard_function_value (ptr_type_node,
981 NULL_TREE));
982 t = build_function_call (t, NULL_TREE);
983 expand_expr (t, const0_rtx, VOIDmode, 0);
984 }
985 else
986#endif
987 emit_throw ();
8d2733ca
MS
988
989 /* no it didn't --> therefore we need to call terminate */
990 emit_label (gotta_call_terminate);
991 do_function_call (Terminate, NULL_TREE, NULL_TREE);
e1cd6e56 992 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7
MS
993
994 {
6633d636
MS
995 rtx ret_val, x;
996 /* code to deal with unwinding and looking for it again */
997 emit_label (gotta_rethrow_it);
f30432d7
MS
998 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
999 0, hard_frame_pointer_rtx);
1000
1001 /* Set it up so that we continue inside, at the top of the loop. */
1002 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173 1003#ifdef RETURN_ADDR_OFFSET
6633d636
MS
1004 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
1005 if (x != ret_val)
1006 emit_move_insn (ret_val, x);
1007#endif
1008
1009#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
1010 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
1011 {
1012 rtx x = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode,
1013 "__eh_pcnthrow"),
1014 NULL_RTX, 1,
1015 Pmode, 0);
1016 /* This is to get a version of throw that will throw properly. */
1017 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode,
1018 plus_constant (x, GET_MODE_SIZE (Pmode)))),
1019 throw_libfunc);
1020#ifdef FUNCTION_OUTGOING_VALUE
1021 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
1022 x);
1023 emit_insn (gen_rtx (USE, VOIDmode, FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
1024#endif
1025 }
f30432d7
MS
1026#endif
1027
e92cc029 1028 /* Fall into epilogue to unwind prologue. */
f30432d7
MS
1029 }
1030
fc378698 1031 expand_end_bindings (getdecls (), 1, 0);
f30432d7
MS
1032 poplevel (1, 0, 0);
1033 pop_momentary ();
1034
1035 finish_function (lineno, 0, 0);
0021b564 1036#endif /* DWARF2_UNWIND_INFO */
8d08fdba 1037}
8d2733ca 1038
6c20b7e9
JM
1039/* An exception spec is implemented more or less like:
1040
1041 try {
1042 function body;
1043 } catch (...) {
1044 void *p[] = { typeid(raises) };
1045 __check_eh_spec (p, count);
1046 }
1047
1048 __check_eh_spec in exception.cc handles all the details. */
8d2733ca 1049
f30432d7
MS
1050void
1051expand_start_eh_spec ()
1052{
6c20b7e9 1053 expand_start_try_stmts ();
f30432d7
MS
1054}
1055
5566b478 1056static void
f30432d7
MS
1057expand_end_eh_spec (raises)
1058 tree raises;
1059{
6c20b7e9
JM
1060 tree tmp, fn, decl, types = NULL_TREE;
1061 int count = 0;
f30432d7 1062
6c20b7e9
JM
1063 expand_start_all_catch ();
1064 expand_start_catch_block (NULL_TREE, NULL_TREE);
f30432d7 1065
6c20b7e9
JM
1066 /* Build up an array of type_infos. */
1067 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
1068 {
1069 types = expr_tree_cons
1070 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
1071 ++count;
1072 }
eb66be0e 1073
6c20b7e9
JM
1074 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
1075 TREE_HAS_CONSTRUCTOR (types) = 1;
6874c264 1076
6c20b7e9
JM
1077 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
1078 tmp = build_array_type (const_ptr_type_node, NULL_TREE);
1079 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
1080 DECL_ARTIFICIAL (decl) = 1;
1081 DECL_INITIAL (decl) = types;
1082 cp_finish_decl (decl, types, NULL_TREE, 0, 0);
1083
1084 decl = decay_conversion (decl);
6874c264 1085
6c20b7e9
JM
1086 fn = get_identifier ("__check_eh_spec");
1087 if (IDENTIFIER_GLOBAL_VALUE (fn))
1088 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1089 else
f30432d7 1090 {
6c20b7e9
JM
1091 push_obstacks_nochange ();
1092 end_temporary_allocation ();
f30432d7 1093
6c20b7e9
JM
1094 tmp = tree_cons
1095 (NULL_TREE, integer_type_node, tree_cons
1096 (NULL_TREE, TREE_TYPE (decl), void_list_node));
1097 tmp = build_function_type (void_type_node, tmp);
f30432d7 1098
6c20b7e9
JM
1099 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1100 DECL_EXTERNAL (fn) = 1;
1101 TREE_PUBLIC (fn) = 1;
1102 DECL_ARTIFICIAL (fn) = 1;
1103 TREE_THIS_VOLATILE (fn) = 1;
1104 pushdecl_top_level (fn);
1105 make_function_rtl (fn);
1106 assemble_external (fn);
1107 pop_obstacks ();
1108 }
1109
1110 tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
1111 (NULL_TREE, decl, NULL_TREE));
1112 tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
1113 expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
1114
1115 expand_end_catch_block ();
1116 expand_end_all_catch ();
f30432d7
MS
1117}
1118
8d2733ca
MS
1119/* This is called to expand all the toplevel exception handling
1120 finalization for a function. It should only be called once per
1121 function. */
6467930b 1122
8d08fdba 1123void
8d2733ca 1124expand_exception_blocks ()
8d08fdba 1125{
92b96838 1126 do_pending_stack_adjust ();
e00737d2 1127 push_to_sequence (catch_clauses);
8d2733ca 1128 expand_leftover_cleanups ();
92b96838 1129 do_pending_stack_adjust ();
e00737d2 1130 catch_clauses = get_insns ();
f30432d7 1131 end_sequence ();
eb448459 1132
eb448459
MS
1133 /* Do this after we expand leftover cleanups, so that the
1134 expand_eh_region_end that expand_end_eh_spec does will match the
1135 right expand_eh_region_start, and make sure it comes out before
1136 the terminate protected region. */
f30432d7
MS
1137 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
1138 {
eb448459 1139 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
92b96838 1140 do_pending_stack_adjust ();
e00737d2 1141 push_to_sequence (catch_clauses);
eb448459 1142 expand_leftover_cleanups ();
92b96838 1143 do_pending_stack_adjust ();
e00737d2 1144 catch_clauses = get_insns ();
eb448459 1145 end_sequence ();
f30432d7
MS
1146 }
1147
e00737d2 1148 if (catch_clauses)
f30432d7 1149 {
e00737d2
MS
1150 rtx funcend = gen_label_rtx ();
1151 emit_jump (funcend);
1152
eb66be0e
MS
1153 /* We cannot protect n regions this way if we must flow into the
1154 EH region through the top of the region, as we have to with
1155 the setjmp/longjmp approach. */
1156 if (exceptions_via_longjmp == 0)
1157 {
1158 /* Is this necessary? */
1159 assemble_external (TREE_OPERAND (Terminate, 0));
1160
1161 expand_eh_region_start ();
1162 }
f30432d7 1163
e00737d2
MS
1164 emit_insns (catch_clauses);
1165 catch_clauses = NULL_RTX;
eb66be0e
MS
1166
1167 if (exceptions_via_longjmp == 0)
1168 expand_eh_region_end (TerminateFunctionCall);
1169
6467930b 1170 expand_leftover_cleanups ();
f30432d7 1171
e00737d2
MS
1172 emit_label (funcend);
1173 }
8d08fdba
MS
1174}
1175
72b7eeff
MS
1176tree
1177start_anon_func ()
1178{
1179 static int counter = 0;
e92cc029 1180 int old_interface_unknown = interface_unknown;
72b7eeff
MS
1181 char name[32];
1182 tree params;
1183 tree t;
1184
1185 push_cp_function_context (NULL_TREE);
1186 push_to_top_level ();
1187
1188 /* No need to mangle this. */
1189 push_lang_context (lang_name_c);
1190
e92cc029
MS
1191 interface_unknown = 1;
1192
72b7eeff
MS
1193 params = void_list_node;
1194 /* tcf stands for throw clean funciton. */
1195 sprintf (name, "__tcf_%d", counter++);
c11b6f21
MS
1196 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
1197 NULL_TREE);
72b7eeff
MS
1198 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
1199 void_list_node),
c11b6f21 1200 t, NULL_TREE, 0);
72b7eeff
MS
1201 store_parm_decls ();
1202 pushlevel (0);
1203 clear_last_expr ();
1204 push_momentary ();
1205 expand_start_bindings (0);
1206 emit_line_note (input_filename, lineno);
1207
e92cc029
MS
1208 interface_unknown = old_interface_unknown;
1209
72b7eeff
MS
1210 pop_lang_context ();
1211
1212 return current_function_decl;
1213}
1214
1215void
1216end_anon_func ()
1217{
fc378698 1218 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
1219 poplevel (1, 0, 0);
1220 pop_momentary ();
1221
1222 finish_function (lineno, 0, 0);
1223
1224 pop_from_top_level ();
1225 pop_cp_function_context (NULL_TREE);
1226}
8d2733ca 1227
6467930b 1228/* Expand a throw statement. This follows the following
8d2733ca
MS
1229 algorithm:
1230
1231 1. Allocate space to save the current PC onto the stack.
1232 2. Generate and emit a label and save its address into the
e1cd6e56 1233 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1234 3. If this is the first call to throw in this function:
1235 generate a label for the throw block
1236 4. jump to the throw block label. */
6467930b 1237
8d08fdba 1238void
8d2733ca
MS
1239expand_throw (exp)
1240 tree exp;
8d08fdba 1241{
8d2733ca 1242 rtx label;
6874c264
JM
1243 tree fn;
1244 static tree cleanup_type;
8d08fdba 1245
8d2733ca
MS
1246 if (! doing_eh (1))
1247 return;
8d08fdba 1248
8d2733ca
MS
1249 if (exp)
1250 {
faae18ab 1251 tree throw_type;
6874c264 1252 tree cleanup = NULL_TREE, e;
faae18ab 1253
a3b49ccd 1254 /* throw expression */
e92cc029 1255 /* First, decay it. */
f30432d7 1256 exp = decay_conversion (exp);
a3b49ccd 1257
6874c264
JM
1258 /* cleanup_type is void (*)(void *, int),
1259 the internal type of a destructor. */
1260 if (cleanup_type == NULL_TREE)
1261 {
1262 push_obstacks_nochange ();
1263 end_temporary_allocation ();
1264 cleanup_type = build_pointer_type
1265 (build_function_type
1266 (void_type_node, tree_cons
1267 (NULL_TREE, ptr_type_node, tree_cons
1268 (NULL_TREE, integer_type_node, void_list_node))));
1269 pop_obstacks ();
1270 }
1271
f30432d7
MS
1272 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1273 {
1274 throw_type = build_eh_type (exp);
1275 exp = build_reinterpret_cast (ptr_type_node, exp);
1276 }
1277 else
1278 {
72b7eeff 1279 tree object;
a50f0918 1280
f30432d7
MS
1281 /* Make a copy of the thrown object. WP 15.1.5 */
1282 exp = build_new (NULL_TREE, TREE_TYPE (exp),
e66d884e 1283 build_expr_list (NULL_TREE, exp),
f30432d7 1284 0);
faae18ab 1285
f30432d7
MS
1286 if (exp == error_mark_node)
1287 error (" in thrown expression");
faae18ab 1288
72b7eeff
MS
1289 object = build_indirect_ref (exp, NULL_PTR);
1290 throw_type = build_eh_type (object);
1291
6874c264
JM
1292 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
1293 {
1294 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
1295 dtor_identifier, 0);
1296 cleanup = TREE_VALUE (cleanup);
1297 mark_addressable (cleanup);
1298 /* Pretend it's a normal function. */
1299 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
1300 }
f30432d7 1301 }
faae18ab 1302
6874c264
JM
1303 if (cleanup == NULL_TREE)
1304 {
1305 cleanup = build_int_2 (0, 0);
1306 TREE_TYPE (cleanup) = cleanup_type;
1307 }
72b7eeff 1308
6874c264
JM
1309 fn = get_identifier ("__cp_push_exception");
1310 if (IDENTIFIER_GLOBAL_VALUE (fn))
1311 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1312 else
1313 {
1314 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
1315 as defined in exception.cc. */
1316 tree tmp;
1317 push_obstacks_nochange ();
1318 end_temporary_allocation ();
1319 tmp = tree_cons
1320 (NULL_TREE, ptr_type_node, tree_cons
1321 (NULL_TREE, ptr_type_node, tree_cons
1322 (NULL_TREE, cleanup_type, void_list_node)));
1323 fn = build_lang_decl (FUNCTION_DECL, fn,
1324 build_function_type (void_type_node, tmp));
1325 DECL_EXTERNAL (fn) = 1;
1326 TREE_PUBLIC (fn) = 1;
1327 DECL_ARTIFICIAL (fn) = 1;
1328 pushdecl_top_level (fn);
1329 make_function_rtl (fn);
1330 assemble_external (fn);
1331 pop_obstacks ();
1332 }
72b7eeff 1333
6874c264
JM
1334 /* The throw expression is a full-expression. */
1335 exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
1336 e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
1337 (NULL_TREE, throw_type, expr_tree_cons
1338 (NULL_TREE, cleanup, NULL_TREE)));
1339 e = build_function_call (fn, e);
1340 expand_expr (e, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1341 }
1342 else
a3b49ccd 1343 {
6874c264
JM
1344 /* rethrow current exception; note that it's no longer caught. */
1345
1346 tree fn = get_identifier ("__uncatch_exception");
1347 if (IDENTIFIER_GLOBAL_VALUE (fn))
1348 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1349 else
1350 {
1351 /* Declare void __uncatch_exception (void)
1352 as defined in exception.cc. */
1353 push_obstacks_nochange ();
1354 end_temporary_allocation ();
1355 fn = build_lang_decl (FUNCTION_DECL, fn,
1356 build_function_type (void_type_node,
1357 void_list_node));
1358 DECL_EXTERNAL (fn) = 1;
1359 TREE_PUBLIC (fn) = 1;
1360 DECL_ARTIFICIAL (fn) = 1;
1361 pushdecl_top_level (fn);
1362 make_function_rtl (fn);
1363 assemble_external (fn);
1364 pop_obstacks ();
1365 }
1366
1367 exp = build_function_call (fn, NULL_TREE);
1368 expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
a3b49ccd 1369 }
8d2733ca 1370
eb66be0e
MS
1371 if (exceptions_via_longjmp)
1372 emit_throw ();
1373 else
1374 {
1375 /* This is the label that represents where in the code we were, when
1376 we got an exception. This needs to be updated when we rethrow an
1377 exception, so that the matching routine knows to search out. */
1378 label = gen_label_rtx ();
1379 emit_label (label);
8d2733ca 1380
eb66be0e
MS
1381 expand_internal_throw (label);
1382 }
f376e137 1383}
8d2733ca
MS
1384
1385/* Build a throw expression. */
6467930b 1386
8d2733ca
MS
1387tree
1388build_throw (e)
1389 tree e;
1390{
db5ae43f
MS
1391 if (e != error_mark_node)
1392 {
5156628f 1393 if (processing_template_decl)
fc378698 1394 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1395 e = build1 (THROW_EXPR, void_type_node, e);
1396 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1397 TREE_USED (e) = 1;
db5ae43f 1398 }
8d2733ca 1399 return e;
8d08fdba 1400}
This page took 0.36083 seconds and 5 git commands to generate.