diff options
5 files changed, 167 insertions, 3 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 6c5964a..50b1626 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2015-05-20 Jonathan Wakely <jwakely@redhat.com> + + PR libstdc++/66078 + * include/bits/stl_iterator.h (__make_move_if_noexcept_iterator): Add + overload for pointers. + * testsuite/20_util/specialized_algorithms/uninitialized_copy/ + 808590.cc: Add -std=gnu++03 switch. + * testsuite/20_util/specialized_algorithms/uninitialized_copy/ + 808590-cxx11.cc: Copy of 808590.cc to test with -std=gnu++11. + * testsuite/23_containers/vector/modifiers/push_back/ + strong_guarantee.cc: New. + 2015-05-19 Jonathan Wakely <jwakely@redhat.com> * include/bits/stl_list.h (_M_resize_pos(size_type&)): Declare. diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index d4ea657..b8e79df 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1194,6 +1194,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __make_move_if_noexcept_iterator(_Iterator __i) { return _ReturnType(__i); } + // Overload for pointers that matches std::move_if_noexcept more closely, + // returning a constant iterator when we don't want to move. + template<typename _Tp, typename _ReturnType + = typename conditional<__move_if_noexcept_cond<_Tp>::value, + const _Tp*, move_iterator<_Tp*>>::type> + inline _ReturnType + __make_move_if_noexcept_iterator(_Tp* __i) + { return _ReturnType(__i); } + // @} group iterators template<typename _Iterator> diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/808590-cxx11.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/808590-cxx11.cc new file mode 100644 index 0000000..9597a7b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/808590-cxx11.cc @@ -0,0 +1,53 @@ +// Copyright (C) 2012-2015 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-options "-std=gnu++11" } + +// This is identical to ./808590.cc but using -std=gnu++11 +// See https://gcc.gnu.org/ml/libstdc++/2014-05/msg00027.html + +#include <vector> +#include <stdexcept> + +// 4.4.x only +struct c +{ + void *m; + + c(void* o = 0) : m(o) {} + c(const c &r) : m(r.m) {} + + template<class T> + explicit c(T &o) : m((void*)0xdeadbeef) { } +}; + +int main() +{ + std::vector<c> cbs; + const c cb((void*)0xcafebabe); + + for (int fd = 62; fd < 67; ++fd) + { + cbs.resize(fd + 1); + cbs[fd] = cb; + } + + for (int fd = 62; fd< 67; ++fd) + if (cb.m != cbs[fd].m) + throw std::runtime_error("wrong"); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/808590.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/808590.cc index 53b2d6d..7d20f85 100644 --- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/808590.cc +++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/808590.cc @@ -15,11 +15,13 @@ // with this library; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. +// { dg-options "-std=gnu++03" } + #include <vector> #include <stdexcept> // 4.4.x only -struct c +struct c { void *m; @@ -30,12 +32,12 @@ struct c explicit c(T &o) : m((void*)0xdeadbeef) { } }; -int main() +int main() { std::vector<c> cbs; const c cb((void*)0xcafebabe); - for (int fd = 62; fd < 67; ++fd) + for (int fd = 62; fd < 67; ++fd) { cbs.resize(fd + 1); cbs[fd] = cb; diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/strong_guarantee.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/strong_guarantee.cc new file mode 100644 index 0000000..461f6ea --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/push_back/strong_guarantee.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2015 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-options "-std=gnu++11" } + +#include <vector> +#include <testsuite_hooks.h> + +template<typename T> +void check(const T& t) +{ + for (auto& e : t) + VERIFY( !e.moved_from); +} + +// This type is CopyInsertable into std::vector<Bomb> so push_back should +// have the strong exception-safety guarantee. +struct Bomb +{ + Bomb() = default; + + Bomb(const Bomb& b) + : armed(b.armed) + { + tick(); + } + + Bomb(Bomb&& b) noexcept(false) + : armed(b.armed) + { + tick(); + b.moved_from = true; + } + + // std::vector in GCC 4.x tries to use this constructor + template<typename T> Bomb(T&) = delete; + + bool moved_from = false; + bool armed = true; + +private: + void tick() + { + if (armed && ticks++) + throw 1; + } + + static int ticks; +}; + +int Bomb::ticks = 0; + +void test01() +{ + std::vector<Bomb> v(2); // fill with armed bombs + v.resize(v.capacity()); // ensure no unused capacity + check(v); // sanity check + + try { + Bomb defused; + // don't want any copies/moves of this object to throw + defused.armed = false; + // insert new element, existing elements will be relocated and explode + v.push_back(defused); + VERIFY(false); // should be unreachable + } catch (int) { + check(v); // make sure no elements have been moved from + } +} + +int main() +{ + test01(); +} |