This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++0x PATCH for c++/46103 (wrong implicit move of class with array member)


When doing a piecewise move of an array member, we need to preserve the xvalueness of the initializer; this was broken because we take the address and then dereference the resulting pointer, which produces an lvalue. It would probably be better to avoid that and just use an ARRAY_REF rather than a pointer, but fixing the current strategy was pretty trivial.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit b517d58d38264bb3c6deec5fd4dc31884b178f39
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Oct 22 09:57:27 2010 -0400

    	PR c++/46103
    	* init.c (build_vec_init): Handle memberwise move.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 5091d4e..72fcf78 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2849,6 +2849,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   tree try_block = NULL_TREE;
   int num_initialized_elts = 0;
   bool is_global;
+  bool xvalue = false;
 
   if (TREE_CODE (atype) == ARRAY_TYPE && TYPE_DOMAIN (atype))
     maxindex = array_type_nelts (atype);
@@ -2939,6 +2940,8 @@ build_vec_init (tree base, tree maxindex, tree init,
      checking.  Evaluate the initializer before entering the try block.  */
   if (from_array && init && TREE_CODE (init) != CONSTRUCTOR)
     {
+      if (lvalue_kind (init) & clk_rvalueref)
+	xvalue = true;
       base2 = decay_conversion (init);
       itype = TREE_TYPE (base2);
       base2 = get_temp_regvar (itype, base2);
@@ -3033,7 +3036,11 @@ build_vec_init (tree base, tree maxindex, tree init,
 	  tree from;
 
 	  if (base2)
-	    from = build1 (INDIRECT_REF, itype, base2);
+	    {
+	      from = build1 (INDIRECT_REF, itype, base2);
+	      if (xvalue)
+		from = move (from);
+	    }
 	  else
 	    from = NULL_TREE;
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit10.C b/gcc/testsuite/g++.dg/cpp0x/implicit10.C
new file mode 100644
index 0000000..721a93d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit10.C
@@ -0,0 +1,19 @@
+// PR c++/46103
+// { dg-options -std=c++0x }
+
+struct MoveOnly {
+  MoveOnly(const MoveOnly&) = delete;
+  MoveOnly(MoveOnly&&) { }
+  MoveOnly() = default;
+};
+
+struct A {
+  MoveOnly mo[1];
+  A() = default;
+  A(A&&) = default;
+};
+
+int main() {
+  A a;
+  A aa = static_cast<A&&>(a);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]