Hi
libstdc++: Fix std::erase_if behavior for std::__debug containers
Complete fix of std::erase_if/std::erase for all std::__debug
containers and
__gnu_debug::basic_string. Make sure that iterators erased by
this function
will be properly detected as such by the debug container and so
considered as
invalid.
Doing so introduce a new std::__detail::__erase_if function
dealing, similarly
to std::__detail::__erase_node_if, with non-node containers.
libstdc++-v3/ChangeLog:
* include/bits/erase_if.h (__detail::__erase_if): New.
* include/debug/deque (std::erase_if<>(__debug::deque<>&,
_Pred): Use latter.
* include/debug/inplace_vector
(std::erase_if<>(__debug::inplace_vector<>&, _Pred)):
Likewise.
* include/debug/vector
(std::erase_if<>(__debug::vector<>&, _Pred)): Likewise.
* include/std/deque: Include erase_if.h.
(std::erase_if<>(std::vector<>&, _Pred)): Adapt to use
__detail::__erase_if.
* include/std/inplace_vector
(std::erase_if<>(std::inplace_vector<>&, _Pred)):
Likewise.
* include/std/string
(std::erase_if<>(std::basic_string<>&, _Pred)): Likewise.
* include/std/vector (std::erase_if<>(std::vector<>&,
_Pred)): Likewise.
* include/debug/forward_list
(std::erase_if<>(__debug::forward_list<>&, _Pred)): New.
(std::erase<>(__debug::forward_list<>&, const _Up&)): New.
* include/debug/list
(std::erase_if<>(__debug::list<>&, _Pred)): New.
(std::erase<>(__debug::list<>&, const _Up&)): New.
* include/debug/map (std::erase_if<>(__debug::map<>&,
_Pred)): New.
(std::erase_if<>(__debug::multimap<>&, _Pred)): New.
* include/debug/set (std::erase_if<>(__debug::set<>&,
_Pred)): New.
(std::erase_if<>(__debug::multiset<>&, _Pred)): New.
* include/debug/string
(std::erase_if<>(__gnu_debug::basic_string<>&, _Pred)): New.
(std::erase<>(__gnu_debug::basic_string<>&, const _Up&)): New.
* include/debug/unordered_map
(std::erase_if<>(__debug::unordered_map<>&, _Pred)): New.
(std::erase_if<>(__debug::unordered_multimap<>&, _Pred)): New.
* include/debug/unordered_set
(std::erase_if<>(__debug::unordered_set<>&, _Pred)): New.
(std::erase_if<>(__debug::unordered_multiset<>&, _Pred)): New.
* include/std/forward_list
(std::erase_if<>(std::forward_list<>&, _Pred)):
Adapt to work exclusively for normal implementation.
(std::erase<>(std::forward_list<>&, const _Up&)): Likewise.
* include/std/list (std::erase_if<>(std::list<>&,
_Pred)): Likewise.
(std::erase<>(std::list<>&, const _Up&)): Likewise.
* include/std/map (std::erase_if<>(std::map<>&, _Pred)):
Likewise.
(std::erase_if<>(std::multimap<>&, _Pred)): Likewise.
* include/debug/set (std::erase_if<>(std::set<>&,
_Pred)): Likewise.
(std::erase_if<>(std::multiset<>&, _Pred)): Likewise.
* include/std/unordered_map
(std::erase_if<>(std::unordered_map<>&, _Pred)): Likewise.
(std::erase_if<>(std::unordered_multimap<>&, _Pred)): Likewise.
* include/std/unordered_set
(std::erase_if<>(std::unordered_set<>&, _Pred)): Likewise.
(std::erase_if<>(std::unordered_multiset<>&, _Pred)): Likewise.
* testsuite/21_strings/basic_string/debug/erase.cc: New
test case.
* testsuite/23_containers/forward_list/debug/erase.cc:
New test case.
*
testsuite/23_containers/forward_list/debug/invalidation/erase.cc: New
test case.
* testsuite/23_containers/list/debug/erase.cc: New test
case.
*
testsuite/23_containers/list/debug/invalidation/erase.cc: New test case.
* testsuite/23_containers/map/debug/erase_if.cc: New test
case.
*
testsuite/23_containers/map/debug/invalidation/erase_if.cc: New test
case.
* testsuite/23_containers/multimap/debug/erase_if.cc: New
test case.
*
testsuite/23_containers/multimap/debug/invalidation/erase_if.cc: New
test case.
* testsuite/23_containers/multiset/debug/erase_if.cc: New
test case.
*
testsuite/23_containers/multiset/debug/invalidation/erase_if.cc: New
test case.
* testsuite/23_containers/set/debug/erase_if.cc: New test
case.
*
testsuite/23_containers/set/debug/invalidation/erase_if.cc: New test
case.
*
testsuite/23_containers/unordered_map/debug/erase_if.cc: New test case.
*
testsuite/23_containers/unordered_map/debug/invalidation/erase_if.cc:
New test case.
*
testsuite/23_containers/unordered_multimap/debug/erase_if.cc: New
test case.
*
testsuite/23_containers/unordered_multimap/debug/invalidation/erase_if.cc:
New test case.
*
testsuite/23_containers/unordered_multiset/debug/erase_if.cc: New
test case.
*
testsuite/23_containers/unordered_multiset/debug/invalidation/erase_if.cc:
New test case.
*
testsuite/23_containers/unordered_set/debug/erase_if.cc: New test case.
*
testsuite/23_containers/unordered_set/debug/invalidation/erase_if.cc:
New test case.
All testsuite/23_containers tests run under Linux x64 normal and
_GLIBCXX_DEBUG modes.
https://forge.sourceware.org/gcc/gcc-TEST/pulls/131
Ok to commit ?
François
diff --git a/libstdc++-v3/include/bits/erase_if.h
b/libstdc++-v3/include/bits/erase_if.h
index fc086b56728..ecf4e7fd4d3 100644
--- a/libstdc++-v3/include/bits/erase_if.h
+++ b/libstdc++-v3/include/bits/erase_if.h
@@ -35,6 +35,7 @@
#endif
#include <bits/c++config.h>
+#include <bits/stl_algobase.h>
// Used by C++17 containers and Library Fundamentals v2 headers.
#if __cplusplus >= 201402L
@@ -44,6 +45,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace __detail
{
+ template<typename _Container, typename _UnsafeContainer,
+ typename _Predicate>
+ _GLIBCXX20_CONSTEXPR
+ typename _Container::size_type
+ __erase_if(_Container& __cont, _UnsafeContainer& __ucont,
+ _Predicate __pred)
+ {
+ const auto __osz = __ucont.size();
+ const auto __end = __ucont.end();
+ auto __removed = std::__remove_if(__ucont.begin(), __end,
+ std::move(__pred));
+ if (__removed != __end)
+ {
+ __cont.erase(__niter_wrap(__cont.cbegin(), __removed),
+ __cont.cend());
+ return __osz - __ucont.size();
+ }
+
+ return 0;
+ }
+
template<typename _Container, typename _UnsafeContainer,
typename _Predicate>
typename _Container::size_type
diff --git a/libstdc++-v3/include/debug/deque
b/libstdc++-v3/include/debug/deque
index b2e5dd32717..2358070bd0a 100644
--- a/libstdc++-v3/include/debug/deque
+++ b/libstdc++-v3/include/debug/deque
@@ -779,18 +779,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
erase_if(__debug::deque<_Tp, _Alloc>& __cont, _Predicate __pred)