libstdc++: Implement N3644 for _GLIBCXX_DEBUG iterators
authorFrançois Dumont <fdumont@gcc.gnu.org>
Fri, 1 Jan 2021 16:35:56 +0000 (17:35 +0100)
committerFrançois Dumont <fdumont@gcc.gnu.org>
Thu, 14 Jan 2021 18:23:54 +0000 (19:23 +0100)
libstdc++-v3/ChangeLog:

PR libstdc++/98466
* include/bits/hashtable_policy.h (_Node_iterator_base()): Set _M_cur to nullptr.
(_Node_iterator()): Make default.
(_Node_const_iterator()): Make default.
* include/debug/macros.h (__glibcxx_check_erae_range_after): Add _M_singular
iterator checks.
* include/debug/safe_iterator.h
(_GLIBCXX_DEBUG_VERIFY_OPERANDS): Accept if both iterator are value initialized.
* include/debug/safe_local_iterator.h (_GLIBCXX_DEBUG_VERIFY_OPERANDS):
Likewise.
* include/debug/safe_iterator.tcc (_Safe_iterator<>::_M_valid_range): Add
_M_singular checks on input iterators.
* src/c++11/debug.cc (_Safe_iterator_base::_M_can_compare): Remove _M_singular
checks.
* testsuite/23_containers/deque/debug/98466.cc: New test.
* testsuite/23_containers/unordered_map/debug/98466.cc: New test.

libstdc++-v3/include/bits/hashtable_policy.h
libstdc++-v3/include/debug/macros.h
libstdc++-v3/include/debug/safe_iterator.h
libstdc++-v3/include/debug/safe_iterator.tcc
libstdc++-v3/include/debug/safe_local_iterator.h
libstdc++-v3/src/c++11/debug.cc
libstdc++-v3/testsuite/23_containers/deque/debug/98466.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_map/debug/98466.cc [new file with mode: 0644]

index 84961849fb45185592445aa7198c1d0e17180c69..999147a68d4eed67b22b6f28cc4133f2edc1eaa4 100644 (file)
@@ -290,7 +290,7 @@ namespace __detail
 
       __node_type* _M_cur;
 
-      _Node_iterator_base() = default;
+      _Node_iterator_base() : _M_cur(nullptr) { }
       _Node_iterator_base(__node_type* __p) noexcept
       : _M_cur(__p) { }
 
@@ -331,8 +331,7 @@ namespace __detail
       using reference = typename std::conditional<__constant_iterators,
                                  const value_type&, value_type&>::type;
 
-      _Node_iterator() noexcept
-      : __base_type(nullptr) { }
+      _Node_iterator() = default;
 
       explicit
       _Node_iterator(__node_type* __p) noexcept
@@ -379,8 +378,7 @@ namespace __detail
       typedef const value_type*                                pointer;
       typedef const value_type&                                reference;
 
-      _Node_const_iterator() noexcept
-      : __base_type(nullptr) { }
+      _Node_const_iterator() = default;
 
       explicit
       _Node_const_iterator(__node_type* __p) noexcept
index 08c49eca55466c161703475724f413ccb914f1a1..0988437046f640ae5d8932107b0b69ff7bbef939 100644 (file)
@@ -244,6 +244,11 @@ _GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this),                 \
  *  valid iterator range within this sequence.
 */
 #define __glibcxx_check_erase_range_after(_First,_Last)                        \
+_GLIBCXX_DEBUG_VERIFY(!_First._M_singular() && !_Last._M_singular(),   \
+                     _M_message(__gnu_debug::__msg_erase_different)    \
+                     ._M_sequence(*this, "this")                       \
+                     ._M_iterator(_First, #_First)                     \
+                     ._M_iterator(_Last, #_Last));                     \
 _GLIBCXX_DEBUG_VERIFY(_First._M_can_compare(_Last),                    \
                      _M_message(__gnu_debug::__msg_erase_different)    \
                      ._M_sequence(*this, "this")                       \
index 11e0f0b14a3000978fd9edbfa91b1017a8225d00..a10df190969ff2de93a567b057358956a8fafb8c 100644 (file)
@@ -40,7 +40,9 @@
 #endif
 
 #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs, _BadMsgId, _DiffMsgId) \
-  _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular(),    \
+  _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular()     \
+                       || (_Lhs.base() == _Iterator()                  \
+                           && _Rhs.base() == _Iterator()),             \
                        _M_message(_BadMsgId)                           \
                        ._M_iterator(_Lhs, #_Lhs)                       \
                        ._M_iterator(_Rhs, #_Rhs));                     \
index 7d6f91782d55bf97011502f910c3181ed6a989ec..81deb10125b81df197f94b45c9749dec2b92fe79 100644 (file)
@@ -186,7 +186,7 @@ namespace __gnu_debug
                   std::pair<difference_type, _Distance_precision>& __dist,
                   bool __check_dereferenceable) const
     {
-      if (!_M_can_compare(__rhs))
+      if (_M_singular() || __rhs._M_singular() || !_M_can_compare(__rhs))
        return false;
 
       /* Determine iterators order */
@@ -217,7 +217,8 @@ namespace __gnu_debug
                   std::pair<difference_type,
                             _Distance_precision>& __dist) const
     {
-      if (!this->_M_can_compare(__rhs))
+      if (this->_M_singular() || __rhs._M_singular()
+         || !this->_M_can_compare(__rhs))
        return false;
 
       /* Determine iterators order */
index 39bb9790e05a928e1f1c19b31541785d9adc0e17..31c48e65a249dc508b760100f382896169109aa4 100644 (file)
@@ -32,7 +32,9 @@
 #include <debug/safe_unordered_base.h>
 
 #define _GLIBCXX_DEBUG_VERIFY_OPERANDS(_Lhs, _Rhs) \
-  _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular(),    \
+  _GLIBCXX_DEBUG_VERIFY(!_Lhs._M_singular() && !_Rhs._M_singular()     \
+                       || (_Lhs.base() == _Iterator{}                  \
+                           && _Rhs.base() == _Iterator{}),             \
                        _M_message(__msg_iter_compare_bad)              \
                        ._M_iterator(_Lhs, "lhs")                       \
                        ._M_iterator(_Rhs, "rhs"));                     \
index 6cf99186a824a7d77df1bee43d718742af612056..5a642097d179cd1654a12ef5f907d3aae2cac960 100644 (file)
@@ -424,10 +424,7 @@ namespace __gnu_debug
   bool
   _Safe_iterator_base::
   _M_can_compare(const _Safe_iterator_base& __x) const throw ()
-  {
-    return (!_M_singular()
-           && !__x._M_singular() && _M_sequence == __x._M_sequence);
-  }
+  { return _M_sequence == __x._M_sequence; }
 
   __gnu_cxx::__mutex&
   _Safe_iterator_base::
diff --git a/libstdc++-v3/testsuite/23_containers/deque/debug/98466.cc b/libstdc++-v3/testsuite/23_containers/deque/debug/98466.cc
new file mode 100644 (file)
index 0000000..720977e
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright (C) 2021 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 <debug/deque>
+#include <testsuite_hooks.h>
+
+// PR libstdc++/98466
+
+void test01()
+{
+  __gnu_debug::deque<int>::iterator it{};
+  VERIFY( it == it );
+
+  __gnu_debug::deque<int>::const_iterator cit{};
+  VERIFY( cit == cit );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/debug/98466.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/debug/98466.cc
new file mode 100644 (file)
index 0000000..cc22b9f
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright (C) 2021 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 <debug/unordered_map>
+#include <testsuite_hooks.h>
+
+// PR libstdc++/98466
+
+void test01()
+{
+  __gnu_debug::unordered_map<int, int>::iterator it{};
+  VERIFY( it == it );
+
+  __gnu_debug::unordered_map<int, int>::const_iterator cit{};
+  VERIFY( cit == cit );
+
+  __gnu_debug::unordered_map<int, int>::local_iterator lit{};
+  VERIFY( lit == lit );
+
+  __gnu_debug::unordered_map<int, int>::const_local_iterator clit{};
+  VERIFY( clit == clit );
+}
+
+int main()
+{
+  test01();
+  return 0;
+}