libstdc++/71545 fix debug checks in binary search algorithms
authorJonathan Wakely <jwakely@redhat.com>
Fri, 17 Jun 2016 18:28:34 +0000 (19:28 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 17 Jun 2016 18:28:34 +0000 (19:28 +0100)
PR libstdc++/71545
* include/bits/stl_algobase.h (lower_bound, lexicographical_compare):
Remove irreflexive checks.
* include/bits/stl_algo.h (lower_bound, upper_bound, equal_range,
binary_search): Likewise.
* testsuite/25_algorithms/equal_range/partitioned.cc: New test.
* testsuite/25_algorithms/lexicographical_compare/71545.cc: New test.
* testsuite/25_algorithms/lower_bound/partitioned.cc: New test.
* testsuite/25_algorithms/upper_bound/partitioned.cc: New test.
* testsuite/util/testsuite_iterators.h (__gnu_test::test_container):
Add constructor from array.

From-SVN: r237560

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_algo.h
libstdc++-v3/include/bits/stl_algobase.h
libstdc++-v3/testsuite/25_algorithms/binary_search/partitioned.cc [new file with mode: 0644]
libstdc++-v3/testsuite/25_algorithms/equal_range/partitioned.cc [new file with mode: 0644]
libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/71545.cc [new file with mode: 0644]
libstdc++-v3/testsuite/25_algorithms/lower_bound/partitioned.cc [new file with mode: 0644]
libstdc++-v3/testsuite/25_algorithms/upper_bound/partitioned.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/testsuite_iterators.h

index 753fb9824b7e168799bdf756daa10e2355969cc8..a97485171146b07993858a0aa5b95843a42018d2 100644 (file)
@@ -1,3 +1,17 @@
+2016-06-17  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/71545
+       * include/bits/stl_algobase.h (lower_bound, lexicographical_compare):
+       Remove irreflexive checks.
+       * include/bits/stl_algo.h (lower_bound, upper_bound, equal_range,
+       binary_search): Likewise.
+       * testsuite/25_algorithms/equal_range/partitioned.cc: New test.
+       * testsuite/25_algorithms/lexicographical_compare/71545.cc: New test.
+       * testsuite/25_algorithms/lower_bound/partitioned.cc: New test.
+       * testsuite/25_algorithms/upper_bound/partitioned.cc: New test.
+       * testsuite/util/testsuite_iterators.h (__gnu_test::test_container):
+       Add constructor from array.
+
 2016-06-16  François Dumont  <fdumont@gcc.gnu.org>
 
        * include/debug/debug.h
index fbd03a79e1ebdfd4624221e7d8d2e37a53406288..c2ac0317f172e88d9aea60adacee671c4b36eb95 100644 (file)
@@ -2026,7 +2026,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
       __glibcxx_requires_partitioned_lower_pred(__first, __last,
                                                __val, __comp);
-      __glibcxx_requires_irreflexive_pred2(__first, __last, __comp);
 
       return std::__lower_bound(__first, __last, __val,
                                __gnu_cxx::__ops::__iter_comp_val(__comp));
@@ -2080,7 +2079,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_function_requires(_LessThanOpConcept<
        _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
-      __glibcxx_requires_irreflexive2(__first, __last);
 
       return std::__upper_bound(__first, __last, __val,
                                __gnu_cxx::__ops::__val_less_iter());
@@ -2112,7 +2110,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_partitioned_upper_pred(__first, __last,
                                                __val, __comp);
-      __glibcxx_requires_irreflexive_pred2(__first, __last, __comp);
 
       return std::__upper_bound(__first, __last, __val,
                                __gnu_cxx::__ops::__val_comp_iter(__comp));
@@ -2186,7 +2183,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
-      __glibcxx_requires_irreflexive2(__first, __last);
 
       return std::__equal_range(__first, __last, __val,
                                __gnu_cxx::__ops::__iter_less_val(),
@@ -2225,7 +2221,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                                                __val, __comp);
       __glibcxx_requires_partitioned_upper_pred(__first, __last,
                                                __val, __comp);
-      __glibcxx_requires_irreflexive_pred2(__first, __last, __comp);
 
       return std::__equal_range(__first, __last, __val,
                                __gnu_cxx::__ops::__iter_comp_val(__comp),
@@ -2255,7 +2250,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        _Tp, typename iterator_traits<_ForwardIterator>::value_type>)
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
       __glibcxx_requires_partitioned_upper(__first, __last, __val);
-      __glibcxx_requires_irreflexive2(__first, __last);
 
       _ForwardIterator __i
        = std::__lower_bound(__first, __last, __val,
@@ -2291,7 +2285,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                                                __val, __comp);
       __glibcxx_requires_partitioned_upper_pred(__first, __last,
                                                __val, __comp);
-      __glibcxx_requires_irreflexive_pred2(__first, __last, __comp);
 
       _ForwardIterator __i
        = std::__lower_bound(__first, __last, __val,
index d95ea513a593f8e9f08c5a90bdcbbd5f23681f88..210b173454559fb0a4d1c5b2fb1ed1962677f29d 100644 (file)
@@ -989,7 +989,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __glibcxx_function_requires(_LessThanOpConcept<
            typename iterator_traits<_ForwardIterator>::value_type, _Tp>)
       __glibcxx_requires_partitioned_lower(__first, __last, __val);
-      __glibcxx_requires_irreflexive2(__first, __last);
 
       return std::__lower_bound(__first, __last, __val,
                                __gnu_cxx::__ops::__iter_less_val());
@@ -1214,9 +1213,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>)
       __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>)
       __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_irreflexive2(__first1, __last1);
       __glibcxx_requires_valid_range(__first2, __last2);
-      __glibcxx_requires_irreflexive2(__first2, __last2);
 
       return std::__lexicographical_compare_aux(std::__niter_base(__first1),
                                                std::__niter_base(__last1),
@@ -1246,9 +1243,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
       __glibcxx_function_requires(_InputIteratorConcept<_II1>)
       __glibcxx_function_requires(_InputIteratorConcept<_II2>)
       __glibcxx_requires_valid_range(__first1, __last1);
-      __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp);
       __glibcxx_requires_valid_range(__first2, __last2);
-      __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp);
 
       return std::__lexicographical_compare_impl
        (__first1, __last1, __first2, __last2,
diff --git a/libstdc++-v3/testsuite/25_algorithms/binary_search/partitioned.cc b/libstdc++-v3/testsuite/25_algorithms/binary_search/partitioned.cc
new file mode 100644 (file)
index 0000000..63a6cad
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright (C) 2016 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 -D_GLIBCXX_DEBUG" }
+
+#include <algorithm>
+#include <functional>
+#include <testsuite_iterators.h>
+#include <testsuite_hooks.h>
+
+using __gnu_test::test_container;
+using __gnu_test::forward_iterator_wrapper;
+
+struct X
+{
+  int val;
+
+  bool odd() const { return val % 2; }
+
+  // Partitioned so that all odd values come before even values:
+  bool operator<(const X& x) const { return this->odd() && !x.odd(); }
+};
+
+void
+test01()
+{
+  bool test __attribute((unused)) = true;
+
+  // Test with range that is partitioned, but not sorted.
+  X seq[] = { 1, 3, 5, 7, 1, 6, 4 };
+  test_container<X, forward_iterator_wrapper> c(seq);
+
+  auto b1 = std::binary_search(c.begin(), c.end(), X{2});
+  VERIFY( b1 );
+  auto b2 = std::binary_search(c.begin(), c.end(), X{2}, std::less<X>{});
+  VERIFY( b2 );
+
+  auto b3 = std::binary_search(c.begin(), c.end(), X{9});
+  VERIFY( b3 );
+  auto b4 = std::binary_search(c.begin(), c.end(), X{9}, std::less<X>{});
+  VERIFY( b4 );
+
+  auto b5 = std::binary_search(seq, seq+5, X{2});
+  VERIFY( !b5 );
+  auto b6 = std::binary_search(seq, seq+5, X{2}, std::less<X>{});
+  VERIFY( !b6 );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/equal_range/partitioned.cc b/libstdc++-v3/testsuite/25_algorithms/equal_range/partitioned.cc
new file mode 100644 (file)
index 0000000..d3a43d0
--- /dev/null
@@ -0,0 +1,66 @@
+// Copyright (C) 2016 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 -D_GLIBCXX_DEBUG" }
+
+#include <algorithm>
+#include <functional>
+#include <testsuite_iterators.h>
+#include <testsuite_hooks.h>
+
+using __gnu_test::test_container;
+using __gnu_test::forward_iterator_wrapper;
+
+struct X
+{
+  int val;
+
+  bool odd() const { return val % 2; }
+
+  // Partitioned so that all odd values come before even values:
+  bool operator<(const X& x) const { return this->odd() && !x.odd(); }
+};
+
+void
+test01()
+{
+  bool test __attribute((unused)) = true;
+
+  // Test with range that is partitioned, but not sorted.
+  X seq[] = { 1, 3, 5, 7, 1, 6, 4, 2 };
+  test_container<X, forward_iterator_wrapper> c(seq);
+
+  auto part1 = std::equal_range(c.begin(), c.end(), X{2});
+  VERIFY( part1.first != c.end() && part1.second == c.end() );
+  VERIFY( part1.first->val == 6 );
+  auto part2 = std::equal_range(c.begin(), c.end(), X{2}, std::less<X>{});
+  VERIFY( part2.first != c.end() && part1.second == c.end() );
+  VERIFY( part2.first->val == 6 );
+
+  auto part3 = std::equal_range(c.begin(), c.end(), X{9});
+  VERIFY( part3.first == c.begin() && part3.second != c.end() );
+  VERIFY( part3.second->val == 6 );
+  auto part4 = std::equal_range(c.begin(), c.end(), X{9}, std::less<X>{});
+  VERIFY( part4.first == c.begin() && part4.second != c.end() );
+  VERIFY( part4.second->val == 6 );
+}
+
+int
+main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/71545.cc b/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/71545.cc
new file mode 100644 (file)
index 0000000..6c9cd12
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright (C) 2016 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 -D_GLIBCXX_DEBUG" }
+// { dg-do link }
+
+#include <algorithm>
+
+struct X { };
+
+bool operator<(X, int) { return true; }
+bool operator<(int, X) { return false; }
+
+bool operator<(X, X); // undefined (PR libstdc++/71545)
+
+int main()
+{
+  X x[1];
+  int i[1];
+  std::lexicographical_compare(x, x+1, i, i+1);
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/partitioned.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/partitioned.cc
new file mode 100644 (file)
index 0000000..bba0b66
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright (C) 2016 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 -D_GLIBCXX_DEBUG" }
+
+#include <algorithm>
+#include <functional>
+#include <testsuite_iterators.h>
+#include <testsuite_hooks.h>
+
+using __gnu_test::test_container;
+using __gnu_test::forward_iterator_wrapper;
+
+struct X
+{
+  int val;
+
+  bool odd() const { return val % 2; }
+
+  // Partitioned so that all odd values come before even values:
+  bool operator<(const X& x) const { return this->odd() && !x.odd(); }
+};
+
+void
+test01()
+{
+  bool test __attribute((unused)) = true;
+
+  // Test with range that is partitioned, but not sorted.
+  X seq[] = { 1, 3, 5, 7, 1, 6, 4, 2 };
+  test_container<X, forward_iterator_wrapper> c(seq);
+
+  auto part1 = std::lower_bound(c.begin(), c.end(), X{2});
+  VERIFY( part1 != c.end() );
+  VERIFY( part1->val == 6 );
+  auto part2 = std::lower_bound(c.begin(), c.end(), X{2}, std::less<X>{});
+  VERIFY( part2 != c.end() );
+  VERIFY( part2->val == 6 );
+
+  auto part3 = std::lower_bound(c.begin(), c.end(), X{9});
+  VERIFY( part3 != c.end() );
+  VERIFY( part3->val == 1 );
+  auto part4 = std::lower_bound(c.begin(), c.end(), X{9}, std::less<X>{});
+  VERIFY( part4 != c.end() );
+  VERIFY( part4->val == 1 );
+}
+
+struct Y
+{
+  double val;
+
+  // Not irreflexive, so not a strict weak order.
+  bool operator<(const Y& y) const { return val < int(y.val); }
+};
+
+void
+test02()
+{
+  bool test __attribute((unused)) = true;
+
+  // Test that Debug Mode checks don't fire (libstdc++/71545)
+
+  Y seq[] = { -0.1, 1.2, 5.0, 5.2, 5.1, 5.9, 5.5, 6.0 };
+  test_container<Y, forward_iterator_wrapper> c(seq);
+
+  auto part1 = std::lower_bound(c.begin(), c.end(), Y{5.5});
+  VERIFY( part1 != c.end() );
+  VERIFY( part1->val == 5.0 );
+  auto part2 = std::lower_bound(c.begin(), c.end(), Y{5.5}, std::less<Y>{});
+  VERIFY( part2 != c.end() );
+  VERIFY( part2->val == 5.0 );
+
+  auto part3 = std::lower_bound(c.begin(), c.end(), Y{1.0});
+  VERIFY( part3 != c.end() );
+  VERIFY( part3->val == 1.2 );
+  auto part4 = std::lower_bound(c.begin(), c.end(), Y{1.0}, std::less<Y>{});
+  VERIFY( part4 != c.end() );
+  VERIFY( part4->val == 1.2 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/partitioned.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/partitioned.cc
new file mode 100644 (file)
index 0000000..96cfb2e
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright (C) 2016 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 -D_GLIBCXX_DEBUG" }
+
+#include <algorithm>
+#include <functional>
+#include <testsuite_iterators.h>
+#include <testsuite_hooks.h>
+
+using __gnu_test::test_container;
+using __gnu_test::forward_iterator_wrapper;
+
+struct X
+{
+  int val;
+
+  bool odd() const { return val % 2; }
+
+  // Partitioned so that all odd values come before even values:
+  bool operator<(const X& x) const { return this->odd() && !x.odd(); }
+};
+
+void
+test01()
+{
+  bool test __attribute((unused)) = true;
+
+  // Test with range that is partitioned, but not sorted.
+  X seq[] = { 1, 3, 5, 7, 1, 6, 4, 2 };
+  test_container<X, forward_iterator_wrapper> c(seq);
+
+  auto part1 = std::upper_bound(c.begin(), c.end(), X{2});
+  VERIFY( part1 == c.end() );
+  auto part2 = std::upper_bound(c.begin(), c.end(), X{2}, std::less<X>{});
+  VERIFY( part2 == c.end() );
+
+  auto part3 = std::upper_bound(c.begin(), c.end(), X{9});
+  VERIFY( part3 != c.end() );
+  VERIFY( part3->val == 6 );
+  auto part4 = std::upper_bound(c.begin(), c.end(), X{9}, std::less<X>{});
+  VERIFY( part3 != c.end() );
+  VERIFY( part4->val == 6 );
+}
+
+struct Y
+{
+  double val;
+
+  // Not irreflexive, so not a strict weak order.
+  bool operator<(const Y& y) const { return val < (int)y.val; }
+};
+
+void
+test02()
+{
+  bool test __attribute((unused)) = true;
+
+  // Test that Debug Mode checks don't fire (libstdc++/71545)
+
+  Y seq[] = { -0.1, 1.2, 5.0, 5.2, 5.1, 5.9, 5.5, 6.0 };
+  test_container<Y, forward_iterator_wrapper> c(seq);
+
+  auto part1 = std::upper_bound(c.begin(), c.end(), Y{5.5});
+  VERIFY( part1 != c.end() );
+  VERIFY( part1->val == 6.0 );
+  auto part2 = std::upper_bound(c.begin(), c.end(), Y{5.5}, std::less<Y>{});
+  VERIFY( part2 != c.end() );
+  VERIFY( part2->val == 6.0 );
+
+  auto part3 = std::upper_bound(c.begin(), c.end(), Y{1.0});
+  VERIFY( part3 != c.end() );
+  VERIFY( part3->val == 5.0 );
+  auto part4 = std::upper_bound(c.begin(), c.end(), Y{1.0}, std::less<Y>{});
+  VERIFY( part4 != c.end() );
+  VERIFY( part4->val == 5.0 );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
index a1c71a23cdd84605355def5e1b71f4a4726353c7..53c9b3d4f643a2e3d8b898af05b98b142f0bce8e 100644 (file)
@@ -542,6 +542,13 @@ namespace __gnu_test
     test_container(T* _first, T* _last):bounds(_first, _last)
     { }
 
+#if __cplusplus >= 201103L
+      template<std::size_t N>
+       explicit
+       test_container(T (&arr)[N]) : test_container(arr, arr+N)
+       { }
+#endif
+
     ItType<T>
     it(int pos)
     {