Commit e77c9aed by Jonathan Wakely Committed by Jonathan Wakely

forward_list: Update to meet allocator-aware requirements.

	* include/profile/forward_list: Update to meet allocator-aware
	requirements.
	* include/debug/forward_list: Likewise.
	* include/debug/vector: Verify allocators are swapped or equal.
	* include/debug/macros.h (__glibcxx_check_equal_allocs): Define.
	* include/debug/formatter.h: Add new debug message.
	* src/c++11/debug.cc: Likewise.
	* testsuite/23_containers/forward_list/allocator/swap.cc: Do not
	swap containers with non-propagating, non-equal allocators.
	* testsuite/23_containers/vector/allocator/swap.cc: Likewise.

From-SVN: r193186
parent 68459267
2012-11-05 Jonathan Wakely <jwakely.gcc@gmail.com>
* include/profile/forward_list: Update to meet allocator-aware
requirements.
* include/debug/forward_list: Likewise.
* include/debug/vector: Verify allocators are swapped or equal.
* include/debug/macros.h (__glibcxx_check_equal_allocs): Define.
* include/debug/formatter.h: Add new debug message.
* src/c++11/debug.cc: Likewise.
* testsuite/23_containers/forward_list/allocator/swap.cc: Do not
swap containers with non-propagating, non-equal allocators.
* testsuite/23_containers/vector/allocator/swap.cc: Likewise.
2012-11-05 Benjamin Kosnik <bkoz@redhat.com> 2012-11-05 Benjamin Kosnik <bkoz@redhat.com>
Oleg Smolsky <oleg@smolsky.net> Oleg Smolsky <oleg@smolsky.net>
......
...@@ -114,7 +114,8 @@ namespace __gnu_debug ...@@ -114,7 +114,8 @@ namespace __gnu_debug
__msg_self_move_assign, __msg_self_move_assign,
// unordered container buckets // unordered container buckets
__msg_bucket_index_oob, __msg_bucket_index_oob,
__msg_valid_load_factor __msg_valid_load_factor,
__msg_equal_allocs
}; };
class _Error_formatter class _Error_formatter
......
...@@ -49,6 +49,12 @@ namespace __debug ...@@ -49,6 +49,12 @@ namespace __debug
typedef typename _Base::iterator _Base_iterator; typedef typename _Base::iterator _Base_iterator;
typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::const_iterator _Base_const_iterator;
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type;
typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
public: public:
typedef typename _Base::reference reference; typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference; typedef typename _Base::const_reference const_reference;
...@@ -78,12 +84,15 @@ namespace __debug ...@@ -78,12 +84,15 @@ namespace __debug
forward_list(forward_list&& __list, const _Alloc& __al) forward_list(forward_list&& __list, const _Alloc& __al)
: _Base(std::move(__list._M_base()), __al) : _Base(std::move(__list._M_base()), __al)
{ {
this->_M_swap(__list); if (__list.get_allocator() == __al)
this->_M_swap(__list);
else
__list._M_invalidate_all();
} }
explicit explicit
forward_list(size_type __n) forward_list(size_type __n, const _Alloc& __al = _Alloc())
: _Base(__n) : _Base(__n, __al)
{ } { }
forward_list(size_type __n, const _Tp& __value, forward_list(size_type __n, const _Tp& __value,
...@@ -128,12 +137,17 @@ namespace __debug ...@@ -128,12 +137,17 @@ namespace __debug
forward_list& forward_list&
operator=(forward_list&& __list) operator=(forward_list&& __list)
noexcept(_Node_alloc_traits::_S_nothrow_move())
{ {
// NB: DR 1204.
// NB: DR 675.
__glibcxx_check_self_move_assign(__list); __glibcxx_check_self_move_assign(__list);
clear(); bool xfer_memory = _Node_alloc_traits::_S_propagate_on_move_assign()
swap(__list); || __list.get_allocator() == this->get_allocator();
static_cast<_Base&>(*this) = std::move(__list);
if (xfer_memory)
this->_M_swap(__list);
else
this->_M_invalidate_all();
__list._M_invalidate_all();
return *this; return *this;
} }
...@@ -333,7 +347,10 @@ namespace __debug ...@@ -333,7 +347,10 @@ namespace __debug
void void
swap(forward_list& __list) swap(forward_list& __list)
noexcept(_Node_alloc_traits::_S_nothrow_swap())
{ {
if (!_Node_alloc_traits::_S_propagate_on_swap())
__glibcxx_check_equal_allocs(__list);
_Base::swap(__list); _Base::swap(__list);
this->_M_swap(__list); this->_M_swap(__list);
} }
......
...@@ -333,6 +333,11 @@ _GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \ ...@@ -333,6 +333,11 @@ _GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \
_M_message(__gnu_debug::__msg_valid_load_factor) \ _M_message(__gnu_debug::__msg_valid_load_factor) \
._M_sequence(*this, "this")) ._M_sequence(*this, "this"))
#define __glibcxx_check_equal_allocs(_Other) \
_GLIBCXX_DEBUG_VERIFY(this->get_allocator() == _Other.get_allocator(), \
_M_message(__gnu_debug::__msg_equal_allocs) \
._M_sequence(*this, "this"))
#ifdef _GLIBCXX_DEBUG_PEDANTIC #ifdef _GLIBCXX_DEBUG_PEDANTIC
# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0) # define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0)
# define __glibcxx_check_string_len(_String,_Len) \ # define __glibcxx_check_string_len(_String,_Len) \
......
...@@ -550,6 +550,10 @@ namespace __debug ...@@ -550,6 +550,10 @@ namespace __debug
noexcept(_Alloc_traits::_S_nothrow_swap()) noexcept(_Alloc_traits::_S_nothrow_swap())
#endif #endif
{ {
#ifdef __GXX_EXPERIMENTAL_CXX0X__
if (!_Alloc_traits::_S_propagate_on_swap())
__glibcxx_check_equal_allocs(__x);
#endif
_Base::swap(__x); _Base::swap(__x);
this->_M_swap(__x); this->_M_swap(__x);
std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity); std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
......
// <forward_list> -*- C++ -*- // <forward_list> -*- C++ -*-
// Copyright (C) 2010, 2011 Free Software Foundation, Inc. // Copyright (C) 2010-2012 Free Software Foundation, Inc.
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -46,10 +46,14 @@ namespace __profile ...@@ -46,10 +46,14 @@ namespace __profile
{ {
typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base; typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base;
typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type;
typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
public: public:
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
public:
// 23.2.3.1 construct/copy/destroy: // 23.2.3.1 construct/copy/destroy:
explicit explicit
forward_list(const _Alloc& __al = _Alloc()) forward_list(const _Alloc& __al = _Alloc())
...@@ -64,8 +68,8 @@ namespace __profile ...@@ -64,8 +68,8 @@ namespace __profile
{ } { }
explicit explicit
forward_list(size_type __n) forward_list(size_type __n, const _Alloc& __al = _Alloc())
: _Base(__n) : _Base(__n, __al)
{ } { }
forward_list(size_type __n, const _Tp& __value, forward_list(size_type __n, const _Tp& __value,
...@@ -103,11 +107,9 @@ namespace __profile ...@@ -103,11 +107,9 @@ namespace __profile
forward_list& forward_list&
operator=(forward_list&& __list) operator=(forward_list&& __list)
noexcept(_Node_alloc_traits::_S_nothrow_move())
{ {
// NB: DR 1204. static_cast<_Base&>(*this) = std::move(__list);
// NB: DR 675.
_Base::clear();
_Base::swap(__list);
return *this; return *this;
} }
......
...@@ -181,7 +181,8 @@ namespace __gnu_debug ...@@ -181,7 +181,8 @@ namespace __gnu_debug
"attempt to self move assign", "attempt to self move assign",
"attempt to access container with out-of-bounds bucket index %2;," "attempt to access container with out-of-bounds bucket index %2;,"
" container only holds %3; buckets", " container only holds %3; buckets",
"load factor shall be positive" "load factor shall be positive",
"allocators must be equal"
}; };
void void
......
...@@ -25,6 +25,23 @@ struct T { int i; }; ...@@ -25,6 +25,23 @@ struct T { int i; };
using __gnu_test::propagating_allocator; using __gnu_test::propagating_allocator;
// It is undefined behaviour to swap() containers wth unequal allocators
// if the allocator doesn't propagate, so ensure the allocators compare
// equal, while still being able to test propagation via get_personality().
bool
operator==(const propagating_allocator<T, false>&,
const propagating_allocator<T, false>&)
{
return true;
}
bool
operator!=(const propagating_allocator<T, false>&,
const propagating_allocator<T, false>&)
{
return false;
}
void test01() void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
......
// Copyright (C) 2011 Free Software Foundation // Copyright (C) 2011-2012 Free Software Foundation
// //
// This file is part of the GNU ISO C++ Library. This library is free // This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the // software; you can redistribute it and/or modify it under the
...@@ -25,6 +25,23 @@ struct T { int i; }; ...@@ -25,6 +25,23 @@ struct T { int i; };
using __gnu_test::propagating_allocator; using __gnu_test::propagating_allocator;
// It is undefined behaviour to swap() containers wth unequal allocators
// if the allocator doesn't propagate, so ensure the allocators compare
// equal, while still being able to test propagation via get_personality().
bool
operator==(const propagating_allocator<T, false>&,
const propagating_allocator<T, false>&)
{
return true;
}
bool
operator!=(const propagating_allocator<T, false>&,
const propagating_allocator<T, false>&)
{
return false;
}
void test01() void test01()
{ {
bool test __attribute__((unused)) = true; bool test __attribute__((unused)) = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment