From: austern Date: Thu, 18 Dec 2003 18:35:38 +0000 (+0000) Subject: * include/bits/demangle.h: Fix allocator type correctness, X-Git-Tag: upstream/4.9.2~74612 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0f9f763311d9f5e59001865f815f8ffbf9bc4868;p=platform%2Fupstream%2Flinaro-gcc.git * include/bits/demangle.h: Fix allocator type correctness, i.e. make sure that when we instantiate a container with a value type and an allocator, the allocator's value type matches the container's. * include/bits/stl_deque.h (_Deque_alloc_base): Eliminate. (_Deque_base): inherit directly from the deque's allocator. Use rebinding instead of _Alloc_traits. Pick up data members from _Deque_alloc_base. * include/bits/stl_list.h (_List_alloc_base): Eliminate. (_List_base): Inherit directly from the list's allocator. Use rebinding instead of _Alloc_traits. Pick up data members from _List_alloc_base. * include/bits/stl_vector.h (_Vector_alloc_base): Eliminate (_Vector_base): Inherit directly from the vector's allocator. Use rebinding instead of _Alloc_traits. Pick up data members from _Vector_alloc_base. * include/ext/hashtable.h: Fix allocator type correctness (the vector of buckets must be passed an allocator for objects of type _Node*). Use rebinding instead of _Alloc_traits. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@74787 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index e86b749..3d9f85e 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,25 @@ +2003-12-18 Matt Austern + + * include/bits/demangle.h: Fix allocator type correctness, + i.e. make sure that when we instantiate a container with a value + type and an allocator, the allocator's value type matches the + container's. + * include/bits/stl_deque.h (_Deque_alloc_base): Eliminate. + (_Deque_base): inherit directly from the deque's allocator. Use + rebinding instead of _Alloc_traits. Pick up data members from + _Deque_alloc_base. + * include/bits/stl_list.h (_List_alloc_base): Eliminate. + (_List_base): Inherit directly from the list's allocator. Use + rebinding instead of _Alloc_traits. Pick up data members from + _List_alloc_base. + * include/bits/stl_vector.h (_Vector_alloc_base): Eliminate + (_Vector_base): Inherit directly from the vector's allocator. Use + rebinding instead of _Alloc_traits. Pick up data members from + _Vector_alloc_base. + * include/ext/hashtable.h: Fix allocator type correctness (the + vector of buckets must be passed an allocator for objects of + type _Node*). Use rebinding instead of _Alloc_traits. + 2003-12-17 Paolo Carlini * include/bits/locale_facets.tcc (time_get::_M_extract_via_format): diff --git a/libstdc++-v3/include/bits/demangle.h b/libstdc++-v3/include/bits/demangle.h index 751e58c..82e2d06 100644 --- a/libstdc++-v3/include/bits/demangle.h +++ b/libstdc++-v3/include/bits/demangle.h @@ -113,7 +113,9 @@ namespace __gnu_cxx template class qualifier { - typedef std::basic_string, Allocator> + typedef typename Allocator::template rebind::other + char_Allocator; + typedef std::basic_string, char_Allocator> string_type; private: @@ -206,17 +208,22 @@ namespace __gnu_cxx template class qualifier_list { - typedef std::basic_string, Allocator> + typedef typename Allocator::template rebind::other + char_Allocator; + typedef std::basic_string, char_Allocator> string_type; private: mutable bool M_printing_suppressed; - std::vector, Allocator> M_qualifier_starts; + typedef qualifier qual; + typedef typename Allocator::template rebind::other qual_Allocator; + typedef std::vector qual_vector; + qual_vector M_qualifier_starts; session& M_demangler; void decode_KVrA(string_type& prefix, string_type& postfix, int cvq, - typename std::vector, Allocator>:: - const_reverse_iterator const& iter_array) const; + typename qual_vector:: + const_reverse_iterator const& iter_array) const; public: qualifier_list(session& demangler_obj) @@ -270,7 +277,7 @@ namespace __gnu_cxx #if _GLIBCXX_DEMANGLER_CWDEBUG friend std::ostream& operator<<(std::ostream& os, qualifier_list const& list) { - typename std::vector, Allocator>::const_iterator + typename qual_vector::const_iterator iter = list.M_qualifier_starts.begin(); if (iter != list.M_qualifier_starts.end()) { @@ -344,7 +351,9 @@ namespace __gnu_cxx class session { friend class qualifier_list; - typedef std::basic_string, Allocator> + typedef typename Allocator::template rebind::other + char_Allocator; + typedef std::basic_string, char_Allocator> string_type; private: @@ -361,9 +370,13 @@ namespace __gnu_cxx bool M_name_is_conversion_operator; bool M_template_args_need_space; string_type M_function_name; - std::vector M_template_arg_pos; + typedef typename Allocator::template rebind::other + int_Allocator; + typedef typename Allocator::template rebind::other + subst_Allocator; + std::vector M_template_arg_pos; int M_template_arg_pos_offset; - std::vector M_substitutions_pos; + std::vector M_substitutions_pos; implementation_details const& M_implementation_details; #if _GLIBCXX_DEMANGLER_CWDEBUG bool M_inside_add_substitution; @@ -1690,8 +1703,7 @@ namespace __gnu_cxx void qualifier_list::decode_KVrA( string_type& prefix, string_type& postfix, int cvq, - typename std::vector, Allocator>:: - const_reverse_iterator const& iter_array) const + typename qual_vector::const_reverse_iterator const& iter_array) const { _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_KVrA"); if ((cvq & cvq_K)) @@ -1703,7 +1715,7 @@ namespace __gnu_cxx if ((cvq & cvq_A)) { int n = cvq >> 5; - for (typename std::vector, Allocator>:: + for (typename qual_vector:: const_reverse_iterator iter = iter_array; iter != M_qualifier_starts.rend(); ++iter) { @@ -1744,9 +1756,8 @@ namespace __gnu_cxx { _GLIBCXX_DEMANGLER_DOUT_ENTERING3("decode_qualifiers"); int cvq = 0; - typename std::vector, Allocator>:: - const_reverse_iterator iter_array; - for(typename std::vector, Allocator>:: + typename qual_vector::const_reverse_iterator iter_array; + for(typename qual_vector:: const_reverse_iterator iter = M_qualifier_starts.rbegin(); iter != M_qualifier_starts.rend(); ++iter) { @@ -2676,8 +2687,8 @@ namespace __gnu_cxx template struct demangle { - typedef Allocator allocator_type; - typedef std::basic_string, Allocator> + typedef typename Allocator::template rebind::other char_Allocator; + typedef std::basic_string, char_Allocator> string_type; static string_type symbol(char const* in, demangler::implementation_details const& id); @@ -2690,7 +2701,7 @@ namespace __gnu_cxx // Demangle `input' which should be a mangled function name as for // instance returned by nm(1). template - std::basic_string, Allocator> + typename demangle::string_type demangle::symbol(char const* input, demangler::implementation_details const& id) { @@ -2741,7 +2752,7 @@ namespace __gnu_cxx // Demangle `input' which must be a zero terminated mangled type // name as for instance returned by std::type_info::name(). template - std::basic_string, Allocator> + typename demangle::string_type demangle::type(char const* input, demangler::implementation_details const& id) { diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index 2498bb6..64a24b1 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -332,139 +332,70 @@ namespace __gnu_norm return __x + __n; } - - /// @if maint Primary default version. @endif /** * @if maint - * Deque base class. It has two purposes. First, its constructor - * and destructor allocate (but don't initialize) storage. This makes - * %exception safety easier. Second, the base class encapsulates all of - * the differences between SGI-style allocators and standard-conforming - * allocators. (See allocator.h for more on this topic.) There are two - * versions: this ordinary one, and the space-saving specialization for - * instanceless allocators. + * Deque base class. This class provides the unified face for %deque's + * allocation. This class's constructor and destructor allocate and + * deallocate (but do not initialize) storage. This makes %exception + * safety easier. + * + * Nothing in this class ever constructs or destroys an actual Tp element. + * (Deque handles that itself.) Only/All memory management is performed + * here. * @endif */ - template - class _Deque_alloc_base - { - public: - typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; - allocator_type get_allocator() const { return _M_node_allocator; } - - _Deque_alloc_base(const allocator_type& __a) - : _M_node_allocator(__a), _M_map_allocator(__a), - _M_map(0), _M_map_size(0) - {} - - protected: - typedef typename _Alloc_traits<_Tp*, _Alloc>::allocator_type - _Map_allocator_type; - - _Tp* - _M_allocate_node() - { - return _M_node_allocator.allocate(__deque_buf_size(sizeof(_Tp))); - } - - void - _M_deallocate_node(_Tp* __p) - { - _M_node_allocator.deallocate(__p, __deque_buf_size(sizeof(_Tp))); - } - - _Tp** - _M_allocate_map(size_t __n) - { return _M_map_allocator.allocate(__n); } - - void - _M_deallocate_map(_Tp** __p, size_t __n) - { _M_map_allocator.deallocate(__p, __n); } - - allocator_type _M_node_allocator; - _Map_allocator_type _M_map_allocator; - _Tp** _M_map; - size_t _M_map_size; - }; - - /// @if maint Specialization for instanceless allocators. @endif template - class _Deque_alloc_base<_Tp, _Alloc, true> + class _Deque_base + : public _Alloc { public: - typedef typename _Alloc_traits<_Tp,_Alloc>::allocator_type allocator_type; - allocator_type get_allocator() const { return allocator_type(); } + typedef _Alloc allocator_type; + allocator_type get_allocator() const + { return *static_cast(this); } + + typedef _Deque_iterator<_Tp,_Tp&,_Tp*> iterator; + typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; - _Deque_alloc_base(const allocator_type&) - : _M_map(0), _M_map_size(0) - {} - + _Deque_base(const allocator_type& __a, size_t __num_elements) + : _Alloc(__a), _M_start(), _M_finish() + { _M_initialize_map(__num_elements); } + _Deque_base(const allocator_type& __a) + : _Alloc(__a), _M_start(), _M_finish() {} + ~_Deque_base(); + protected: - typedef typename _Alloc_traits<_Tp,_Alloc>::_Alloc_type _Node_alloc_type; - typedef typename _Alloc_traits<_Tp*,_Alloc>::_Alloc_type _Map_alloc_type; - + typedef typename _Alloc::template rebind<_Tp*>::other _Map_alloc_type; + _Map_alloc_type _M_get_map_allocator() const + { return _Map_alloc_type(this->get_allocator()); } + _Tp* _M_allocate_node() { - return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp))); + return _Alloc::allocate(__deque_buf_size(sizeof(_Tp))); } void _M_deallocate_node(_Tp* __p) { - _Node_alloc_type::deallocate(__p, __deque_buf_size(sizeof(_Tp))); + _Alloc::deallocate(__p, __deque_buf_size(sizeof(_Tp))); } _Tp** _M_allocate_map(size_t __n) - { return _Map_alloc_type::allocate(__n); } + { return _M_get_map_allocator().allocate(__n); } void _M_deallocate_map(_Tp** __p, size_t __n) - { _Map_alloc_type::deallocate(__p, __n); } - - _Tp** _M_map; - size_t _M_map_size; - }; - - - /** - * @if maint - * Deque base class. Using _Alloc_traits in the instantiation of the parent - * class provides the compile-time dispatching mentioned in the parent's - * docs. This class provides the unified face for %deque's allocation. - * - * Nothing in this class ever constructs or destroys an actual Tp element. - * (Deque handles that itself.) Only/All memory management is performed - * here. - * @endif - */ - template - class _Deque_base - : public _Deque_alloc_base<_Tp,_Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> - { - public: - typedef _Deque_alloc_base<_Tp,_Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> - _Base; - typedef typename _Base::allocator_type allocator_type; - typedef _Deque_iterator<_Tp,_Tp&,_Tp*> iterator; - typedef _Deque_iterator<_Tp,const _Tp&,const _Tp*> const_iterator; - - _Deque_base(const allocator_type& __a, size_t __num_elements) - : _Base(__a), _M_start(), _M_finish() - { _M_initialize_map(__num_elements); } - _Deque_base(const allocator_type& __a) - : _Base(__a), _M_start(), _M_finish() {} - ~_Deque_base(); - + { _M_get_map_allocator().deallocate(__p, __n); } + protected: void _M_initialize_map(size_t); void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish); void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish); enum { _S_initial_map_size = 8 }; + _Tp** _M_map; + size_t _M_map_size; iterator _M_start; iterator _M_finish; }; @@ -670,9 +601,7 @@ namespace __gnu_norm using _Base::_M_deallocate_map; /** @if maint - * A total of four data members accumulated down the heirarchy. If the - * _Alloc type requires separate instances, then two of them will also be - * included in each deque. + * A total of four data members accumulated down the heirarchy. * @endif */ using _Base::_M_map; diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index 4524e9e..8fd2f71 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -202,36 +202,16 @@ namespace __gnu_norm } }; - - /// @if maint Primary default version. @endif /** * @if maint - * See bits/stl_deque.h's _Deque_alloc_base for an explanation. + * See bits/stl_deque.h's _Deque_base for an explanation. * @endif */ - template - class _List_alloc_base + template + class _List_base + : public _Alloc::template rebind<_List_node<_Tp> >::other { - public: - typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type - allocator_type; - - allocator_type - get_allocator() const { return _M_node_allocator; } - - _List_alloc_base(const allocator_type& __a) - : _M_node_allocator(__a) - { } - protected: - _List_node<_Tp>* - _M_get_node() - { return _M_node_allocator.allocate(1); } - - void - _M_put_node(_List_node<_Tp>* __p) - { _M_node_allocator.deallocate(__p, 1); } - // NOTA BENE // The stored instance is not actually of "allocator_type"'s type. // Instead we rebind the type to Allocator>, which @@ -240,69 +220,29 @@ namespace __gnu_norm // larger), and specializations on Tp may go unused because // List_node is being bound instead. // - // We put this to the test in get_allocator above; if the two - // types are actually different, there had better be a conversion - // between them. - // - // None of the predefined allocators shipped with the library (as - // of 3.1) use this instantiation anyhow; they're all - // instanceless. - typename _Alloc_traits<_List_node<_Tp>, _Allocator>::allocator_type - _M_node_allocator; - - _List_node_base _M_node; - }; - - /// @if maint Specialization for instanceless allocators. @endif - template - class _List_alloc_base<_Tp, _Allocator, true> - { - public: - typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type - allocator_type; - - allocator_type - get_allocator() const { return allocator_type(); } - - _List_alloc_base(const allocator_type&) - { } - - protected: - // See comment in primary template class about why this is safe for the - // standard predefined classes. - typedef typename _Alloc_traits<_List_node<_Tp>, _Allocator>::_Alloc_type - _Alloc_type; - + // 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; + _List_node<_Tp>* _M_get_node() - { return _Alloc_type::allocate(1); } - + { return _Node_Alloc_type::allocate(1); } + void _M_put_node(_List_node<_Tp>* __p) - { _Alloc_type::deallocate(__p, 1); } - + { _Node_Alloc_type::deallocate(__p, 1); } + _List_node_base _M_node; - }; - - - /** - * @if maint - * See bits/stl_deque.h's _Deque_base for an explanation. - * @endif - */ - template - class _List_base - : public _List_alloc_base<_Tp, _Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> - { public: - typedef _List_alloc_base<_Tp, _Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> - _Base; - typedef typename _Base::allocator_type allocator_type; - + typedef _Alloc allocator_type; + allocator_type get_allocator() const + + { return allocator_type(*static_cast(this)); } + _List_base(const allocator_type& __a) - : _Base(__a) + : _Node_Alloc_type(__a) { this->_M_node._M_next = &this->_M_node; this->_M_node._M_prev = &this->_M_node; diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 94d6a4a..de9c1a3 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -67,70 +67,6 @@ namespace __gnu_norm { - /// @if maint Primary default version. @endif - /** - * @if maint - * See bits/stl_deque.h's _Deque_alloc_base for an explanation. - * @endif - */ - template - class _Vector_alloc_base - { - public: - typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type - allocator_type; - - allocator_type - get_allocator() const { return _M_data_allocator; } - - _Vector_alloc_base(const allocator_type& __a) - : _M_data_allocator(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) - { } - - protected: - allocator_type _M_data_allocator; - _Tp* _M_start; - _Tp* _M_finish; - _Tp* _M_end_of_storage; - - _Tp* - _M_allocate(size_t __n) { return _M_data_allocator.allocate(__n); } - - void - _M_deallocate(_Tp* __p, size_t __n) - { if (__p) _M_data_allocator.deallocate(__p, __n); } - }; - - /// @if maint Specialization for instanceless allocators. @endif - template - class _Vector_alloc_base<_Tp, _Allocator, true> - { - public: - typedef typename _Alloc_traits<_Tp, _Allocator>::allocator_type - allocator_type; - - allocator_type - get_allocator() const { return allocator_type(); } - - _Vector_alloc_base(const allocator_type&) - : _M_start(0), _M_finish(0), _M_end_of_storage(0) - { } - - protected: - _Tp* _M_start; - _Tp* _M_finish; - _Tp* _M_end_of_storage; - - typedef typename _Alloc_traits<_Tp, _Allocator>::_Alloc_type _Alloc_type; - - _Tp* - _M_allocate(size_t __n) { return _Alloc_type::allocate(__n); } - - void - _M_deallocate(_Tp* __p, size_t __n) { _Alloc_type::deallocate(__p, __n);} - }; - - /** * @if maint * See bits/stl_deque.h's _Deque_base for an explanation. @@ -138,20 +74,19 @@ namespace __gnu_norm */ template struct _Vector_base - : public _Vector_alloc_base<_Tp, _Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> + : public _Alloc { public: - typedef _Vector_alloc_base<_Tp, _Alloc, - _Alloc_traits<_Tp, _Alloc>::_S_instanceless> - _Base; - typedef typename _Base::allocator_type allocator_type; + typedef _Alloc allocator_type; + + allocator_type + get_allocator() const { return *static_cast(this); } _Vector_base(const allocator_type& __a) - : _Base(__a) { } + : _Alloc(__a), _M_start(0), _M_finish(0), _M_end_of_storage(0) { } _Vector_base(size_t __n, const allocator_type& __a) - : _Base(__a) + : _Alloc(__a) { this->_M_start = this->_M_allocate(__n); this->_M_finish = this->_M_start; @@ -161,6 +96,18 @@ namespace __gnu_norm ~_Vector_base() { _M_deallocate(this->_M_start, this->_M_end_of_storage - this->_M_start); } + + public: + _Tp* _M_start; + _Tp* _M_finish; + _Tp* _M_end_of_storage; + + _Tp* + _M_allocate(size_t __n) { return _Alloc::allocate(__n); } + + void + _M_deallocate(_Tp* __p, size_t __n) + { if (__p) _Alloc::deallocate(__p, __n); } }; @@ -209,8 +156,7 @@ namespace __gnu_norm protected: /** @if maint * These two functions and three data members are all from the - * top-most base class, which varies depending on the type of - * %allocator. They should be pretty self-explanatory, as + * base class. They should be pretty self-explanatory, as * %vector uses a simple contiguous allocation scheme. @endif */ using _Base::_M_allocate; @@ -347,8 +293,7 @@ namespace __gnu_norm } /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const { return _Base::get_allocator(); } + using _Base::get_allocator; // iterators /** diff --git a/libstdc++-v3/include/ext/hashtable.h b/libstdc++-v3/include/ext/hashtable.h index 4e5ea09..54540c4 100644 --- a/libstdc++-v3/include/ext/hashtable.h +++ b/libstdc++-v3/include/ext/hashtable.h @@ -77,7 +77,6 @@ using std::size_t; using std::ptrdiff_t; using std::forward_iterator_tag; using std::input_iterator_tag; -using std::_Alloc_traits; using std::_Construct; using std::_Destroy; using std::distance; @@ -242,10 +241,14 @@ private: typedef _Hashtable_node<_Val> _Node; public: - typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type; + typedef _Alloc allocator_type; allocator_type get_allocator() const { return _M_node_allocator; } private: - typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator; + typedef typename _Alloc::template rebind<_Node>::other _Node_Alloc; + typedef typename _Alloc::template rebind<_Node*>::other _Nodeptr_Alloc; + typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type; + + _Node_Alloc _M_node_allocator; _Node* _M_get_node() { return _M_node_allocator.allocate(1); } void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); } @@ -253,7 +256,7 @@ private: hasher _M_hash; key_equal _M_equals; _ExtractKey _M_get_key; - vector<_Node*,_Alloc> _M_buckets; + _Vector_type _M_buckets; size_type _M_num_elements; public: @@ -876,8 +879,7 @@ void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All> if (__num_elements_hint > __old_n) { const size_type __n = _M_next_size(__num_elements_hint); if (__n > __old_n) { - vector<_Node*, _All> __tmp(__n, (_Node*)(0), - _M_buckets.get_allocator()); + _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator()); try { for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) { _Node* __first = _M_buckets[__bucket];