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