00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "coretypes.h"
00029 #include "tm.h"
00030 #include "tree.h"
00031 #include "rtl.h"
00032 #include "expr.h"
00033 #include "libfuncs.h"
00034 #include "cp-tree.h"
00035 #include "flags.h"
00036 #include "output.h"
00037 #include "except.h"
00038 #include "toplev.h"
00039 #include "tree-inline.h"
00040 #include "tree-iterator.h"
00041
00042 static void push_eh_cleanup (tree);
00043 static tree prepare_eh_type (tree);
00044 static tree build_eh_type_type (tree);
00045 static tree do_begin_catch (void);
00046 static int dtor_nothrow (tree);
00047 static tree do_end_catch (tree);
00048 static bool decl_is_java_type (tree decl, int err);
00049 static void initialize_handler_parm (tree, tree);
00050 static tree do_allocate_exception (tree);
00051 static tree wrap_cleanups_r (tree *, int *, void *);
00052 static int complete_ptr_ref_or_void_ptr_p (tree, tree);
00053 static bool is_admissible_throw_operand (tree);
00054 static int can_convert_eh (tree, tree);
00055 static tree cp_protect_cleanup_actions (void);
00056
00057
00058
00059
00060 void
00061 init_exception_processing (void)
00062 {
00063 tree tmp;
00064
00065
00066 push_namespace (std_identifier);
00067 tmp = build_function_type (void_type_node, void_list_node);
00068 terminate_node = build_cp_library_fn_ptr ("terminate", tmp);
00069 TREE_THIS_VOLATILE (terminate_node) = 1;
00070 TREE_NOTHROW (terminate_node) = 1;
00071 pop_namespace ();
00072
00073
00074 tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
00075 tmp = build_function_type (void_type_node, tmp);
00076 call_unexpected_node
00077 = push_throw_library_fn (get_identifier ("__cxa_call_unexpected"), tmp);
00078
00079 eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
00080 ? "__gxx_personality_sj0"
00081 : "__gxx_personality_v0");
00082
00083 lang_eh_runtime_type = build_eh_type_type;
00084 lang_protect_cleanup_actions = &cp_protect_cleanup_actions;
00085 }
00086
00087
00088
00089
00090 static tree
00091 cp_protect_cleanup_actions (void)
00092 {
00093
00094
00095
00096
00097 return build_call (terminate_node, NULL_TREE);
00098 }
00099
00100 static tree
00101 prepare_eh_type (tree type)
00102 {
00103 if (type == NULL_TREE)
00104 return type;
00105 if (type == error_mark_node)
00106 return error_mark_node;
00107
00108
00109 type = non_reference (type);
00110
00111
00112 type = TYPE_MAIN_VARIANT (type);
00113
00114 return type;
00115 }
00116
00117
00118 tree
00119 eh_type_info (tree type)
00120 {
00121 tree exp;
00122
00123 if (type == NULL_TREE || type == error_mark_node)
00124 return type;
00125
00126 if (decl_is_java_type (type, 0))
00127 exp = build_java_class_ref (TREE_TYPE (type));
00128 else
00129 exp = get_tinfo_decl (type);
00130
00131 return exp;
00132 }
00133
00134
00135
00136
00137 static tree
00138 build_eh_type_type (tree type)
00139 {
00140 tree exp = eh_type_info (type);
00141
00142 if (!exp)
00143 return NULL;
00144
00145 mark_used (exp);
00146
00147 return convert (ptr_type_node, build_address (exp));
00148 }
00149
00150 tree
00151 build_exc_ptr (void)
00152 {
00153 return build0 (EXC_PTR_EXPR, ptr_type_node);
00154 }
00155
00156
00157
00158
00159 static tree
00160 do_get_exception_ptr (void)
00161 {
00162 tree fn;
00163
00164 fn = get_identifier ("__cxa_get_exception_ptr");
00165 if (!get_global_value_if_present (fn, &fn))
00166 {
00167
00168 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
00169 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
00170 }
00171
00172 return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
00173 NULL_TREE));
00174 }
00175
00176
00177
00178
00179 static tree
00180 do_begin_catch (void)
00181 {
00182 tree fn;
00183
00184 fn = get_identifier ("__cxa_begin_catch");
00185 if (!get_global_value_if_present (fn, &fn))
00186 {
00187
00188 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
00189 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
00190 }
00191
00192 return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (),
00193 NULL_TREE));
00194 }
00195
00196
00197
00198
00199 static int
00200 dtor_nothrow (tree type)
00201 {
00202 if (type == NULL_TREE)
00203 return 0;
00204
00205 if (!CLASS_TYPE_P (type))
00206 return 1;
00207
00208 if (CLASSTYPE_LAZY_DESTRUCTOR (type))
00209 lazily_declare_fn (sfk_destructor, type);
00210
00211 return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
00212 }
00213
00214
00215
00216
00217 static tree
00218 do_end_catch (tree type)
00219 {
00220 tree fn, cleanup;
00221
00222 fn = get_identifier ("__cxa_end_catch");
00223 if (!get_global_value_if_present (fn, &fn))
00224 {
00225
00226 fn = push_void_library_fn (fn, void_list_node);
00227
00228 TREE_NOTHROW (fn) = 0;
00229 }
00230
00231 cleanup = build_function_call (fn, NULL_TREE);
00232 TREE_NOTHROW (cleanup) = dtor_nothrow (type);
00233
00234 return cleanup;
00235 }
00236
00237
00238
00239 static void
00240 push_eh_cleanup (tree type)
00241 {
00242 finish_decl_cleanup (NULL_TREE, do_end_catch (type));
00243 }
00244
00245
00246
00247
00248 static bool
00249 decl_is_java_type (tree decl, int err)
00250 {
00251 bool r = (TREE_CODE (decl) == POINTER_TYPE
00252 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
00253 && TYPE_FOR_JAVA (TREE_TYPE (decl)));
00254
00255 if (err)
00256 {
00257 if (TREE_CODE (decl) == REFERENCE_TYPE
00258 && TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
00259 && TYPE_FOR_JAVA (TREE_TYPE (decl)))
00260 {
00261
00262 error ("type %qT is disallowed in Java %<throw%> or %<catch%>",
00263 decl);
00264 }
00265
00266 if (r)
00267 {
00268 tree jthrow_node
00269 = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jthrowable"));
00270
00271 if (jthrow_node == NULL_TREE)
00272 fatal_error
00273 ("call to Java %<catch%> or %<throw%> with %<jthrowable%> undefined");
00274
00275 jthrow_node = TREE_TYPE (TREE_TYPE (jthrow_node));
00276
00277 if (! DERIVED_FROM_P (jthrow_node, TREE_TYPE (decl)))
00278 {
00279
00280 error ("type %qT is not derived from %<java::lang::Throwable%>",
00281 TREE_TYPE (decl));
00282 }
00283 }
00284 }
00285
00286 return r;
00287 }
00288
00289
00290
00291
00292
00293
00294
00295 void
00296 choose_personality_routine (enum languages lang)
00297 {
00298 static enum {
00299 chose_none,
00300 chose_cpp,
00301 chose_java,
00302 gave_error
00303 } state;
00304
00305 switch (state)
00306 {
00307 case gave_error:
00308 return;
00309
00310 case chose_cpp:
00311 if (lang != lang_cplusplus)
00312 goto give_error;
00313 return;
00314
00315 case chose_java:
00316 if (lang != lang_java)
00317 goto give_error;
00318 return;
00319
00320 case chose_none:
00321 ;
00322 }
00323
00324 switch (lang)
00325 {
00326 case lang_cplusplus:
00327 state = chose_cpp;
00328 break;
00329
00330 case lang_java:
00331 state = chose_java;
00332 eh_personality_libfunc = init_one_libfunc (USING_SJLJ_EXCEPTIONS
00333 ? "__gcj_personality_sj0"
00334 : "__gcj_personality_v0");
00335 break;
00336
00337 default:
00338 gcc_unreachable ();
00339 }
00340 return;
00341
00342 give_error:
00343 error ("mixing C++ and Java catches in a single translation unit");
00344 state = gave_error;
00345 }
00346
00347
00348
00349 static void
00350 initialize_handler_parm (tree decl, tree exp)
00351 {
00352 tree init;
00353 tree init_type;
00354
00355
00356
00357 TREE_USED (decl) = 1;
00358
00359
00360
00361
00362 init_type = TREE_TYPE (decl);
00363 if (!POINTER_TYPE_P (init_type))
00364 init_type = build_reference_type (init_type);
00365
00366 choose_personality_routine (decl_is_java_type (init_type, 0)
00367 ? lang_java : lang_cplusplus);
00368
00369
00370
00371 if (TREE_CODE (init_type) == REFERENCE_TYPE
00372 && TYPE_PTR_P (TREE_TYPE (init_type)))
00373 exp = build_unary_op (ADDR_EXPR, exp, 1);
00374
00375 exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
00376
00377 init = convert_from_reference (exp);
00378
00379
00380
00381 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
00382 {
00383
00384
00385 init = ocp_convert (TREE_TYPE (decl), init,
00386 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
00387 init = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (init), init);
00388 }
00389
00390
00391 DECL_INITIAL (decl) = error_mark_node;
00392 decl = pushdecl (decl);
00393
00394 start_decl_1 (decl);
00395 cp_finish_decl (decl, init, NULL_TREE,
00396 LOOKUP_ONLYCONVERTING|DIRECT_BIND);
00397 }
00398
00399
00400
00401 tree
00402 expand_start_catch_block (tree decl)
00403 {
00404 tree exp;
00405 tree type;
00406
00407 if (! doing_eh (1))
00408 return NULL_TREE;
00409
00410
00411 if (decl && !complete_ptr_ref_or_void_ptr_p (TREE_TYPE (decl), NULL_TREE))
00412 decl = NULL_TREE;
00413
00414 if (decl)
00415 type = prepare_eh_type (TREE_TYPE (decl));
00416 else
00417 type = NULL_TREE;
00418
00419 if (decl && decl_is_java_type (type, 1))
00420 {
00421
00422
00423
00424 exp = build_exc_ptr ();
00425 exp = build1 (NOP_EXPR, build_pointer_type (type), exp);
00426 exp = build2 (MINUS_EXPR, TREE_TYPE (exp), exp,
00427 TYPE_SIZE_UNIT (TREE_TYPE (exp)));
00428 exp = build_indirect_ref (exp, NULL);
00429 initialize_handler_parm (decl, exp);
00430 return type;
00431 }
00432
00433
00434 push_eh_cleanup (type);
00435
00436
00437
00438 if (decl == NULL)
00439 finish_expr_stmt (do_begin_catch ());
00440
00441
00442
00443
00444 else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
00445 {
00446 exp = do_get_exception_ptr ();
00447 initialize_handler_parm (decl, exp);
00448 finish_expr_stmt (do_begin_catch ());
00449 }
00450
00451
00452
00453
00454 else
00455 {
00456 tree init = do_begin_catch ();
00457 exp = create_temporary_var (ptr_type_node);
00458 DECL_REGISTER (exp) = 1;
00459 cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
00460 finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
00461 initialize_handler_parm (decl, exp);
00462 }
00463
00464 return type;
00465 }
00466
00467
00468
00469
00470
00471
00472 void
00473 expand_end_catch_block (void)
00474 {
00475 if (! doing_eh (1))
00476 return;
00477
00478
00479
00480 if (in_function_try_handler
00481 && (DECL_CONSTRUCTOR_P (current_function_decl)
00482 || DECL_DESTRUCTOR_P (current_function_decl)))
00483 finish_expr_stmt (build_throw (NULL_TREE));
00484 }
00485
00486 tree
00487 begin_eh_spec_block (void)
00488 {
00489 tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
00490 add_stmt (r);
00491 EH_SPEC_STMTS (r) = push_stmt_list ();
00492 return r;
00493 }
00494
00495 void
00496 finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
00497 {
00498 tree raises;
00499
00500 EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block));
00501
00502
00503 for (raises = NULL_TREE;
00504 raw_raises && TREE_VALUE (raw_raises);
00505 raw_raises = TREE_CHAIN (raw_raises))
00506 {
00507 tree type = prepare_eh_type (TREE_VALUE (raw_raises));
00508 tree tinfo = eh_type_info (type);
00509
00510 mark_used (tinfo);
00511 raises = tree_cons (NULL_TREE, type, raises);
00512 }
00513
00514 EH_SPEC_RAISES (eh_spec_block) = raises;
00515 }
00516
00517
00518
00519 static tree
00520 do_allocate_exception (tree type)
00521 {
00522 tree fn;
00523
00524 fn = get_identifier ("__cxa_allocate_exception");
00525 if (!get_global_value_if_present (fn, &fn))
00526 {
00527
00528 tree tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
00529 fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp));
00530 }
00531
00532 return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type),
00533 NULL_TREE));
00534 }
00535
00536
00537
00538
00539 static tree
00540 do_free_exception (tree ptr)
00541 {
00542 tree fn;
00543
00544 fn = get_identifier ("__cxa_free_exception");
00545 if (!get_global_value_if_present (fn, &fn))
00546 {
00547
00548 fn = push_void_library_fn (fn, tree_cons (NULL_TREE, ptr_type_node,
00549 void_list_node));
00550 }
00551
00552 return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE));
00553 }
00554
00555
00556
00557
00558 static tree
00559 wrap_cleanups_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
00560 void *data ATTRIBUTE_UNUSED)
00561 {
00562 tree exp = *tp;
00563 tree cleanup;
00564
00565
00566 if (TYPE_P (exp))
00567 {
00568 *walk_subtrees = 0;
00569 return NULL_TREE;
00570 }
00571 if (TREE_CODE (exp) != TARGET_EXPR)
00572 return NULL_TREE;
00573
00574 cleanup = TARGET_EXPR_CLEANUP (exp);
00575 if (cleanup)
00576 {
00577 cleanup = build1 (MUST_NOT_THROW_EXPR, void_type_node, cleanup);
00578 TARGET_EXPR_CLEANUP (exp) = cleanup;
00579 }
00580
00581
00582 return NULL_TREE;
00583 }
00584
00585
00586
00587 tree
00588 build_throw (tree exp)
00589 {
00590 tree fn;
00591
00592 if (exp == error_mark_node)
00593 return exp;
00594
00595 if (processing_template_decl)
00596 {
00597 current_function_returns_abnormally = 1;
00598 return build_min (THROW_EXPR, void_type_node, exp);
00599 }
00600
00601 if (exp == null_node)
00602 warning ("throwing NULL, which has integral, not pointer type");
00603
00604 if (exp != NULL_TREE)
00605 {
00606 if (!is_admissible_throw_operand (exp))
00607 return error_mark_node;
00608 }
00609
00610 if (! doing_eh (1))
00611 return error_mark_node;
00612
00613 if (exp && decl_is_java_type (TREE_TYPE (exp), 1))
00614 {
00615 tree fn = get_identifier ("_Jv_Throw");
00616 if (!get_global_value_if_present (fn, &fn))
00617 {
00618
00619 tree tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
00620 tmp = build_function_type (ptr_type_node, tmp);
00621 fn = push_throw_library_fn (fn, tmp);
00622 }
00623 else if (really_overloaded_fn (fn))
00624 {
00625 error ("%qD should never be overloaded", fn);
00626 return error_mark_node;
00627 }
00628 fn = OVL_CURRENT (fn);
00629 exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE));
00630 }
00631 else if (exp)
00632 {
00633 tree throw_type;
00634 tree cleanup;
00635 tree object, ptr;
00636 tree tmp;
00637 tree temp_expr, allocate_expr;
00638 bool elided;
00639
00640
00641 if (!cleanup_type)
00642 {
00643 tmp = void_list_node;
00644 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
00645 tmp = build_function_type (void_type_node, tmp);
00646 cleanup_type = build_pointer_type (tmp);
00647 }
00648
00649 fn = get_identifier ("__cxa_throw");
00650 if (!get_global_value_if_present (fn, &fn))
00651 {
00652
00653
00654 tmp = void_list_node;
00655 tmp = tree_cons (NULL_TREE, cleanup_type, tmp);
00656 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
00657 tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
00658 tmp = build_function_type (void_type_node, tmp);
00659 fn = push_throw_library_fn (fn, tmp);
00660 }
00661
00662
00663
00664 exp = decay_conversion (exp);
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 allocate_expr = do_allocate_exception (TREE_TYPE (exp));
00681 allocate_expr = get_target_expr (allocate_expr);
00682 ptr = TARGET_EXPR_SLOT (allocate_expr);
00683 object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
00684 object = build_indirect_ref (object, NULL);
00685
00686 elided = (TREE_CODE (exp) == TARGET_EXPR);
00687
00688
00689 exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
00690 if (exp == error_mark_node)
00691 {
00692 error (" in thrown expression");
00693 return error_mark_node;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 temp_expr = NULL_TREE;
00715 stabilize_init (exp, &temp_expr);
00716
00717 if (elided)
00718 exp = build2 (TRY_CATCH_EXPR, void_type_node, exp,
00719 do_free_exception (ptr));
00720 else
00721 exp = build1 (MUST_NOT_THROW_EXPR, void_type_node, exp);
00722
00723
00724 exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
00725 if (temp_expr)
00726 {
00727
00728
00729
00730
00731
00732 walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
00733 exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
00734 exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
00735 }
00736
00737 throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
00738
00739 if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object)))
00740 {
00741 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
00742 complete_dtor_identifier, 0);
00743 cleanup = BASELINK_FUNCTIONS (cleanup);
00744 mark_used (cleanup);
00745 cxx_mark_addressable (cleanup);
00746
00747 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
00748 }
00749 else
00750 cleanup = build_int_cst (cleanup_type, 0);
00751
00752 tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
00753 tmp = tree_cons (NULL_TREE, throw_type, tmp);
00754 tmp = tree_cons (NULL_TREE, ptr, tmp);
00755
00756 tmp = build_function_call (fn, tmp);
00757
00758
00759 exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
00760 }
00761 else
00762 {
00763
00764
00765 tree fn = get_identifier ("__cxa_rethrow");
00766 if (!get_global_value_if_present (fn, &fn))
00767 {
00768
00769 fn = push_throw_library_fn
00770 (fn, build_function_type (void_type_node, void_list_node));
00771 }
00772
00773
00774
00775 exp = build_function_call (fn, NULL_TREE);
00776 }
00777
00778 exp = build1 (THROW_EXPR, void_type_node, exp);
00779
00780 return exp;
00781 }
00782
00783
00784
00785
00786
00787
00788 static int
00789 complete_ptr_ref_or_void_ptr_p (tree type, tree from)
00790 {
00791 int is_ptr;
00792
00793
00794 type = complete_type_or_else (type, from);
00795 if (!type)
00796 return 0;
00797
00798
00799 is_ptr = TREE_CODE (type) == POINTER_TYPE;
00800 if (is_ptr || TREE_CODE (type) == REFERENCE_TYPE)
00801 {
00802 tree core = TREE_TYPE (type);
00803
00804 if (is_ptr && VOID_TYPE_P (core))
00805 ;
00806 else if (!complete_type_or_else (core, from))
00807 return 0;
00808 }
00809 return 1;
00810 }
00811
00812
00813
00814
00815
00816 static bool
00817 is_admissible_throw_operand (tree expr)
00818 {
00819 tree type = TREE_TYPE (expr);
00820
00821
00822
00823
00824
00825
00826
00827
00828 if (!complete_ptr_ref_or_void_ptr_p (type, expr))
00829 return false;
00830
00831
00832
00833
00834 else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
00835 {
00836 error ("expression %qE of abstract class type %qT cannot "
00837 "be used in throw-expression", expr, type);
00838 return false;
00839 }
00840
00841 return true;
00842 }
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 #include "cfns.h"
00853
00854 int
00855 nothrow_libfn_p (tree fn)
00856 {
00857 tree id;
00858
00859 if (TREE_PUBLIC (fn)
00860 && DECL_EXTERNAL (fn)
00861 && DECL_NAMESPACE_SCOPE_P (fn)
00862 && DECL_EXTERN_C_P (fn))
00863 ;
00864 else
00865
00866 return 0;
00867
00868
00869
00870
00871 id = DECL_NAME (fn);
00872 return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id));
00873 }
00874
00875
00876
00877
00878 static int
00879 can_convert_eh (tree to, tree from)
00880 {
00881 to = non_reference (to);
00882 from = non_reference (from);
00883
00884 if (TREE_CODE (to) == POINTER_TYPE && TREE_CODE (from) == POINTER_TYPE)
00885 {
00886 to = TREE_TYPE (to);
00887 from = TREE_TYPE (from);
00888
00889 if (! at_least_as_qualified_p (to, from))
00890 return 0;
00891
00892 if (TREE_CODE (to) == VOID_TYPE)
00893 return 1;
00894
00895
00896 }
00897
00898 if (CLASS_TYPE_P (to) && CLASS_TYPE_P (from)
00899 && PUBLICLY_UNIQUELY_DERIVED_P (to, from))
00900 return 1;
00901
00902 return 0;
00903 }
00904
00905
00906
00907
00908
00909
00910
00911 static void
00912 check_handlers_1 (tree master, tree_stmt_iterator i)
00913 {
00914 tree type = TREE_TYPE (master);
00915
00916 for (; !tsi_end_p (i); tsi_next (&i))
00917 {
00918 tree handler = tsi_stmt (i);
00919 if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
00920 {
00921 warning ("%Hexception of type %qT will be caught",
00922 EXPR_LOCUS (handler), TREE_TYPE (handler));
00923 warning ("%H by earlier handler for %qT",
00924 EXPR_LOCUS (master), type);
00925 break;
00926 }
00927 }
00928 }
00929
00930
00931
00932 void
00933 check_handlers (tree handlers)
00934 {
00935 tree_stmt_iterator i;
00936
00937
00938
00939 if (TREE_CODE (handlers) != STATEMENT_LIST)
00940 return;
00941
00942 i = tsi_start (handlers);
00943 if (!tsi_end_p (i))
00944 while (1)
00945 {
00946 tree handler = tsi_stmt (i);
00947 tsi_next (&i);
00948
00949
00950 if (tsi_end_p (i))
00951 break;
00952 if (TREE_TYPE (handler) == NULL_TREE)
00953 pedwarn ("%H%<...%> handler must be the last handler for"
00954 " its try block", EXPR_LOCUS (handler));
00955 else
00956 check_handlers_1 (handler, i);
00957 }
00958 }