aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-10-17 15:21:27 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2019-10-17 15:21:27 +0100
commit47519a5687d48af4b932d54b0525fafcdc0e48d6 (patch)
tree3613ae6f84da1b3ebd3fbbf1e137b4286ffb4dc1
parent58baf7ab85cbb1068a651c96f7d56e2902ead6cc (diff)
downloadgcc-47519a5687d48af4b932d54b0525fafcdc0e48d6.zip
gcc-47519a5687d48af4b932d54b0525fafcdc0e48d6.tar.gz
gcc-47519a5687d48af4b932d54b0525fafcdc0e48d6.tar.bz2
PR libstdc++/92124 fix incorrect container move assignment
The container requirements say that for move assignment "All existing elements of [the target] are either move assigned or destroyed". Some of our containers currently use __make_move_if_noexcept which makes the move depend on whether the element type is nothrow move constructible. This is incorrect, because the standard says we must move assign, not move or copy depending on the move constructor. Use make_move_iterator instead so that we move unconditionally. This ensures existing elements won't be copy assigned. PR libstdc++/92124 * include/bits/forward_list.h (_M_move_assign(forward_list&&, false_type)): Do not use __make_move_if_noexcept, instead move unconditionally. * include/bits/stl_deque.h (_M_move_assign2(deque&&, false_type)): Likewise. * include/bits/stl_list.h (_M_move_assign(list&&, false_type)): Likewise. * include/bits/stl_vector.h (_M_move_assign(vector&&, false_type)): Likewise. * testsuite/23_containers/vector/92124.cc: New test. From-SVN: r277113
-rw-r--r--libstdc++-v3/ChangeLog14
-rw-r--r--libstdc++-v3/include/bits/forward_list.h4
-rw-r--r--libstdc++-v3/include/bits/stl_deque.h4
-rw-r--r--libstdc++-v3/include/bits/stl_list.h4
-rw-r--r--libstdc++-v3/include/bits/stl_vector.h5
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/92124.cc49
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/92124.cc49
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/92124.cc49
-rw-r--r--libstdc++-v3/testsuite/23_containers/vector/92124.cc49
9 files changed, 219 insertions, 8 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index c95aa32..4c26879 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,17 @@
+2019-10-17 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/92124
+ * include/bits/forward_list.h
+ (_M_move_assign(forward_list&&, false_type)): Do not use
+ __make_move_if_noexcept, instead move unconditionally.
+ * include/bits/stl_deque.h (_M_move_assign2(deque&&, false_type)):
+ Likewise.
+ * include/bits/stl_list.h (_M_move_assign(list&&, false_type)):
+ Likewise.
+ * include/bits/stl_vector.h (_M_move_assign(vector&&, false_type)):
+ Likewise.
+ * testsuite/23_containers/vector/92124.cc: New test.
+
2019-10-16 Jonathan Wakely <jwakely@redhat.com>
* include/bits/c++config (_GLIBCXX_BUILTIN_IS_SAME_AS): Define to
diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index e686283..cab2ae7 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -1336,8 +1336,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
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(__list.begin()),
- std::__make_move_if_noexcept_iterator(__list.end()));
+ this->assign(std::make_move_iterator(__list.begin()),
+ std::make_move_iterator(__list.end()));
}
// Called by assign(_InputIterator, _InputIterator) if _Tp is
diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
index ac76d68..50491e7 100644
--- a/libstdc++-v3/include/bits/stl_deque.h
+++ b/libstdc++-v3/include/bits/stl_deque.h
@@ -2256,8 +2256,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
// The rvalue's allocator cannot be moved and is not equal,
// so we need to individually move each element.
- _M_assign_aux(std::__make_move_if_noexcept_iterator(__x.begin()),
- std::__make_move_if_noexcept_iterator(__x.end()),
+ _M_assign_aux(std::make_move_iterator(__x.begin()),
+ std::make_move_iterator(__x.end()),
std::random_access_iterator_tag());
__x.clear();
}
diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h
index 7019825..328a798 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -1957,8 +1957,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
else
// The rvalue's allocator cannot be moved, or is not equal,
// so we need to individually move each element.
- _M_assign_dispatch(std::__make_move_if_noexcept_iterator(__x.begin()),
- std::__make_move_if_noexcept_iterator(__x.end()),
+ _M_assign_dispatch(std::make_move_iterator(__x.begin()),
+ std::make_move_iterator(__x.end()),
__false_type{});
}
#endif
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index d33e589..ff08b26 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1828,8 +1828,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{
// 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()));
+ this->_M_assign_aux(std::make_move_iterator(__x.begin()),
+ std::make_move_iterator(__x.end()),
+ std::random_access_iterator_tag());
__x.clear();
}
}
diff --git a/libstdc++-v3/testsuite/23_containers/deque/92124.cc b/libstdc++-v3/testsuite/23_containers/deque/92124.cc
new file mode 100644
index 0000000..6f8cf55
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/deque/92124.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2019 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 run { target c++11 } }
+
+#include <deque>
+#include <testsuite_allocator.h>
+
+struct X {
+ X() = default;
+ X(const X&) = default;
+
+ // Move constructor might throw
+ X(X&&) noexcept(false) {}
+
+ // Tracking calls to assignment functions
+ X& operator=(const X&) { throw 1; }
+
+ X& operator=(X&&) noexcept(true) { return *this; }
+};
+
+void
+test01()
+{
+ using A = __gnu_test::propagating_allocator<X, false>;
+ A a1(1), a2(2);
+ std::deque<X, A> v1(1, a1), v2(1, a2);
+ v1 = std::move(v2);
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/92124.cc b/libstdc++-v3/testsuite/23_containers/forward_list/92124.cc
new file mode 100644
index 0000000..52a2807
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/92124.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2019 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 run { target c++11 } }
+
+#include <forward_list>
+#include <testsuite_allocator.h>
+
+struct X {
+ X() = default;
+ X(const X&) = default;
+
+ // Move constructor might throw
+ X(X&&) noexcept(false) {}
+
+ // Tracking calls to assignment functions
+ X& operator=(const X&) { throw 1; }
+
+ X& operator=(X&&) noexcept(true) { return *this; }
+};
+
+void
+test01()
+{
+ using A = __gnu_test::propagating_allocator<X, false>;
+ A a1(1), a2(2);
+ std::forward_list<X, A> v1(1, a1), v2(1, a2);
+ v1 = std::move(v2);
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/list/92124.cc b/libstdc++-v3/testsuite/23_containers/list/92124.cc
new file mode 100644
index 0000000..117cb71
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/list/92124.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2019 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 run { target c++11 } }
+
+#include <list>
+#include <testsuite_allocator.h>
+
+struct X {
+ X() = default;
+ X(const X&) = default;
+
+ // Move constructor might throw
+ X(X&&) noexcept(false) {}
+
+ // Tracking calls to assignment functions
+ X& operator=(const X&) { throw 1; }
+
+ X& operator=(X&&) noexcept(true) { return *this; }
+};
+
+void
+test01()
+{
+ using A = __gnu_test::propagating_allocator<X, false>;
+ A a1(1), a2(2);
+ std::list<X, A> v1(1, a1), v2(1, a2);
+ v1 = std::move(v2);
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/92124.cc b/libstdc++-v3/testsuite/23_containers/vector/92124.cc
new file mode 100644
index 0000000..3cb487d
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/92124.cc
@@ -0,0 +1,49 @@
+// Copyright (C) 2019 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 run { target c++11 } }
+
+#include <vector>
+#include <testsuite_allocator.h>
+
+struct X {
+ X() = default;
+ X(const X&) = default;
+
+ // Move constructor might throw
+ X(X&&) noexcept(false) {}
+
+ // Tracking calls to assignment functions
+ X& operator=(const X&) { throw 1; }
+
+ X& operator=(X&&) noexcept(true) { return *this; }
+};
+
+void
+test01()
+{
+ using A = __gnu_test::propagating_allocator<X, false>;
+ A a1(1), a2(2);
+ std::vector<X, A> v1(1, a1), v2(1, a2);
+ v1 = std::move(v2);
+}
+
+int
+main()
+{
+ test01();
+}