mirror of git://gcc.gnu.org/git/gcc.git
re PR libstdc++/63698 (std::set leaks nodes on assignment)
2014-11-04 François Dumont <fdumont@gcc.gnu.org> Jonathan Wakely <jwakely@redhat.com> PR libstdc++/63698 * include/bits/stl_tree.h (_Reuse_or_alloc_node): Simplify constructor. Always move to the left node if there is one. * testsuite/23_containers/set/allocator/move_assign.cc (test04): New. Co-Authored-By: Jonathan Wakely <jwakely@redhat.com> From-SVN: r217154
This commit is contained in:
parent
e028b0bbca
commit
6c52b7dfc4
|
|
@ -1,3 +1,11 @@
|
||||||
|
2014-11-05 François Dumont <fdumont@gcc.gnu.org>
|
||||||
|
Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
PR libstdc++/63698
|
||||||
|
* include/bits/stl_tree.h (_Reuse_or_alloc_node): Simplify constructor.
|
||||||
|
Always move to the left node if there is one.
|
||||||
|
* testsuite/23_containers/set/allocator/move_assign.cc (test04): New.
|
||||||
|
|
||||||
2014-11-04 Jonathan Wakely <jwakely@redhat.com>
|
2014-11-04 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
* include/bits/unique_ptr.h (make_unique): Use alias for trait.
|
* include/bits/unique_ptr.h (make_unique): Use alias for trait.
|
||||||
|
|
|
||||||
|
|
@ -359,16 +359,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
typedef const _Rb_tree_node<_Val>* _Const_Link_type;
|
typedef const _Rb_tree_node<_Val>* _Const_Link_type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Functor recycling a pool of nodes and using allocation once the pool is
|
// Functor recycling a pool of nodes and using allocation once the pool
|
||||||
// empty.
|
// is empty.
|
||||||
struct _Reuse_or_alloc_node
|
struct _Reuse_or_alloc_node
|
||||||
{
|
{
|
||||||
_Reuse_or_alloc_node(const _Rb_tree_node_base& __header,
|
_Reuse_or_alloc_node(_Rb_tree& __t)
|
||||||
_Rb_tree& __t)
|
: _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t)
|
||||||
: _M_root(__header._M_parent), _M_nodes(__header._M_right), _M_t(__t)
|
|
||||||
{
|
{
|
||||||
if (_M_root)
|
if (_M_root)
|
||||||
_M_root->_M_parent = 0;
|
{
|
||||||
|
_M_root->_M_parent = 0;
|
||||||
|
|
||||||
|
if (_M_nodes->_M_left)
|
||||||
|
_M_nodes = _M_nodes->_M_left;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
_M_nodes = 0;
|
_M_nodes = 0;
|
||||||
}
|
}
|
||||||
|
|
@ -420,6 +424,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
while (_M_nodes->_M_right)
|
while (_M_nodes->_M_right)
|
||||||
_M_nodes = _M_nodes->_M_right;
|
_M_nodes = _M_nodes->_M_right;
|
||||||
|
|
||||||
|
if (_M_nodes->_M_left)
|
||||||
|
_M_nodes = _M_nodes->_M_left;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // __node is on the left.
|
else // __node is on the left.
|
||||||
|
|
@ -436,7 +443,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Rb_tree& _M_t;
|
_Rb_tree& _M_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Functor similar to the previous one but without any pool of node to
|
// Functor similar to the previous one but without any pool of nodes to
|
||||||
// recycle.
|
// recycle.
|
||||||
struct _Alloc_node
|
struct _Alloc_node
|
||||||
{
|
{
|
||||||
|
|
@ -1271,7 +1278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
// Try to move each node reusing existing nodes and copying __x nodes
|
// Try to move each node reusing existing nodes and copying __x nodes
|
||||||
// structure.
|
// structure.
|
||||||
_Reuse_or_alloc_node __roan(_M_impl._M_header, *this);
|
_Reuse_or_alloc_node __roan(*this);
|
||||||
_M_impl._M_reset();
|
_M_impl._M_reset();
|
||||||
if (__x._M_root() != nullptr)
|
if (__x._M_root() != nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -1297,7 +1304,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
|
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
|
||||||
_M_assign_unique(_Iterator __first, _Iterator __last)
|
_M_assign_unique(_Iterator __first, _Iterator __last)
|
||||||
{
|
{
|
||||||
_Reuse_or_alloc_node __roan(this->_M_impl._M_header, *this);
|
_Reuse_or_alloc_node __roan(*this);
|
||||||
_M_impl._M_reset();
|
_M_impl._M_reset();
|
||||||
for (; __first != __last; ++__first)
|
for (; __first != __last; ++__first)
|
||||||
_M_insert_unique_(end(), *__first, __roan);
|
_M_insert_unique_(end(), *__first, __roan);
|
||||||
|
|
@ -1310,7 +1317,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
|
_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::
|
||||||
_M_assign_equal(_Iterator __first, _Iterator __last)
|
_M_assign_equal(_Iterator __first, _Iterator __last)
|
||||||
{
|
{
|
||||||
_Reuse_or_alloc_node __roan(this->_M_impl._M_header, *this);
|
_Reuse_or_alloc_node __roan(*this);
|
||||||
_M_impl._M_reset();
|
_M_impl._M_reset();
|
||||||
for (; __first != __last; ++__first)
|
for (; __first != __last; ++__first)
|
||||||
_M_insert_equal_(end(), *__first, __roan);
|
_M_insert_equal_(end(), *__first, __roan);
|
||||||
|
|
@ -1342,7 +1349,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_Reuse_or_alloc_node __roan(this->_M_impl._M_header, *this);
|
_Reuse_or_alloc_node __roan(*this);
|
||||||
_M_impl._M_reset();
|
_M_impl._M_reset();
|
||||||
_M_impl._M_key_compare = __x._M_impl._M_key_compare;
|
_M_impl._M_key_compare = __x._M_impl._M_key_compare;
|
||||||
if (__x._M_root() != 0)
|
if (__x._M_root() != 0)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
// { dg-options "-std=gnu++11" }
|
// { dg-options "-std=gnu++11" }
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#include <testsuite_hooks.h>
|
#include <testsuite_hooks.h>
|
||||||
#include <testsuite_allocator.h>
|
#include <testsuite_allocator.h>
|
||||||
|
|
||||||
|
|
@ -89,10 +91,43 @@ void test03()
|
||||||
VERIFY( tracker_allocator_counter::get_construct_count() == constructs + 2 );
|
VERIFY( tracker_allocator_counter::get_construct_count() == constructs + 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test04()
|
||||||
|
{
|
||||||
|
bool test __attribute__((unused)) = true;
|
||||||
|
|
||||||
|
using namespace __gnu_test;
|
||||||
|
|
||||||
|
typedef tracker_allocator<int> alloc_type;
|
||||||
|
typedef std::set<int, std::less<int>, alloc_type> test_type;
|
||||||
|
|
||||||
|
std::mt19937 rng;
|
||||||
|
std::uniform_int_distribution<int> d;
|
||||||
|
std::uniform_int_distribution<int>::param_type p{0, 100};
|
||||||
|
std::uniform_int_distribution<int>::param_type x{0, 1000};
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
test_type l, r;
|
||||||
|
for (int n = d(rng, p); n > 0; --n)
|
||||||
|
{
|
||||||
|
int i = d(rng, x);
|
||||||
|
l.insert(i);
|
||||||
|
r.insert(i);
|
||||||
|
|
||||||
|
tracker_allocator_counter::reset();
|
||||||
|
|
||||||
|
l = r;
|
||||||
|
|
||||||
|
VERIFY( tracker_allocator_counter::get_allocation_count() == 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
test01();
|
test01();
|
||||||
test02();
|
test02();
|
||||||
test03();
|
test03();
|
||||||
|
test04();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue