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