From b340a9ea726710235ff009fd0f6e767742ff8939 Mon Sep 17 00:00:00 2001 From: ian Date: Wed, 25 May 2011 23:09:14 +0000 Subject: [PATCH] PR libstdc++/49060 * include/backward/hashtable.h (hashtable::erase): Don't crash if erasing first and another element with a reference to the other element. * testsuite/backward/hash_set/49060.cc: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@174240 138bc75d-0d04-0410-961f-82ee72b054a4 --- libstdc++-v3/ChangeLog | 8 ++++++ libstdc++-v3/include/backward/hashtable.h | 15 +++++----- libstdc++-v3/testsuite/backward/hash_set/49060.cc | 35 +++++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) create mode 100644 libstdc++-v3/testsuite/backward/hash_set/49060.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7c7758e66ef..2f5b10365b5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,11 @@ +2011-05-25 Ian Lance Taylor + + PR libstdc++/49060 + * include/backward/hashtable.h (hashtable::erase): Don't crash if + erasing first and another element with a reference to the other + element. + * testsuite/backward/hash_set/49060.cc: New. + 2011-05-25 Paolo Carlini * include/bits/random.h (random_device::min, max): Specify constexpr. diff --git a/libstdc++-v3/include/backward/hashtable.h b/libstdc++-v3/include/backward/hashtable.h index 0bcaec4fdc2..91b0c602cec 100644 --- a/libstdc++-v3/include/backward/hashtable.h +++ b/libstdc++-v3/include/backward/hashtable.h @@ -898,13 +898,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __next = __cur->_M_next; } } - if (_M_equals(_M_get_key(__first->_M_val), __key)) - { - _M_buckets[__n] = __first->_M_next; - _M_delete_node(__first); - ++__erased; - --_M_num_elements; - } + bool __delete_first = _M_equals(_M_get_key(__first->_M_val), __key); if (__saved_slot) { __next = __saved_slot->_M_next; @@ -913,6 +907,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ++__erased; --_M_num_elements; } + if (__delete_first) + { + _M_buckets[__n] = __first->_M_next; + _M_delete_node(__first); + ++__erased; + --_M_num_elements; + } } return __erased; } diff --git a/libstdc++-v3/testsuite/backward/hash_set/49060.cc b/libstdc++-v3/testsuite/backward/hash_set/49060.cc new file mode 100644 index 00000000000..985cfcf6afd --- /dev/null +++ b/libstdc++-v3/testsuite/backward/hash_set/49060.cc @@ -0,0 +1,35 @@ +// { dg-options "-Wno-deprecated" } + +#include +#include + +struct modulo2_hash +{ + size_t operator()(int const key) const + { + return key % 2; + } +}; + +struct modulo2_eq +{ + bool operator()(int const left, int const right) const + { + return left % 2 == right % 2; + } +}; + +int main() +{ + typedef std::_Select1st > extract_type; + typedef + __gnu_cxx::hashtable, int, modulo2_hash, + extract_type, modulo2_eq, std::allocator > + table_type; + table_type table(4, modulo2_hash(), modulo2_eq(), extract_type(), + std::allocator()); + + table.insert_equal(std::make_pair(2, 1)); + table_type::iterator it(table.insert_equal(std::make_pair(4, 2))); + table.erase(it->first); +} -- 2.11.0