public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-9489] libstdc++: Call predicate with non-const values in std::erase_if [PR107850]
@ 2023-04-27 17:38 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2023-04-27 17:38 UTC (permalink / raw)
  To: gcc-cvs, libstdc++-cvs

https://gcc.gnu.org/g:ee5ab84e5f15b6d7c488bc371e4fb0304543844f

commit r12-9489-gee5ab84e5f15b6d7c488bc371e4fb0304543844f
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Nov 24 21:09:03 2022 +0000

    libstdc++: Call predicate with non-const values in std::erase_if [PR107850]
    
    As specified in the standard, the predicate for std::erase_if has to be
    invocable as non-const with a non-const lvalues argument. Restore
    support for predicates that only accept non-const arguments.
    
    It's not strictly nevessary to change it for the set and unordered_set
    overloads, because they only give const access to the elements anyway.
    I've done it for them too just to keep them all consistent.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/107850
            * include/bits/erase_if.h (__erase_nodes_if): Use non-const
            reference to the container.
            * include/experimental/map (erase_if): Likewise.
            * include/experimental/set (erase_if): Likewise.
            * include/experimental/unordered_map (erase_if): Likewise.
            * include/experimental/unordered_set (erase_if): Likewise.
            * include/std/map (erase_if): Likewise.
            * include/std/set (erase_if): Likewise.
            * include/std/unordered_map (erase_if): Likewise.
            * include/std/unordered_set (erase_if): Likewise.
            * testsuite/23_containers/map/erasure.cc: Check with
            const-incorrect predicate.
            * testsuite/23_containers/set/erasure.cc: Likewise.
            * testsuite/23_containers/unordered_map/erasure.cc: Likewise.
            * testsuite/23_containers/unordered_set/erasure.cc: Likewise.
            * testsuite/experimental/map/erasure.cc: Likewise.
            * testsuite/experimental/set/erasure.cc: Likewise.
            * testsuite/experimental/unordered_map/erasure.cc: Likewise.
            * testsuite/experimental/unordered_set/erasure.cc: Likewise.
    
    (cherry picked from commit f54ceb2062c7fef294f85ae093914fa6c7ca35b8)

Diff:
---
 libstdc++-v3/include/bits/erase_if.h                        |  2 +-
 libstdc++-v3/include/experimental/map                       |  6 ++----
 libstdc++-v3/include/experimental/set                       |  4 ++--
 libstdc++-v3/include/experimental/unordered_map             |  4 ++--
 libstdc++-v3/include/experimental/unordered_set             |  4 ++--
 libstdc++-v3/include/std/map                                |  6 ++----
 libstdc++-v3/include/std/set                                |  4 ++--
 libstdc++-v3/include/std/unordered_map                      |  4 ++--
 libstdc++-v3/include/std/unordered_set                      |  4 ++--
 libstdc++-v3/testsuite/23_containers/map/erasure.cc         | 13 +++++++++++++
 libstdc++-v3/testsuite/23_containers/set/erasure.cc         | 13 +++++++++++++
 .../testsuite/23_containers/unordered_map/erasure.cc        | 13 +++++++++++++
 .../testsuite/23_containers/unordered_set/erasure.cc        | 13 +++++++++++++
 libstdc++-v3/testsuite/experimental/map/erasure.cc          | 13 +++++++++++++
 libstdc++-v3/testsuite/experimental/set/erasure.cc          | 13 +++++++++++++
 .../testsuite/experimental/unordered_map/erasure.cc         | 13 +++++++++++++
 .../testsuite/experimental/unordered_set/erasure.cc         | 13 +++++++++++++
 17 files changed, 121 insertions(+), 21 deletions(-)

diff --git a/libstdc++-v3/include/bits/erase_if.h b/libstdc++-v3/include/bits/erase_if.h
index 397207f4b56..b336e263d2d 100644
--- a/libstdc++-v3/include/bits/erase_if.h
+++ b/libstdc++-v3/include/bits/erase_if.h
@@ -49,7 +49,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     template<typename _Container, typename _UnsafeContainer,
 	     typename _Predicate>
       typename _Container::size_type
-      __erase_nodes_if(_Container& __cont, const _UnsafeContainer& __ucont,
+      __erase_nodes_if(_Container& __cont, _UnsafeContainer& __ucont,
 		       _Predicate __pred)
       {
 	typename _Container::size_type __num = 0;
diff --git a/libstdc++-v3/include/experimental/map b/libstdc++-v3/include/experimental/map
index 4936a660189..4e615c7793b 100644
--- a/libstdc++-v3/include/experimental/map
+++ b/libstdc++-v3/include/experimental/map
@@ -51,8 +51,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>&
-	__ucont = __cont;
+      _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -61,8 +60,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>&
-	__ucont = __cont;
+      _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
diff --git a/libstdc++-v3/include/experimental/set b/libstdc++-v3/include/experimental/set
index aa43a2b2fc3..3d46a0bff7c 100644
--- a/libstdc++-v3/include/experimental/set
+++ b/libstdc++-v3/include/experimental/set
@@ -51,7 +51,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -60,7 +60,7 @@ inline namespace fundamentals_v2
     inline void
     erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
diff --git a/libstdc++-v3/include/experimental/unordered_map b/libstdc++-v3/include/experimental/unordered_map
index 1a41687d593..26fff83c893 100644
--- a/libstdc++-v3/include/experimental/unordered_map
+++ b/libstdc++-v3/include/experimental/unordered_map
@@ -52,7 +52,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -63,7 +63,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
diff --git a/libstdc++-v3/include/experimental/unordered_set b/libstdc++-v3/include/experimental/unordered_set
index 583c43798a7..22fe49d8fdf 100644
--- a/libstdc++-v3/include/experimental/unordered_set
+++ b/libstdc++-v3/include/experimental/unordered_set
@@ -52,7 +52,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -63,7 +63,7 @@ inline namespace fundamentals_v2
     erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       std::__detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map
index 93c956af916..1311d617404 100644
--- a/libstdc++-v3/include/std/map
+++ b/libstdc++-v3/include/std/map
@@ -96,8 +96,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type
     erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>&
-	__ucont = __cont;
+      _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -106,8 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type
     erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>&
-	__ucont = __cont;
+      _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set
index 45fed14c51e..751279120a2 100644
--- a/libstdc++-v3/include/std/set
+++ b/libstdc++-v3/include/std/set
@@ -92,7 +92,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename set<_Key, _Compare, _Alloc>::size_type
     erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::set<_Key, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 
@@ -101,7 +101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     inline typename multiset<_Key, _Compare, _Alloc>::size_type
     erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
+      _GLIBCXX_STD_C::multiset<_Key, _Compare, _Alloc>& __ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map
index bb14ffa7f2e..d57e8dd4959 100644
--- a/libstdc++-v3/include/std/unordered_map
+++ b/libstdc++-v3/include/std/unordered_map
@@ -84,7 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -96,7 +96,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set
index 777e3b81116..a86a80c36be 100644
--- a/libstdc++-v3/include/std/unordered_set
+++ b/libstdc++-v3/include/std/unordered_set
@@ -84,7 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_set<_Key, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
@@ -95,7 +95,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
 	     _Predicate __pred)
     {
-      const _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
+      _GLIBCXX_STD_C::unordered_multiset<_Key, _Hash, _CPred, _Alloc>&
 	__ucont = __cont;
       return __detail::__erase_nodes_if(__cont, __ucont, __pred);
     }
diff --git a/libstdc++-v3/testsuite/23_containers/map/erasure.cc b/libstdc++-v3/testsuite/23_containers/map/erasure.cc
index badf7896df6..643ad0a3f17 100644
--- a/libstdc++-v3/testsuite/23_containers/map/erasure.cc
+++ b/libstdc++-v3/testsuite/23_containers/map/erasure.cc
@@ -61,11 +61,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::map<int, int> m;
+  std::erase_if(m, pred);
+  std::multimap<int, int> mm;
+  std::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/set/erasure.cc b/libstdc++-v3/testsuite/23_containers/set/erasure.cc
index fe0c4b8766b..bfa28f26009 100644
--- a/libstdc++-v3/testsuite/23_containers/set/erasure.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/erasure.cc
@@ -49,11 +49,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::set<int> s;
+  std::erase_if(s, pred);
+  std::multiset<int> ms;
+  std::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc
index e6018186bf2..8392e538ac7 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc
@@ -61,11 +61,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_map<int, int> m;
+  std::erase_if(m, pred);
+  std::unordered_multimap<int, int> mm;
+  std::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc
index 4cb80413ff0..76845494289 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc
@@ -51,11 +51,24 @@ test02()
   VERIFY( num == 4 );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_set<int> s;
+  std::erase_if(s, pred);
+  std::unordered_multiset<int> ms;
+  std::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/experimental/map/erasure.cc b/libstdc++-v3/testsuite/experimental/map/erasure.cc
index 8470ab2e99b..b377926898f 100644
--- a/libstdc++-v3/testsuite/experimental/map/erasure.cc
+++ b/libstdc++-v3/testsuite/experimental/map/erasure.cc
@@ -52,11 +52,24 @@ test02()
   VERIFY( mm == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::map<int, int> m;
+  std::experimental::erase_if(m, pred);
+  std::multimap<int, int> mm;
+  std::experimental::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/experimental/set/erasure.cc b/libstdc++-v3/testsuite/experimental/set/erasure.cc
index 1e04c3461a4..b4272282c32 100644
--- a/libstdc++-v3/testsuite/experimental/set/erasure.cc
+++ b/libstdc++-v3/testsuite/experimental/set/erasure.cc
@@ -40,11 +40,24 @@ test02()
   VERIFY( ms == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::set<int> s;
+  std::experimental::erase_if(s, pred);
+  std::multiset<int> ms;
+  std::experimental::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc b/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc
index 022f57583b0..cd281bc70da 100644
--- a/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc
+++ b/libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc
@@ -52,11 +52,24 @@ test02()
   VERIFY( umm == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const and only accepts non-const argument.
+  struct Pred { bool operator()(std::pair<const int, int>&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_map<int, int> m;
+  std::experimental::erase_if(m, pred);
+  std::unordered_multimap<int, int> mm;
+  std::experimental::erase_if(mm, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc b/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc
index d261812d4ec..918f455f5c0 100644
--- a/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc
+++ b/libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc
@@ -42,11 +42,24 @@ test02()
   VERIFY( ums == t );
 }
 
+void
+test_pr107850()
+{
+  // Predicate only callable as non-const.
+  struct Pred { bool operator()(const int&) { return false; } };
+  const Pred pred; // erase_if parameter is passed by value, so non-const.
+  std::unordered_set<int> s;
+  std::experimental::erase_if(s, pred);
+  std::unordered_multiset<int> ms;
+  std::experimental::erase_if(ms, pred);
+}
+
 int
 main()
 {
   test01();
   test02();
+  test_pr107850();
 
   return 0;
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-04-27 17:38 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-27 17:38 [gcc r12-9489] libstdc++: Call predicate with non-const values in std::erase_if [PR107850] Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).