]> gcc.gnu.org Git - gcc.git/commitdiff
stmt.c (expand_decl_cleanup_no_eh): New fn.
authorJason Merrill <jason@gcc.gnu.org>
Mon, 10 Nov 1997 20:03:49 +0000 (15:03 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 10 Nov 1997 20:03:49 +0000 (15:03 -0500)
* stmt.c (expand_decl_cleanup_no_eh): New fn.

* except.c (expand_leftover_cleanups): do_pending_stack_adjust.

Complete nested exception support.
* except.c (do_pop_exception): Split out...
(push_eh_cleanup): From here.  Handle the EH region by hand.
(expand_start_catch_block): Add a new level for the catch parm.
Move the rethrow region outside the two cleanup regions.
Protect the initializer for the catch parm with terminate.
(expand_end_catch_block): Likewise.  End the region for the eh_cleanup.
* exception.cc (__cp_pop_exception): Now takes two parms.  Handle
popping off the middle of the stack.
* tree.c (lvalue_p, real_lvalue_p): Handle TRY_CATCH_EXPR,
WITH_CLEANUP_EXPR, and UNSAVE_EXPR.
(build_cplus_new): Only wrap CALL_EXPRs.
* init.c (expand_default_init): Handle a TRY_CATCH_EXPR around
the constructor call.

From-SVN: r16419

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/except.c
gcc/cp/exception.cc
gcc/cp/init.c
gcc/cp/tree.c
gcc/except.c
gcc/stmt.c

index 689259e3d1fa530c28011a48dad98d637bd42d66..33222307c4f9bc99b6ab4132c6884de491cd2528 100644 (file)
@@ -1,3 +1,9 @@
+Mon Nov 10 03:02:19 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * stmt.c (expand_decl_cleanup_no_eh): New fn.
+
+       * except.c (expand_leftover_cleanups): do_pending_stack_adjust.
+
 Mon Nov 10 00:05:56 1997  Jeffrey A Law  (law@cygnus.com)
 
        * alias.c (MAX_ALIAS_LOOP_PASSES): Define.
index d4eed7b8f4966e94bcbf4321cc6a4fee2bf56de3..b96f7b27434cbf511308c5a52b709549b10b6fa2 100644 (file)
@@ -4,6 +4,27 @@ Sun Nov  9 01:29:55 1997  Jim Wilson  (wilson@cygnus.com)
        * init.c (build_vec_delete_1): Delete build_block and
        add_block_current_level calls.
 
+Mon Nov 10 03:04:20 1997  Jason Merrill  <jason@yorick.cygnus.com>
+
+       Complete nested exception support.
+       * except.c (do_pop_exception): Split out...
+       (push_eh_cleanup): From here.  Handle the EH region by hand.
+       (expand_start_catch_block): Add a new level for the catch parm.
+       Move the rethrow region outside the two cleanup regions.
+       Protect the initializer for the catch parm with terminate.
+       (expand_end_catch_block): Likewise.  End the region for the eh_cleanup.
+       * exception.cc (__cp_pop_exception): Now takes two parms.  Handle
+       popping off the middle of the stack.
+       * tree.c (lvalue_p, real_lvalue_p): Handle TRY_CATCH_EXPR, 
+       WITH_CLEANUP_EXPR, and UNSAVE_EXPR.
+       (build_cplus_new): Only wrap CALL_EXPRs.
+       * init.c (expand_default_init): Handle a TRY_CATCH_EXPR around 
+       the constructor call.
+
+Sun Nov  9 18:00:26 1997  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
+
+       * Make-lang.in (c++.distdir): Make inc subdirectory.
+
 Fri Nov  7 11:57:28 1997  Jason Merrill  <jason@yorick.cygnus.com>
 
        * decl2.c (finish_file): Put back some code.
index 78123ef40b055a95770e4bc69e1652bd5a3cfc8d..a1e5794492dd6887b263c0d6cd9ae685074ad8ae 100644 (file)
@@ -1,5 +1,5 @@
 # Top level makefile fragment for GNU C++.
-#   Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+#   Copyright (C) 1994, 1995, 1997 Free Software Foundation, Inc.
 
 #This file is part of GNU CC.
 
@@ -265,8 +265,14 @@ c++.stage4: stage4-start
 # distribution anyway.  It then copies the files to the distdir directory.
 c++.distdir:
        mkdir tmp/cp
+       mkdir tmp/cp/inc
        cd cp ; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) parse.c hash.h
        cd cp; \
        for file in *[0-9a-zA-Z+]; do \
          $(LN) $$file ../tmp/cp; \
        done
+       cd cp/inc; \
+       for file in *[0-9a-zA-Z+]; do \
+         ln $$file ../../tmp/cp/inc >/dev/null 2>&1 \
+          || cp $$file ../../tmp/cp/inc; \
+       done
index b95e8ab776afe729a760b32e2955e0af159d67e6..e4cff1f823b936a968d5a1e7e926d790894cb192 100644 (file)
@@ -461,26 +461,31 @@ build_eh_type (exp)
   return build_eh_type_type (TREE_TYPE (exp));
 }
 
-/* This routine creates the cleanup for the current exception.  */
+/* Build up a call to __cp_pop_exception, to destroy the exception object
+   for the current catch block.  HANDLER is either true or false, telling
+   the library whether or not it is being called from an exception handler;
+   if it is, it avoids destroying the object on rethrow.  */
 
-static void
-push_eh_cleanup ()
+static tree
+do_pop_exception (handler)
+     tree handler;
 {
-  /* All cleanups must last longer than normal.  */
-  int yes = suspend_momentary ();
   tree fn, cleanup;
-
   fn = get_identifier ("__cp_pop_exception");
   if (IDENTIFIER_GLOBAL_VALUE (fn))
     fn = IDENTIFIER_GLOBAL_VALUE (fn);
   else
     {
-      /* Declare void __cp_pop_exception (void), as defined in exception.cc. */
+      /* Declare void __cp_pop_exception (void *),
+        as defined in exception.cc. */
       push_obstacks_nochange ();
       end_temporary_allocation ();
-      fn = build_lang_decl (FUNCTION_DECL, fn,
-                           build_function_type (void_type_node,
-                                                void_list_node));
+      fn = build_lang_decl
+       (FUNCTION_DECL, fn,
+        build_function_type (void_type_node, tree_cons
+                             (NULL_TREE, ptr_type_node, tree_cons
+                              (NULL_TREE, boolean_type_node,
+                               void_list_node))));
       DECL_EXTERNAL (fn) = 1;
       TREE_PUBLIC (fn) = 1;
       DECL_ARTIFICIAL (fn) = 1;
@@ -491,12 +496,26 @@ push_eh_cleanup ()
     }
 
   /* Arrange to do a dynamically scoped cleanup upon exit from this region.  */
-  cleanup = build_function_call (fn, NULL_TREE);
-  expand_decl_cleanup (NULL_TREE, cleanup);
+  cleanup = lookup_name (get_identifier ("__exception_info"), 0);
+  cleanup = build_function_call (fn, expr_tree_cons
+                                (NULL_TREE, cleanup, expr_tree_cons
+                                 (NULL_TREE, handler, NULL_TREE)));
+}
+
+/* This routine creates the cleanup for the current exception.  */
 
+static void
+push_eh_cleanup ()
+{
+  /* All cleanups must last longer than normal.  */
+  int yes = suspend_momentary ();
+  expand_decl_cleanup_no_eh (NULL_TREE, do_pop_exception (boolean_false_node));
   resume_momentary (yes);
-}
 
+  /* We don't destroy the exception object on rethrow, so we can't use
+     the normal cleanup mechanism for it.  */
+  expand_eh_region_start ();
+}
 
 /* call this to start a catch block. Typename is the typename, and identifier
    is the variable to place the object in or NULL if the variable doesn't
@@ -530,7 +549,18 @@ expand_start_catch_block (declspecs, declarator)
   if (! doing_eh (1))
     return;
 
-  /* Create a binding level for the parm.  */
+  /* If we are not doing setjmp/longjmp EH, because we are reordered
+     out of line, we arrange to rethrow in the outer context so as to
+     skip through the terminate region we are nested in, should we
+     encounter an exception in the catch handler.  We also need to do
+     this because we are not physically within the try block, if any,
+     that contains this catch block.
+
+     Matches the end in expand_end_catch_block.  */
+  expand_eh_region_start ();
+
+  /* Create a binding level for the eh_info and the exception object
+     cleanup.  */
   pushlevel (0);
   expand_start_bindings (0);
 
@@ -543,23 +573,17 @@ expand_start_catch_block (declspecs, declarator)
 
   if (declspecs)
     {
-      tree exp;
-      rtx call_rtx, return_value_rtx;
-      tree init_type;
-
       decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
 
       if (decl == NULL_TREE)
-       {
-         error ("invalid catch parameter");
-
-         /* This is cheap, but we want to maintain the data
-             structures.  */
-
-         expand_eh_region_start ();
+       error ("invalid catch parameter");
+    }
 
-         return;
-       }
+  if (decl)
+    {
+      tree exp;
+      rtx call_rtx, return_value_rtx;
+      tree init_type;
 
       /* Make sure we mark the catch param as used, otherwise we'll get
         a warning about an unused ((anonymous)).  */
@@ -592,37 +616,44 @@ expand_start_catch_block (declspecs, declarator)
 
       push_eh_cleanup ();
 
-      init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
+      /* Create a binding level for the parm.  */
+      pushlevel (0);
+      expand_start_bindings (0);
+
+      init = convert_from_reference (make_tree (init_type, call_rtx));
+
+      /* If the constructor for the catch parm exits via an exception, we
+         must call terminate.  See eh23.C.  */
+      if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+       {
+         /* Generate the copy constructor call directly so we can wrap it.
+            See also expand_default_init.  */
+         init = ocp_convert (TREE_TYPE (decl), init,
+                             CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
+         init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
+                       TerminateFunctionCall);
+       }
 
-      /* Do we need the below two lines? */
       /* Let `cp_finish_decl' know that this initializer is ok.  */
       DECL_INITIAL (decl) = init;
       decl = pushdecl (decl);
+
       cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
     }
   else
     {
       push_eh_cleanup ();
 
+      /* Create a binding level for the parm.  */
+      pushlevel (0);
+      expand_start_bindings (0);
+
       /* Fall into the catch all section.  */
     }
 
   init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
   expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
 
-  /* If we are not doing setjmp/longjmp EH, because we are reordered
-     out of line, we arrange to rethrow in the outer context so as to
-     skip through the terminate region we are nested in, should we
-     encounter an exception in the catch handler.
-
-     If we are doing setjmp/longjmp EH, we need to skip through the EH
-     object cleanup region.  This isn't quite right, as we really need
-     to clean the object up, but we cannot do that until we track
-     multiple EH objects.
-
-     Matches the end in expand_end_catch_block.  */
-  expand_eh_region_start ();
-
   emit_line_note (input_filename, lineno);
 }
 
@@ -642,6 +673,17 @@ expand_end_catch_block ()
   if (! doing_eh (1))
     return;
 
+  /* Cleanup the EH parameter.  */
+  expand_end_bindings (getdecls (), kept_level_p (), 0);
+  poplevel (kept_level_p (), 1, 0);
+      
+  /* Matches push_eh_cleanup.  */
+  expand_eh_region_end (do_pop_exception (boolean_true_node));
+
+  /* Cleanup the EH object.  */
+  expand_end_bindings (getdecls (), kept_level_p (), 0);
+  poplevel (kept_level_p (), 1, 0);
+      
   t = make_node (RTL_EXPR);
   TREE_TYPE (t) = void_type_node;
   RTL_EXPR_RTL (t) = const0_rtx;
@@ -672,7 +714,7 @@ expand_end_catch_block ()
   RTL_EXPR_SEQUENCE (t) = get_insns ();
   end_sequence ();
 
-  /* Matches the start in expand_start_catch_block.  */
+  /* For the rethrow region.  */
   expand_eh_region_end (t);
 
   /* Fall to outside the try statement when done executing handler and
@@ -682,10 +724,6 @@ expand_end_catch_block ()
 
   expand_leftover_cleanups ();
 
-  /* Cleanup the EH parameter.  */
-  expand_end_bindings (getdecls (), kept_level_p (), 0);
-  poplevel (kept_level_p (), 1, 0);
-      
   /* label we emit to jump to if this catch block didn't match.  */
   /* This the closing } in the `if (eq) {' of the documentation.  */
   emit_label (pop_label_entry (&false_label_stack));
index 4099d4776203097450099d3ae312f253b0b11d91..2d1ae08124703757a482771064643e3bad199cee 100644 (file)
@@ -118,12 +118,26 @@ __cp_push_exception (void *value, void *type, void (*cleanup)(void *, int))
 }
 
 /* Compiler hook to pop an exception that has been finalized.  Used by
-   push_eh_cleanup().  */
+   push_eh_cleanup().  P is the info for the exception caught by the
+   current catch block, and HANDLER determines if we've been called from
+   an exception handler; if so, we avoid destroying the object on rethrow.  */
 
 extern "C" void
-__cp_pop_exception (void)
+__cp_pop_exception (cp_eh_info *p, bool handler)
 {
-  cp_eh_info *p = __eh_info;
+  cp_eh_info **q = &__eh_info;
+
+  if (handler && p == *q)
+    return;
+
+  for (; *q; q = &((*q)->next))
+    if (*q == p)
+      break;
+
+  if (! *q)
+    terminate ();
+
+  *q = p->next;
 
   if (p->cleanup)
     /* 3 is a magic value for destructors; see build_delete().  */
@@ -133,7 +147,6 @@ __cp_pop_exception (void)
   else
     delete p->value;
 
-  __eh_info = p->next;
   delete p;
 }
 
index 1ae838cc273455776bfef9806503bb26a103b69e..09a3de18c14e4fae4bc984f784c5a5aec4b6d1df 100644 (file)
@@ -1266,7 +1266,17 @@ expand_default_init (binfo, true_exp, exp, init, alias_this, flags)
             && TREE_CODE (init) == TARGET_EXPR && TREE_TYPE (init) == type))
        init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
 
-      expand_assignment (exp, init, 0, 0);
+      if (TREE_CODE (init) == TRY_CATCH_EXPR)
+       /* We need to protect the initialization of a catch parm
+          with a call to terminate(), which shows up as a TRY_CATCH_EXPR
+          around the TARGET_EXPR for the copy constructor.  See
+          expand_start_catch_block.  */
+       TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,
+                                       TREE_OPERAND (init, 0));
+      else
+       init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);
+      TREE_SIDE_EFFECTS (init) = 1;
+      expand_expr_stmt (init);
       return;
     }
 
index c681651ebf1f32267ed343d52d88c04a8405efcf..9d2589fec6dce7fa4f08974264c32e807162f82d 100644 (file)
@@ -78,6 +78,9 @@ real_lvalue_p (ref)
     case PREDECREMENT_EXPR:
     case COMPONENT_REF:
     case SAVE_EXPR:
+    case UNSAVE_EXPR:
+    case TRY_CATCH_EXPR:
+    case WITH_CLEANUP_EXPR:
       return real_lvalue_p (TREE_OPERAND (ref, 0));
 
     case STRING_CST:
@@ -152,6 +155,9 @@ lvalue_p (ref)
     case IMAGPART_EXPR:
     case COMPONENT_REF:
     case SAVE_EXPR:
+    case UNSAVE_EXPR:
+    case TRY_CATCH_EXPR:
+    case WITH_CLEANUP_EXPR:
       return lvalue_p (TREE_OPERAND (ref, 0));
 
     case STRING_CST:
@@ -238,7 +244,7 @@ build_cplus_new (type, init)
   tree slot;
   tree rval;
 
-  if (TREE_CODE (init) == TARGET_EXPR || init == error_mark_node)
+  if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != NEW_EXPR)
     return init;
 
   slot = build (VAR_DECL, type);
index bf9cebffca9f730a309e0c1f0e3e0f6e420098dd..29adf3b66c916999a6461d727286d7a1ef7807cf 100644 (file)
@@ -1224,6 +1224,7 @@ expand_leftover_cleanups ()
            }
        }
 
+      do_pending_stack_adjust ();
       free (entry);
     }
 }
index b7a2c52f43c237f88d57b0687a30bf94564cac08..97a8d48a07948469354ac527c0903c6b6d9e6fc9 100644 (file)
@@ -4012,6 +4012,19 @@ expand_decl_cleanup (decl, cleanup)
   return 1;
 }
 
+/* Like expand_decl_cleanup, but suppress generating an exception handler
+   to perform the cleanup.  */
+
+int
+expand_decl_cleanup_no_eh (decl, cleanup)
+     tree decl, cleanup;
+{
+  int save_eh = using_eh_for_cleanups_p;
+  using_eh_for_cleanups_p = 0;
+  expand_decl_cleanup (decl, cleanup);
+  using_eh_for_cleanups_p = save_eh;
+}
+
 /* Arrange for the top element of the dynamic cleanup chain to be
    popped if we exit the current binding contour.  DECL is the
    associated declaration, if any, otherwise NULL_TREE.  If the
This page took 0.106941 seconds and 5 git commands to generate.