aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2022-11-24 21:09:03 +0000
committerJonathan Wakely <jwakely@redhat.com>2023-04-27 17:42:05 +0100
commitee5ab84e5f15b6d7c488bc371e4fb0304543844f (patch)
tree59abc5a75c2eb8e559a8c78fda973a4ac408744f
parent26b877fc4d2a08493762a7db8c66668891064707 (diff)
downloadgcc-ee5ab84e5f15b6d7c488bc371e4fb0304543844f.zip
gcc-ee5ab84e5f15b6d7c488bc371e4fb0304543844f.tar.gz
gcc-ee5ab84e5f15b6d7c488bc371e4fb0304543844f.tar.bz2
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)
-rw-r--r--libstdc++-v3/include/bits/erase_if.h2
-rw-r--r--libstdc++-v3/include/experimental/map6
-rw-r--r--libstdc++-v3/include/experimental/set4
-rw-r--r--libstdc++-v3/include/experimental/unordered_map4
-rw-r--r--libstdc++-v3/include/experimental/unordered_set4
-rw-r--r--libstdc++-v3/include/std/map6
-rw-r--r--libstdc++-v3/include/std/set4
-rw-r--r--libstdc++-v3/include/std/unordered_map4
-rw-r--r--libstdc++-v3/include/std/unordered_set4
-rw-r--r--libstdc++-v3/testsuite/23_containers/map/erasure.cc13
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/erasure.cc13
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_map/erasure.cc13
-rw-r--r--libstdc++-v3/testsuite/23_containers/unordered_set/erasure.cc13
-rw-r--r--libstdc++-v3/testsuite/experimental/map/erasure.cc13
-rw-r--r--libstdc++-v3/testsuite/experimental/set/erasure.cc13
-rw-r--r--libstdc++-v3/testsuite/experimental/unordered_map/erasure.cc13
-rw-r--r--libstdc++-v3/testsuite/experimental/unordered_set/erasure.cc13
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 397207f..b336e26 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 4936a66..4e615c7 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 aa43a2b2..3d46a0b 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 1a41687..26fff83 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 583c437..22fe49d 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 93c956a..1311d61 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 45fed14..7512791 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 bb14ffa..d57e8dd 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 777e3b8..a86a80c 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 badf789..643ad0a 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 fe0c4b8..bfa28f2 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 e6018186..8392e53 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 4cb8041..7684549 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 8470ab2..b377926 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 1e04c34..b427228 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 022f575..cd281bc 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 d261812..918f455 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;
}