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