re PR c++/57510 (subobjects not destroyed when exception thrown during list-initializ...
authorJason Merrill <jason@redhat.com>
Fri, 12 Dec 2014 03:48:55 +0000 (22:48 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 12 Dec 2014 03:48:55 +0000 (22:48 -0500)
PR c++/57510
* typeck2.c (split_nonconstant_init_1): Handle arrays here.
(store_init_value): Not here.
(split_nonconstant_init): Look through TARGET_EXPR.  No longer static.
* cp-tree.h: Declare split_nonconstant_init.
* call.c (set_up_extended_ref_temp): Use split_nonconstant_init.

From-SVN: r218653

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/typeck2.c
gcc/testsuite/g++.dg/cpp0x/initlist90.C [new file with mode: 0644]

index 0442ef3a8c79a7f03395afed04383e01a46e802c..be8f3a00cdeb3bf3dfb46847fb1bf85e579fd26f 100644 (file)
@@ -1,3 +1,12 @@
+2014-12-11  Jason Merrill  <jason@redhat.com>
+
+       PR c++/57510
+       * typeck2.c (split_nonconstant_init_1): Handle arrays here.
+       (store_init_value): Not here.
+       (split_nonconstant_init): Look through TARGET_EXPR.  No longer static.
+       * cp-tree.h: Declare split_nonconstant_init.
+       * call.c (set_up_extended_ref_temp): Use split_nonconstant_init.
+
 2014-12-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * typeck.c (maybe_warn_about_useless_cast): Remove unnecessary
index d8075bd97ea72d15466d7da3a86501da9d3761a4..312dfdf242101a2434caa68d443ace2dd23949f7 100644 (file)
@@ -9574,7 +9574,7 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups,
   else
     /* Create the INIT_EXPR that will initialize the temporary
        variable.  */
-    init = build2 (INIT_EXPR, type, var, expr);
+    init = split_nonconstant_init (var, expr);
   if (at_function_scope_p ())
     {
       add_decl_expr (var);
index d41a834ac0a9d8501c5622bf3425ed70a7e54846..ad1cc71162ff02a9ca6a783325f7398f6f782da2 100644 (file)
@@ -6291,6 +6291,7 @@ extern int abstract_virtuals_error_sfinae (tree, tree, tsubst_flags_t);
 extern int abstract_virtuals_error_sfinae      (abstract_class_use, tree, tsubst_flags_t);
 
 extern tree store_init_value                   (tree, tree, vec<tree, va_gc>**, int);
+extern tree split_nonconstant_init             (tree, tree);
 extern bool check_narrowing                    (tree, tree, tsubst_flags_t);
 extern tree digest_init                                (tree, tree, tsubst_flags_t);
 extern tree digest_init_flags                  (tree, tree, int);
index 92c04178c213f694170462b958e4453afb0ddb91..c53a9b529236e917693c4871778be4c61d9d6e55 100644 (file)
@@ -604,6 +604,17 @@ split_nonconstant_init_1 (tree dest, tree init)
     case ARRAY_TYPE:
       inner_type = TREE_TYPE (type);
       array_type_p = true;
+      if ((TREE_SIDE_EFFECTS (init)
+          && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
+         || array_of_runtime_bound_p (type))
+       {
+         /* For an array, we only need/want a single cleanup region rather
+            than one per element.  */
+         tree code = build_vec_init (dest, NULL_TREE, init, false, 1,
+                                     tf_warning_or_error);
+         add_stmt (code);
+         return true;
+       }
       /* FALLTHRU */
 
     case RECORD_TYPE:
@@ -721,11 +732,13 @@ split_nonconstant_init_1 (tree dest, tree init)
    perform the non-constant part of the initialization to DEST.
    Returns the code for the runtime init.  */
 
-static tree
+tree
 split_nonconstant_init (tree dest, tree init)
 {
   tree code;
 
+  if (TREE_CODE (init) == TARGET_EXPR)
+    init = TARGET_EXPR_INITIAL (init);
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
       code = push_stmt_list ();
@@ -830,17 +843,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
       && (TREE_SIDE_EFFECTS (value)
          || array_of_runtime_bound_p (type)
          || ! reduced_constant_expression_p (value)))
-    {
-      if (TREE_CODE (type) == ARRAY_TYPE
-         && (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type))
-             || array_of_runtime_bound_p (type)))
-       /* For an array, we only need/want a single cleanup region rather
-          than one per element.  */
-       return build_vec_init (decl, NULL_TREE, value, false, 1,
-                              tf_warning_or_error);
-      else
-       return split_nonconstant_init (decl, value);
-    }
+    return split_nonconstant_init (decl, value);
   /* If the value is a constant, just put it in DECL_INITIAL.  If DECL
      is an automatic variable, the middle end will turn this into a
      dynamic initialization later.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist90.C b/gcc/testsuite/g++.dg/cpp0x/initlist90.C
new file mode 100644 (file)
index 0000000..330517a
--- /dev/null
@@ -0,0 +1,35 @@
+// PR c++/57510
+// { dg-do run { target c++11 } }
+
+#include <initializer_list>
+
+struct counter
+{
+  static int n;
+
+  counter() { ++n; }
+  counter(const counter&) { ++n; }
+  ~counter() { --n; }
+};
+
+int counter::n = 0;
+
+struct X
+{
+    X () { if (counter::n > 1) throw 1; }
+
+    counter c;
+};
+
+int main ()
+{
+  try
+  {
+    auto x = { X{}, X{} };
+  }
+  catch (...)
+  {
+    if ( counter::n != 0 )
+      throw;
+  }
+}