[PATCH][Bug libstdc++/70303] Value-initialized debug iterators

Jonathan Wakely jwakely@redhat.com
Mon Feb 1 17:43:22 GMT 2021


On 31/01/21 16:59 +0100, François Dumont via Libstdc++ wrote:
>After the debug issue has been fixed in PR 98466 the problem was not 
>in the debug iterator implementation itself but in the deque iterator 
>operator- implementation.
>
>    libstdc++: Make deque iterator operator- usable with value-init 
>iterators
>
>    N3644 implies that operator- can be used on value-init iterators. 
>We now return
>    0 if both iterators are value initialized. If only one is value 
>initialized we
>    keep the UB by returning the result of a normal computation which 
>is an unexpected
>    value.
>
>    libstdc++/ChangeLog:
>
>            PR libstdc++/70303
>            * include/bits/stl_deque.h 
>(std::deque<>::operator-(iterator, iterator)):
>            Return 0 if both iterators are value-initialized.
>            * testsuite/23_containers/deque/70303.cc: New test.
>            * testsuite/23_containers/vector/70303.cc: New test.
>
>Tested under Linux x86_64, ok to commit ?

OK.

I don't like adding the branch there though. Even with the
__builtin_expect it causes worse code to be generated than the
original.

This would be branchless, but a bit harder to understand:

     return difference_type(__x._S_buffer_size())
       * (__x._M_node - __y._M_node - int(__x._M_node == __y._M_node))
       + (__x._M_cur - __x._M_first) + (__y._M_last - __y._M_cur);

Please commit the fix and we can think about it later.

>François
>

>diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h
>index d41c27717a3..04b70b77621 100644
>--- a/libstdc++-v3/include/bits/stl_deque.h
>+++ b/libstdc++-v3/include/bits/stl_deque.h
>@@ -352,9 +352,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
>       friend difference_type
>       operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT
>       {
>-	return difference_type(_S_buffer_size())
>-	  * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
>-	  + (__y._M_last - __y._M_cur);
>+	if (__builtin_expect(__x._M_node || __y._M_node, true))
>+	  return difference_type(_S_buffer_size())
>+	    * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
>+	    + (__y._M_last - __y._M_cur);
>+
>+	return 0;
>       }
> 
>       // _GLIBCXX_RESOLVE_LIB_DEFECTS
>@@ -366,9 +369,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
> 	operator-(const _Self& __x,
> 		  const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT
> 	{
>-	  return difference_type(_S_buffer_size())
>-	    * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
>-	    + (__y._M_last - __y._M_cur);
>+	  if (__builtin_expect(__x._M_node || __y._M_node, true))
>+	    return difference_type(_S_buffer_size())
>+	      * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first)
>+	      + (__y._M_last - __y._M_cur);
>+
>+	  return 0;
> 	}
> 
>       friend _Self
>diff --git a/libstdc++-v3/testsuite/23_containers/deque/70303.cc b/libstdc++-v3/testsuite/23_containers/deque/70303.cc
>new file mode 100644
>index 00000000000..e0e63694170
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/23_containers/deque/70303.cc
>@@ -0,0 +1,67 @@
>+// 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 }
>+
>+#include <deque>
>+#include <testsuite_hooks.h>
>+
>+// PR libstdc++/70303
>+
>+void test01()
>+{
>+  typedef typename std::deque<int>::iterator It;
>+  It it = It();
>+  VERIFY(it == it);
>+  VERIFY(!(it != it));
>+  VERIFY(it - it == 0);
>+  VERIFY(!(it < it));
>+  VERIFY(!(it > it));
>+  VERIFY(it <= it);
>+  VERIFY(it >= it);
>+
>+  typedef typename std::deque<int>::const_iterator CIt;
>+  CIt cit = CIt();
>+  VERIFY(cit == cit);
>+  VERIFY(!(cit != cit));
>+  VERIFY(cit - cit == 0);
>+  VERIFY(!(cit < cit));
>+  VERIFY(!(cit > cit));
>+  VERIFY(cit <= cit);
>+  VERIFY(cit >= cit);
>+
>+  VERIFY(it == cit);
>+  VERIFY(!(it != cit));
>+  VERIFY(cit == it);
>+  VERIFY(!(cit != it));
>+  VERIFY(it - cit == 0);
>+  VERIFY(cit - it == 0);
>+  VERIFY(!(it < cit));
>+  VERIFY(!(it > cit));
>+  VERIFY(it <= cit);
>+  VERIFY(it >= cit);
>+  VERIFY(!(cit < it));
>+  VERIFY(!(cit > it));
>+  VERIFY(cit <= it);
>+  VERIFY(cit >= it);
>+}
>+
>+int main()
>+{
>+  test01();
>+  return 0;
>+}
>diff --git a/libstdc++-v3/testsuite/23_containers/vector/70303.cc b/libstdc++-v3/testsuite/23_containers/vector/70303.cc
>new file mode 100644
>index 00000000000..af18a0503d8
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/23_containers/vector/70303.cc
>@@ -0,0 +1,67 @@
>+// 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 }
>+
>+#include <vector>
>+#include <testsuite_hooks.h>
>+
>+// PR libstdc++/70303
>+
>+void test01()
>+{
>+  typedef typename std::vector<int>::iterator It;
>+  It it = It();
>+  VERIFY(it == it);
>+  VERIFY(!(it != it));
>+  VERIFY(it - it == 0);
>+  VERIFY(!(it < it));
>+  VERIFY(!(it > it));
>+  VERIFY(it <= it);
>+  VERIFY(it >= it);
>+
>+  typedef typename std::vector<int>::const_iterator CIt;
>+  CIt cit = CIt();
>+  VERIFY(cit == cit);
>+  VERIFY(!(cit != cit));
>+  VERIFY(cit - cit == 0);
>+  VERIFY(!(cit < cit));
>+  VERIFY(!(cit > cit));
>+  VERIFY(cit <= cit);
>+  VERIFY(cit >= cit);
>+
>+  VERIFY(it == cit);
>+  VERIFY(!(it != cit));
>+  VERIFY(cit == it);
>+  VERIFY(!(cit != it));
>+  VERIFY(it - cit == 0);
>+  VERIFY(cit - it == 0);
>+  VERIFY(!(it < cit));
>+  VERIFY(!(it > cit));
>+  VERIFY(it <= cit);
>+  VERIFY(it >= cit);
>+  VERIFY(!(cit < it));
>+  VERIFY(!(cit > it));
>+  VERIFY(cit <= it);
>+  VERIFY(cit >= it);
>+}
>+
>+int main()
>+{
>+  test01();
>+  return 0;
>+}



More information about the Gcc-patches mailing list