diff options
author | Mark Mitchell <mark@codesourcery.com> | 2003-04-22 05:44:12 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2003-04-22 05:44:12 +0000 |
commit | b2dd096b0c7e5c48380b99b3d2b1ff4763b7f525 (patch) | |
tree | 0b42d76e5fdf7dbe6a765ae20af65b5a2ed24e6d /gcc | |
parent | f71c12554b607c5980b932a4dff5cba4c7decb89 (diff) | |
download | gcc-b2dd096b0c7e5c48380b99b3d2b1ff4763b7f525.zip gcc-b2dd096b0c7e5c48380b99b3d2b1ff4763b7f525.tar.gz gcc-b2dd096b0c7e5c48380b99b3d2b1ff4763b7f525.tar.bz2 |
Makefile.in (calls.o): Depend on except.h.
* Makefile.in (calls.o): Depend on except.h.
* calls.c: Include except.h.
(emit_call_1): Call note_eh_region_may_contain_throw if
appropriate.
* except.c (eh_region): Add may_contain_throw.
(expand_eh_region_end_cleanup): Do not include handler code when
it cannot be reached.
(note_eh_region_may_contain_throw): New function.
* except.h (note_eh_region_may_contain_throw): New function.
* call.c (build_over_call): Use build_cxx_call.
(build_cxx_call): New method, split out of build_over_call.
* cp-tree.h (language_function): Add can_throw.
(build_cxx_call): Declare it.
* decl.c (finish_function): If a function does not contain any
calls to functions that can throw an exception, indicate that
fact.
* decl2.c (mark_used): Do not defer the instantiation of
functions, if the current function does not throw.
* optimize.c (maybe_clone_body): Copy TREE_NOTHROW to the clones.
* pt.c (instantiate_decl): Make sure import_export_decl is called
before emitting things.
* rtti.c (throw_bad_cast): Use build_cxx_call.
(build_dynamic_cast_1): Likewise.
* typeck.c (build_function_call): Likewise.
* g++.dg/template/recurse.C: Adjust location of error messages.
From-SVN: r65929
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/calls.c | 3 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/cp/call.c | 30 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/decl.c | 6 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 28 | ||||
-rw-r--r-- | gcc/cp/optimize.c | 3 | ||||
-rw-r--r-- | gcc/cp/pt.c | 13 | ||||
-rw-r--r-- | gcc/cp/rtti.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 13 | ||||
-rw-r--r-- | gcc/except.c | 66 | ||||
-rw-r--r-- | gcc/except.h | 4 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/recurse.C | 2 |
16 files changed, 162 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index faad4e5..d6ffa22 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,17 @@ 2003-04-21 Mark Mitchell <mark@codesourcery.com> + * Makefile.in (calls.o): Depend on except.h. + * calls.c: Include except.h. + (emit_call_1): Call note_eh_region_may_contain_throw if + appropriate. + * except.c (eh_region): Add may_contain_throw. + (expand_eh_region_end_cleanup): Do not include handler code when + it cannot be reached. + (note_eh_region_may_contain_throw): New function. + * except.h (note_eh_region_may_contain_throw): New function. + +2003-04-21 Mark Mitchell <mark@codesourcery.com> + * config/i386/winnt.c (i386_pe_mark_dllimport): Revert previous changes. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 67e9412..2858145 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1532,7 +1532,7 @@ builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(T except.h $(TM_P_H) $(PREDICT_H) libfuncs.h real.h langhooks.h calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) flags.h \ $(EXPR_H) langhooks.h $(TARGET_H) \ - libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) cgraph.h + libfuncs.h $(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H) cgraph.h except.h expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ flags.h insn-config.h $(EXPR_H) $(OPTABS_H) $(RECOG_H) real.h \ toplev.h $(TM_P_H) langhooks.h diff --git a/gcc/calls.c b/gcc/calls.c index 06ed14a..bd889e1 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -38,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "langhooks.h" #include "target.h" #include "cgraph.h" +#include "except.h" /* Decide whether a function's arguments should be processed from first to last or from last to first. @@ -588,6 +589,8 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, if (ecf_flags & ECF_NOTHROW) REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx, REG_NOTES (call_insn)); + else + note_eh_region_may_contain_throw (); if (ecf_flags & ECF_NORETURN) REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cbe913e..28dde85 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,21 @@ +2003-04-21 Mark Mitchell <mark@codesourcery.com> + + * call.c (build_over_call): Use build_cxx_call. + (build_cxx_call): New method, split out of build_over_call. + * cp-tree.h (language_function): Add can_throw. + (build_cxx_call): Declare it. + * decl.c (finish_function): If a function does not contain any + calls to functions that can throw an exception, indicate that + fact. + * decl2.c (mark_used): Do not defer the instantiation of + functions, if the current function does not throw. + * optimize.c (maybe_clone_body): Copy TREE_NOTHROW to the clones. + * pt.c (instantiate_decl): Make sure import_export_decl is called + before emitting things. + * rtti.c (throw_bad_cast): Use build_cxx_call. + (build_dynamic_cast_1): Likewise. + * typeck.c (build_function_call): Likewise. + 2003-04-21 Nathan Sidwell <nathan@codesourcery.com> PR c++/9881 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d70b1a1..f7253d5 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4707,10 +4707,22 @@ build_over_call (struct z_candidate *cand, int flags) else fn = build_addr_func (fn); + return build_cxx_call (fn, args, converted_args); +} + +/* Build and return a call to FN, using the the CONVERTED_ARGS. ARGS + gives the original form of the arguments. This function performs + no overload resolution, conversion, or other high-level + operations. */ + +tree +build_cxx_call(tree fn, tree args, tree converted_args) +{ + tree fndecl; + /* Recognize certain built-in functions so we can make tree-codes other than CALL_EXPR. We do this when it enables fold-const.c to do something useful. */ - if (TREE_CODE (fn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL && DECL_BUILT_IN (TREE_OPERAND (fn, 0))) @@ -4721,14 +4733,24 @@ build_over_call (struct z_candidate *cand, int flags) return exp; } - /* Some built-in function calls will be evaluated at - compile-time in fold (). */ - fn = fold (build_call (fn, converted_args)); + fn = build_call (fn, converted_args); + + /* If this call might throw an exception, note that fact. */ + fndecl = get_callee_fndecl (fn); + if ((!fndecl || !TREE_NOTHROW (fndecl)) && at_function_scope_p ()) + cp_function_chain->can_throw = 1; + + /* Some built-in function calls will be evaluated at compile-time in + fold (). */ + fn = fold (fn); + if (VOID_TYPE_P (TREE_TYPE (fn))) return fn; + fn = require_complete_type (fn); if (fn == error_mark_node) return error_mark_node; + if (IS_AGGR_TYPE (TREE_TYPE (fn))) fn = build_cplus_new (TREE_TYPE (fn), fn); return convert_from_reference (fn); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0e9a201..cbee534 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -794,6 +794,9 @@ struct language_function GTY(()) int in_base_initializer; int x_expanding_p; + /* True if this function can throw an exception. */ + bool can_throw : 1; + struct named_label_use_list *x_named_label_uses; struct named_label_list *x_named_labels; struct cp_binding_level *bindings; @@ -3522,6 +3525,7 @@ extern tree make_temporary_var_for_ref_to_temp (tree, tree); extern tree strip_top_quals (tree); extern tree perform_implicit_conversion (tree, tree); extern tree in_charge_arg_for_name (tree); +extern tree build_cxx_call (tree, tree, tree); /* in class.c */ extern tree build_base_path (enum tree_code, tree, tree, int); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5abb3f4..a14389f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -13961,6 +13961,12 @@ finish_function (int flags) /* If we're saving up tree structure, tie off the function now. */ finish_stmt_tree (&DECL_SAVED_TREE (fndecl)); + /* If this function can't throw any exceptions, remember that. */ + if (!processing_template_decl + && !cp_function_chain->can_throw + && !flag_non_call_exceptions) + TREE_NOTHROW (fndecl) = 1; + /* This must come after expand_function_end because cleanups might have declarations (from inline functions) that need to go into this function's blocks. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 7b7dd47..3f9c66f 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4581,7 +4581,33 @@ mark_used (tree decl) && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) && (!DECL_EXPLICIT_INSTANTIATION (decl) || (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)))) - instantiate_decl (decl, /*defer_ok=*/1); + { + bool defer; + + /* Normally, we put off instantiating functions in order to + improve compile times. Maintaining a stack of active + functions is expensive, and the inliner knows to + instantiate any functions it might need. + + However, if instantiating this function might help us mark + the current function TREE_NOTHROW, we go ahead and + instantiate it now. */ + defer = (!flag_exceptions + || TREE_CODE (decl) != FUNCTION_DECL + /* If the called function can't throw, we don't need to + generate its body to find that out. */ + || TREE_NOTHROW (decl) + || !cfun + /* If we already know the current function can't throw, + then we don't need to work hard to prove it. */ + || TREE_NOTHROW (current_function_decl) + /* If we already know that the current function *can* + throw, there's no point in gathering more + information. */ + || cp_function_chain->can_throw); + + instantiate_decl (decl, defer); + } } /* Called when a class-head is encountered. TAG_KIND is the class-key diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index d461b0d..2c1c15d 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -259,6 +259,9 @@ maybe_clone_body (tree fn) /* Clean up. */ splay_tree_delete (decl_map); + /* The clone can throw iff the original function can throw. */ + cp_function_chain->can_throw = !TREE_NOTHROW (fn); + /* Now, expand this function into RTL, if appropriate. */ finish_function (0); BLOCK_ABSTRACT_ORIGIN (DECL_INITIAL (clone)) = DECL_INITIAL (fn); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 41baea5..74f497e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10948,13 +10948,8 @@ instantiate_decl (d, defer_ok) SET_DECL_RTL (d, NULL_RTX); DECL_IN_AGGR_P (d) = 0; - if (DECL_INTERFACE_KNOWN (d)) - DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d); - else - { - DECL_EXTERNAL (d) = 1; - DECL_NOT_REALLY_EXTERN (d) = 1; - } + import_export_decl (d); + DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d); cp_finish_decl (d, (!DECL_INITIALIZED_IN_CLASS_P (d) ? DECL_INITIAL (d) : NULL_TREE), @@ -11007,7 +11002,9 @@ instantiate_decl (d, defer_ok) local_specializations = saved_local_specializations; /* Finish the function. */ - expand_body (finish_function (0)); + d = finish_function (0); + import_export_decl (d); + expand_body (d); } /* We're not deferring instantiation any more. */ diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 8283acb..e02e693 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -177,7 +177,7 @@ throw_bad_cast (void) fn = push_throw_library_fn (fn, build_function_type (ptr_type_node, void_list_node)); - return build_call (fn, NULL_TREE); + return build_cxx_call (fn, NULL_TREE, NULL_TREE); } /* Return an expression for "__cxa_bad_typeid()". The expression @@ -660,7 +660,7 @@ build_dynamic_cast_1 (tree type, tree expr) pop_nested_namespace (ns); dynamic_cast_node = dcast_fn; } - result = build_call (dcast_fn, elems); + result = build_cxx_call (dcast_fn, elems, elems); if (tc == REFERENCE_TYPE) { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e60eb10..3afb13c 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2660,7 +2660,6 @@ build_function_call (function, params) tree function, params; { register tree fntype, fndecl; - register tree value_type; register tree coerced_params; tree result; tree name = NULL_TREE, assembler_name = NULL_TREE; @@ -2755,17 +2754,7 @@ build_function_call (function, params) return result; } - /* Some built-in function calls will be evaluated at - compile-time in fold (). */ - result = fold (build_call (function, coerced_params)); - value_type = TREE_TYPE (result); - - if (TREE_CODE (value_type) == VOID_TYPE) - return result; - result = require_complete_type (result); - if (IS_AGGR_TYPE (value_type)) - result = build_cplus_new (value_type, result); - return convert_from_reference (result); + return build_cxx_call (function, params, coerced_params); } /* Convert the actual parameter expressions in the list VALUES diff --git a/gcc/except.c b/gcc/except.c index a999834..afc6a01 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -209,6 +209,9 @@ struct eh_region GTY(()) /* The RESX insn for handing off control to the next outermost handler, if appropriate. */ rtx resume; + + /* True if something in this region may throw. */ + unsigned may_contain_throw : 1; }; struct call_site_record GTY(()) @@ -561,33 +564,38 @@ expand_eh_region_end_cleanup (handler) emit_label (region->label); - /* Give the language a chance to specify an action to be taken if an - exception is thrown that would propagate out of the HANDLER. */ - protect_cleanup_actions - = (lang_protect_cleanup_actions - ? (*lang_protect_cleanup_actions) () - : NULL_TREE); + if (flag_non_call_exceptions + || flag_forced_unwind_exceptions + || region->may_contain_throw) + { + /* Give the language a chance to specify an action to be taken if an + exception is thrown that would propagate out of the HANDLER. */ + protect_cleanup_actions + = (lang_protect_cleanup_actions + ? (*lang_protect_cleanup_actions) () + : NULL_TREE); - if (protect_cleanup_actions) - expand_eh_region_start (); + if (protect_cleanup_actions) + expand_eh_region_start (); - /* In case this cleanup involves an inline destructor with a try block in - it, we need to save the EH return data registers around it. */ - data_save[0] = gen_reg_rtx (ptr_mode); - emit_move_insn (data_save[0], get_exception_pointer (cfun)); - data_save[1] = gen_reg_rtx (word_mode); - emit_move_insn (data_save[1], get_exception_filter (cfun)); + /* In case this cleanup involves an inline destructor with a try block in + it, we need to save the EH return data registers around it. */ + data_save[0] = gen_reg_rtx (ptr_mode); + emit_move_insn (data_save[0], get_exception_pointer (cfun)); + data_save[1] = gen_reg_rtx (word_mode); + emit_move_insn (data_save[1], get_exception_filter (cfun)); - expand_expr (handler, const0_rtx, VOIDmode, 0); + expand_expr (handler, const0_rtx, VOIDmode, 0); - emit_move_insn (cfun->eh->exc_ptr, data_save[0]); - emit_move_insn (cfun->eh->filter, data_save[1]); + emit_move_insn (cfun->eh->exc_ptr, data_save[0]); + emit_move_insn (cfun->eh->filter, data_save[1]); - if (protect_cleanup_actions) - expand_eh_region_end_must_not_throw (protect_cleanup_actions); + if (protect_cleanup_actions) + expand_eh_region_end_must_not_throw (protect_cleanup_actions); - /* We need any stack adjustment complete before the around_label. */ - do_pending_stack_adjust (); + /* We need any stack adjustment complete before the around_label. */ + do_pending_stack_adjust (); + } /* We delay the generation of the _Unwind_Resume until we generate landing pads. We emit a marker here so as to get good control @@ -823,6 +831,22 @@ expand_eh_region_end_fixup (handler) fixup->u.fixup.cleanup_exp = handler; } +/* Note that the current EH region (if any) may contain a throw, or a + call to a function which itself may contain a throw. */ + +void +note_eh_region_may_contain_throw () +{ + struct eh_region *region; + + region = cfun->eh->cur_region; + while (region && !region->may_contain_throw) + { + region->may_contain_throw = 1; + region = region->outer; + } +} + /* Return an rtl expression for a pointer to the exception object within a handler. */ diff --git a/gcc/except.h b/gcc/except.h index ba37dab..40d1676 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -78,6 +78,10 @@ extern void expand_eh_region_end_throw PARAMS ((tree)); destroying an object twice. */ extern void expand_eh_region_end_fixup PARAMS ((tree)); +/* Note that the current EH region (if any) may contain a throw, or a + call to a function which itself may contain a throw. */ +extern void note_eh_region_may_contain_throw PARAMS ((void)); + /* Invokes CALLBACK for every exception handler label. Only used by old loop hackery; should not be used by new code. */ extern void for_each_eh_label PARAMS ((void (*) (rtx))); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fe9eb5c..577a609 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-04-21 Mark Mitchell <mark@codesourcery.com> + + * g++.dg/template/recurse.C: Adjust location of error messages. + 2003-04-21 Nathan Sidwell <nathan@codesourcery.com> PR c++/9881 diff --git a/gcc/testsuite/g++.dg/template/recurse.C b/gcc/testsuite/g++.dg/template/recurse.C index 61b9409..ce4c926 100644 --- a/gcc/testsuite/g++.dg/template/recurse.C +++ b/gcc/testsuite/g++.dg/template/recurse.C @@ -6,7 +6,7 @@ template <int I> struct F int operator()() { F<I+1> f; // { dg-error "" "" } - return f()*I; + return f()*I; // { dg-error "" "" } } }; |