]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
sparc.c (sparc_emit_float_lib_cmp): Handle TARGET_ARCH32 again.
[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 40static tree build_eh_type_type PROTO((tree));
69ac77ce
JL
41static tree call_eh_info PROTO((void));
42static void push_eh_info PROTO((void));
43static tree get_eh_info PROTO((void));
44static tree get_eh_value PROTO((void));
87603ed0 45#if 0
69ac77ce
JL
46static tree get_eh_type PROTO((void));
47static tree get_eh_caught PROTO((void));
48static tree get_eh_handlers PROTO((void));
e833cb11 49#endif
69ac77ce 50static tree do_pop_exception PROTO((void));
5816cb14 51static tree build_eh_type_type_ref PROTO((tree));
c6160f8f
JM
52static tree build_terminate_handler PROTO((void));
53static tree alloc_eh_object PROTO((tree));
4cfbc546 54static int complete_ptr_ref_or_void_ptr_p PROTO((tree, tree));
b35d4555 55static void initialize_handler_parm PROTO((tree));
59ccf49d 56static tree expand_throw PROTO((tree));
8d2733ca 57
8d2733ca 58#if 0
e92cc029 59/* This is the startup, and finish stuff per exception table. */
8d08fdba 60
8d2733ca
MS
61/* XXX - Tad: exception handling section */
62#ifndef EXCEPT_SECTION_ASM_OP
63#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
64#endif
8d08fdba 65
8d2733ca 66#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 67
8d2733ca
MS
68 /* on machines which support it, the exception table lives in another section,
69 but it needs a label so we can reference it... This sets up that
70 label! */
71asm (EXCEPT_SECTION_ASM_OP);
72exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
73asm (TEXT_SECTION_ASM_OP);
8d08fdba 74
8d2733ca 75#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 76
8d2733ca
MS
77#ifdef EXCEPT_SECTION_ASM_OP
78
79 /* we need to know where the end of the exception table is... so this
80 is how we do it! */
81
82asm (EXCEPT_SECTION_ASM_OP);
83exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
84asm (TEXT_SECTION_ASM_OP);
85
86#endif /* EXCEPT_SECTION_ASM_OP */
87
88#endif
8d08fdba 89
8d2733ca 90#include "decl.h"
8d2733ca
MS
91#include "insn-flags.h"
92#include "obstack.h"
8d2733ca
MS
93
94/* ======================================================================
95 Briefly the algorithm works like this:
96
97 When a constructor or start of a try block is encountered,
98 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
99 new entry in the unwind protection stack and returns a label to
100 output to start the protection for that block.
101
102 When a destructor or end try block is encountered, pop_eh_entry
6467930b
MS
103 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
104 created when push_eh_entry () was called. The eh_entry structure
8d2733ca
MS
105 contains three things at this point. The start protect label,
106 the end protect label, and the exception handler label. The end
107 protect label should be output before the call to the destructor
108 (if any). If it was a destructor, then its parse tree is stored
6467930b 109 in the finalization variable in the eh_entry structure. Otherwise
8d2733ca 110 the finalization variable is set to NULL to reflect the fact that
38e01259 111 it is the end of a try block. Next, this modified eh_entry node
8d2733ca
MS
112 is enqueued in the finalizations queue by calling
113 enqueue_eh_entry (&queue,entry).
114
115 +---------------------------------------------------------------+
116 |XXX: Will need modification to deal with partially |
117 | constructed arrays of objects |
118 | |
119 | Basically, this consists of keeping track of how many |
120 | of the objects have been constructed already (this |
121 | should be in a register though, so that shouldn't be a |
122 | problem. |
123 +---------------------------------------------------------------+
124
125 When a catch block is encountered, there is a lot of work to be
126 done.
127
128 Since we don't want to generate the catch block inline with the
129 regular flow of the function, we need to have some way of doing
f30432d7
MS
130 so. Luckily, we can use sequences to defer the catch sections.
131 When the start of a catch block is encountered, we start the
132 sequence. After the catch block is generated, we end the
133 sequence.
134
8d2733ca
MS
135 Next we must insure that when the catch block is executed, all
136 finalizations for the matching try block have been completed. If
137 any of those finalizations throw an exception, we must call
138 terminate according to the ARM (section r.15.6.1). What this
139 means is that we need to dequeue and emit finalizations for each
6467930b 140 entry in the eh_queue until we get to an entry with a NULL
8d2733ca
MS
141 finalization field. For any of the finalization entries, if it
142 is not a call to terminate (), we must protect it by giving it
143 another start label, end label, and exception handler label,
144 setting its finalization tree to be a call to terminate (), and
6467930b 145 enqueue'ing this new eh_entry to be output at an outer level.
8d2733ca
MS
146 Finally, after all that is done, we can get around to outputting
147 the catch block which basically wraps all the "catch (...) {...}"
148 statements in a big if/then/else construct that matches the
149 correct block to call.
150
151 ===================================================================== */
152
8d2733ca
MS
153/* ====================================================================== */
154
8d2733ca 155/* sets up all the global eh stuff that needs to be initialized at the
bbd0d54a 156 start of compilation. */
8d08fdba 157
8d08fdba 158void
8d2733ca 159init_exception_processing ()
8d08fdba 160{
6633d636
MS
161 /* void vtype () */
162 tree vtype = build_function_type (void_type_node, void_list_node);
163
2c73f9f5
ML
164 if (flag_honor_std)
165 push_namespace (get_identifier ("std"));
c2a37c55 166 terminate_node = auto_function (get_identifier ("terminate"), vtype);
9cd64686 167 TREE_THIS_VOLATILE (terminate_node) = 1;
2c73f9f5
ML
168 if (flag_honor_std)
169 pop_namespace ();
8ccc31eb 170
9a0d1e1b
AM
171 set_exception_lang_code (EH_LANG_C_plus_plus);
172 set_exception_version_code (1);
9a0d1e1b 173
eb66be0e
MS
174 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
175 be protected with __terminate. */
176 protect_cleanup_actions_with_terminate = 1;
8d2733ca
MS
177}
178
95e8dcba 179/* Retrieve a pointer to the cp_eh_info node for the current exception. */
6874c264 180
95e8dcba
JM
181static tree
182call_eh_info ()
6874c264 183{
95e8dcba 184 tree fn;
6874c264 185
e6cfb550 186 fn = get_identifier ("__start_cp_handler");
6874c264
JM
187 if (IDENTIFIER_GLOBAL_VALUE (fn))
188 fn = IDENTIFIER_GLOBAL_VALUE (fn);
189 else
190 {
a1622f83 191 tree t1, t, fields[7];
6874c264 192
e6cfb550 193 /* Declare cp_eh_info * __start_cp_handler (void),
6874c264 194 as defined in exception.cc. */
6874c264
JM
195
196 /* struct cp_eh_info. This must match exception.cc. Note that this
197 type is not pushed anywhere. */
33848bb0 198 t1= make_aggr_type (RECORD_TYPE);
4ce3d537 199 fields[0] = build_lang_decl (FIELD_DECL,
9a0d1e1b 200 get_identifier ("handler_label"), ptr_type_node);
4ce3d537 201 fields[1] = build_lang_decl (FIELD_DECL,
9a0d1e1b 202 get_identifier ("dynamic_handler_chain"), ptr_type_node);
4ce3d537 203 fields[2] = build_lang_decl (FIELD_DECL,
9a0d1e1b 204 get_identifier ("info"), ptr_type_node);
4ce3d537 205 fields[3] = build_lang_decl (FIELD_DECL,
e6cfb550 206 get_identifier ("table_index"), ptr_type_node);
9a0d1e1b
AM
207 /* N.B.: The fourth field LEN is expected to be
208 the number of fields - 1, not the total number of fields. */
e6cfb550 209 finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
9a0d1e1b
AM
210 t1 = build_pointer_type (t1);
211
33848bb0 212 t1= make_aggr_type (RECORD_TYPE);
4ce3d537 213 fields[0] = build_lang_decl (FIELD_DECL,
9a0d1e1b 214 get_identifier ("match_function"), ptr_type_node);
4ce3d537 215 fields[1] = build_lang_decl (FIELD_DECL,
9a0d1e1b 216 get_identifier ("language"), short_integer_type_node);
4ce3d537 217 fields[2] = build_lang_decl (FIELD_DECL,
9a0d1e1b
AM
218 get_identifier ("version"), short_integer_type_node);
219 /* N.B.: The fourth field LEN is expected to be
220 the number of fields - 1, not the total number of fields. */
5816cb14 221 finish_builtin_type (t1, "__eh_info", fields, 2, ptr_type_node);
33848bb0 222 t = make_aggr_type (RECORD_TYPE);
4ce3d537
MM
223 fields[0] = build_lang_decl (FIELD_DECL,
224 get_identifier ("eh_info"), t1);
225 fields[1] = build_lang_decl (FIELD_DECL, get_identifier ("value"),
226 ptr_type_node);
227 fields[2] = build_lang_decl (FIELD_DECL, get_identifier ("type"),
228 ptr_type_node);
229 fields[3] = build_lang_decl
6874c264
JM
230 (FIELD_DECL, get_identifier ("cleanup"),
231 build_pointer_type (build_function_type
232 (ptr_type_node, tree_cons
233 (NULL_TREE, ptr_type_node, void_list_node))));
4ce3d537
MM
234 fields[4] = build_lang_decl (FIELD_DECL, get_identifier ("caught"),
235 boolean_type_node);
236 fields[5] = build_lang_decl (FIELD_DECL, get_identifier ("next"),
237 build_pointer_type (t));
238 fields[6] = build_lang_decl
20b90169 239 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
cf9d67e3
BK
240 /* N.B.: The fourth field LEN is expected to be
241 the number of fields - 1, not the total number of fields. */
a1622f83 242 finish_builtin_type (t, "cp_eh_info", fields, 6, ptr_type_node);
6874c264
JM
243 t = build_pointer_type (t);
244
245 /* And now the function. */
246 fn = build_lang_decl (FUNCTION_DECL, fn,
247 build_function_type (t, void_list_node));
248 DECL_EXTERNAL (fn) = 1;
249 TREE_PUBLIC (fn) = 1;
250 DECL_ARTIFICIAL (fn) = 1;
251 pushdecl_top_level (fn);
252 make_function_rtl (fn);
6874c264 253 }
a6ecf8b6 254 mark_used (fn);
95e8dcba
JM
255 return build_function_call (fn, NULL_TREE);
256}
257
258/* Retrieve a pointer to the cp_eh_info node for the current exception
259 and save it in the current binding level. */
260
261static void
262push_eh_info ()
263{
264 tree decl, fn = call_eh_info ();
6874c264
JM
265
266 /* Remember the pointer to the current exception info; it won't change
267 during this catch block. */
268 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
269 TREE_TYPE (fn));
270 DECL_ARTIFICIAL (decl) = 1;
271 DECL_INITIAL (decl) = fn;
272 decl = pushdecl (decl);
cd9f6678 273 cp_finish_decl (decl, fn, NULL_TREE, 0);
6874c264
JM
274}
275
276/* Returns a reference to the cp_eh_info node for the current exception. */
277
278static tree
279get_eh_info ()
280{
281 /* Look for the pointer pushed in push_eh_info. */
282 tree t = lookup_name (get_identifier ("__exception_info"), 0);
283 return build_indirect_ref (t, NULL_PTR);
284}
285
286/* Returns a reference to the current exception object. */
287
288static tree
289get_eh_value ()
290{
291 return build_component_ref (get_eh_info (), get_identifier ("value"),
292 NULL_TREE, 0);
293}
294
295/* Returns a reference to the current exception type. */
296
87603ed0 297#if 0
6874c264
JM
298static tree
299get_eh_type ()
300{
301 return build_component_ref (get_eh_info (), get_identifier ("type"),
302 NULL_TREE, 0);
303}
304
305/* Returns a reference to whether or not the current exception
306 has been caught. */
307
308static tree
309get_eh_caught ()
310{
311 return build_component_ref (get_eh_info (), get_identifier ("caught"),
312 NULL_TREE, 0);
313}
314
20b90169
JM
315/* Returns a reference to whether or not the current exception
316 has been caught. */
317
318static tree
319get_eh_handlers ()
320{
321 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
322 NULL_TREE, 0);
323}
e833cb11 324#endif
20b90169 325
f30432d7
MS
326/* Build a type value for use at runtime for a type that is matched
327 against by the exception handling system. */
6467930b 328
f30432d7
MS
329static tree
330build_eh_type_type (type)
331 tree type;
8d08fdba 332{
f30432d7
MS
333 if (type == error_mark_node)
334 return error_mark_node;
8d2733ca 335
e92cc029 336 /* peel back references, so they match. */
f30432d7
MS
337 if (TREE_CODE (type) == REFERENCE_TYPE)
338 type = TREE_TYPE (type);
8d08fdba 339
e92cc029 340 /* Peel off cv qualifiers. */
f30432d7 341 type = TYPE_MAIN_VARIANT (type);
8d2733ca 342
db48b831 343 return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
8d08fdba 344}
8d08fdba 345
e5f614d7 346/* Build the address of a typeinfo decl for use in the runtime
db48b831 347 matching field of the new exception model */
5816cb14
AM
348
349static tree
350build_eh_type_type_ref (type)
351 tree type;
352{
5816cb14 353 tree exp;
5816cb14
AM
354
355 if (type == error_mark_node)
356 return error_mark_node;
357
358 /* peel back references, so they match. */
359 if (TREE_CODE (type) == REFERENCE_TYPE)
360 type = TREE_TYPE (type);
361
362 /* Peel off cv qualifiers. */
363 type = TYPE_MAIN_VARIANT (type);
364
e5f614d7
NS
365 exp = get_tinfo_decl (type);
366 mark_used (exp);
db48b831 367 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
5816cb14 368
5816cb14
AM
369 return (exp);
370}
371
9c606f69 372/* This routine is called to mark all the symbols representing runtime
ae673f14 373 type functions in the exception table as having been referenced.
9c606f69
AM
374 This will make sure code is emitted for them. Called from finish_file. */
375void
376mark_all_runtime_matches ()
377{
378 int x,num;
379 void **ptr;
380 tree exp;
381
382 num = find_all_handler_type_matches (&ptr);
383 if (num == 0 || ptr == NULL)
384 return;
385
386 for (x=0; x <num; x++)
387 {
388 exp = (tree) ptr[x];
389 if (TREE_CODE (exp) == ADDR_EXPR)
390 {
391 exp = TREE_OPERAND (exp, 0);
392 if (TREE_CODE (exp) == FUNCTION_DECL)
393 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;
394 }
395 }
396
397 free (ptr);
398}
399
c7ae64f2
JM
400/* Build up a call to __cp_pop_exception, to destroy the exception object
401 for the current catch block. HANDLER is either true or false, telling
402 the library whether or not it is being called from an exception handler;
403 if it is, it avoids destroying the object on rethrow. */
6467930b 404
c7ae64f2 405static tree
de35891e 406do_pop_exception ()
72b7eeff 407{
6874c264 408 tree fn, cleanup;
6874c264
JM
409 fn = get_identifier ("__cp_pop_exception");
410 if (IDENTIFIER_GLOBAL_VALUE (fn))
411 fn = IDENTIFIER_GLOBAL_VALUE (fn);
412 else
413 {
c7ae64f2
JM
414 /* Declare void __cp_pop_exception (void *),
415 as defined in exception.cc. */
c7ae64f2
JM
416 fn = build_lang_decl
417 (FUNCTION_DECL, fn,
418 build_function_type (void_type_node, tree_cons
de35891e 419 (NULL_TREE, ptr_type_node, void_list_node)));
6874c264
JM
420 DECL_EXTERNAL (fn) = 1;
421 TREE_PUBLIC (fn) = 1;
422 DECL_ARTIFICIAL (fn) = 1;
423 pushdecl_top_level (fn);
424 make_function_rtl (fn);
6874c264 425 }
72b7eeff 426
a6ecf8b6 427 mark_used (fn);
72b7eeff 428 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
c7ae64f2 429 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
e1b3e07d 430 cleanup = build_function_call (fn, tree_cons
de35891e 431 (NULL_TREE, cleanup, NULL_TREE));
c0700ea5 432 return cleanup;
c7ae64f2
JM
433}
434
435/* This routine creates the cleanup for the current exception. */
72b7eeff 436
c7ae64f2
JM
437static void
438push_eh_cleanup ()
439{
b35d4555 440 finish_decl_cleanup (NULL_TREE, do_pop_exception ());
c7ae64f2 441}
72b7eeff 442
f4a23343
JM
443/* Build up a call to terminate on the function obstack, for use as an
444 exception handler. */
445
c6160f8f 446static tree
f4a23343
JM
447build_terminate_handler ()
448{
80048418 449 return build_function_call (terminate_node, NULL_TREE);
f4a23343
JM
450}
451
b35d4555 452/* Initialize the catch parameter DECL. */
6467930b 453
b35d4555
MM
454static void
455initialize_handler_parm (decl)
3c5c0849 456 tree decl;
8d08fdba 457{
b35d4555
MM
458 tree exp;
459 tree init;
460 tree init_type;
461
462 /* Make sure we mark the catch param as used, otherwise we'll get a
463 warning about an unused ((anonymous)). */
464 TREE_USED (decl) = 1;
465
466 /* Figure out the type that the initializer is. */
467 init_type = TREE_TYPE (decl);
468 if (TREE_CODE (init_type) != REFERENCE_TYPE
469 && TREE_CODE (init_type) != POINTER_TYPE)
470 init_type = build_reference_type (init_type);
471
472 exp = get_eh_value ();
473
474 /* Since pointers are passed by value, initialize a reference to
475 pointer catch parm with the address of the value slot. */
476 if (TREE_CODE (init_type) == REFERENCE_TYPE
477 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
478 exp = build_unary_op (ADDR_EXPR, exp, 1);
479
480 exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
481
482 init = convert_from_reference (exp);
483
484 /* If the constructor for the catch parm exits via an exception, we
485 must call terminate. See eh23.C. */
486 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
faf5394a 487 {
b35d4555
MM
488 /* Generate the copy constructor call directly so we can wrap it.
489 See also expand_default_init. */
490 init = ocp_convert (TREE_TYPE (decl), init,
491 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
492 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
493 build_terminate_handler ());
faf5394a
MS
494 }
495
b35d4555
MM
496 /* Let `cp_finish_decl' know that this initializer is ok. */
497 DECL_INITIAL (decl) = error_mark_node;
498 decl = pushdecl (decl);
8d2733ca 499
b35d4555 500 start_decl_1 (decl);
cd9f6678 501 cp_finish_decl (decl, init, NULL_TREE,
b35d4555 502 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
5816cb14
AM
503}
504
b35d4555 505/* Call this to start a catch block. DECL is the catch parameter. */
5816cb14 506
b35d4555
MM
507tree
508expand_start_catch_block (decl)
3c5c0849 509 tree decl;
5816cb14 510{
b35d4555
MM
511 tree compound_stmt_1;
512 tree compound_stmt_2;
513 tree type;
5816cb14 514
b35d4555
MM
515 if (! doing_eh (1))
516 return NULL_TREE;
5816cb14 517
b35d4555 518 /* Make sure this declaration is reasonable. */
3c5c0849
MM
519 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
520 decl = NULL_TREE;
5816cb14 521
b35d4555
MM
522 /* Create a binding level for the eh_info and the exception object
523 cleanup. */
524 compound_stmt_1 = begin_compound_stmt (/*has_no_scope=*/0);
525
5816cb14 526 if (decl)
b35d4555 527 type = build_eh_type_type_ref (TREE_TYPE (decl));
5816cb14 528 else
b35d4555
MM
529 type = NULL_TREE;
530 begin_catch_block (type);
5816cb14
AM
531
532 push_eh_info ();
b35d4555 533 push_eh_cleanup ();
5816cb14 534
b35d4555
MM
535 /* Create a binding level for the parm. */
536 compound_stmt_2 = begin_compound_stmt (/*has_no_scope=*/0);
5816cb14 537
b35d4555
MM
538 if (decl)
539 initialize_handler_parm (decl);
5816cb14 540
b35d4555 541 return build_tree_list (compound_stmt_1, compound_stmt_2);
5816cb14
AM
542}
543
f30432d7 544
8d2733ca
MS
545/* Call this to end a catch block. Its responsible for emitting the
546 code to handle jumping back to the correct place, and for emitting
547 the label to jump to if this catch block didn't match. */
6467930b 548
824b9a4c 549void
b35d4555
MM
550expand_end_catch_block (blocks)
551 tree blocks;
8d08fdba 552{
b35d4555
MM
553 tree compound_stmt_1 = blocks ? TREE_PURPOSE (blocks): NULL_TREE;
554 tree compound_stmt_2 = blocks ? TREE_VALUE (blocks): NULL_TREE;
555
f30432d7
MS
556 if (! doing_eh (1))
557 return;
8d2733ca 558
0dde4175
JM
559 /* The exception being handled is rethrown if control reaches the end of
560 a handler of the function-try-block of a constructor or destructor. */
561 if (in_function_try_handler
562 && (DECL_CONSTRUCTOR_P (current_function_decl)
563 || DECL_DESTRUCTOR_P (current_function_decl)))
b35d4555 564 finish_expr_stmt (build_throw (NULL_TREE));
0dde4175 565
c7ae64f2 566 /* Cleanup the EH parameter. */
b35d4555 567 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_2);
46e8c075 568 /* Cleanup the EH object. */
4a6ef811 569 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_1);
8d2733ca 570}
8d08fdba 571
6c20b7e9
JM
572/* An exception spec is implemented more or less like:
573
574 try {
575 function body;
576 } catch (...) {
577 void *p[] = { typeid(raises) };
578 __check_eh_spec (p, count);
579 }
580
581 __check_eh_spec in exception.cc handles all the details. */
8d2733ca 582
b35d4555 583tree
f30432d7
MS
584expand_start_eh_spec ()
585{
b35d4555 586 return begin_try_block ();
f30432d7
MS
587}
588
b35d4555
MM
589void
590expand_end_eh_spec (raises, try_block)
f30432d7 591 tree raises;
b35d4555 592 tree try_block;
f30432d7 593{
6c20b7e9 594 tree tmp, fn, decl, types = NULL_TREE;
b35d4555
MM
595 tree blocks;
596 tree handler;
6c20b7e9 597 int count = 0;
f30432d7 598
b35d4555
MM
599 finish_try_block (try_block);
600 handler = begin_handler ();
601 blocks = finish_handler_parms (NULL_TREE, handler);
f30432d7 602
6c20b7e9
JM
603 /* Build up an array of type_infos. */
604 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
605 {
e1b3e07d 606 types = tree_cons
6c20b7e9
JM
607 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
608 ++count;
609 }
eb66be0e 610
6c20b7e9
JM
611 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
612 TREE_HAS_CONSTRUCTOR (types) = 1;
6874c264 613
6c20b7e9 614 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
52bf7d5d 615 tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
6c20b7e9
JM
616 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
617 DECL_ARTIFICIAL (decl) = 1;
618 DECL_INITIAL (decl) = types;
46e8c075 619 DECL_CONTEXT (decl) = current_function_decl;
cd9f6678 620 cp_finish_decl (decl, types, NULL_TREE, 0);
6c20b7e9
JM
621
622 decl = decay_conversion (decl);
6874c264 623
6c20b7e9
JM
624 fn = get_identifier ("__check_eh_spec");
625 if (IDENTIFIER_GLOBAL_VALUE (fn))
626 fn = IDENTIFIER_GLOBAL_VALUE (fn);
627 else
f30432d7 628 {
6c20b7e9
JM
629 tmp = tree_cons
630 (NULL_TREE, integer_type_node, tree_cons
631 (NULL_TREE, TREE_TYPE (decl), void_list_node));
632 tmp = build_function_type (void_type_node, tmp);
f30432d7 633
6c20b7e9
JM
634 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
635 DECL_EXTERNAL (fn) = 1;
636 TREE_PUBLIC (fn) = 1;
637 DECL_ARTIFICIAL (fn) = 1;
638 TREE_THIS_VOLATILE (fn) = 1;
639 pushdecl_top_level (fn);
640 make_function_rtl (fn);
6c20b7e9
JM
641 }
642
a6ecf8b6 643 mark_used (fn);
e1b3e07d
MM
644 tmp = tree_cons (NULL_TREE, build_int_2 (count, 0),
645 tree_cons (NULL_TREE, decl, NULL_TREE));
6c20b7e9 646 tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
b35d4555 647 finish_expr_stmt (tmp);
6c20b7e9 648
b35d4555
MM
649 finish_handler (blocks, handler);
650 finish_handler_sequence (try_block);
f30432d7
MS
651}
652
8d2733ca
MS
653/* This is called to expand all the toplevel exception handling
654 finalization for a function. It should only be called once per
655 function. */
6467930b 656
8d08fdba 657void
8d2733ca 658expand_exception_blocks ()
8d08fdba 659{
92b96838 660 do_pending_stack_adjust ();
eb448459 661
e00737d2 662 if (catch_clauses)
f30432d7 663 {
e00737d2
MS
664 rtx funcend = gen_label_rtx ();
665 emit_jump (funcend);
666
eb66be0e
MS
667 /* We cannot protect n regions this way if we must flow into the
668 EH region through the top of the region, as we have to with
669 the setjmp/longjmp approach. */
670 if (exceptions_via_longjmp == 0)
fb98cff6 671 expand_eh_region_start ();
f30432d7 672
e00737d2
MS
673 emit_insns (catch_clauses);
674 catch_clauses = NULL_RTX;
eb66be0e
MS
675
676 if (exceptions_via_longjmp == 0)
f4a23343 677 expand_eh_region_end (build_terminate_handler ());
eb66be0e 678
4a6ef811
MM
679 emit_insns (catch_clauses);
680 catch_clauses = NULL_RTX;
e00737d2
MS
681 emit_label (funcend);
682 }
8d08fdba
MS
683}
684
f4a23343
JM
685/* Return a pointer to a buffer for an exception object of type TYPE. */
686
c6160f8f 687static tree
f4a23343
JM
688alloc_eh_object (type)
689 tree type;
690{
691 tree fn, exp;
692
693 fn = get_identifier ("__eh_alloc");
694 if (IDENTIFIER_GLOBAL_VALUE (fn))
695 fn = IDENTIFIER_GLOBAL_VALUE (fn);
696 else
697 {
698 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
699 tree tmp;
f4a23343
JM
700 tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
701 fn = build_lang_decl (FUNCTION_DECL, fn,
702 build_function_type (ptr_type_node, tmp));
703 DECL_EXTERNAL (fn) = 1;
704 TREE_PUBLIC (fn) = 1;
705 DECL_ARTIFICIAL (fn) = 1;
706 pushdecl_top_level (fn);
707 make_function_rtl (fn);
f4a23343
JM
708 }
709
a6ecf8b6 710 mark_used (fn);
e1b3e07d 711 exp = build_function_call (fn, tree_cons
f4a23343
JM
712 (NULL_TREE, size_in_bytes (type), NULL_TREE));
713 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
714 return exp;
715}
716
6467930b 717/* Expand a throw statement. This follows the following
8d2733ca
MS
718 algorithm:
719
720 1. Allocate space to save the current PC onto the stack.
721 2. Generate and emit a label and save its address into the
e1cd6e56 722 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
723 3. If this is the first call to throw in this function:
724 generate a label for the throw block
725 4. jump to the throw block label. */
6467930b 726
225ff119 727static tree
8d2733ca
MS
728expand_throw (exp)
729 tree exp;
8d08fdba 730{
6874c264 731 tree fn;
8d08fdba 732
8d2733ca 733 if (! doing_eh (1))
59ccf49d 734 return error_mark_node;
8d08fdba 735
8d2733ca
MS
736 if (exp)
737 {
faae18ab 738 tree throw_type;
6874c264 739 tree cleanup = NULL_TREE, e;
59ccf49d
MM
740 tree stmt_expr;
741 tree compound_stmt;
742 tree try_block;
743
744 begin_init_stmts (&stmt_expr, &compound_stmt);
faae18ab 745
a3b49ccd 746 /* throw expression */
e92cc029 747 /* First, decay it. */
f30432d7 748 exp = decay_conversion (exp);
a3b49ccd 749
6874c264
JM
750 /* cleanup_type is void (*)(void *, int),
751 the internal type of a destructor. */
752 if (cleanup_type == NULL_TREE)
59ccf49d
MM
753 cleanup_type = build_pointer_type
754 (build_function_type
755 (void_type_node, tree_cons
756 (NULL_TREE, ptr_type_node, tree_cons
757 (NULL_TREE, integer_type_node, void_list_node))));
6874c264 758
08b24bda 759 if (TYPE_PTR_P (TREE_TYPE (exp)))
db48b831 760 throw_type = build_eh_type_type (TREE_TYPE (exp));
f30432d7
MS
761 else
762 {
f4a23343
JM
763 tree object, ptr;
764
765 /* OK, this is kind of wacky. The WP says that we call
46e8c075
MM
766 terminate when the exception handling mechanism, after
767 completing evaluation of the expression to be thrown but
768 before the exception is caught (_except.throw_), calls a
769 user function that exits via an uncaught exception.
f4a23343
JM
770
771 So we have to protect the actual initialization of the
772 exception object with terminate(), but evaluate the expression
773 first. We also expand the call to __eh_alloc
774 first. Since there could be temps in the expression, we need
775 to handle that, too. */
a50f0918 776
59ccf49d 777 my_friendly_assert (stmts_are_full_exprs_p == 1, 19990926);
f4a23343 778
f4a23343
JM
779 /* Store the throw expression into a temp. This can be less
780 efficient than storing it into the allocated space directly, but
781 oh well. To do this efficiently we would need to insinuate
782 ourselves into expand_call. */
783 if (TREE_SIDE_EFFECTS (exp))
784 {
f1dedc31 785 tree temp = create_temporary_var (TREE_TYPE (exp));
c37dc68e 786 DECL_INITIAL (temp) = exp;
cd9f6678 787 cp_finish_decl (temp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
f4a23343
JM
788 exp = temp;
789 }
f4a23343
JM
790
791 /* Allocate the space for the exception. */
792 ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
59ccf49d 793 finish_expr_stmt (ptr);
f4a23343 794
59ccf49d 795 try_block = begin_try_block ();
f4a23343
JM
796 object = build_indirect_ref (ptr, NULL_PTR);
797 exp = build_modify_expr (object, INIT_EXPR, exp);
faae18ab 798
f30432d7 799 if (exp == error_mark_node)
8251199e 800 error (" in thrown expression");
faae18ab 801
59ccf49d
MM
802 finish_expr_stmt (exp);
803 finish_cleanup_try_block (try_block);
804 finish_cleanup (build_terminate_handler (), try_block);
f4a23343 805
db48b831 806 throw_type = build_eh_type_type (TREE_TYPE (object));
72b7eeff 807
6874c264
JM
808 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
809 {
810 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
811 dtor_identifier, 0);
812 cleanup = TREE_VALUE (cleanup);
e872bb7a 813 mark_used (cleanup);
6874c264
JM
814 mark_addressable (cleanup);
815 /* Pretend it's a normal function. */
816 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
817 }
f4a23343
JM
818
819 exp = ptr;
f30432d7 820 }
faae18ab 821
bbeeb2b0
MM
822 /* Cast EXP to `void *' so that it will match the prototype for
823 __cp_push_exception. */
c37dc68e 824 exp = convert (ptr_type_node, exp);
bbeeb2b0 825
6874c264
JM
826 if (cleanup == NULL_TREE)
827 {
828 cleanup = build_int_2 (0, 0);
829 TREE_TYPE (cleanup) = cleanup_type;
830 }
72b7eeff 831
6874c264
JM
832 fn = get_identifier ("__cp_push_exception");
833 if (IDENTIFIER_GLOBAL_VALUE (fn))
834 fn = IDENTIFIER_GLOBAL_VALUE (fn);
835 else
836 {
837 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
838 as defined in exception.cc. */
839 tree tmp;
6874c264
JM
840 tmp = tree_cons
841 (NULL_TREE, ptr_type_node, tree_cons
842 (NULL_TREE, ptr_type_node, tree_cons
843 (NULL_TREE, cleanup_type, void_list_node)));
844 fn = build_lang_decl (FUNCTION_DECL, fn,
845 build_function_type (void_type_node, tmp));
846 DECL_EXTERNAL (fn) = 1;
847 TREE_PUBLIC (fn) = 1;
848 DECL_ARTIFICIAL (fn) = 1;
849 pushdecl_top_level (fn);
850 make_function_rtl (fn);
6874c264 851 }
72b7eeff 852
a6ecf8b6 853 mark_used (fn);
e1b3e07d
MM
854 e = tree_cons (NULL_TREE, exp, tree_cons
855 (NULL_TREE, throw_type, tree_cons
856 (NULL_TREE, cleanup, NULL_TREE)));
59ccf49d
MM
857 finish_expr_stmt (build_function_call (fn, e));
858
859 exp = finish_init_stmts (stmt_expr, compound_stmt);
8d2733ca
MS
860 }
861 else
a3b49ccd 862 {
6874c264
JM
863 /* rethrow current exception; note that it's no longer caught. */
864
865 tree fn = get_identifier ("__uncatch_exception");
866 if (IDENTIFIER_GLOBAL_VALUE (fn))
867 fn = IDENTIFIER_GLOBAL_VALUE (fn);
868 else
869 {
870 /* Declare void __uncatch_exception (void)
871 as defined in exception.cc. */
6874c264
JM
872 fn = build_lang_decl (FUNCTION_DECL, fn,
873 build_function_type (void_type_node,
874 void_list_node));
875 DECL_EXTERNAL (fn) = 1;
876 TREE_PUBLIC (fn) = 1;
877 DECL_ARTIFICIAL (fn) = 1;
878 pushdecl_top_level (fn);
879 make_function_rtl (fn);
6874c264
JM
880 }
881
a6ecf8b6 882 mark_used (fn);
6874c264 883 exp = build_function_call (fn, NULL_TREE);
a3b49ccd 884 }
8d2733ca 885
59ccf49d 886 return exp;
f376e137 887}
8d2733ca
MS
888
889/* Build a throw expression. */
6467930b 890
8d2733ca
MS
891tree
892build_throw (e)
893 tree e;
894{
02020185
JM
895 if (e == error_mark_node)
896 return e;
897
898 if (processing_template_decl)
899 return build_min (THROW_EXPR, void_type_node, e);
900
e0f9a8bc 901 if (e == null_node)
8251199e 902 cp_warning ("throwing NULL, which has integral, not pointer type");
980c394c
NS
903
904 if (e != NULL_TREE)
905 {
4cfbc546
NS
906 if (!complete_ptr_ref_or_void_ptr_p (TREE_TYPE (e), e))
907 return error_mark_node;
980c394c 908 }
02020185 909
59ccf49d 910 e = expand_throw (e);
02020185
JM
911 e = build1 (THROW_EXPR, void_type_node, e);
912 TREE_SIDE_EFFECTS (e) = 1;
913 TREE_USED (e) = 1;
914
8d2733ca 915 return e;
8d08fdba 916}
4cfbc546
NS
917
918/* Make sure TYPE is complete, pointer to complete, reference to
919 complete, or pointer to cv void. Issue diagnostic on failure.
920 Return the zero on failure and non-zero on success. FROM can be
921 the expr or decl from whence TYPE came, if available. */
922
923static int
924complete_ptr_ref_or_void_ptr_p (type, from)
925 tree type;
926 tree from;
927{
928 int is_ptr;
929
930 /* Check complete. */
931 type = complete_type_or_else (type, from);
932 if (!type)
933 return 0;
934
935 /* Or a pointer or ref to one, or cv void *. */
936 is_ptr = TREE_CODE (type) == POINTER_TYPE;
937 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
938 {
939 tree core = TREE_TYPE (type);
940
941 if (is_ptr && same_type_p (TYPE_MAIN_VARIANT (core), void_type_node))
942 /* OK */;
943 else if (!complete_type_or_else (core, from))
944 return 0;
945 }
946 return 1;
947}
948
This page took 0.617338 seconds and 5 git commands to generate.