@@ -114,7 +114,8 @@ namespace __gnu_debug
__msg_self_move_assign,
// unordered container buckets
__msg_bucket_index_oob,
- __msg_valid_load_factor
+ __msg_valid_load_factor,
+ __msg_equal_allocs
};
class _Error_formatter
@@ -49,6 +49,12 @@ namespace __debug
typedef typename _Base::iterator _Base_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:
typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference;
@@ -78,12 +84,15 @@ namespace __debug
forward_list(forward_list&& __list, const _Alloc& __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
- forward_list(size_type __n)
- : _Base(__n)
+ forward_list(size_type __n, const _Alloc& __al = _Alloc())
+ : _Base(__n, __al)
{ }
forward_list(size_type __n, const _Tp& __value,
@@ -128,12 +137,17 @@ namespace __debug
forward_list&
operator=(forward_list&& __list)
+ noexcept(_Node_alloc_traits::_S_nothrow_move())
{
- // NB: DR 1204.
- // NB: DR 675.
__glibcxx_check_self_move_assign(__list);
- clear();
- swap(__list);
+ bool xfer_memory = _Node_alloc_traits::_S_propagate_on_move_assign()
+ || __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;
}
@@ -333,7 +347,10 @@ namespace __debug
void
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);
this->_M_swap(__list);
}
@@ -333,6 +333,11 @@ _GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \
_M_message(__gnu_debug::__msg_valid_load_factor) \
._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
# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0)
# define __glibcxx_check_string_len(_String,_Len) \
@@ -550,6 +550,10 @@ namespace __debug
noexcept(_Alloc_traits::_S_nothrow_swap())
#endif
{
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+ if (!_Alloc_traits::_S_propagate_on_swap())
+ __glibcxx_check_equal_allocs(__x);
+#endif
_Base::swap(__x);
this->_M_swap(__x);
std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity);
@@ -1,6 +1,6 @@
// <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
// software; you can redistribute it and/or modify it under the
@@ -46,10 +46,14 @@ namespace __profile
{
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:
typedef typename _Base::size_type size_type;
- public:
// 23.2.3.1 construct/copy/destroy:
explicit
forward_list(const _Alloc& __al = _Alloc())
@@ -64,8 +68,8 @@ namespace __profile
{ }
explicit
- forward_list(size_type __n)
- : _Base(__n)
+ forward_list(size_type __n, const _Alloc& __al = _Alloc())
+ : _Base(__n, __al)
{ }
forward_list(size_type __n, const _Tp& __value,
@@ -103,11 +107,9 @@ namespace __profile
forward_list&
operator=(forward_list&& __list)
+ noexcept(_Node_alloc_traits::_S_nothrow_move())
{
- // NB: DR 1204.
- // NB: DR 675.
- _Base::clear();
- _Base::swap(__list);
+ static_cast<_Base&>(*this) = std::move(__list);
return *this;
}
@@ -181,7 +181,8 @@ namespace __gnu_debug
"attempt to self move assign",
"attempt to access container with out-of-bounds bucket index %2;,"
" container only holds %3; buckets",
- "load factor shall be positive"
+ "load factor shall be positive",
+ "allocators must be equal"
};
void
@@ -25,6 +25,23 @@ struct T { int i; };
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()
{
bool test __attribute__((unused)) = true;
@@ -1,4 +1,4 @@
-// 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
// software; you can redistribute it and/or modify it under the
@@ -25,6 +25,23 @@ struct T { int i; };
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()
{
bool test __attribute__((unused)) = true;