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