]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
stdio-opt-2.c: Also test __builtin_puts and __builtin_putchar.
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
d6a8bdff 2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
158991b7 3 Free Software Foundation, Inc.
8d2733ca
MS
4 Contributed by Michael Tiemann <tiemann@cygnus.com>
5 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
6 initial re-implementation courtesy Tad Hunt.
8d08fdba
MS
7
8This file is part of GNU CC.
9
10GNU CC is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15GNU CC is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with GNU CC; see the file COPYING. If not, write to
e9fa0c7c
RK
22the Free Software Foundation, 59 Temple Place - Suite 330,
23Boston, MA 02111-1307, USA. */
8d08fdba
MS
24
25
8d08fdba 26#include "config.h"
8d052bc7 27#include "system.h"
8d08fdba
MS
28#include "tree.h"
29#include "rtl.h"
8f17b5c5 30#include "expr.h"
8d08fdba
MS
31#include "cp-tree.h"
32#include "flags.h"
8d2733ca 33#include "obstack.h"
21451173 34#include "output.h"
6467930b 35#include "except.h"
0021b564 36#include "defaults.h"
54f92bfb 37#include "toplev.h"
9a0d1e1b 38#include "eh-common.h"
8d08fdba 39
93ca4ba7 40static void push_eh_cleanup PARAMS ((tree));
158991b7
KG
41static tree build_eh_type_type PARAMS ((tree));
42static tree call_eh_info PARAMS ((void));
43static void push_eh_info PARAMS ((void));
44static tree get_eh_info PARAMS ((void));
45static tree get_eh_value PARAMS ((void));
87603ed0 46#if 0
158991b7
KG
47static tree get_eh_type PARAMS ((void));
48static tree get_eh_caught PARAMS ((void));
49static tree get_eh_handlers PARAMS ((void));
e833cb11 50#endif
93ca4ba7
JM
51static int dtor_nothrow PARAMS ((tree));
52static tree do_pop_exception PARAMS ((tree));
158991b7
KG
53static tree build_eh_type_type_ref PARAMS ((tree));
54static tree build_terminate_handler PARAMS ((void));
55static tree alloc_eh_object PARAMS ((tree));
56static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
fbd40359
ZW
57static int can_convert_eh PARAMS ((tree, tree));
58static void check_handlers_1 PARAMS ((tree, tree));
158991b7
KG
59static void initialize_handler_parm PARAMS ((tree));
60static tree expand_throw PARAMS ((tree));
e97f22c9 61static int decl_is_java_type PARAMS ((tree decl, int err));
8d2733ca 62
8d2733ca 63#include "decl.h"
8d2733ca
MS
64#include "insn-flags.h"
65#include "obstack.h"
8d2733ca 66
e97f22c9
TT
67/* In a given translation unit we are constrained to catch only C++
68 types or only Java types. `catch_language' holds the current type,
69 and `catch_language_init' registers whether `catch_language' has
70 been set. */
71
72static int catch_language_init = 0;
73static int catch_language;
74
8d2733ca
MS
75/* ======================================================================
76 Briefly the algorithm works like this:
77
78 When a constructor or start of a try block is encountered,
79 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
80 new entry in the unwind protection stack and returns a label to
81 output to start the protection for that block.
82
83 When a destructor or end try block is encountered, pop_eh_entry
6467930b
MS
84 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
85 created when push_eh_entry () was called. The eh_entry structure
8d2733ca
MS
86 contains three things at this point. The start protect label,
87 the end protect label, and the exception handler label. The end
88 protect label should be output before the call to the destructor
89 (if any). If it was a destructor, then its parse tree is stored
6467930b 90 in the finalization variable in the eh_entry structure. Otherwise
8d2733ca 91 the finalization variable is set to NULL to reflect the fact that
38e01259 92 it is the end of a try block. Next, this modified eh_entry node
8d2733ca
MS
93 is enqueued in the finalizations queue by calling
94 enqueue_eh_entry (&queue,entry).
95
96 +---------------------------------------------------------------+
97 |XXX: Will need modification to deal with partially |
98 | constructed arrays of objects |
99 | |
100 | Basically, this consists of keeping track of how many |
101 | of the objects have been constructed already (this |
102 | should be in a register though, so that shouldn't be a |
103 | problem. |
104 +---------------------------------------------------------------+
105
106 When a catch block is encountered, there is a lot of work to be
107 done.
108
109 Since we don't want to generate the catch block inline with the
110 regular flow of the function, we need to have some way of doing
f30432d7
MS
111 so. Luckily, we can use sequences to defer the catch sections.
112 When the start of a catch block is encountered, we start the
113 sequence. After the catch block is generated, we end the
114 sequence.
115
8d2733ca
MS
116 Next we must insure that when the catch block is executed, all
117 finalizations for the matching try block have been completed. If
118 any of those finalizations throw an exception, we must call
119 terminate according to the ARM (section r.15.6.1). What this
120 means is that we need to dequeue and emit finalizations for each
6467930b 121 entry in the eh_queue until we get to an entry with a NULL
8d2733ca
MS
122 finalization field. For any of the finalization entries, if it
123 is not a call to terminate (), we must protect it by giving it
124 another start label, end label, and exception handler label,
125 setting its finalization tree to be a call to terminate (), and
6467930b 126 enqueue'ing this new eh_entry to be output at an outer level.
8d2733ca
MS
127 Finally, after all that is done, we can get around to outputting
128 the catch block which basically wraps all the "catch (...) {...}"
129 statements in a big if/then/else construct that matches the
130 correct block to call.
131
132 ===================================================================== */
133
8d2733ca
MS
134/* ====================================================================== */
135
8d2733ca 136/* sets up all the global eh stuff that needs to be initialized at the
bbd0d54a 137 start of compilation. */
8d08fdba 138
8d08fdba 139void
8d2733ca 140init_exception_processing ()
8d08fdba 141{
6633d636
MS
142 /* void vtype () */
143 tree vtype = build_function_type (void_type_node, void_list_node);
144
2c73f9f5 145 if (flag_honor_std)
6bcedb4e 146 push_namespace (std_identifier);
0c11ada6 147 terminate_node = build_cp_library_fn_ptr ("terminate", vtype);
9cd64686 148 TREE_THIS_VOLATILE (terminate_node) = 1;
0c11ada6 149 TREE_NOTHROW (terminate_node) = 1;
2c73f9f5
ML
150 if (flag_honor_std)
151 pop_namespace ();
8ccc31eb 152
9a0d1e1b
AM
153 set_exception_lang_code (EH_LANG_C_plus_plus);
154 set_exception_version_code (1);
9a0d1e1b 155
eb66be0e
MS
156 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
157 be protected with __terminate. */
158 protect_cleanup_actions_with_terminate = 1;
8d2733ca
MS
159}
160
95e8dcba 161/* Retrieve a pointer to the cp_eh_info node for the current exception. */
6874c264 162
95e8dcba
JM
163static tree
164call_eh_info ()
6874c264 165{
95e8dcba 166 tree fn;
6874c264 167
e6cfb550 168 fn = get_identifier ("__start_cp_handler");
6874c264
JM
169 if (IDENTIFIER_GLOBAL_VALUE (fn))
170 fn = IDENTIFIER_GLOBAL_VALUE (fn);
171 else
172 {
a1622f83 173 tree t1, t, fields[7];
6874c264 174
e6cfb550 175 /* Declare cp_eh_info * __start_cp_handler (void),
6874c264 176 as defined in exception.cc. */
6874c264
JM
177
178 /* struct cp_eh_info. This must match exception.cc. Note that this
179 type is not pushed anywhere. */
33848bb0 180 t1= make_aggr_type (RECORD_TYPE);
721c3b42 181 fields[0] = build_decl (FIELD_DECL,
9a0d1e1b 182 get_identifier ("handler_label"), ptr_type_node);
721c3b42 183 fields[1] = build_decl (FIELD_DECL,
9a0d1e1b 184 get_identifier ("dynamic_handler_chain"), ptr_type_node);
721c3b42 185 fields[2] = build_decl (FIELD_DECL,
9a0d1e1b 186 get_identifier ("info"), ptr_type_node);
721c3b42 187 fields[3] = build_decl (FIELD_DECL,
e6cfb550 188 get_identifier ("table_index"), ptr_type_node);
9a0d1e1b
AM
189 /* N.B.: The fourth field LEN is expected to be
190 the number of fields - 1, not the total number of fields. */
e6cfb550 191 finish_builtin_type (t1, "eh_context", fields, 3, ptr_type_node);
9a0d1e1b
AM
192 t1 = build_pointer_type (t1);
193
33848bb0 194 t1= make_aggr_type (RECORD_TYPE);
721c3b42 195 fields[0] = build_decl (FIELD_DECL,
9a0d1e1b 196 get_identifier ("match_function"), ptr_type_node);
721c3b42 197 fields[1] = build_decl (FIELD_DECL,
9a0d1e1b 198 get_identifier ("language"), short_integer_type_node);
721c3b42 199 fields[2] = build_decl (FIELD_DECL,
9a0d1e1b
AM
200 get_identifier ("version"), short_integer_type_node);
201 /* N.B.: The fourth field LEN is expected to be
202 the number of fields - 1, not the total number of fields. */
5816cb14 203 finish_builtin_type (t1, "__eh_info", fields, 2, ptr_type_node);
33848bb0 204 t = make_aggr_type (RECORD_TYPE);
721c3b42
MM
205 fields[0] = build_decl (FIELD_DECL,
206 get_identifier ("eh_info"), t1);
207 fields[1] = build_decl (FIELD_DECL, get_identifier ("value"),
208 ptr_type_node);
209 fields[2] = build_decl (FIELD_DECL, get_identifier ("type"),
210 ptr_type_node);
211 fields[3] = build_decl
6874c264
JM
212 (FIELD_DECL, get_identifier ("cleanup"),
213 build_pointer_type (build_function_type
214 (ptr_type_node, tree_cons
215 (NULL_TREE, ptr_type_node, void_list_node))));
721c3b42
MM
216 fields[4] = build_decl (FIELD_DECL, get_identifier ("caught"),
217 boolean_type_node);
218 fields[5] = build_decl (FIELD_DECL, get_identifier ("next"),
219 build_pointer_type (t));
220 fields[6] = build_decl
20b90169 221 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
cf9d67e3
BK
222 /* N.B.: The fourth field LEN is expected to be
223 the number of fields - 1, not the total number of fields. */
a1622f83 224 finish_builtin_type (t, "cp_eh_info", fields, 6, ptr_type_node);
6874c264
JM
225 t = build_pointer_type (t);
226
227 /* And now the function. */
0c11ada6 228 fn = push_library_fn (fn, build_function_type (t, void_list_node));
6874c264 229 }
95e8dcba
JM
230 return build_function_call (fn, NULL_TREE);
231}
232
233/* Retrieve a pointer to the cp_eh_info node for the current exception
234 and save it in the current binding level. */
235
236static void
237push_eh_info ()
238{
239 tree decl, fn = call_eh_info ();
6874c264
JM
240
241 /* Remember the pointer to the current exception info; it won't change
242 during this catch block. */
243 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
244 TREE_TYPE (fn));
245 DECL_ARTIFICIAL (decl) = 1;
246 DECL_INITIAL (decl) = fn;
247 decl = pushdecl (decl);
cd9f6678 248 cp_finish_decl (decl, fn, NULL_TREE, 0);
6874c264
JM
249}
250
251/* Returns a reference to the cp_eh_info node for the current exception. */
252
253static tree
254get_eh_info ()
255{
256 /* Look for the pointer pushed in push_eh_info. */
257 tree t = lookup_name (get_identifier ("__exception_info"), 0);
258 return build_indirect_ref (t, NULL_PTR);
259}
260
261/* Returns a reference to the current exception object. */
262
263static tree
264get_eh_value ()
265{
266 return build_component_ref (get_eh_info (), get_identifier ("value"),
267 NULL_TREE, 0);
268}
269
270/* Returns a reference to the current exception type. */
271
87603ed0 272#if 0
6874c264
JM
273static tree
274get_eh_type ()
275{
276 return build_component_ref (get_eh_info (), get_identifier ("type"),
277 NULL_TREE, 0);
278}
279
280/* Returns a reference to whether or not the current exception
281 has been caught. */
282
283static tree
284get_eh_caught ()
285{
286 return build_component_ref (get_eh_info (), get_identifier ("caught"),
287 NULL_TREE, 0);
288}
289
20b90169
JM
290/* Returns a reference to whether or not the current exception
291 has been caught. */
292
293static tree
294get_eh_handlers ()
295{
296 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
297 NULL_TREE, 0);
298}
e833cb11 299#endif
20b90169 300
f30432d7
MS
301/* Build a type value for use at runtime for a type that is matched
302 against by the exception handling system. */
6467930b 303
f30432d7
MS
304static tree
305build_eh_type_type (type)
306 tree type;
8d08fdba 307{
f30432d7
MS
308 if (type == error_mark_node)
309 return error_mark_node;
8d2733ca 310
e92cc029 311 /* peel back references, so they match. */
f30432d7
MS
312 if (TREE_CODE (type) == REFERENCE_TYPE)
313 type = TREE_TYPE (type);
8d08fdba 314
e92cc029 315 /* Peel off cv qualifiers. */
f30432d7 316 type = TYPE_MAIN_VARIANT (type);
8d2733ca 317
db48b831 318 return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));
8d08fdba 319}
8d08fdba 320
e5f614d7 321/* Build the address of a typeinfo decl for use in the runtime
db48b831 322 matching field of the new exception model */
5816cb14
AM
323
324static tree
325build_eh_type_type_ref (type)
326 tree type;
327{
5816cb14 328 tree exp;
5816cb14 329
93ca4ba7
JM
330 if (type == NULL_TREE || type == error_mark_node)
331 return type;
5816cb14
AM
332
333 /* peel back references, so they match. */
334 if (TREE_CODE (type) == REFERENCE_TYPE)
335 type = TREE_TYPE (type);
336
337 /* Peel off cv qualifiers. */
338 type = TYPE_MAIN_VARIANT (type);
339
e5f614d7
NS
340 exp = get_tinfo_decl (type);
341 mark_used (exp);
db48b831 342 exp = build1 (ADDR_EXPR, ptr_type_node, exp);
5816cb14 343
5816cb14
AM
344 return (exp);
345}
346
9c606f69 347/* This routine is called to mark all the symbols representing runtime
ae673f14 348 type functions in the exception table as having been referenced.
9c606f69 349 This will make sure code is emitted for them. Called from finish_file. */
93ca4ba7 350
9c606f69
AM
351void
352mark_all_runtime_matches ()
353{
354 int x,num;
355 void **ptr;
356 tree exp;
357
358 num = find_all_handler_type_matches (&ptr);
359 if (num == 0 || ptr == NULL)
360 return;
361
362 for (x=0; x <num; x++)
363 {
364 exp = (tree) ptr[x];
365 if (TREE_CODE (exp) == ADDR_EXPR)
366 {
367 exp = TREE_OPERAND (exp, 0);
368 if (TREE_CODE (exp) == FUNCTION_DECL)
369 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;
370 }
371 }
372
373 free (ptr);
374}
375
93ca4ba7
JM
376/* Returns nonzero if cleaning up an exception of type TYPE (which can be
377 NULL_TREE for a ... handler) will not throw an exception. */
378
379static int
380dtor_nothrow (type)
381 tree type;
382{
383 tree fn;
384
385 if (type == NULL_TREE)
386 return 0;
387
388 if (! TYPE_HAS_DESTRUCTOR (type))
389 return 1;
390
391 fn = lookup_member (type, dtor_identifier, 0, 0);
392 fn = TREE_VALUE (fn);
393 return TREE_NOTHROW (fn);
394}
395
c7ae64f2 396/* Build up a call to __cp_pop_exception, to destroy the exception object
93ca4ba7 397 for the current catch block if no others are currently using it. */
6467930b 398
c7ae64f2 399static tree
93ca4ba7
JM
400do_pop_exception (type)
401 tree type;
72b7eeff 402{
6874c264 403 tree fn, cleanup;
6874c264
JM
404 fn = get_identifier ("__cp_pop_exception");
405 if (IDENTIFIER_GLOBAL_VALUE (fn))
406 fn = IDENTIFIER_GLOBAL_VALUE (fn);
407 else
408 {
c7ae64f2
JM
409 /* Declare void __cp_pop_exception (void *),
410 as defined in exception.cc. */
0c11ada6
JM
411 fn = push_void_library_fn
412 (fn, tree_cons (NULL_TREE, ptr_type_node, void_list_node));
413 /* This can throw if the destructor for the exception throws. */
414 TREE_NOTHROW (fn) = 0;
6874c264 415 }
72b7eeff
MS
416
417 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
c7ae64f2 418 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
e1b3e07d 419 cleanup = build_function_call (fn, tree_cons
de35891e 420 (NULL_TREE, cleanup, NULL_TREE));
93ca4ba7 421 TREE_NOTHROW (cleanup) = dtor_nothrow (type);
c0700ea5 422 return cleanup;
c7ae64f2
JM
423}
424
425/* This routine creates the cleanup for the current exception. */
72b7eeff 426
c7ae64f2 427static void
93ca4ba7
JM
428push_eh_cleanup (type)
429 tree type;
c7ae64f2 430{
93ca4ba7 431 finish_decl_cleanup (NULL_TREE, do_pop_exception (type));
c7ae64f2 432}
72b7eeff 433
f4a23343
JM
434/* Build up a call to terminate on the function obstack, for use as an
435 exception handler. */
436
c6160f8f 437static tree
f4a23343
JM
438build_terminate_handler ()
439{
80048418 440 return build_function_call (terminate_node, NULL_TREE);
f4a23343
JM
441}
442
e97f22c9
TT
443/* Return nonzero value if DECL is a Java type suitable for catch or
444 throw. */
445
446static int
447decl_is_java_type (decl, err)
448 tree decl;
449 int err;
450{
451 int r = (TREE_CODE (decl) == POINTER_TYPE
452 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
453 && TYPE_FOR_JAVA (TREE_TYPE (decl)));
454
455 if (err)
456 {
457 if (TREE_CODE (decl) == REFERENCE_TYPE
458 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
459 && TYPE_FOR_JAVA (TREE_TYPE (decl)))
460 {
461 /* Can't throw a reference. */
462 cp_error ("type `%T' is disallowed in Java `throw' or `catch'",
463 decl);
464 }
465
466 if (r)
467 {
468 tree jthrow_node
469 = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
470 if (jthrow_node == NULL_TREE)
471 fatal ("call to Java `catch' or `throw', while `jthrowable' undefined");
472 jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
473
474 if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
475 {
476 /* Thrown object must be a Throwable. */
477 cp_error ("type `%T' is not derived from `java::lang::Throwable'",
478 TREE_TYPE (decl));
479 }
480 }
481 }
482
483 return r;
484}
485
b35d4555 486/* Initialize the catch parameter DECL. */
6467930b 487
b35d4555
MM
488static void
489initialize_handler_parm (decl)
3c5c0849 490 tree decl;
8d08fdba 491{
b35d4555
MM
492 tree exp;
493 tree init;
494 tree init_type;
e97f22c9 495 int lang;
b35d4555
MM
496
497 /* Make sure we mark the catch param as used, otherwise we'll get a
498 warning about an unused ((anonymous)). */
499 TREE_USED (decl) = 1;
500
501 /* Figure out the type that the initializer is. */
502 init_type = TREE_TYPE (decl);
503 if (TREE_CODE (init_type) != REFERENCE_TYPE
504 && TREE_CODE (init_type) != POINTER_TYPE)
505 init_type = build_reference_type (init_type);
506
e97f22c9
TT
507 if (decl_is_java_type (init_type, 0))
508 {
509 tree fn
510 = builtin_function ("_Jv_exception_info",
511 build_function_type (ptr_type_node,
512 tree_cons (NULL_TREE,
513 void_type_node,
514 NULL_TREE)),
515 0, NOT_BUILT_IN, NULL_PTR);
516
517 exp = build (CALL_EXPR, ptr_type_node,
518 build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)),
519 fn),
520 NULL_TREE, NULL_TREE);
521 TREE_SIDE_EFFECTS (exp) = 1;
522 lang = EH_LANG_Java;
523
524 set_exception_lang_code (EH_LANG_Java);
525 set_exception_version_code (1);
526 }
527 else
528 {
529 exp = get_eh_value ();
530 lang = EH_LANG_C_plus_plus;
531 }
532
533 if (catch_language_init)
534 {
535 if (lang != catch_language)
536 error ("mixing C++ and Java `catch'es in single translation unit");
537 }
538 else
539 {
540 catch_language_init = 1;
541 catch_language = lang;
542 }
b35d4555
MM
543
544 /* Since pointers are passed by value, initialize a reference to
545 pointer catch parm with the address of the value slot. */
546 if (TREE_CODE (init_type) == REFERENCE_TYPE
547 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
548 exp = build_unary_op (ADDR_EXPR, exp, 1);
549
550 exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
551
552 init = convert_from_reference (exp);
553
554 /* If the constructor for the catch parm exits via an exception, we
555 must call terminate. See eh23.C. */
556 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
faf5394a 557 {
b35d4555
MM
558 /* Generate the copy constructor call directly so we can wrap it.
559 See also expand_default_init. */
560 init = ocp_convert (TREE_TYPE (decl), init,
561 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
562 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
563 build_terminate_handler ());
faf5394a
MS
564 }
565
b35d4555
MM
566 /* Let `cp_finish_decl' know that this initializer is ok. */
567 DECL_INITIAL (decl) = error_mark_node;
568 decl = pushdecl (decl);
8d2733ca 569
b35d4555 570 start_decl_1 (decl);
cd9f6678 571 cp_finish_decl (decl, init, NULL_TREE,
b35d4555 572 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
5816cb14
AM
573}
574
b35d4555 575/* Call this to start a catch block. DECL is the catch parameter. */
5816cb14 576
b35d4555
MM
577tree
578expand_start_catch_block (decl)
3c5c0849 579 tree decl;
5816cb14 580{
b35d4555
MM
581 tree compound_stmt_1;
582 tree compound_stmt_2;
5816cb14 583
b35d4555
MM
584 if (! doing_eh (1))
585 return NULL_TREE;
5816cb14 586
b35d4555 587 /* Make sure this declaration is reasonable. */
3c5c0849
MM
588 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
589 decl = NULL_TREE;
5816cb14 590
b35d4555
MM
591 /* Create a binding level for the eh_info and the exception object
592 cleanup. */
593 compound_stmt_1 = begin_compound_stmt (/*has_no_scope=*/0);
594
e97f22c9
TT
595 if (! decl || ! decl_is_java_type (TREE_TYPE (decl), 1))
596 {
597 /* The ordinary C++ case. */
93ca4ba7 598 tree type;
5816cb14 599
e97f22c9 600 if (decl)
93ca4ba7 601 type = TREE_TYPE (decl);
e97f22c9
TT
602 else
603 type = NULL_TREE;
93ca4ba7 604 begin_catch_block (build_eh_type_type_ref (type));
e97f22c9
TT
605
606 push_eh_info ();
93ca4ba7 607 push_eh_cleanup (type);
e97f22c9
TT
608 }
609 else
610 {
611 /* The Java case. In this case, the match_info is a pointer to
612 the Java class object. We assume that the class is a
613 compiled class. */
614 tree ref = build_java_class_ref (TREE_TYPE (TREE_TYPE (decl)));
615 begin_catch_block (build1 (ADDR_EXPR, jclass_node, ref));
616 }
5816cb14 617
b35d4555
MM
618 /* Create a binding level for the parm. */
619 compound_stmt_2 = begin_compound_stmt (/*has_no_scope=*/0);
5816cb14 620
b35d4555
MM
621 if (decl)
622 initialize_handler_parm (decl);
5816cb14 623
b35d4555 624 return build_tree_list (compound_stmt_1, compound_stmt_2);
5816cb14
AM
625}
626
f30432d7 627
8d2733ca
MS
628/* Call this to end a catch block. Its responsible for emitting the
629 code to handle jumping back to the correct place, and for emitting
630 the label to jump to if this catch block didn't match. */
6467930b 631
824b9a4c 632void
b35d4555
MM
633expand_end_catch_block (blocks)
634 tree blocks;
8d08fdba 635{
b35d4555
MM
636 tree compound_stmt_1 = blocks ? TREE_PURPOSE (blocks): NULL_TREE;
637 tree compound_stmt_2 = blocks ? TREE_VALUE (blocks): NULL_TREE;
638
f30432d7
MS
639 if (! doing_eh (1))
640 return;
8d2733ca 641
0dde4175
JM
642 /* The exception being handled is rethrown if control reaches the end of
643 a handler of the function-try-block of a constructor or destructor. */
644 if (in_function_try_handler
645 && (DECL_CONSTRUCTOR_P (current_function_decl)
646 || DECL_DESTRUCTOR_P (current_function_decl)))
b35d4555 647 finish_expr_stmt (build_throw (NULL_TREE));
0dde4175 648
c7ae64f2 649 /* Cleanup the EH parameter. */
b35d4555 650 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_2);
46e8c075 651 /* Cleanup the EH object. */
4a6ef811 652 finish_compound_stmt (/*has_no_scope=*/0, compound_stmt_1);
8d2733ca 653}
8d08fdba 654
6c20b7e9
JM
655/* An exception spec is implemented more or less like:
656
657 try {
658 function body;
659 } catch (...) {
660 void *p[] = { typeid(raises) };
661 __check_eh_spec (p, count);
662 }
663
664 __check_eh_spec in exception.cc handles all the details. */
8d2733ca 665
b35d4555 666tree
f30432d7
MS
667expand_start_eh_spec ()
668{
b35d4555 669 return begin_try_block ();
f30432d7
MS
670}
671
b35d4555
MM
672void
673expand_end_eh_spec (raises, try_block)
f30432d7 674 tree raises;
b35d4555 675 tree try_block;
f30432d7 676{
6c20b7e9 677 tree tmp, fn, decl, types = NULL_TREE;
b35d4555
MM
678 tree blocks;
679 tree handler;
6c20b7e9 680 int count = 0;
f30432d7 681
b35d4555
MM
682 finish_try_block (try_block);
683 handler = begin_handler ();
684 blocks = finish_handler_parms (NULL_TREE, handler);
f30432d7 685
1ef9f749 686 if (TREE_VALUE (raises) == NULL_TREE)
6c20b7e9 687 {
1ef9f749
JM
688 fn = get_identifier ("__check_null_eh_spec");
689 if (IDENTIFIER_GLOBAL_VALUE (fn))
690 fn = IDENTIFIER_GLOBAL_VALUE (fn);
691 else
692 {
693 tmp = build_function_type (void_type_node, void_list_node);
694 fn = push_throw_library_fn (fn, tmp);
c00996a3
JM
695 /* Since the spec doesn't allow any exceptions, this call will
696 never throw. We use push_throw_library_fn because we do want
697 TREE_THIS_VOLATILE to be set. */
1ef9f749
JM
698 TREE_NOTHROW (fn) = 1;
699 }
700 tmp = NULL_TREE;
6c20b7e9 701 }
1ef9f749
JM
702 else
703 {
704 /* Build up an array of type_infos. */
705 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
706 {
707 types = tree_cons
708 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
709 ++count;
710 }
eb66be0e 711
1ef9f749
JM
712 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
713 TREE_HAS_CONSTRUCTOR (types) = 1;
6874c264 714
1ef9f749
JM
715 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
716 tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);
717 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
718 DECL_ARTIFICIAL (decl) = 1;
719 DECL_INITIAL (decl) = types;
720 DECL_CONTEXT (decl) = current_function_decl;
721 cp_finish_decl (decl, types, NULL_TREE, 0);
6c20b7e9 722
1ef9f749 723 decl = decay_conversion (decl);
6874c264 724
1ef9f749
JM
725 fn = get_identifier ("__check_eh_spec");
726 if (IDENTIFIER_GLOBAL_VALUE (fn))
727 fn = IDENTIFIER_GLOBAL_VALUE (fn);
728 else
729 {
730 tmp = tree_cons
731 (NULL_TREE, integer_type_node, tree_cons
732 (NULL_TREE, TREE_TYPE (decl), void_list_node));
733 tmp = build_function_type (void_type_node, tmp);
734
735 fn = push_throw_library_fn (fn, tmp);
736 }
0c11ada6 737
1ef9f749
JM
738 tmp = tree_cons (NULL_TREE, build_int_2 (count, 0),
739 tree_cons (NULL_TREE, decl, NULL_TREE));
6c20b7e9
JM
740 }
741
0c11ada6 742 tmp = build_call (fn, tmp);
b35d4555 743 finish_expr_stmt (tmp);
6c20b7e9 744
b35d4555
MM
745 finish_handler (blocks, handler);
746 finish_handler_sequence (try_block);
f30432d7
MS
747}
748
8d2733ca
MS
749/* This is called to expand all the toplevel exception handling
750 finalization for a function. It should only be called once per
751 function. */
6467930b 752
8d08fdba 753void
8d2733ca 754expand_exception_blocks ()
8d08fdba 755{
92b96838 756 do_pending_stack_adjust ();
eb448459 757
e00737d2 758 if (catch_clauses)
f30432d7 759 {
e00737d2
MS
760 rtx funcend = gen_label_rtx ();
761 emit_jump (funcend);
762
eb66be0e
MS
763 /* We cannot protect n regions this way if we must flow into the
764 EH region through the top of the region, as we have to with
765 the setjmp/longjmp approach. */
766 if (exceptions_via_longjmp == 0)
fb98cff6 767 expand_eh_region_start ();
f30432d7 768
e00737d2 769 emit_insns (catch_clauses);
c14f7160 770 catch_clauses = catch_clauses_last = NULL_RTX;
eb66be0e
MS
771
772 if (exceptions_via_longjmp == 0)
f4a23343 773 expand_eh_region_end (build_terminate_handler ());
eb66be0e 774
4a6ef811 775 emit_insns (catch_clauses);
c14f7160 776 catch_clauses = catch_clauses_last = NULL_RTX;
e00737d2
MS
777 emit_label (funcend);
778 }
8d08fdba
MS
779}
780
f4a23343
JM
781/* Return a pointer to a buffer for an exception object of type TYPE. */
782
c6160f8f 783static tree
f4a23343
JM
784alloc_eh_object (type)
785 tree type;
786{
787 tree fn, exp;
788
789 fn = get_identifier ("__eh_alloc");
790 if (IDENTIFIER_GLOBAL_VALUE (fn))
791 fn = IDENTIFIER_GLOBAL_VALUE (fn);
792 else
793 {
794 /* Declare __eh_alloc (size_t), as defined in exception.cc. */
0c11ada6
JM
795 tree tmp = tree_cons (NULL_TREE, sizetype, void_list_node);
796 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
f4a23343
JM
797 }
798
e1b3e07d 799 exp = build_function_call (fn, tree_cons
f4a23343
JM
800 (NULL_TREE, size_in_bytes (type), NULL_TREE));
801 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
802 return exp;
803}
804
6467930b 805/* Expand a throw statement. This follows the following
8d2733ca
MS
806 algorithm:
807
808 1. Allocate space to save the current PC onto the stack.
809 2. Generate and emit a label and save its address into the
e1cd6e56 810 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
811 3. If this is the first call to throw in this function:
812 generate a label for the throw block
813 4. jump to the throw block label. */
6467930b 814
225ff119 815static tree
8d2733ca
MS
816expand_throw (exp)
817 tree exp;
8d08fdba 818{
6874c264 819 tree fn;
8d08fdba 820
8d2733ca 821 if (! doing_eh (1))
59ccf49d 822 return error_mark_node;
8d08fdba 823
e97f22c9
TT
824 if (exp
825 && decl_is_java_type (TREE_TYPE (exp), 1))
826 {
827 /* A Java `throw' statement. */
828 tree args = tree_cons (NULL_TREE, exp, NULL);
829
830 fn = get_identifier (exceptions_via_longjmp
d9420976 831 ? "_Jv_Sjlj_Throw"
e97f22c9
TT
832 : "_Jv_Throw");
833 if (IDENTIFIER_GLOBAL_VALUE (fn))
834 fn = IDENTIFIER_GLOBAL_VALUE (fn);
835 else
836 {
837 /* Declare _Jv_Throw (void *), as defined in Java's
838 exception.cc. */
0c11ada6
JM
839 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
840 tmp = build_function_type (ptr_type_node, tmp);
c00996a3 841 fn = push_throw_library_fn (fn, tmp);
e97f22c9
TT
842 }
843
844 exp = build_function_call (fn, args);
845 }
846 else if (exp)
8d2733ca 847 {
faae18ab 848 tree throw_type;
6874c264 849 tree cleanup = NULL_TREE, e;
59ccf49d
MM
850 tree stmt_expr;
851 tree compound_stmt;
852 tree try_block;
853
854 begin_init_stmts (&stmt_expr, &compound_stmt);
faae18ab 855
a3b49ccd 856 /* throw expression */
e92cc029 857 /* First, decay it. */
f30432d7 858 exp = decay_conversion (exp);
a3b49ccd 859
298d6f60
MM
860 /* The CLEANUP_TYPE is the internal type of a destructor. Under
861 the old ABI, destructors are two-argument functions; under
862 the new ABI they take only one argument. */
6874c264 863 if (cleanup_type == NULL_TREE)
298d6f60
MM
864 {
865 tree arg_types;
866
867 arg_types = void_list_node;
868 if (!flag_new_abi)
869 arg_types = tree_cons (NULL_TREE, integer_type_node, arg_types);
870 arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
871 cleanup_type = (build_pointer_type
872 (build_function_type (void_type_node, arg_types)));
873 }
6874c264 874
08b24bda 875 if (TYPE_PTR_P (TREE_TYPE (exp)))
db48b831 876 throw_type = build_eh_type_type (TREE_TYPE (exp));
f30432d7
MS
877 else
878 {
f4a23343
JM
879 tree object, ptr;
880
cab1f180 881 /* OK, this is kind of wacky. The standard says that we call
46e8c075
MM
882 terminate when the exception handling mechanism, after
883 completing evaluation of the expression to be thrown but
884 before the exception is caught (_except.throw_), calls a
885 user function that exits via an uncaught exception.
f4a23343
JM
886
887 So we have to protect the actual initialization of the
c00996a3
JM
888 exception object with terminate(), but evaluate the
889 expression first. Since there could be temps in the
890 expression, we need to handle that, too. We also expand
891 the call to __eh_alloc first (which doesn't matter, since
892 it can't throw). */
a50f0918 893
f2c5f623 894 my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
f4a23343 895
f4a23343
JM
896 /* Store the throw expression into a temp. This can be less
897 efficient than storing it into the allocated space directly, but
c00996a3
JM
898 if we allocated the space first we would have to deal with
899 cleaning it up if evaluating this expression throws. */
f4a23343
JM
900 if (TREE_SIDE_EFFECTS (exp))
901 {
f1dedc31 902 tree temp = create_temporary_var (TREE_TYPE (exp));
c37dc68e 903 DECL_INITIAL (temp) = exp;
cd9f6678 904 cp_finish_decl (temp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
f4a23343
JM
905 exp = temp;
906 }
f4a23343
JM
907
908 /* Allocate the space for the exception. */
909 ptr = save_expr (alloc_eh_object (TREE_TYPE (exp)));
59ccf49d 910 finish_expr_stmt (ptr);
f4a23343 911
59ccf49d 912 try_block = begin_try_block ();
f4a23343
JM
913 object = build_indirect_ref (ptr, NULL_PTR);
914 exp = build_modify_expr (object, INIT_EXPR, exp);
faae18ab 915
f30432d7 916 if (exp == error_mark_node)
8251199e 917 error (" in thrown expression");
faae18ab 918
59ccf49d
MM
919 finish_expr_stmt (exp);
920 finish_cleanup_try_block (try_block);
921 finish_cleanup (build_terminate_handler (), try_block);
f4a23343 922
db48b831 923 throw_type = build_eh_type_type (TREE_TYPE (object));
72b7eeff 924
6874c264
JM
925 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
926 {
927 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
298d6f60
MM
928 (flag_new_abi
929 ? complete_dtor_identifier
930 : dtor_identifier),
931 0);
6874c264 932 cleanup = TREE_VALUE (cleanup);
e872bb7a 933 mark_used (cleanup);
6874c264
JM
934 mark_addressable (cleanup);
935 /* Pretend it's a normal function. */
936 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
937 }
f4a23343
JM
938
939 exp = ptr;
f30432d7 940 }
faae18ab 941
bbeeb2b0
MM
942 /* Cast EXP to `void *' so that it will match the prototype for
943 __cp_push_exception. */
c37dc68e 944 exp = convert (ptr_type_node, exp);
bbeeb2b0 945
6874c264
JM
946 if (cleanup == NULL_TREE)
947 {
948 cleanup = build_int_2 (0, 0);
949 TREE_TYPE (cleanup) = cleanup_type;
950 }
72b7eeff 951
298d6f60 952 fn = cp_push_exception_identifier;
6874c264
JM
953 if (IDENTIFIER_GLOBAL_VALUE (fn))
954 fn = IDENTIFIER_GLOBAL_VALUE (fn);
955 else
956 {
957 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
958 as defined in exception.cc. */
959 tree tmp;
6874c264
JM
960 tmp = tree_cons
961 (NULL_TREE, ptr_type_node, tree_cons
962 (NULL_TREE, ptr_type_node, tree_cons
963 (NULL_TREE, cleanup_type, void_list_node)));
0c11ada6 964 fn = push_void_library_fn (fn, tmp);
6874c264 965 }
72b7eeff 966
e1b3e07d
MM
967 e = tree_cons (NULL_TREE, exp, tree_cons
968 (NULL_TREE, throw_type, tree_cons
969 (NULL_TREE, cleanup, NULL_TREE)));
59ccf49d
MM
970 finish_expr_stmt (build_function_call (fn, e));
971
972 exp = finish_init_stmts (stmt_expr, compound_stmt);
8d2733ca
MS
973 }
974 else
a3b49ccd 975 {
6874c264
JM
976 /* rethrow current exception; note that it's no longer caught. */
977
978 tree fn = get_identifier ("__uncatch_exception");
979 if (IDENTIFIER_GLOBAL_VALUE (fn))
980 fn = IDENTIFIER_GLOBAL_VALUE (fn);
981 else
0c11ada6
JM
982 /* Declare void __uncatch_exception (void)
983 as defined in exception.cc. */
984 fn = push_void_library_fn (fn, void_list_node);
6874c264
JM
985
986 exp = build_function_call (fn, NULL_TREE);
a3b49ccd 987 }
8d2733ca 988
59ccf49d 989 return exp;
f376e137 990}
8d2733ca
MS
991
992/* Build a throw expression. */
6467930b 993
8d2733ca
MS
994tree
995build_throw (e)
996 tree e;
997{
02020185
JM
998 if (e == error_mark_node)
999 return e;
1000
1001 if (processing_template_decl)
1002 return build_min (THROW_EXPR, void_type_node, e);
1003
e0f9a8bc 1004 if (e == null_node)
8251199e 1005 cp_warning ("throwing NULL, which has integral, not pointer type");
980c394c
NS
1006
1007 if (e != NULL_TREE)
1008 {
4cfbc546
NS
1009 if (!complete_ptr_ref_or_void_ptr_p (TREE_TYPE (e), e))
1010 return error_mark_node;
980c394c 1011 }
02020185 1012
59ccf49d 1013 e = expand_throw (e);
02020185
JM
1014 e = build1 (THROW_EXPR, void_type_node, e);
1015 TREE_SIDE_EFFECTS (e) = 1;
1016 TREE_USED (e) = 1;
1017
8d2733ca 1018 return e;
8d08fdba 1019}
4cfbc546
NS
1020
1021/* Make sure TYPE is complete, pointer to complete, reference to
1022 complete, or pointer to cv void. Issue diagnostic on failure.
1023 Return the zero on failure and non-zero on success. FROM can be
1024 the expr or decl from whence TYPE came, if available. */
1025
1026static int
1027complete_ptr_ref_or_void_ptr_p (type, from)
1028 tree type;
1029 tree from;
1030{
1031 int is_ptr;
1032
1033 /* Check complete. */
1034 type = complete_type_or_else (type, from);
1035 if (!type)
1036 return 0;
1037
1038 /* Or a pointer or ref to one, or cv void *. */
1039 is_ptr = TREE_CODE (type) == POINTER_TYPE;
1040 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
1041 {
1042 tree core = TREE_TYPE (type);
1043
b72801e2 1044 if (is_ptr && VOID_TYPE_P (core))
4cfbc546
NS
1045 /* OK */;
1046 else if (!complete_type_or_else (core, from))
1047 return 0;
1048 }
1049 return 1;
1050}
1051
1660cb3a
JM
1052/* Returns nonzero if FN is a declaration of a standard C library
1053 function which is known not to throw.
1054
1055 [lib.res.on.exception.handling]: None of the functions from the
1056 Standard C library shall report an error by throwing an
1057 exception, unless it calls a program-supplied function that
1058 throws an exception. */
1059
1060#include "cfns.h"
1061
1062int
1063nothrow_libfn_p (fn)
1064 tree fn;
1065{
1066 tree id;
1067
1068 if (TREE_PUBLIC (fn)
1069 && DECL_EXTERNAL (fn)
eb68cb58 1070 && DECL_EXTERN_C_P (fn))
1660cb3a
JM
1071 /* OK */;
1072 else
1073 /* Can't be a C library function. */
1074 return 0;
1075
1076 id = DECL_ASSEMBLER_NAME (fn);
1077 return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
1078}
2bc9f1d1
JM
1079
1080/* Returns nonzero if an exception of type FROM will be caught by a
1081 handler for type TO, as per [except.handle]. */
1082
1083static int
1084can_convert_eh (to, from)
1085 tree to, from;
1086{
1087 if (TREE_CODE (to) == REFERENCE_TYPE)
1088 to = TREE_TYPE (to);
1089 if (TREE_CODE (from) == REFERENCE_TYPE)
1090 from = TREE_TYPE (from);
1091
1092 if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
1093 {
1094 to = TREE_TYPE (to);
1095 from = TREE_TYPE (from);
1096
1097 if (! at_least_as_qualified_p (to, from))
1098 return 0;
1099
1100 if (TREE_CODE (to) == VOID_TYPE)
1101 return 1;
1102
1103 /* else fall through */
1104 }
1105
1106 if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
1107 && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
1108 return 1;
1109
1110 return 0;
1111}
1112
1113/* Check whether any of HANDLERS are shadowed by another handler accepting
1114 TYPE. Note that the shadowing may not be complete; even if an exception
1115 of type B would be caught by a handler for A, there could be a derived
1116 class C for which A is an ambiguous base but B is not, so the handler
1117 for B would catch an exception of type C. */
1118
1119static void
1120check_handlers_1 (master, handlers)
1121 tree master;
1122 tree handlers;
1123{
1124 tree type = TREE_TYPE (master);
1125 tree handler;
1126
1127 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
1128 if (TREE_TYPE (handler)
1129 && can_convert_eh (type, TREE_TYPE (handler)))
1130 {
1131 lineno = STMT_LINENO (handler);
1132 cp_warning ("exception of type `%T' will be caught",
1133 TREE_TYPE (handler));
1134 lineno = STMT_LINENO (master);
1135 cp_warning (" by earlier handler for `%T'", type);
1136 break;
1137 }
1138}
1139
1140/* Given a chain of HANDLERs, make sure that they're OK. */
1141
1142void
1143check_handlers (handlers)
1144 tree handlers;
1145{
1146 tree handler;
1147 int save_line = lineno;
1148 for (handler = handlers; handler; handler = TREE_CHAIN (handler))
1149 {
1150 if (TREE_CHAIN (handler) == NULL_TREE)
1151 /* No more handlers; nothing to shadow. */;
1152 else if (TREE_TYPE (handler) == NULL_TREE)
1153 {
1154 lineno = STMT_LINENO (handler);
1155 cp_pedwarn
1156 ("`...' handler must be the last handler for its try block");
1157 }
1158 else
1159 check_handlers_1 (handler, TREE_CHAIN (handler));
1160 }
1161 lineno = save_line;
1162}
This page took 0.854896 seconds and 5 git commands to generate.