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