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