Commit cc7f3d0e by Jonathan Wakely Committed by Jonathan Wakely

C++11 allocator support for std::list.

	PR libstdc++/55409
	* include/bits/list.tcc (_List_base::_M_clear()): Use allocator traits.
	(list::list(const list&)): Use allocator propagation trait. Use
	_M_assign_dispatch to copy elements.
	* include/bits/stl_list.h (_List_node): Use __aligned_membuf in C++11.
	(_List_node::_M_valptr()): Add accessor for stored value.
	(_List_iterator, _List_const_iterator, _List_base): Use _M_valptr().
	(_List_base, list): Use allocator traits.
	(_List_base::_M_get_Tp_allocator, _List_base::get_allocator): Remove.
	(_List_base::_M_move_nodes): New function.
	(_List_base(_List_base&&)): Use _M_move_nodes.
	(_List_base(_List_base&&, _Node_alloc_type&&)): New constructor.
	(list::_M_create_node, list::_M_erase, list::max_size): Use allocator
	traits.
	(list(size_type)): Add allocator parameter.
	(list(const list&)): Use allocator propagation trait.
	(list(const list&, const allocator_type&)): New constructor.
	(list(list&&, const allocator_type&)): Likewise.
	(list::operator=(list&&), list::swap(list&)): Use allocator
	propagation traits.
	(list::_M_move_assign): New functions.
	* include/debug/list: Add allocator-extended constructors.
	* include/profile/list: Likewise.
	* python/libstdcxx/v6/printers.py (get_value_from_list_node): New
	function to get value from _List_node.
	(StdListPrinter): Use get_value_from_list_node.
	* testsuite/23_containers/list/allocator/copy.cc: New.
	* testsuite/23_containers/list/allocator/copy_assign.cc: New.
	* testsuite/23_containers/list/allocator/minimal.cc: New.
	* testsuite/23_containers/list/allocator/move.cc: New.
	* testsuite/23_containers/list/allocator/move_assign.cc: New.
	* testsuite/23_containers/list/allocator/noexcept.cc: New.
	* testsuite/23_containers/list/allocator/swap.cc: New.
	* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
	Adjust dg-prune-output line number.
	* testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc:
	Likewise.
	* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
	Likewise.

From-SVN: r224580
parent 917ad3c6
2015-06-17 Jonathan Wakely <jwakely@redhat.com> 2015-06-17 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/55409
* include/bits/list.tcc (_List_base::_M_clear()): Use allocator traits.
(list::list(const list&)): Use allocator propagation trait. Use
_M_assign_dispatch to copy elements.
* include/bits/stl_list.h (_List_node): Use __aligned_membuf in C++11.
(_List_node::_M_valptr()): Add accessor for stored value.
(_List_iterator, _List_const_iterator, _List_base): Use _M_valptr().
(_List_base, list): Use allocator traits.
(_List_base::_M_get_Tp_allocator, _List_base::get_allocator): Remove.
(_List_base::_M_move_nodes): New function.
(_List_base(_List_base&&)): Use _M_move_nodes.
(_List_base(_List_base&&, _Node_alloc_type&&)): New constructor.
(list::_M_create_node, list::_M_erase, list::max_size): Use allocator
traits.
(list(size_type)): Add allocator parameter.
(list(const list&)): Use allocator propagation trait.
(list(const list&, const allocator_type&)): New constructor.
(list(list&&, const allocator_type&)): Likewise.
(list::operator=(list&&), list::swap(list&)): Use allocator
propagation traits.
(list::_M_move_assign): New functions.
* include/debug/list: Add allocator-extended constructors.
* include/profile/list: Likewise.
* python/libstdcxx/v6/printers.py (get_value_from_list_node): New
function to get value from _List_node.
(StdListPrinter): Use get_value_from_list_node.
* testsuite/23_containers/list/allocator/copy.cc: New.
* testsuite/23_containers/list/allocator/copy_assign.cc: New.
* testsuite/23_containers/list/allocator/minimal.cc: New.
* testsuite/23_containers/list/allocator/move.cc: New.
* testsuite/23_containers/list/allocator/move_assign.cc: New.
* testsuite/23_containers/list/allocator/noexcept.cc: New.
* testsuite/23_containers/list/allocator/swap.cc: New.
* testsuite/23_containers/list/requirements/dr438/assign_neg.cc:
Adjust dg-prune-output line number.
* testsuite/23_containers/list/requirements/dr438/constructor_1_neg.cc:
Likewise.
* testsuite/23_containers/list/requirements/dr438/insert_neg.cc:
Likewise.
* include/bits/forward_list.h * include/bits/forward_list.h
(_Fwd_list_base(const _Node_alloc_type&)): Change parameter to (_Fwd_list_base(const _Node_alloc_type&)): Change parameter to
rvalue-reference. rvalue-reference.
......
...@@ -71,10 +71,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -71,10 +71,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ {
_Node* __tmp = static_cast<_Node*>(__cur); _Node* __tmp = static_cast<_Node*>(__cur);
__cur = __tmp->_M_next; __cur = __tmp->_M_next;
_Tp* __val = __tmp->_M_valptr();
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
_M_get_Node_allocator().destroy(__tmp); _Node_alloc_traits::destroy(_M_get_Node_allocator(), __val);
#else #else
_M_get_Tp_allocator().destroy(std::__addressof(__tmp->_M_data)); _Tp_alloc_type(_M_get_Node_allocator()).destroy(__val);
#endif #endif
_M_put_node(__tmp); _M_put_node(__tmp);
} }
...@@ -267,17 +268,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -267,17 +268,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
{ {
if (this != std::__addressof(__x)) if (this != std::__addressof(__x))
{ {
iterator __first1 = begin(); #if __cplusplus >= 201103L
iterator __last1 = end(); if (_Node_alloc_traits::_S_propagate_on_copy_assign())
const_iterator __first2 = __x.begin(); {
const_iterator __last2 = __x.end(); auto& __this_alloc = this->_M_get_Node_allocator();
for (; __first1 != __last1 && __first2 != __last2; auto& __that_alloc = __x._M_get_Node_allocator();
++__first1, ++__first2) if (!_Node_alloc_traits::_S_always_equal()
*__first1 = *__first2; && __this_alloc != __that_alloc)
if (__first2 == __last2) {
erase(__first1, __last1); // replacement allocator cannot free existing storage
else clear();
insert(__last1, __first2, __last2); }
std::__alloc_on_copy(__this_alloc, __that_alloc);
}
#endif
_M_assign_dispatch(__x.begin(), __x.end(), __false_type());
} }
return *this; return *this;
} }
......
...@@ -57,8 +57,11 @@ ...@@ -57,8 +57,11 @@
#define _STL_LIST_H 1 #define _STL_LIST_H 1
#include <bits/concept_check.h> #include <bits/concept_check.h>
#include <ext/alloc_traits.h>
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
#include <initializer_list> #include <initializer_list>
#include <bits/allocated_ptr.h>
#include <ext/aligned_buffer.h>
#endif #endif
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
...@@ -105,14 +108,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -105,14 +108,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
template<typename _Tp> template<typename _Tp>
struct _List_node : public __detail::_List_node_base struct _List_node : public __detail::_List_node_base
{ {
///< User's data.
_Tp _M_data;
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
template<typename... _Args> __gnu_cxx::__aligned_membuf<_Tp> _M_storage;
_List_node(_Args&&... __args) _Tp* _M_valptr() { return _M_storage._M_ptr(); }
: __detail::_List_node_base(), _M_data(std::forward<_Args>(__args)...) _Tp const* _M_valptr() const { return _M_storage._M_ptr(); }
{ } #else
_Tp _M_data;
_Tp* _M_valptr() { return std::__addressof(_M_data); }
_Tp const* _M_valptr() const { return std::__addressof(_M_data); }
#endif #endif
}; };
...@@ -144,14 +147,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -144,14 +147,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_const_cast() const _GLIBCXX_NOEXCEPT _M_const_cast() const _GLIBCXX_NOEXCEPT
{ return *this; } { return *this; }
// Must downcast from _List_node_base to _List_node to get to _M_data. // Must downcast from _List_node_base to _List_node to get to value.
reference reference
operator*() const _GLIBCXX_NOEXCEPT operator*() const _GLIBCXX_NOEXCEPT
{ return static_cast<_Node*>(_M_node)->_M_data; } { return *static_cast<_Node*>(_M_node)->_M_valptr(); }
pointer pointer
operator->() const _GLIBCXX_NOEXCEPT operator->() const _GLIBCXX_NOEXCEPT
{ return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); } { return static_cast<_Node*>(_M_node)->_M_valptr(); }
_Self& _Self&
operator++() _GLIBCXX_NOEXCEPT operator++() _GLIBCXX_NOEXCEPT
...@@ -228,15 +231,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -228,15 +231,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_const_cast() const _GLIBCXX_NOEXCEPT _M_const_cast() const _GLIBCXX_NOEXCEPT
{ return iterator(const_cast<__detail::_List_node_base*>(_M_node)); } { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); }
// Must downcast from List_node_base to _List_node to get to // Must downcast from List_node_base to _List_node to get to value.
// _M_data.
reference reference
operator*() const _GLIBCXX_NOEXCEPT operator*() const _GLIBCXX_NOEXCEPT
{ return static_cast<_Node*>(_M_node)->_M_data; } { return *static_cast<_Node*>(_M_node)->_M_valptr(); }
pointer pointer
operator->() const _GLIBCXX_NOEXCEPT operator->() const _GLIBCXX_NOEXCEPT
{ return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); } { return static_cast<_Node*>(_M_node)->_M_valptr(); }
_Self& _Self&
operator++() _GLIBCXX_NOEXCEPT operator++() _GLIBCXX_NOEXCEPT
...@@ -298,23 +300,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -298,23 +300,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
class _List_base class _List_base
{ {
protected: protected:
// NOTA BENE typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template
// The stored instance is not actually of "allocator_type"'s rebind<_Tp>::other _Tp_alloc_type;
// type. Instead we rebind the type to typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tp_alloc_traits;
// Allocator<List_node<Tp>>, which according to [20.1.5]/4 typedef typename _Tp_alloc_traits::template
// should probably be the same. List_node<Tp> is not the same rebind<_List_node<_Tp> >::other _Node_alloc_type;
// size as Tp (it's two pointers larger), and specializations on typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits;
// Tp may go unused because List_node<Tp> is being bound
// instead.
//
// We put this to the test in the constructors and in
// get_allocator, where we use conversions between
// allocator_type and _Node_alloc_type. The conversion is
// required by table 32 in [20.1.5].
typedef typename _Alloc::template rebind<_List_node<_Tp> >::other
_Node_alloc_type;
typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
static size_t static size_t
_S_distance(const __detail::_List_node_base* __first, _S_distance(const __detail::_List_node_base* __first,
...@@ -338,7 +329,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -338,7 +329,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__detail::_List_node_base _M_node; __detail::_List_node_base _M_node;
#endif #endif
_List_impl() _List_impl() _GLIBCXX_NOEXCEPT
: _Node_alloc_type(), _M_node() : _Node_alloc_type(), _M_node()
{ } { }
...@@ -347,7 +338,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -347,7 +338,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ } { }
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
_List_impl(_Node_alloc_type&& __a) _GLIBCXX_NOEXCEPT _List_impl(_Node_alloc_type&& __a) noexcept
: _Node_alloc_type(std::move(__a)), _M_node() : _Node_alloc_type(std::move(__a)), _M_node()
{ } { }
#endif #endif
...@@ -356,13 +347,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -356,13 +347,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_List_impl _M_impl; _List_impl _M_impl;
#if _GLIBCXX_USE_CXX11_ABI #if _GLIBCXX_USE_CXX11_ABI
size_t _M_get_size() const { return _M_impl._M_node._M_data; } size_t _M_get_size() const { return *_M_impl._M_node._M_valptr(); }
void _M_set_size(size_t __n) { _M_impl._M_node._M_data = __n; } void _M_set_size(size_t __n) { *_M_impl._M_node._M_valptr() = __n; }
void _M_inc_size(size_t __n) { _M_impl._M_node._M_data += __n; } void _M_inc_size(size_t __n) { *_M_impl._M_node._M_valptr() += __n; }
void _M_dec_size(size_t __n) { _M_impl._M_node._M_data -= __n; } void _M_dec_size(size_t __n) { *_M_impl._M_node._M_valptr() -= __n; }
size_t size_t
_M_distance(const __detail::_List_node_base* __first, _M_distance(const __detail::_List_node_base* __first,
...@@ -370,7 +361,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -370,7 +361,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ return _S_distance(__first, __last); } { return _S_distance(__first, __last); }
// return the stored size // return the stored size
size_t _M_node_count() const { return _M_impl._M_node._M_data; } size_t _M_node_count() const { return *_M_impl._M_node._M_valptr(); }
#else #else
// dummy implementations used when the size is not stored // dummy implementations used when the size is not stored
size_t _M_get_size() const { return 0; } size_t _M_get_size() const { return 0; }
...@@ -387,32 +378,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -387,32 +378,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
} }
#endif #endif
_List_node<_Tp>* typename _Node_alloc_traits::pointer
_M_get_node() _M_get_node()
{ return _M_impl._Node_alloc_type::allocate(1); } { return _Node_alloc_traits::allocate(_M_impl, 1); }
void void
_M_put_node(_List_node<_Tp>* __p) _GLIBCXX_NOEXCEPT _M_put_node(typename _Node_alloc_traits::pointer __p) _GLIBCXX_NOEXCEPT
{ _M_impl._Node_alloc_type::deallocate(__p, 1); } { _Node_alloc_traits::deallocate(_M_impl, __p, 1); }
public: public:
typedef _Alloc allocator_type; typedef _Alloc allocator_type;
_Node_alloc_type& _Node_alloc_type&
_M_get_Node_allocator() _GLIBCXX_NOEXCEPT _M_get_Node_allocator() _GLIBCXX_NOEXCEPT
{ return *static_cast<_Node_alloc_type*>(&_M_impl); } { return _M_impl; }
const _Node_alloc_type& const _Node_alloc_type&
_M_get_Node_allocator() const _GLIBCXX_NOEXCEPT _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT
{ return *static_cast<const _Node_alloc_type*>(&_M_impl); } { return _M_impl; }
_Tp_alloc_type
_M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT
{ return _Tp_alloc_type(_M_get_Node_allocator()); }
allocator_type
get_allocator() const _GLIBCXX_NOEXCEPT
{ return allocator_type(_M_get_Node_allocator()); }
_List_base() _List_base()
: _M_impl() : _M_impl()
...@@ -425,6 +408,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -425,6 +408,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
_List_base(_List_base&& __x) noexcept _List_base(_List_base&& __x) noexcept
: _M_impl(std::move(__x._M_get_Node_allocator())) : _M_impl(std::move(__x._M_get_Node_allocator()))
{ _M_move_nodes(std::move(__x)); }
_List_base(_List_base&& __x, _Node_alloc_type&& __a)
: _M_impl(std::move(__a))
{
if (__x._M_get_Node_allocator() == _M_get_Node_allocator())
_M_move_nodes(std::move(__x));
else
_M_init(); // Caller must move individual elements.
}
void
_M_move_nodes(_List_base&& __x)
{ {
auto* const __xnode = std::__addressof(__x._M_impl._M_node); auto* const __xnode = std::__addressof(__x._M_impl._M_node);
if (__xnode->_M_next == __xnode) if (__xnode->_M_next == __xnode)
...@@ -513,14 +509,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -513,14 +509,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
typedef _List_base<_Tp, _Alloc> _Base; typedef _List_base<_Tp, _Alloc> _Base;
typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; typedef typename _Base::_Tp_alloc_type _Tp_alloc_type;
typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits;
typedef typename _Base::_Node_alloc_type _Node_alloc_type; typedef typename _Base::_Node_alloc_type _Node_alloc_type;
typedef typename _Base::_Node_alloc_traits _Node_alloc_traits;
public: public:
typedef _Tp value_type; typedef _Tp value_type;
typedef typename _Tp_alloc_type::pointer pointer; typedef typename _Tp_alloc_traits::pointer pointer;
typedef typename _Tp_alloc_type::const_pointer const_pointer; typedef typename _Tp_alloc_traits::const_pointer const_pointer;
typedef typename _Tp_alloc_type::reference reference; typedef typename _Tp_alloc_traits::reference reference;
typedef typename _Tp_alloc_type::const_reference const_reference; typedef typename _Tp_alloc_traits::const_reference const_reference;
typedef _List_iterator<_Tp> iterator; typedef _List_iterator<_Tp> iterator;
typedef _List_const_iterator<_Tp> const_iterator; typedef _List_const_iterator<_Tp> const_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
...@@ -537,7 +535,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -537,7 +535,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
using _Base::_M_impl; using _Base::_M_impl;
using _Base::_M_put_node; using _Base::_M_put_node;
using _Base::_M_get_node; using _Base::_M_get_node;
using _Base::_M_get_Tp_allocator;
using _Base::_M_get_Node_allocator; using _Base::_M_get_Node_allocator;
/** /**
...@@ -553,8 +550,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -553,8 +550,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_Node* __p = this->_M_get_node(); _Node* __p = this->_M_get_node();
__try __try
{ {
_M_get_Tp_allocator().construct _Tp_alloc_type __alloc(_M_get_Node_allocator());
(std::__addressof(__p->_M_data), __x); __alloc.construct(__p->_M_valptr(), __x);
} }
__catch(...) __catch(...)
{ {
...@@ -568,17 +565,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -568,17 +565,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_Node* _Node*
_M_create_node(_Args&&... __args) _M_create_node(_Args&&... __args)
{ {
_Node* __p = this->_M_get_node(); auto __p = this->_M_get_node();
__try auto& __alloc = _M_get_Node_allocator();
{ __allocated_ptr<_Node_alloc_type> __guard{__alloc, __p};
_M_get_Node_allocator().construct(__p, _Node_alloc_traits::construct(__alloc, __p->_M_valptr(),
std::forward<_Args>(__args)...); std::forward<_Args>(__args)...);
} __guard = nullptr;
__catch(...)
{
_M_put_node(__p);
__throw_exception_again;
}
return __p; return __p;
} }
#endif #endif
...@@ -608,13 +600,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -608,13 +600,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
/** /**
* @brief Creates a %list with default constructed elements. * @brief Creates a %list with default constructed elements.
* @param __n The number of elements to initially create. * @param __n The number of elements to initially create.
* @param __a An allocator object.
* *
* This constructor fills the %list with @a __n default * This constructor fills the %list with @a __n default
* constructed elements. * constructed elements.
*/ */
explicit explicit
list(size_type __n) list(size_type __n, const allocator_type& __a = allocator_type())
: _Base() : _Base(_Node_alloc_type(__a))
{ _M_default_initialize(__n); } { _M_default_initialize(__n); }
/** /**
...@@ -653,7 +646,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -653,7 +646,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* by @a __x. * by @a __x.
*/ */
list(const list& __x) list(const list& __x)
: _Base(__x._M_get_Node_allocator()) : _Base(_Node_alloc_traits::
_S_select_on_copy(__x._M_get_Node_allocator()))
{ _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
...@@ -679,6 +673,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -679,6 +673,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(_Node_alloc_type(__a)) : _Base(_Node_alloc_type(__a))
{ _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); } { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); }
list(const list& __x, const allocator_type& __a)
: _Base(_Node_alloc_type(__a))
{ _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); }
list(list&& __x, const allocator_type& __a)
noexcept(_Node_alloc_traits::_S_always_equal())
: _Base(std::move(__x), _Node_alloc_type(__a))
{
// If __x is not empty it means its allocator is not equal to __a,
// so we need to move from each element individually.
insert(begin(), std::__make_move_if_noexcept_iterator(__x.begin()),
std::__make_move_if_noexcept_iterator(__x.end()));
}
#endif #endif
/** /**
...@@ -738,11 +746,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -738,11 +746,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/ */
list& list&
operator=(list&& __x) operator=(list&& __x)
noexcept(_Node_alloc_traits::_S_nothrow_move())
{ {
// NB: DR 1204. constexpr bool __move_storage =
// NB: DR 675. _Node_alloc_traits::_S_propagate_on_move_assign()
this->clear(); || _Node_alloc_traits::_S_always_equal();
this->swap(__x); _M_move_assign(std::move(__x),
integral_constant<bool, __move_storage>());
return *this; return *this;
} }
...@@ -820,7 +830,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -820,7 +830,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
/// Get a copy of the memory allocation object. /// Get a copy of the memory allocation object.
allocator_type allocator_type
get_allocator() const _GLIBCXX_NOEXCEPT get_allocator() const _GLIBCXX_NOEXCEPT
{ return _Base::get_allocator(); } { return allocator_type(_Base::_M_get_Node_allocator()); }
// iterators // iterators
/** /**
...@@ -949,7 +959,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -949,7 +959,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
/** Returns the size() of the largest possible %list. */ /** Returns the size() of the largest possible %list. */
size_type size_type
max_size() const _GLIBCXX_NOEXCEPT max_size() const _GLIBCXX_NOEXCEPT
{ return _M_get_Node_allocator().max_size(); } { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); }
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
/** /**
...@@ -1342,6 +1352,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -1342,6 +1352,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/ */
void void
swap(list& __x) swap(list& __x)
#if __cplusplus >= 201103L
noexcept(_Node_alloc_traits::_S_nothrow_swap())
#endif
{ {
__detail::_List_node_base::swap(this->_M_impl._M_node, __detail::_List_node_base::swap(this->_M_impl._M_node,
__x._M_impl._M_node); __x._M_impl._M_node);
...@@ -1350,10 +1363,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -1350,10 +1363,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__x._M_set_size(this->_M_get_size()); __x._M_set_size(this->_M_get_size());
this->_M_set_size(__xsize); this->_M_set_size(__xsize);
// _GLIBCXX_RESOLVE_LIB_DEFECTS _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(),
// 431. Swapping containers with unequal allocators. __x._M_get_Node_allocator());
std::__alloc_swap<typename _Base::_Node_alloc_type>::
_S_do_it(_M_get_Node_allocator(), __x._M_get_Node_allocator());
} }
/** /**
...@@ -1774,10 +1785,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -1774,10 +1785,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__position._M_node->_M_unhook(); __position._M_node->_M_unhook();
_Node* __n = static_cast<_Node*>(__position._M_node); _Node* __n = static_cast<_Node*>(__position._M_node);
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
_M_get_Node_allocator().destroy(__n); _Node_alloc_traits::destroy(_M_get_Node_allocator(), __n->_M_valptr());
#else #else
_M_get_Tp_allocator().destroy(std::__addressof(__n->_M_data)); _Tp_alloc_type(_M_get_Node_allocator()).destroy(__n->_M_valptr());
#endif #endif
_M_put_node(__n); _M_put_node(__n);
} }
...@@ -1793,6 +1805,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 ...@@ -1793,6 +1805,40 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
// Used to implement resize. // Used to implement resize.
const_iterator const_iterator
_M_resize_pos(size_type& __new_size) const; _M_resize_pos(size_type& __new_size) const;
#if __cplusplus >= 201103L
void
_M_move_assign(list&& __x, true_type) noexcept
{
this->_M_clear();
if (__x.empty())
this->_M_init();
else
{
this->_M_impl._M_node._M_next = __x._M_impl._M_node._M_next;
this->_M_impl._M_node._M_next->_M_prev = &this->_M_impl._M_node;
this->_M_impl._M_node._M_prev = __x._M_impl._M_node._M_prev;
this->_M_impl._M_node._M_prev->_M_next = &this->_M_impl._M_node;
this->_M_set_size(__x._M_get_size());
__x._M_init();
}
std::__alloc_on_move(this->_M_get_Node_allocator(),
__x._M_get_Node_allocator());
}
void
_M_move_assign(list&& __x, false_type)
{
if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator())
_M_move_assign(std::move(__x), true_type{});
else
// The rvalue's allocator cannot be moved, or is not equal,
// so we need to individually move each element.
_M_assign_dispatch(std::__make_move_if_noexcept_iterator(__x.begin()),
std::__make_move_if_noexcept_iterator(__x.end()),
__false_type{});
}
#endif
}; };
_GLIBCXX_END_NAMESPACE_CXX11 _GLIBCXX_END_NAMESPACE_CXX11
...@@ -1903,7 +1949,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1903,7 +1949,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
++__beyond; ++__beyond;
bool __whole = __first == __beyond; bool __whole = __first == __beyond;
if (__builtin_constant_p (__whole) && __whole) if (__builtin_constant_p (__whole) && __whole)
return static_cast<const _Sentinel*>(__last._M_node)->_M_data; return *static_cast<const _Sentinel*>(__last._M_node)->_M_valptr();
ptrdiff_t __n = 0; ptrdiff_t __n = 0;
while (__first != __last) while (__first != __last)
......
...@@ -94,6 +94,12 @@ namespace __debug ...@@ -94,6 +94,12 @@ namespace __debug
: _Base(__l, __a) { } : _Base(__l, __a) { }
~list() = default; ~list() = default;
list(const list& __x, const allocator_type& __a)
: _Base(__x, __a) { }
list(list&& __x, const allocator_type& __a)
: _Base(std::move(__x), __a) { }
#endif #endif
explicit explicit
...@@ -102,8 +108,8 @@ namespace __debug ...@@ -102,8 +108,8 @@ namespace __debug
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
explicit explicit
list(size_type __n) list(size_type __n, const allocator_type& __a = allocator_type())
: _Base(__n) { } : _Base(__n, __a) { }
list(size_type __n, const _Tp& __value, list(size_type __n, const _Tp& __value,
const _Allocator& __a = _Allocator()) const _Allocator& __a = _Allocator())
......
...@@ -145,6 +145,12 @@ namespace __profile ...@@ -145,6 +145,12 @@ namespace __profile
list(initializer_list<value_type> __l, list(initializer_list<value_type> __l,
const allocator_type& __a = allocator_type()) const allocator_type& __a = allocator_type())
: _Base(__l, __a) { } : _Base(__l, __a) { }
list(const list& __x, const allocator_type& __a)
: _Base(__x, __a) { }
list(list&& __x, const allocator_type& __a)
: _Base(std::move(__x), __a) { }
#endif #endif
explicit explicit
...@@ -153,8 +159,8 @@ namespace __profile ...@@ -153,8 +159,8 @@ namespace __profile
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
explicit explicit
list(size_type __n) list(size_type __n, const allocator_type& __a = allocator_type())
: _Base(__n) { } : _Base(__n, __a) { }
list(size_type __n, const _Tp& __value, list(size_type __n, const _Tp& __value,
const _Allocator& __a = _Allocator()) const _Allocator& __a = _Allocator())
......
...@@ -128,6 +128,22 @@ class UniquePointerPrinter: ...@@ -128,6 +128,22 @@ class UniquePointerPrinter:
return ('std::unique_ptr<%s> containing %s' % (str(v.type.target()), return ('std::unique_ptr<%s> containing %s' % (str(v.type.target()),
str(v))) str(v)))
def get_value_from_list_node(node):
"""Returns the value held in an _List_node<_Val>"""
try:
member = node.type.fields()[1].name
if member == '_M_data':
# C++03 implementation, node contains the value as a member
return node['_M_data']
elif member == '_M_storage':
# C++11 implementation, node stores value in __aligned_membuf
p = node['_M_storage']['_M_storage'].address
p = p.cast(node.type.template_argument(0).pointer())
return p.dereference()
except:
pass
raise ValueError("Unsupported implementation for %s" % str(node.type))
class StdListPrinter: class StdListPrinter:
"Print a std::list" "Print a std::list"
...@@ -148,7 +164,8 @@ class StdListPrinter: ...@@ -148,7 +164,8 @@ class StdListPrinter:
self.base = elt['_M_next'] self.base = elt['_M_next']
count = self.count count = self.count
self.count = self.count + 1 self.count = self.count + 1
return ('[%d]' % count, elt['_M_data']) val = get_value_from_list_node(elt)
return ('[%d]' % count, val)
def __init__(self, typename, val): def __init__(self, typename, val):
self.typename = typename self.typename = typename
...@@ -174,7 +191,8 @@ class StdListIteratorPrinter: ...@@ -174,7 +191,8 @@ class StdListIteratorPrinter:
def to_string(self): def to_string(self):
nodetype = find_type(self.val.type, '_Node') nodetype = find_type(self.val.type, '_Node')
nodetype = nodetype.strip_typedefs().pointer() nodetype = nodetype.strip_typedefs().pointer()
return self.val['_M_node'].cast(nodetype).dereference()['_M_data'] node = self.val['_M_node'].cast(nodetype).dereference()
return get_value_from_list_node(node)
class StdSlistPrinter: class StdSlistPrinter:
"Print a __gnu_cxx::slist" "Print a __gnu_cxx::slist"
...@@ -440,7 +458,7 @@ def get_value_from_Rb_tree_node(node): ...@@ -440,7 +458,7 @@ def get_value_from_Rb_tree_node(node):
# C++03 implementation, node contains the value as a member # C++03 implementation, node contains the value as a member
return node['_M_value_field'] return node['_M_value_field']
elif member == '_M_storage': elif member == '_M_storage':
# C++11 implementation, node stores value in __aligned_buffer # C++11 implementation, node stores value in __aligned_membuf
p = node['_M_storage']['_M_storage'].address p = node['_M_storage']['_M_storage'].address
p = p.cast(node.type.template_argument(0).pointer()) p = p.cast(node.type.template_argument(0).pointer())
return p.dereference() return p.dereference()
......
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++11" }
#include <list>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
struct T { int i; };
using __gnu_test::propagating_allocator;
void test01()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, false> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(v1);
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(0 == v2.get_allocator().get_personality());
}
void test02()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, true> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(v1);
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
}
void test03()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, true> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(v1, alloc_type(2));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(2 == v2.get_allocator().get_personality());
}
int main()
{
test01();
test02();
test03();
return 0;
}
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++11" }
#include <list>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
struct T { int i; };
using __gnu_test::propagating_allocator;
void test01()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, false> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(alloc_type(2));
v2.push_front(T());
v2 = v1;
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(2 == v2.get_allocator().get_personality());
}
void test02()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, true> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(alloc_type(2));
v2.push_front(T());
v2 = v1;
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
}
int main()
{
test01();
test02();
return 0;
}
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++11" }
#include <list>
#include <memory>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
struct T { int i; };
bool operator==(const T& l, const T& r) { return l.i == r.i; }
bool operator<(const T& l, const T& r) { return l.i < r.i; }
using __gnu_test::SimpleAllocator;
template class std::list<T, SimpleAllocator<T>>;
void test01()
{
bool test __attribute__((unused)) = true;
typedef SimpleAllocator<T> alloc_type;
typedef std::allocator_traits<alloc_type> traits_type;
typedef std::list<T, alloc_type> test_type;
test_type v(alloc_type{});
v.push_front(T());
VERIFY( v.max_size() < traits_type::max_size(v.get_allocator()) );
}
int main()
{
test01();
return 0;
}
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++11" }
#include <list>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
struct T { int i; };
using __gnu_test::uneq_allocator;
void test01()
{
bool test __attribute__((unused)) = true;
typedef uneq_allocator<T> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { T() };
auto it = v1.begin();
test_type v2(std::move(v1));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
VERIFY( it == v2.begin() );
}
void test02()
{
bool test __attribute__((unused)) = true;
typedef uneq_allocator<T> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1 = { T() };
test_type v2(std::move(v1), alloc_type(2));
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(2 == v2.get_allocator().get_personality());
}
int main()
{
test01();
test02();
return 0;
}
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++11" }
#include <list>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
struct T { int i; };
using __gnu_test::propagating_allocator;
void test01()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, false> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(alloc_type(2));
v2.push_front(T());
v2 = std::move(v1);
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(2 == v2.get_allocator().get_personality());
}
void test02()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, true> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
auto it = v1.begin();
test_type v2(alloc_type(2));
v2.push_front(T());
v2 = std::move(v1);
VERIFY(0 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
VERIFY( it == v2.begin() );
}
int main()
{
test01();
test02();
return 0;
}
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-do compile }
// { dg-options "-std=gnu++11" }
#include <list>
#include <testsuite_allocator.h>
struct T { int i; };
namespace __gnu_test
{
template<typename U>
inline void
swap(propagating_allocator<U, true>& l, propagating_allocator<U, true>& r)
noexcept(false)
{ }
}
using __gnu_test::propagating_allocator;
void test01()
{
typedef std::allocator<T> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1;
test_type v2;
// this is a GNU extension for std::allocator
static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" );
static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" );
}
void test02()
{
typedef propagating_allocator<T, false> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
test_type v2(alloc_type(2));
static_assert( !noexcept( v1 = std::move(v2) ), "Move assign can throw" );
static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" );
}
void test03()
{
typedef propagating_allocator<T, true> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
test_type v2(alloc_type(2));
static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" );
static_assert( !noexcept( v1.swap(v2) ), "Swap can throw" );
}
// Copyright (C) 2015 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
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-std=gnu++11" }
#include <list>
#include <testsuite_hooks.h>
#include <testsuite_allocator.h>
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;
typedef propagating_allocator<T, false> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(alloc_type(2));
v2.push_front(T());
std::swap(v1, v2);
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(2 == v2.get_allocator().get_personality());
// swap back so assertions in uneq_allocator::deallocate don't fail
std::swap(v1, v2);
}
void test02()
{
bool test __attribute__((unused)) = true;
typedef propagating_allocator<T, true> alloc_type;
typedef std::list<T, alloc_type> test_type;
test_type v1(alloc_type(1));
v1.push_front(T());
test_type v2(alloc_type(2));
v2.push_front(T());
std::swap(v1, v2);
VERIFY(2 == v1.get_allocator().get_personality());
VERIFY(1 == v2.get_allocator().get_personality());
}
int main()
{
test01();
test02();
return 0;
}
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1730 } // { dg-prune-output 1741 }
#include <list> #include <list>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1682 } // { dg-prune-output 1693 }
#include <list> #include <list>
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
// <http://www.gnu.org/licenses/>. // <http://www.gnu.org/licenses/>.
// { dg-do compile } // { dg-do compile }
// { dg-prune-output 1682 } // { dg-prune-output 1693 }
#include <list> #include <list>
......
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