From: Jason Merrill Date: Wed, 24 Jun 2015 15:41:52 +0000 (-0400) Subject: re PR c++/66501 (Default move assignment does not move array members) X-Git-Tag: releases/gcc-4.9.3~53 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1218e81ebb678ec27236a4266d17422d687471a5;p=thirdparty%2Fgcc.git re PR c++/66501 (Default move assignment does not move array members) PR c++/66501 * init.c (vec_copy_assign_is_trivial): New. (build_vec_init): Use it. From-SVN: r224906 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 94ab7dd88a5e..0886fa79d136 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2015-06-24 Jason Merrill + + PR c++/66501 + * init.c (vec_copy_assign_is_trivial): New. + (build_vec_init): Use it. + 2015-06-23 Jason Merrill PR c++/65879 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 5cb7fc4e0f3d..09a897f0ef8d 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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 index 000000000000..907576484721 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/rv-array1.C @@ -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; +}