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