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