]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/66501 (Default move assignment does not move array members)
authorJason Merrill <jason@redhat.com>
Wed, 24 Jun 2015 15:41:52 +0000 (11:41 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 24 Jun 2015 15:41:52 +0000 (11:41 -0400)
PR c++/66501
* init.c (vec_copy_assign_is_trivial): New.
(build_vec_init): Use it.

From-SVN: r224906

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/g++.dg/cpp0x/rv-array1.C [new file with mode: 0644]

index 94ab7dd88a5efda642746164e02014653c76507b..0886fa79d136695b36f07a3871576a832308142e 100644 (file)
@@ -1,3 +1,9 @@
+2015-06-24  Jason Merrill  <jason@redhat.com>
+
+       PR c++/66501
+       * init.c (vec_copy_assign_is_trivial): New.
+       (build_vec_init): Use it.
+
 2015-06-23  Jason Merrill  <jason@redhat.com>
 
        PR c++/65879
index 5cb7fc4e0f3d7e83bb029dd0c28cfa8890bfe08e..09a897f0ef8d8f865c112ee9abb6dbaa726aaddc 100644 (file)
@@ -3379,6 +3379,21 @@ get_temp_regvar (tree type, tree init)
   return decl;
 }
 
+/* Subroutine of build_vec_init.  Returns true if assigning to an array of
+   INNER_ELT_TYPE from INIT is trivial.  */
+
+static bool
+vec_copy_assign_is_trivial (tree inner_elt_type, tree init)
+{
+  if (!CLASS_TYPE_P (inner_elt_type))
+    return true;
+  if (cxx_dialect >= cxx11
+      && !real_lvalue_p (init)
+      && type_has_move_assign (inner_elt_type))
+    return !TYPE_HAS_COMPLEX_MOVE_ASSIGN (inner_elt_type);
+  return TYPE_HAS_TRIVIAL_COPY_ASSIGN (inner_elt_type);
+}
+
 /* `build_vec_init' returns tree structure that performs
    initialization of a vector of aggregate types.
 
@@ -3460,8 +3475,7 @@ build_vec_init (tree base, tree maxindex, tree init,
       && TREE_CODE (atype) == ARRAY_TYPE
       && TREE_CONSTANT (maxindex)
       && (from_array == 2
-         ? (!CLASS_TYPE_P (inner_elt_type)
-            || !TYPE_HAS_COMPLEX_COPY_ASSIGN (inner_elt_type))
+         ? vec_copy_assign_is_trivial (inner_elt_type, init)
          : !TYPE_NEEDS_CONSTRUCTING (type))
       && ((TREE_CODE (init) == CONSTRUCTOR
           /* Don't do this if the CONSTRUCTOR might contain something
diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-array1.C b/gcc/testsuite/g++.dg/cpp0x/rv-array1.C
new file mode 100644 (file)
index 0000000..9075764
--- /dev/null
@@ -0,0 +1,55 @@
+// PR c++/66501
+// { dg-do run { target c++11 } }
+
+int total_size;
+
+struct Object
+{
+  int size = 0;
+
+  Object () = default;
+
+  ~Object () {
+    total_size -= size;
+  }
+
+  Object (const Object &) = delete;
+  Object & operator= (const Object &) = delete;
+
+  Object (Object && b) {
+    size = b.size;
+    b.size = 0;
+  }
+
+  Object & operator= (Object && b) {
+    if (this != & b) {
+      total_size -= size;
+      size = b.size;
+      b.size = 0;
+    }
+    return * this;
+  }
+
+  void grow () {
+    size ++;
+    total_size ++;
+  }
+};
+
+struct Container {
+  Object objects[2];
+};
+
+int main (void)
+{
+  Container container;
+
+  // grow some objects in the container
+  for (auto & object : container.objects)
+    object.grow ();
+
+  // now empty it
+  container = Container ();
+
+  return total_size;
+}