diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 2e1f141bac8..4c2c6d9c5f4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2013-03-24 Jonathan Wakely + + PR libstdc++/56170 + * include/ext/debug_allocator.h (debug_allocator): Add missing members + to meet allocator requirements. + * testsuite/ext/debug_allocator/56170.cc: New. + 2013-03-22 Paolo Carlini PR libstdc++/56678 diff --git a/libstdc++-v3/include/ext/debug_allocator.h b/libstdc++-v3/include/ext/debug_allocator.h index 8190d2a89a7..9bb73f06161 100644 --- a/libstdc++-v3/include/ext/debug_allocator.h +++ b/libstdc++-v3/include/ext/debug_allocator.h @@ -43,6 +43,8 @@ #define _DEBUG_ALLOCATOR_H 1 #include +#include +#include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { @@ -51,24 +53,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using std::size_t; /** - * @brief A meta-allocator with debugging bits, as per [20.4]. + * @brief A meta-allocator with debugging bits. * @ingroup allocators * - * This is precisely the allocator defined in the C++ Standard. - * - all allocation calls operator new - * - all deallocation calls operator delete + * This is precisely the allocator defined in the C++03 Standard. */ template class debug_allocator { + template friend class debug_allocator; + + typedef __alloc_traits<_Alloc> _Traits; + public: - typedef typename _Alloc::size_type size_type; - typedef typename _Alloc::difference_type difference_type; - typedef typename _Alloc::pointer pointer; - typedef typename _Alloc::const_pointer const_pointer; - typedef typename _Alloc::reference reference; - typedef typename _Alloc::const_reference const_reference; - typedef typename _Alloc::value_type value_type; + typedef typename _Traits::size_type size_type; + typedef typename _Traits::difference_type difference_type; + typedef typename _Traits::pointer pointer; + typedef typename _Traits::const_pointer const_pointer; + typedef typename _Traits::reference reference; + typedef typename _Traits::const_reference const_reference; + typedef typename _Traits::value_type value_type; + + template + class rebind + { + typedef typename _Traits::template rebind<_Up>::other __other; + + public: + typedef debug_allocator<__other> other; + }; private: // _M_extra is the number of objects that correspond to the @@ -77,13 +90,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Alloc _M_allocator; - public: - debug_allocator() + template::other> + struct __convertible + { }; + + template + struct __convertible<_Alloc2, _Alloc> + { + typedef void* __type; + }; + + size_type _S_extra() { const size_t __obj_size = sizeof(value_type); - _M_extra = (sizeof(size_type) + __obj_size - 1) / __obj_size; + return (sizeof(size_type) + __obj_size - 1) / __obj_size; } - + + public: + debug_allocator() : _M_extra(_S_extra()) { } + + template + debug_allocator(const debug_allocator<_Alloc2>& __a2, + typename __convertible<_Alloc2>::__type = 0) + : _M_allocator(__a2._M_allocator), _M_extra(_S_extra()) { } + + debug_allocator(const _Alloc& __a) + : _M_allocator(__a), _M_extra(_S_extra()) { } + pointer allocate(size_type __n) { @@ -105,21 +139,52 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void deallocate(pointer __p, size_type __n) { + using std::__throw_runtime_error; if (__p) { pointer __real_p = __p - _M_extra; if (*reinterpret_cast(__real_p) != __n) - { - throw std::runtime_error("debug_allocator::deallocate" - " wrong size"); - } + __throw_runtime_error("debug_allocator::deallocate wrong size"); _M_allocator.deallocate(__real_p, __n + _M_extra); } else - throw std::runtime_error("debug_allocator::deallocate null pointer"); + __throw_runtime_error("debug_allocator::deallocate null pointer"); } + + void + construct(pointer __p, const value_type& __val) + { _Traits::construct(_M_allocator, __p, __val); } + +#if __cplusplus >= 201103L + template + void + construct(_Tp* __p, _Args&&... __args) + { + _Traits::construct(_M_allocator, __p, + std::forward<_Args>(__args)...); + } +#endif + + template + void + destroy(_Tp* __p) + { _Traits::destroy(_M_allocator, __p); } + + size_type + max_size() const throw() + { return _Traits::max_size(_M_allocator) - _M_extra; } + + friend bool + operator==(const debug_allocator& __lhs, const debug_allocator& __rhs) + { return __lhs._M_allocator == __rhs._M_allocator; } }; + template + inline bool + operator!=(const debug_allocator<_Alloc>& __lhs, + const debug_allocator<_Alloc>& __rhs) + { return !(__lhs == __rhs); } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/testsuite/ext/debug_allocator/56170.cc b/libstdc++-v3/testsuite/ext/debug_allocator/56170.cc new file mode 100644 index 00000000000..217fc323baf --- /dev/null +++ b/libstdc++-v3/testsuite/ext/debug_allocator/56170.cc @@ -0,0 +1,27 @@ +// Copyright (C) 2013 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 +// . + +// { dg-do compile } + +#include +#include +#include + +using __gnu_cxx::debug_allocator; + +template class std::list > >; +template class std::vector > >;