* call.c (extend_ref_init_temps): Fix TARGET_EXPR handling.
authorJason Merrill <jason@redhat.com>
Wed, 5 Oct 2016 22:57:58 +0000 (18:57 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 5 Oct 2016 22:57:58 +0000 (18:57 -0400)
From-SVN: r240818

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/g++.dg/cpp1z/elide2.C [new file with mode: 0644]

index e95faf65e92168fbb0922d5c63c9a1454092888b..f8752a6911c3556b3575ec0ee37a57f62839798d 100644 (file)
@@ -1,5 +1,7 @@
 2016-10-05  Jason Merrill  <jason@redhat.com>
 
+       * call.c (extend_ref_init_temps): Fix TARGET_EXPR handling.
+
        * parser.c (cp_parser_skip_to_end_of_statement): Add missing break.
 
        * semantics.c (finish_compound_literal): Handle class placeholder.
index 0914ae2a0f36f5a8fc3596e66af0b37019bb396f..c33341813cf23e69449f923eca5c238a87eecfa2 100644 (file)
@@ -10172,28 +10172,31 @@ extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups)
     return init;
   if (TREE_CODE (type) == REFERENCE_TYPE)
     init = extend_ref_init_temps_1 (decl, init, cleanups);
-  else if (is_std_init_list (type))
+  else
     {
-      /* The temporary array underlying a std::initializer_list
-        is handled like a reference temporary.  */
       tree ctor = init;
       if (TREE_CODE (ctor) == TARGET_EXPR)
        ctor = TARGET_EXPR_INITIAL (ctor);
       if (TREE_CODE (ctor) == CONSTRUCTOR)
        {
-         tree array = CONSTRUCTOR_ELT (ctor, 0)->value;
-         array = extend_ref_init_temps_1 (decl, array, cleanups);
-         CONSTRUCTOR_ELT (ctor, 0)->value = array;
+         if (is_std_init_list (type))
+           {
+             /* The temporary array underlying a std::initializer_list
+                is handled like a reference temporary.  */
+             tree array = CONSTRUCTOR_ELT (ctor, 0)->value;
+             array = extend_ref_init_temps_1 (decl, array, cleanups);
+             CONSTRUCTOR_ELT (ctor, 0)->value = array;
+           }
+         else
+           {
+             unsigned i;
+             constructor_elt *p;
+             vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
+             FOR_EACH_VEC_SAFE_ELT (elts, i, p)
+               p->value = extend_ref_init_temps (decl, p->value, cleanups);
+           }
        }
     }
-  else if (TREE_CODE (init) == CONSTRUCTOR)
-    {
-      unsigned i;
-      constructor_elt *p;
-      vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (init);
-      FOR_EACH_VEC_SAFE_ELT (elts, i, p)
-       p->value = extend_ref_init_temps (decl, p->value, cleanups);
-    }
 
   return init;
 }
diff --git a/gcc/testsuite/g++.dg/cpp1z/elide2.C b/gcc/testsuite/g++.dg/cpp1z/elide2.C
new file mode 100644 (file)
index 0000000..277decf
--- /dev/null
@@ -0,0 +1,25 @@
+// DR 1697
+// { dg-do run { target c++11 } }
+
+#define assert(X) do { if (!(X)) __builtin_abort(); } while(0)
+
+int i;
+struct S {
+  ~S() { assert (i++ == 2); }
+};
+struct X {
+  X() { assert (i++ == 0); }
+  X(const X&);
+};
+struct T {
+  S &&s;
+  X x;
+};
+void f() { assert (i++ == 1); }
+int main() {
+  {
+    T t = T{ {}, {} };
+    f();
+  }
+  assert (i == 3);
+}