From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2181) id ABD773858D33; Thu, 27 Apr 2023 17:38:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org ABD773858D33 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1682617080; bh=2ZY/wqlD3lk9tYK/V8/gDha/J2iX4EyiMDeaGHWDJiw=; h=From:To:Subject:Date:From; b=c7nyrgXfJdvlpoIuioDRtK2pp4CF2Hg8s22eZHD6s3DxAXRHssjGAaPbV44le/qGB jxHpo3Mgu8EiLTAocSocR7An05tcXmLqrX19QhVrcmE+PKO7cCFwAU/Pf0t4ue1Bjt 1Pmb3GQyiOAFxQ5Dg9gd/E0akfUH4tesFToeD8zw= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jonathan Wakely To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc r12-9489] libstdc++: Call predicate with non-const values in std::erase_if [PR107850] X-Act-Checkin: gcc X-Git-Author: Jonathan Wakely X-Git-Refname: refs/heads/releases/gcc-12 X-Git-Oldrev: 26b877fc4d2a08493762a7db8c66668891064707 X-Git-Newrev: ee5ab84e5f15b6d7c488bc371e4fb0304543844f Message-Id: <20230427173800.ABD773858D33@sourceware.org> Date: Thu, 27 Apr 2023 17:38:00 +0000 (GMT) List-Id: https://gcc.gnu.org/g:ee5ab84e5f15b6d7c488bc371e4fb0304543844f commit r12-9489-gee5ab84e5f15b6d7c488bc371e4fb0304543844f Author: Jonathan Wakely 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::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&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::map m; + std::erase_if(m, pred); + std::multimap 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 s; + std::erase_if(s, pred); + std::multiset 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&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::unordered_map m; + std::erase_if(m, pred); + std::unordered_multimap 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 s; + std::erase_if(s, pred); + std::unordered_multiset 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&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::map m; + std::experimental::erase_if(m, pred); + std::multimap 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 s; + std::experimental::erase_if(s, pred); + std::multiset 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&) { return false; } }; + const Pred pred; // erase_if parameter is passed by value, so non-const. + std::unordered_map m; + std::experimental::erase_if(m, pred); + std::unordered_multimap 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 s; + std::experimental::erase_if(s, pred); + std::unordered_multiset ms; + std::experimental::erase_if(ms, pred); +} + int main() { test01(); test02(); + test_pr107850(); return 0; }