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