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