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