]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/5636 (gcc-3.0.3, memory leakage: function that take a string as parameter...
authorJason Merrill <jason@gcc.gnu.org>
Thu, 4 Apr 2002 00:11:00 +0000 (19:11 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 4 Apr 2002 00:11:00 +0000 (19:11 -0500)
        PR c++/5636
        * tree.h (CLEANUP_EH_ONLY): New macro.
        * stmt.c (expand_decl_cleanup_eh): New fn.
        (expand_cleanups): Check CLEANUP_EH_ONLY.
        * c-semantics.c (genrtl_decl_cleanup): Just take the CLEANUP_STMT.
        Use expand_decl_cleanup_eh.
        (expand_stmt): Adjust.
        * c-common.h: Adjust prototype.
        * cp/semantics.c (nullify_returns_r): Just set CLEANUP_EH_ONLY on
        cleanup for nrv.

        * except.c (struct eh_status): Remove protect_list.
        (begin_protect_partials, end_protect_partials): Remove.
        (add_partial_entry): Remove.
        * except.h: Remove prototypes.

        * expr.c (expand_expr) [WITH_CLEANUP_EXPR, TARGET_EXPR]: Use
        expand_decl_cleanup_eh.

cp/:
        * semantics.c (finish_eh_cleanup): New fn.
        * cp-tree.h: Add prototype.
        * init.c (perform_member_init, expand_cleanup_for_base): Use
        finish_eh_cleanup.
        * cp-tree.def (SUBOBJECT, CTOR_STMT): Remove.
        * cp-tree.h: Remove references.
        * decl.c (begin_constructor_body, end_constructor_body): Likewise.
        * dump.c (cp_dump_tree): Likewise.
        * pt.c (tsubst_expr): Likewise.
        * semantics.c (genrtl_ctor_stmt, genrtl_subobject): Remove.
        (cp_expand_stmt): Remove handling of CTOR_STMT and SUBOBJECT.
        * tree.c (cp_statement_code_p): Likewise.

        * init.c (build_new_1): Set CLEANUP_EH_ONLY on deleting cleanup.

From-SVN: r51827

18 files changed:
gcc/ChangeLog
gcc/c-common.h
gcc/c-semantics.c
gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/dump.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/except.c
gcc/except.h
gcc/expr.c
gcc/stmt.c
gcc/testsuite/g++.dg/eh/nrv1.C [new file with mode: 0644]
gcc/tree.h

index ce125acd123a5d29d263c4746b24a601d6c090c6..57e66e4c992edc0d6f6cfa89b55bebfd2d6d87fb 100644 (file)
@@ -1,3 +1,22 @@
+2002-04-03  Jason Merrill  <jason@redhat.com>
+
+       * except.c (struct eh_status): Remove protect_list.
+       (begin_protect_partials, end_protect_partials): Remove.
+       (add_partial_entry): Remove.
+       * except.h: Remove prototypes.
+
+       * expr.c (expand_expr) [WITH_CLEANUP_EXPR, TARGET_EXPR]: Use
+       expand_decl_cleanup_eh.
+
+       PR c++/5636
+       * tree.h (CLEANUP_EH_ONLY): New macro.
+       * stmt.c (expand_decl_cleanup_eh): New fn.
+       (expand_cleanups): Check CLEANUP_EH_ONLY.
+       * c-semantics.c (genrtl_decl_cleanup): Just take the CLEANUP_STMT.
+       Use expand_decl_cleanup_eh.
+       (expand_stmt): Adjust.
+       * c-common.h: Adjust prototype.
+
 2002-04-04  Hans-Peter Nilsson  <hp@axis.com>
 
        * config/cris/cris.c (cris_target_asm_function_prologue): Cast
@@ -1497,7 +1516,7 @@ Fri Mar 22 12:08:36 CET 2002  Jan Hubicka  <jh@suse.cz>
 
        * flags.h (flag_really_no_inline): New.
 
-       * c-common.c (c_common_post_options): Initialzie
+       * c-common.c (c_common_post_options): Initialize
        flag_really_no_inline.
 
        * toplev.c (flag_really_no_inline): New.
index 5dde85a8ee3d81bddc40d2c30a091482b8731069..cb49b529e80c4a88acac329308ce55cd81f52281 100644 (file)
@@ -765,7 +765,7 @@ extern void genrtl_compound_stmt                PARAMS ((tree));
 extern void genrtl_asm_stmt                     PARAMS ((tree, tree,
                                                         tree, tree,
                                                         tree, int));
-extern void genrtl_decl_cleanup                 PARAMS ((tree, tree));
+extern void genrtl_decl_cleanup                 PARAMS ((tree));
 extern int stmts_are_full_exprs_p               PARAMS ((void));
 extern int anon_aggr_type_p                     PARAMS ((tree));
 
index 3d8759d8584cdf4237a6d297bae0b3300b9a53ed..030a04cb00954479b72642427f45b8b526ed2335 100644 (file)
@@ -737,12 +737,12 @@ genrtl_asm_stmt (cv_qualifier, string, output_operands,
 /* Generate the RTL for a DECL_CLEANUP.  */
 
 void 
-genrtl_decl_cleanup (decl, cleanup)
-     tree decl;
-     tree cleanup;
+genrtl_decl_cleanup (t)
+     tree t;
 {
+  tree decl = CLEANUP_DECL (t);
   if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
-    expand_decl_cleanup (decl, cleanup);
+    expand_decl_cleanup_eh (decl, CLEANUP_EXPR (t), CLEANUP_EH_ONLY (t));
 }
 
 /* We're about to expand T, a statement.  Set up appropriate context
@@ -848,7 +848,7 @@ expand_stmt (t)
          break;
 
        case CLEANUP_STMT:
-         genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
+         genrtl_decl_cleanup (t);
          break;
 
        default:
index 15e12d6858cc71acffec2427611e0d12a119e105..756d2b30c63115cdfcdf3d64552b2bd0d9bb902a 100644 (file)
@@ -1,5 +1,24 @@
 2002-04-04  Jason Merrill  <jason@redhat.com>
 
+       * semantics.c (finish_eh_cleanup): New fn.
+       * cp-tree.h: Add prototype.
+       * init.c (perform_member_init, expand_cleanup_for_base): Use 
+       finish_eh_cleanup.
+       * cp-tree.def (SUBOBJECT, CTOR_STMT): Remove.
+       * cp-tree.h: Remove references.
+       * decl.c (begin_constructor_body, end_constructor_body): Likewise.
+       * dump.c (cp_dump_tree): Likewise.
+       * pt.c (tsubst_expr): Likewise.
+       * semantics.c (genrtl_ctor_stmt, genrtl_subobject): Remove.
+       (cp_expand_stmt): Remove handling of CTOR_STMT and SUBOBJECT.
+       * tree.c (cp_statement_code_p): Likewise.
+
+       * init.c (build_new_1): Set CLEANUP_EH_ONLY on deleting cleanup.
+
+       PR c++/5636
+       * semantics.c (nullify_returns_r): Just set CLEANUP_EH_ONLY on
+       cleanup for nrv.
+
        PR c++/5104
        * typeck.c (comptypes) [FUNCTION_TYPE]: Don't compare exception
        specifiers.
index 3854525611413c4764ab482bdbc65f2a732027fc..1bf4c0d2ec63ad8c206408019e586fe67dd66fe8 100644 (file)
@@ -220,16 +220,6 @@ DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", 'e', 2)
 DEFTREECODE (TYPEID_EXPR, "typeid_expr", 'e', 1)
 DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3)
 
-/* A SUBOBJECT statement marks the point at which a sub-object is
-   fully constructed.  After this point, the SUBOBJECT_CLEANUP must be
-   run if an exception is thrown before the end of the enclosing
-   function.  */
-DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
-/* An CTOR_STMT marks the beginning (if CTOR_BEGIN_P holds) or end of
-   a constructor (if CTOR_END_P) holds.  At the end of a constructor,
-   the cleanups associated with any SUBOBJECT_CLEANUPS need no longer
-   be run.  */
-DEFTREECODE (CTOR_STMT, "ctor_stmt", 'e', 0)
 /* CTOR_INITIALIZER is a placeholder in template code for a call to
    setup_vtbl_pointer (and appears in all functions, not just ctors).  */
 DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
index dbd955502422fbd257d520dc8e97496d5c4b3d4a..b65467bae1d58314c5b7ec300426a49f951b6824 100644 (file)
@@ -47,7 +47,6 @@ struct diagnostic_context;
       ICS_USER_FLAG (in _CONV)
       CLEANUP_P (in TRY_BLOCK)
       AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
-      CTOR_BEGIN_P (in CTOR_STMT)
       BV_USE_VCALL_INDEX_P (in the BINFO_VIRTUALS TREE_LIST)
       PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
       PARMLIST_ELLIPSIS_P (in PARMLIST)
@@ -2969,15 +2968,6 @@ enum ptrmemfunc_vbit_where_t
 #define HANDLER_PARMS(NODE)     TREE_OPERAND (HANDLER_CHECK (NODE), 0)
 #define HANDLER_BODY(NODE)      TREE_OPERAND (HANDLER_CHECK (NODE), 1)
 #define HANDLER_TYPE(NODE)     TREE_TYPE (HANDLER_CHECK (NODE))
-#define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (SUBOBJECT_CHECK (NODE), 0)
-
-/* Nonzero if this CTOR_STMT is for the beginning of a constructor.  */
-#define CTOR_BEGIN_P(NODE) \
-  (TREE_LANG_FLAG_0 (CTOR_STMT_CHECK (NODE)))
-
-/* Nonzero if this CTOR_STMT is for the end of a constructor.  */
-#define CTOR_END_P(NODE) \
-  (!CTOR_BEGIN_P (NODE))
 
 /* The parameters for a call-declarator.  */
 #define CALL_DECLARATOR_PARMS(NODE) \
@@ -4217,6 +4207,7 @@ extern tree finish_typeof                 PARAMS ((tree));
 extern tree finish_sizeof                      PARAMS ((tree));
 extern tree finish_alignof                     PARAMS ((tree));
 extern void finish_decl_cleanup                 PARAMS ((tree, tree));
+extern void finish_eh_cleanup                   PARAMS ((tree));
 extern void finish_named_return_value           PARAMS ((tree, tree));
 extern void expand_body                         PARAMS ((tree));
 extern tree nullify_returns_r                PARAMS ((tree *, int *, void *));
index 840dcff2d500b792a145726b0a5be8c8ce42eddf..78f1b14a7f385a4c4e79198811a3a732bed53c4b 100644 (file)
@@ -13948,9 +13948,6 @@ save_function_data (decl)
 static void
 begin_constructor_body ()
 {
-  tree ctor_stmt = build_stmt (CTOR_STMT);
-  CTOR_BEGIN_P (ctor_stmt) = 1;
-  add_stmt (ctor_stmt);
 }
 
 /* Add a note to mark the end of the main body of the constructor.  This is
@@ -13960,12 +13957,6 @@ begin_constructor_body ()
 static void
 finish_constructor_body ()
 {
-  /* Mark the end of the cleanups for a partially constructed object.
-
-     ??? These should really be handled automatically by closing the block,
-     as with the destructor cleanups; the only difference is that these are
-     only run if an exception is thrown.  */
-  add_stmt (build_stmt (CTOR_STMT));
 }
 
 /* Do all the processing for the beginning of a destructor; set up the
index 6dd60baf73be26581b34c727ff32677a2a5c042d..e0bc410bcae0cd90e739b7c809d237dfd1ee6efb 100644 (file)
@@ -390,15 +390,6 @@ cp_dump_tree (dump_info, t)
       dump_child ("decl", TREE_OPERAND (t, 2));
       break;
       
-    case CTOR_STMT:
-      dump_stmt (di, t);
-      if (CTOR_BEGIN_P (t))
-       dump_string (di, "begn");
-      else
-       dump_string (di, "end");
-      dump_next_stmt (di, t);
-      break;
-
     case HANDLER:
       dump_stmt (di, t);
       dump_child ("parm", HANDLER_PARMS (t));
@@ -412,12 +403,6 @@ cp_dump_tree (dump_info, t)
       dump_next_stmt (di, t);
       break;
 
-    case SUBOBJECT:
-      dump_stmt (di, t);
-      dump_child ("clnp", TREE_OPERAND (t, 0));
-      dump_next_stmt (di, t);
-      break;
-
     case USING_STMT:
       dump_stmt (di, t);
       dump_child ("nmsp", USING_STMT_NAMESPACE (t));
index 10098e72cfad9eea1077abb73bd7cd800be035f3..8b7e1f239a43678ade683c0e494a379e15893be7 100644 (file)
@@ -296,7 +296,7 @@ perform_member_init (member, init, explicit)
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
 
       if (expr != error_mark_node)
-       finish_subobject (expr);
+       finish_eh_cleanup (expr);
     }
 }
 
@@ -844,7 +844,7 @@ expand_cleanup_for_base (binfo, flag)
                        truthvalue_conversion (flag),
                        expr, integer_zero_node));
 
-  finish_subobject (expr);
+  finish_eh_cleanup (expr);
 }
 
 /* Subroutine of `expand_aggr_vbase_init'.
@@ -2498,9 +2498,11 @@ build_new_1 (exp)
              tree end, sentry, begin;
 
              begin = get_target_expr (boolean_true_node);
-             sentry = TREE_OPERAND (begin, 0);
+             CLEANUP_EH_ONLY (begin) = 1;
 
-             TREE_OPERAND (begin, 2)
+             sentry = TARGET_EXPR_SLOT (begin);
+
+             TARGET_EXPR_CLEANUP (begin)
                = build (COND_EXPR, void_type_node, sentry,
                         cleanup, void_zero_node);
 
index d28298a56a3d6d2e9bc06f4debace8ae96300d8c..b7057830686ebad93e37bbf70f7aefcbc2e70d84 100644 (file)
@@ -7584,10 +7584,6 @@ tsubst_expr (t, args, complain, in_decl)
       tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
       break;
 
-    case CTOR_STMT:
-      add_stmt (copy_node (t));
-      break;
-
     default:
       abort ();
     }
index 8666d7f02c4fbf80e62adca309f12edbff4c050b..ee609f45363366a7d99eb625bd341b347d4489a9 100644 (file)
@@ -56,8 +56,6 @@ static void emit_associated_thunks PARAMS ((tree));
 static void genrtl_try_block PARAMS ((tree));
 static void genrtl_eh_spec_block PARAMS ((tree));
 static void genrtl_handler PARAMS ((tree));
-static void genrtl_ctor_stmt PARAMS ((tree));
-static void genrtl_subobject PARAMS ((tree));
 static void genrtl_named_return_value PARAMS ((void));
 static void cp_expand_stmt PARAMS ((tree));
 static void genrtl_start_function PARAMS ((tree));
@@ -777,21 +775,6 @@ finish_handler (handler)
   RECHAIN_STMTS (handler, HANDLER_BODY (handler));
 }
 
-/* Generate the RTL for T, which is a CTOR_STMT. */
-
-static void
-genrtl_ctor_stmt (t)
-     tree t;
-{
-  if (CTOR_BEGIN_P (t))
-    begin_protect_partials ();
-  else
-    /* After this point, any exceptions will cause the
-       destructor to be executed, so we no longer need to worry
-       about destroying the various subobjects ourselves.  */
-    end_protect_partials ();
-}
-
 /* Begin a compound-statement.  If HAS_NO_SCOPE is non-zero, the
    compound-statement does not define a scope.  Returns a new
    COMPOUND_STMT if appropriate.  */
@@ -976,35 +959,25 @@ finish_label_decl (name)
   add_decl_stmt (decl);
 }
 
-/* Generate the RTL for a SUBOBJECT. */
-
-static void 
-genrtl_subobject (cleanup)
-     tree cleanup;
-{
-  add_partial_entry (cleanup);
-}
-
-/* We're in a constructor, and have just constructed a a subobject of
-   *THIS.  CLEANUP is code to run if an exception is thrown before the
-   end of the current function is reached.   */
+/* When DECL goes out of scope, make sure that CLEANUP is executed.  */
 
 void 
-finish_subobject (cleanup)
+finish_decl_cleanup (decl, cleanup)
+     tree decl;
      tree cleanup;
 {
-  tree r = build_stmt (SUBOBJECT, cleanup);
-  add_stmt (r);
+  add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
 }
 
-/* When DECL goes out of scope, make sure that CLEANUP is executed.  */
+/* If the current scope exits with an exception, run CLEANUP.  */
 
-void 
-finish_decl_cleanup (decl, cleanup)
-     tree decl;
+void
+finish_eh_cleanup (cleanup)
      tree cleanup;
 {
-  add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+  tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup);
+  CLEANUP_EH_ONLY (r) = 1;
+  add_stmt (r);
 }
 
 /* Generate the RTL for a RETURN_INIT. */
@@ -2130,10 +2103,6 @@ cp_expand_stmt (t)
 {
   switch (TREE_CODE (t))
     {
-    case CTOR_STMT:
-      genrtl_ctor_stmt (t);
-      break;
-
     case TRY_BLOCK:
       genrtl_try_block (t);
       break;
@@ -2146,10 +2115,6 @@ cp_expand_stmt (t)
       genrtl_handler (t);
       break;
 
-    case SUBOBJECT:
-      genrtl_subobject (SUBOBJECT_CLEANUP (t));
-      break;
-
     case RETURN_INIT:
       genrtl_named_return_value ();
       break;
@@ -2458,7 +2423,7 @@ nullify_returns_r (tp, walk_subtrees, data)
     RETURN_EXPR (*tp) = NULL_TREE;
   else if (TREE_CODE (*tp) == CLEANUP_STMT
           && CLEANUP_DECL (*tp) == nrv)
-    CLEANUP_EXPR (*tp) = NULL_TREE;
+    CLEANUP_EH_ONLY (*tp) = 1;
 
   /* Keep iterating.  */
   return NULL_TREE;
index c96f0e24d775811db2a82dba6a5759c425c64d2d..e0f736174499ad98774d4166101ce88b0159a1a9 100644 (file)
@@ -1030,8 +1030,6 @@ cp_statement_code_p (code)
 {
   switch (code)
     {
-    case SUBOBJECT:
-    case CTOR_STMT:
     case CTOR_INITIALIZER:
     case RETURN_INIT:
     case TRY_BLOCK:
index 3eb31bd0237ec82eef42a28755d3c3009c9ba117..e5079f99e0dcf637203c39fcab30555da83b61b2 100644 (file)
@@ -214,12 +214,6 @@ struct eh_status
   /* This is the region for which we are processing catch blocks.  */
   struct eh_region *try_region;
 
-  /* A stack (TREE_LIST) of lists of handlers.  The TREE_VALUE of each
-     node is itself a TREE_CHAINed list of handlers for regions that
-     are not yet closed. The TREE_VALUE of each entry contains the
-     handler for the corresponding entry on the ehstack.  */
-  tree protect_list;
-
   rtx filter;
   rtx exc_ptr;
 
@@ -560,7 +554,6 @@ mark_eh_status (eh)
     tree_done:;
     }
 
-  ggc_mark_tree (eh->protect_list);
   ggc_mark_rtx (eh->filter);
   ggc_mark_rtx (eh->exc_ptr);
   ggc_mark_tree_varray (eh->ttype_data);
@@ -1011,55 +1004,6 @@ get_exception_filter (fun)
     }
   return filter;
 }
-\f
-/* Begin a region that will contain entries created with
-   add_partial_entry.  */
-
-void
-begin_protect_partials ()
-{
-  /* Push room for a new list.  */
-  cfun->eh->protect_list
-    = tree_cons (NULL_TREE, NULL_TREE, cfun->eh->protect_list);
-}
-
-/* Start a new exception region for a region of code that has a
-   cleanup action and push the HANDLER for the region onto
-   protect_list. All of the regions created with add_partial_entry
-   will be ended when end_protect_partials is invoked.
-
-   ??? The only difference between this purpose and that of
-   expand_decl_cleanup is that in this case, we only want the cleanup to
-   run if an exception is thrown.  This should also be handled using
-   binding levels.  */
-
-void
-add_partial_entry (handler)
-     tree handler;
-{
-  expand_eh_region_start ();
-
-  /* Add this entry to the front of the list.  */
-  TREE_VALUE (cfun->eh->protect_list)
-    = tree_cons (NULL_TREE, handler, TREE_VALUE (cfun->eh->protect_list));
-}
-
-/* End all the pending exception regions on protect_list.  */
-
-void
-end_protect_partials ()
-{
-  tree t;
-
-  /* Pop the topmost entry.  */
-  t = TREE_VALUE (cfun->eh->protect_list);
-  cfun->eh->protect_list = TREE_CHAIN (cfun->eh->protect_list);
-
-  /* End all the exception regions.  */
-  for (; t; t = TREE_CHAIN (t))
-    expand_eh_region_end_cleanup (TREE_VALUE (t));
-}
-
 \f
 /* This section is for the exception handling specific optimization pass.  */
 
index 27dc7143f6c03c7cec31e99b3ad78bafd130d6e5..200210f31bc852392f93f2d17cc8553999b730ff 100644 (file)
@@ -83,20 +83,6 @@ extern void expand_eh_region_end_throw               PARAMS ((tree));
    destroying an object twice.  */
 extern void expand_eh_region_end_fixup         PARAMS ((tree));
 
-/* Begin a region that will contain entries created with
-   add_partial_entry.  */
-extern void begin_protect_partials              PARAMS ((void));
-
-/* Create a new exception region and add the handler for the region
-   onto a list. These regions will be ended (and their handlers emitted)
-   when end_protect_partials is invoked.  */
-extern void add_partial_entry                  PARAMS ((tree));
-
-/* End all of the pending exception regions that have handlers added with
-   add_partial_entry.  */
-extern void end_protect_partials               PARAMS ((void));
-
-
 /* A list of labels used for exception handlers.  */
 extern rtx exception_handler_labels;
 
index 6f1a0d62eef2f323d039968e4cf48a3dd2640e5f..066b454a735e19a452eadf04d7fc3fe12d5559be 100644 (file)
@@ -7209,7 +7209,8 @@ expand_expr (exp, target, tmode, modifier)
        {
          WITH_CLEANUP_EXPR_RTL (exp)
            = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
-         expand_decl_cleanup (NULL_TREE, TREE_OPERAND (exp, 1));
+         expand_decl_cleanup_eh (NULL_TREE, TREE_OPERAND (exp, 1),
+                                 CLEANUP_EH_ONLY (exp));
 
          /* That's it for this cleanup.  */
          TREE_OPERAND (exp, 1) = 0;
@@ -8422,7 +8423,7 @@ expand_expr (exp, target, tmode, modifier)
 
        store_expr (exp1, target, 0);
 
-       expand_decl_cleanup (NULL_TREE, cleanups);
+       expand_decl_cleanup_eh (NULL_TREE, cleanups, CLEANUP_EH_ONLY (exp));
 
        return target;
       }
index 9a72b8784f4662e3532bc9a2f43e7d0a4e7b1b07..2e8aeb628c67668ef44262a88a0368cea6783211 100644 (file)
@@ -4169,6 +4169,23 @@ expand_decl_cleanup (decl, cleanup)
     }
   return 1;
 }
+
+/* Like expand_decl_cleanup, but maybe only run the cleanup if an exception
+   is thrown.  */
+
+int
+expand_decl_cleanup_eh (decl, cleanup, eh_only)
+     tree decl, cleanup;
+     int eh_only;
+{
+  int ret = expand_decl_cleanup (decl, cleanup);
+  if (cleanup && ret)
+    {
+      tree node = block_stack->data.block.cleanups;
+      CLEANUP_EH_ONLY (node) = eh_only;
+    }
+  return ret;
+}
 \f
 /* DECL is an anonymous union.  CLEANUP is a cleanup for DECL.
    DECL_ELTS is the list of elements that belong to DECL's type.
@@ -4277,7 +4294,7 @@ expand_cleanups (list, dont_do, in_fixup, reachable)
            if (! in_fixup && using_eh_for_cleanups_p)
              expand_eh_region_end_cleanup (TREE_VALUE (tail));
 
-           if (reachable)
+           if (reachable && !CLEANUP_EH_ONLY (tail))
              {
                /* Cleanups may be run multiple times.  For example,
                   when exiting a binding contour, we expand the
diff --git a/gcc/testsuite/g++.dg/eh/nrv1.C b/gcc/testsuite/g++.dg/eh/nrv1.C
new file mode 100644 (file)
index 0000000..e2457e8
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/5636
+// Bug: the named return value optimization interfered with EH cleanups.
+
+int c, d;
+
+struct A
+{
+  A() { ++c; }
+  ~A() { ++d; }
+};
+
+A f()
+{
+  A nrv;
+  throw 42;
+  return nrv;
+}
+
+int main()
+{
+  try
+    { A a = f(); }
+  catch (...) { }
+  return (d < c);
+}
index ad24904f1d61d4171f523a577b163568bfa1dcd9..950463f637279cea0266ebc640885dad3951ecab 100644 (file)
@@ -177,6 +177,9 @@ struct tree_common
            INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST
        TREE_SYMBOL_REFERENCED in
            IDENTIFIER_NODE
+       CLEANUP_EH_ONLY in
+           TARGET_EXPR, WITH_CLEANUP_EXPR, CLEANUP_STMT,
+          TREE_LIST elements of a block's cleanup list.
 
    public_flag:
 
@@ -194,7 +197,7 @@ struct tree_common
        TREE_VIA_PRIVATE in
            TREE_LIST or TREE_VEC
        TREE_PRIVATE in
-           ??? unspecified nodes
+           ..._DECL
 
    protected_flag:
 
@@ -203,7 +206,7 @@ struct tree_common
           TREE_VEC
        TREE_PROTECTED in
            BLOCK
-          ??? unspecified nodes
+          ..._DECL
 
    side_effects_flag:
 
@@ -503,6 +506,11 @@ extern void tree_class_check_failed PARAMS ((const tree, int,
    In a CONSTRUCTOR, nonzero means allocate static storage.  */
 #define TREE_STATIC(NODE) ((NODE)->common.static_flag)
 
+/* In a TARGET_EXPR, WITH_CLEANUP_EXPR, CLEANUP_STMT, or element of a
+   block's cleanup list, means that the pertinent cleanup should only be
+   executed if an exception is thrown, not on normal exit of its scope.  */
+#define CLEANUP_EH_ONLY(NODE) ((NODE)->common.static_flag)
+
 /* In a CONVERT_EXPR, NOP_EXPR or COMPOUND_EXPR, this means the node was
    made implicitly and should not lead to an "unused value" warning.  */
 #define TREE_NO_UNUSED_WARNING(NODE) ((NODE)->common.static_flag)
@@ -2985,6 +2993,7 @@ extern void expand_elseif         PARAMS ((tree));
 extern void save_stack_pointer         PARAMS ((void));
 extern void expand_decl                        PARAMS ((tree));
 extern int expand_decl_cleanup         PARAMS ((tree, tree));
+extern int expand_decl_cleanup_eh      PARAMS ((tree, tree, int));
 extern void expand_anon_union_decl     PARAMS ((tree, tree, tree));
 extern void move_cleanups_up           PARAMS ((void));
 extern void expand_start_case_dummy    PARAMS ((void));