Makefile.in (calls.o): Depend on except.h.
authorMark Mitchell <mark@codesourcery.com>
Tue, 22 Apr 2003 05:44:12 +0000 (05:44 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 22 Apr 2003 05:44:12 +0000 (05:44 +0000)
* 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

16 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/calls.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/optimize.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/typeck.c
gcc/except.c
gcc/except.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/recurse.C

index faad4e5b0bc2dd4c64779caa168c7fb97e036669..d6ffa22f2f685715c3f801e40b78418e5283fcaf 100644 (file)
@@ -1,3 +1,15 @@
+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
index 67e94128b7648250dacf1579b44a90adfeab2e5e..2858145d81c2339ef5fcaa5cb8d4d06e1c98fc4f 100644 (file)
@@ -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
index 06ed14a00e473359564fe39822a72a5aac325c4b..bd889e1ae71537f4b07377202598ac21c506f70c 100644 (file)
@@ -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,
index cbe913e8d7269c721dd49174c507adccc2d9ba8a..28dde85070f3e8745042b1e57725e31f5b8ca1d4 100644 (file)
@@ -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
index d70b1a1c0c571794ba9032009525fae701514d96..f7253d500034ba262014c5814f54816ea6aa14d0 100644 (file)
@@ -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);
index 0e9a201cc91b8297a4e099de95d637878ca8810d..cbee534b4da882660d19b8e5a63cf71512e57672 100644 (file)
@@ -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);
index 5abb3f4c36253b62eaeb81638b862cecc31b1778..a14389f12565443f875894d4f8651a3566aae1d6 100644 (file)
@@ -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.  */
index 7b7dd471be5f85a3f26f72a741e52e27926fdb0c..3f9c66fd4d4abaa8bd0531f669e5efdfd5037aef 100644 (file)
@@ -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
index d461b0d08b5c3d83d63abb4d249c44db09b01fe2..2c1c15d003eb727b6476b67f3770b130a0e13357 100644 (file)
@@ -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);
index 41baea5b4dc2b35001089e0ef27009eedad3ca71..74f497e1cf699a443b201bbe15a6594719a5bfe8 100644 (file)
@@ -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.  */
index 8283acb7f4601a00f3607c6c103a30bd740ab91d..e02e69359b1d2fbf3128be7f83df024cf8634557 100644 (file)
@@ -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)
            {
index e60eb105ada27f26c3297feb262b452e13425111..3afb13c384d657207487e0083e26759e95701e29 100644 (file)
@@ -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);
 }
 \f
 /* Convert the actual parameter expressions in the list VALUES
index a99983462cc8b2ad615effc1d0b918543981638e..afc6a01f3dafe712a39e8a20de4a9ac83f0df9a4 100644 (file)
@@ -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.  */
 
index ba37dabaacf98ec07068f294e9a6679a8714d4a1..40d1676794396cc16818d3457cb709c2327b26ba 100644 (file)
@@ -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)));
index fe9eb5cf4804800ff746dc032c91071b531cd61a..577a6090432b0e8df41f2525ba575e9d87e0f375 100644 (file)
@@ -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
index 61b94096783657fe2ab6ed6e890e86428a34bcec..ce4c9268cfe0523787de01180362e8cbdded7e6d 100644 (file)
@@ -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 "" "" }
     }
 };