OSDN Git Service

PR libstdc++/52591
authorredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 Apr 2012 21:13:45 +0000 (21:13 +0000)
committerredi <redi@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 Apr 2012 21:13:45 +0000 (21:13 +0000)
* include/bits/stl_vector.h (vector::operator=(vector&&)): Dispatch
to _M_move_assign depending on whether allocator is moved.
(vector::_M_move_assign): Add overloaded functions.
* testsuite/23_containers/vector/52591.cc: New.
* testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
Adjust dg-error line number.
* testsuite/23_containers/vector/requirements/dr438/
        constructor_1_neg.cc: Likewise.
* testsuite/23_containers/vector/requirements/dr438/
        constructor_2_neg.cc: Likewise.
* testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@186359 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_vector.h
libstdc++-v3/testsuite/23_containers/vector/52591.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/assign_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc
libstdc++-v3/testsuite/23_containers/vector/requirements/dr438/insert_neg.cc

index 2811abf..8e9dcd2 100644 (file)
@@ -1,3 +1,19 @@
+2012-04-11  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       PR libstdc++/52591
+       * include/bits/stl_vector.h (vector::operator=(vector&&)): Dispatch
+       to _M_move_assign depending on whether allocator is moved.
+       (vector::_M_move_assign): Add overloaded functions.
+       * testsuite/23_containers/vector/52591.cc: New.
+       * testsuite/23_containers/vector/requirements/dr438/assign_neg.cc:
+       Adjust dg-error line number.
+       * testsuite/23_containers/vector/requirements/dr438/constructor_1_neg.cc:
+       Likewise.
+       * testsuite/23_containers/vector/requirements/dr438/constructor_2_neg.cc:
+       Likewise.
+       * testsuite/23_containers/vector/requirements/dr438/insert_neg.cc:
+       Likewise.
+
 2012-04-09  Fran├žois Dumont  <fdumont@gcc.gnu.org>
 
        PR libstdc++/52476
index ec21807..c4c707c 100644 (file)
@@ -419,36 +419,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        *  @brief  %Vector move assignment operator.
        *  @param  __x  A %vector of identical element and allocator types.
        *
-       *  The contents of @a __x are moved into this %vector (without copying).
+       *  The contents of @a __x are moved into this %vector (without copying,
+       *  if the allocators permit it).
        *  @a __x is a valid, but unspecified %vector.
        */
       vector&
       operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move())
       {
-       if (_Alloc_traits::_S_propagate_on_move_assign())
-         {
-           // We're moving the rvalue's allocator so can move the data too.
-           const vector __tmp(std::move(*this));     // discard existing data
-           this->_M_impl._M_swap_data(__x._M_impl);
-           std::__alloc_on_move(_M_get_Tp_allocator(),
-                                __x._M_get_Tp_allocator());
-         }
-       else if (_Alloc_traits::_S_always_equal()
-                || __x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
-         {
-           // The rvalue's allocator can free our storage and vice versa,
-           // so can swap the data storage after destroying our contents.
-           this->clear();
-           this->_M_impl._M_swap_data(__x._M_impl);
-         }
-       else
-         {
-           // The rvalue's allocator cannot be moved, or is not equal,
-           // so we need to individually move each element.
-           this->assign(std::__make_move_if_noexcept_iterator(__x.begin()),
-                        std::__make_move_if_noexcept_iterator(__x.end()));
-           __x.clear();
-         }
+        constexpr bool __move_storage =
+          _Alloc_traits::_S_propagate_on_move_assign()
+          || _Alloc_traits::_S_always_equal();
+        _M_move_assign(std::move(__x),
+                       integral_constant<bool, __move_storage>());
        return *this;
       }
 
@@ -1337,6 +1319,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
        std::_Destroy(__pos, this->_M_impl._M_finish, _M_get_Tp_allocator());
        this->_M_impl._M_finish = __pos;
       }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+    private:
+      // Constant-time move assignment when source object's memory can be
+      // moved, either because the source's allocator will move too
+      // or because the allocators are equal.
+      void
+      _M_move_assign(vector&& __x, std::true_type) noexcept
+      {
+       const vector __tmp(std::move(*this));
+       this->_M_impl._M_swap_data(__x._M_impl);
+       if (_Alloc_traits::_S_propagate_on_move_assign())
+         std::__alloc_on_move(_M_get_Tp_allocator(),
+                              __x._M_get_Tp_allocator());
+      }
+
+      // Do move assignment when it might not be possible to move source
+      // object's memory, resulting in a linear-time operation.
+      void
+      _M_move_assign(vector&& __x, std::false_type)
+      {
+       if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator())
+         _M_move_assign(std::move(__x), std::true_type());
+       else
+         {
+           // The rvalue's allocator cannot be moved and is not equal,
+           // so we need to individually move each element.
+           this->assign(std::__make_move_if_noexcept_iterator(__x.begin()),
+                        std::__make_move_if_noexcept_iterator(__x.end()));
+           __x.clear();
+         }
+      }
+#endif
     };
 
 
diff --git a/libstdc++-v3/testsuite/23_containers/vector/52591.cc b/libstdc++-v3/testsuite/23_containers/vector/52591.cc
new file mode 100644 (file)
index 0000000..c018c72
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (C) 2012 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// libstdc++/52591
+
+#include <vector>
+
+// As an extension we allow move-assignment of std::vector when the element
+// type is not MoveAssignable, as long as the allocator type propagates or
+// is known to always compare equal.
+
+struct C
+{
+    C& operator=(C&&) = delete;
+};
+
+void test01()
+{
+    std::vector<C> a;
+    a = std::vector<C>();
+}
index 1855fdd..1aebaa2 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1225 }
+// { dg-error "no matching" "" { target *-*-* } 1207 }
 
 #include <vector>
 
index 9c05486..0d35bbf 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1155 }
+// { dg-error "no matching" "" { target *-*-* } 1137 }
 
 #include <vector>
 
index 152393c..cb96ece 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1155 }
+// { dg-error "no matching" "" { target *-*-* } 1137 }
 
 #include <vector>
 #include <utility>
index f44ae63..c88b763 100644 (file)
@@ -18,7 +18,7 @@
 // <http://www.gnu.org/licenses/>.
 
 // { dg-do compile }
-// { dg-error "no matching" "" { target *-*-* } 1266 }
+// { dg-error "no matching" "" { target *-*-* } 1248 }
 
 #include <vector>