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]

[patch] libstdc++/66078 __make_move_if_noexcept_iterator should return a constant iterator or a move iterator


As discussed in the thread starting at
https://gcc.gnu.org/ml/libstdc++/2014-05/msg00027.html when
__make_move_if_noexcept_iterator decides not to move it returns a
mutable iterator, which can then result in the wrong constructor being
used. This ensures that when not moving we will get a pointer-to-const
which will result in the copy constructor being called.

Tested powerpc64-linux, committed to trunk.
commit 7dc39df13857920ecbb3da1336c2469fdfb30e42
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri May 9 13:51:39 2014 +0100

    	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.

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();
+}

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