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