diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4db8a132818..7a775d4f68b 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,25 @@ +2006-01-03 Paolo Carlini + + * include/bits/stl_list.h (_List_base<>::_M_get_Node_allocator): Add. + (_M_get_Tp_allocator, get_allocator): Tidy. + (list<>::list(const list&), insert(iterator, size_type, const + value_type&), insert(iterator, _InputIterator, _InputIterator)): + Use _M_get_Node_allocator. + * include/bits/stl_tree.h (_Rb_tree<>::_M_get_Node_allocator()): Add. + (_Rb_tree(const _Rb_tree<>&): Use it. + * include/bits/stl_deque.h (_Deque_base<>::_M_get_map_allocator, + get_allocator): Tidy. + * include/bits/stl_vector.h (_Vector_base<>::get_allocator): Tidy. + * testsuite/23_containers/map/operators/1_neg.cc: Adjust dg-error + line numbers. + * testsuite/23_containers/set/operators/1_neg.cc: Likewise. + + * testsuite/testsuite_allocator.h (uneq_allocator<>::swap): Fix. + + * testsuite/testsuite_allocator.h (class uneq_allocator): A simple + non-empty testing allocator which can be endowed of a "personality" + at construction time. + 2006-01-03 Paolo Carlini * testsuite/27_io/basic_stringstream/str/char/1.cc: Initialize vars. diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index 2eb77673e28..d9bbb007b06 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -1,6 +1,7 @@ // Deque implementation -*- C++ -*- -// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 +// 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 @@ -369,7 +370,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) allocator_type get_allocator() const - { return _M_get_Tp_allocator(); } + { return allocator_type(_M_get_Tp_allocator()); } typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; @@ -416,7 +417,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) _Map_alloc_type _M_get_map_allocator() const - { return _M_get_Tp_allocator(); } + { return _Map_alloc_type(_M_get_Tp_allocator()); } _Tp* _M_allocate_node() diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index 03b70a39fb0..1761bf5c133 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -1,6 +1,7 @@ // List implementation -*- C++ -*- -// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 +// 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 @@ -322,13 +323,21 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) public: typedef _Alloc allocator_type; + _Node_alloc_type& + _M_get_Node_allocator() + { return *static_cast<_Node_alloc_type*>(&this->_M_impl); } + + const _Node_alloc_type& + _M_get_Node_allocator() const + { return *static_cast(&this->_M_impl); } + _Tp_alloc_type _M_get_Tp_allocator() const - { return *static_cast(&this->_M_impl); } + { return _Tp_alloc_type(_M_get_Node_allocator()); } allocator_type get_allocator() const - { return _M_get_Tp_allocator(); } + { return allocator_type(_M_get_Node_allocator()); } _List_base(const allocator_type& __a) : _M_impl(__a) @@ -424,16 +433,11 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) // iterator types. typedef _List_node<_Tp> _Node; - /** @if maint - * One data member plus two memory-handling functions. If the - * _Alloc type requires separate instances, then one of those - * will also be included, accumulated from the topmost parent. - * @endif - */ using _Base::_M_impl; using _Base::_M_put_node; using _Base::_M_get_node; using _Base::_M_get_Tp_allocator; + using _Base::_M_get_Node_allocator; /** * @if maint @@ -489,7 +493,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) * by @a x. */ list(const list& __x) - : _Base(__x.get_allocator()) + : _Base(__x._M_get_Node_allocator()) { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } /** @@ -803,7 +807,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) void insert(iterator __position, size_type __n, const value_type& __x) { - list __tmp(__n, __x, get_allocator()); + list __tmp(__n, __x, _M_get_Node_allocator()); splice(__position, __tmp); } @@ -825,7 +829,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) insert(iterator __position, _InputIterator __first, _InputIterator __last) { - list __tmp(__first, __last, get_allocator()); + list __tmp(__first, __last, _M_get_Node_allocator()); splice(__position, __tmp); } diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index ad0e68df9c1..c2acf87e350 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -1,6 +1,7 @@ // RB tree implementation -*- C++ -*- -// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 +// 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 @@ -348,10 +349,18 @@ _GLIBCXX_BEGIN_NAMESPACE(std) typedef ptrdiff_t difference_type; typedef _Alloc allocator_type; - allocator_type - get_allocator() const + _Node_allocator& + _M_get_Node_allocator() + { return *static_cast<_Node_allocator*>(&this->_M_impl); } + + const _Node_allocator& + _M_get_Node_allocator() const { return *static_cast(&this->_M_impl); } + allocator_type + get_allocator() const + { return allocator_type(_M_get_Node_allocator()); } + protected: _Rb_tree_node* _M_get_node() @@ -563,7 +572,7 @@ _GLIBCXX_BEGIN_NAMESPACE(std) { } _Rb_tree(const _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x) - : _M_impl(__x.get_allocator(), __x._M_impl._M_key_compare) + : _M_impl(__x._M_get_Node_allocator(), __x._M_impl._M_key_compare) { if (__x._M_root() != 0) { diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index c4107fa6e77..43f69de450e 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1,6 +1,7 @@ // Vector implementation -*- C++ -*- -// Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 +// 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 @@ -101,7 +102,7 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) allocator_type get_allocator() const - { return _M_get_Tp_allocator(); } + { return allocator_type(_M_get_Tp_allocator()); } _Vector_base(const allocator_type& __a) : _M_impl(__a) @@ -182,11 +183,6 @@ _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) typedef _Alloc allocator_type; protected: - /** @if maint - * These two functions and three data members are all from the - * base class. They should be pretty self-explanatory, as - * %vector uses a simple contiguous allocation scheme. @endif - */ using _Base::_M_allocate; using _Base::_M_deallocate; using _Base::_M_impl; diff --git a/libstdc++-v3/testsuite/23_containers/map/operators/1_neg.cc b/libstdc++-v3/testsuite/23_containers/map/operators/1_neg.cc index 405f8e4caa7..54e741425de 100644 --- a/libstdc++-v3/testsuite/23_containers/map/operators/1_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/map/operators/1_neg.cc @@ -1,6 +1,7 @@ // { dg-do compile } -// Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 +// 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 @@ -41,5 +42,5 @@ void test01() test &= itr == mapByName.end(); // { dg-error "no" } } -// { dg-error "candidates are" "" { target *-*-* } 210 } -// { dg-error "candidates are" "" { target *-*-* } 214 } +// { dg-error "candidates are" "" { target *-*-* } 211 } +// { dg-error "candidates are" "" { target *-*-* } 215 } diff --git a/libstdc++-v3/testsuite/23_containers/set/operators/1_neg.cc b/libstdc++-v3/testsuite/23_containers/set/operators/1_neg.cc index a0286b0566d..48f6ae68f69 100644 --- a/libstdc++-v3/testsuite/23_containers/set/operators/1_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/set/operators/1_neg.cc @@ -1,6 +1,7 @@ // { dg-do compile } -// Copyright (C) 2000, 2001, 2002, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006 +// 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 @@ -39,5 +40,5 @@ void test01() test &= itr == setByName.end(); // { dg-error "no" } } -// { dg-error "candidates are" "" { target *-*-* } 285 } -// { dg-error "candidates are" "" { target *-*-* } 289 } +// { dg-error "candidates are" "" { target *-*-* } 286 } +// { dg-error "candidates are" "" { target *-*-* } 290 } diff --git a/libstdc++-v3/testsuite/testsuite_allocator.h b/libstdc++-v3/testsuite/testsuite_allocator.h index 170c4db45c9..0ea1215e3b4 100644 --- a/libstdc++-v3/testsuite/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/testsuite_allocator.h @@ -1,7 +1,7 @@ // -*- C++ -*- // Testing allocator for the C++ library testsuite. // -// Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +// Copyright (C) 2002, 2003, 2004, 2005, 2006 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 @@ -37,6 +37,8 @@ #include #include +#include +#include namespace { @@ -231,6 +233,137 @@ namespace __gnu_test throw; } + + // A simple allocator which can be constructed endowed of a given + // "personality" (an integer), queried in operator== to simulate the + // behavior of realworld "unequal" allocators (i.e., not exploiting + // the provision in 20.1.5/4, first bullet). A global unordered_map, + // filled at allocation time with (pointer, personality) pairs, is + // then consulted to enforce the requirements in Table 32 about + // deallocation vs allocator equality. Note that this allocator is + // swappable, not assignable, consistently with Option 3 of DR 431 + // (see N1599). + struct uneq_allocator_base + { + typedef std::tr1::unordered_map map_type; + + // Avoid static initialization troubles and/or bad interactions + // with tests linking testsuite_allocator.o and playing globally + // with operator new/delete. + static map_type& + get_map() + { + static map_type alloc_map; + return alloc_map; + } + }; + + template + class uneq_allocator + : private uneq_allocator_base + { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef Tp* pointer; + typedef const Tp* const_pointer; + typedef Tp& reference; + typedef const Tp& const_reference; + typedef Tp value_type; + + template + struct rebind + { typedef uneq_allocator other; }; + + uneq_allocator() throw() + : personality(0) { } + + uneq_allocator(int person) throw() + : personality(person) { } + + template + uneq_allocator(const uneq_allocator& b) throw() + : personality(b.get_personality()) { } + + int get_personality() const { return personality; } + + pointer + address(reference x) const { return &x; } + + const_pointer + address(const_reference x) const { return &x; } + + pointer + allocate(size_type n, const void* = 0) + { + if (__builtin_expect(n > this->max_size(), false)) + std::__throw_bad_alloc(); + + pointer p = static_cast(::operator new(n * sizeof(Tp))); + try + { + get_map().insert(map_type::value_type(reinterpret_cast(p), + personality)); + } + catch(...) + { + ::operator delete(p); + __throw_exception_again; + } + return p; + } + + void + deallocate(pointer p, size_type) + { + assert( p ); + + map_type::iterator it = get_map().find(reinterpret_cast(p)); + assert( it != get_map().end() ); + + // Enforce requirements in Table 32 about deallocation vs + // allocator equality. + assert( it->second == personality ); + + get_map().erase(it); + ::operator delete(p); + } + + size_type + max_size() const throw() + { return size_t(-1) / sizeof(Tp); } + + void + construct(pointer p, const Tp& val) + { ::new(p) Tp(val); } + + void + destroy(pointer p) { p->~Tp(); } + + private: + // Not assignable... + uneq_allocator& + operator=(const uneq_allocator&); + + // ... yet swappable! + friend inline void + swap(uneq_allocator& a, uneq_allocator& b) + { std::swap(a.personality, b.personality); } + + template + friend inline bool + operator==(const uneq_allocator& a, const uneq_allocator& b) + { return a.personality == b.personality; } + + template + friend inline bool + operator!=(const uneq_allocator& a, const uneq_allocator& b) + { return !(a == b); } + + int personality; + }; + + template class throw_allocator {