diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libstdc++-v3/include/debug | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libstdc++-v3/include/debug')
23 files changed, 9926 insertions, 0 deletions
diff --git a/libstdc++-v3/include/debug/bitset b/libstdc++-v3/include/debug/bitset new file mode 100644 index 000000000..c18754542 --- /dev/null +++ b/libstdc++-v3/include/debug/bitset @@ -0,0 +1,419 @@ +// Debugging bitset implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/bitset + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_BITSET +#define _GLIBCXX_DEBUG_BITSET + +#include <bitset> +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::bitset with additional safety/checking/debug instrumentation. + template<size_t _Nb> + class bitset + : public _GLIBCXX_STD_C::bitset<_Nb> +#ifndef __GXX_EXPERIMENTAL_CXX0X__ + , public __gnu_debug::_Safe_sequence_base +#endif + { + typedef _GLIBCXX_STD_C::bitset<_Nb> _Base; + + public: + // In C++0x we rely on normal reference type to preserve the property + // of bitset to be use as a literal. + // TODO: Find an other solution. +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + typedef typename _Base::reference reference; +#else + // bit reference: + class reference + : private _Base::reference + , public __gnu_debug::_Safe_iterator_base + { + typedef typename _Base::reference _Base_ref; + + friend class bitset; + reference(); + + reference(const _Base_ref& __base, + bitset* __seq __attribute__((__unused__))) + : _Base_ref(__base) + , _Safe_iterator_base(__seq, false) + { } + + public: + reference(const reference& __x) + : _Base_ref(__x) + , _Safe_iterator_base(__x, false) + { } + + reference& + operator=(bool __x) + { + _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), + _M_message(__gnu_debug::__msg_bad_bitset_write) + ._M_iterator(*this)); + *static_cast<_Base_ref*>(this) = __x; + return *this; + } + + reference& + operator=(const reference& __x) + { + _GLIBCXX_DEBUG_VERIFY(! __x._M_singular(), + _M_message(__gnu_debug::__msg_bad_bitset_read) + ._M_iterator(__x)); + _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), + _M_message(__gnu_debug::__msg_bad_bitset_write) + ._M_iterator(*this)); + *static_cast<_Base_ref*>(this) = __x; + return *this; + } + + bool + operator~() const + { + _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), + _M_message(__gnu_debug::__msg_bad_bitset_read) + ._M_iterator(*this)); + return ~(*static_cast<const _Base_ref*>(this)); + } + + operator bool() const + { + _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), + _M_message(__gnu_debug::__msg_bad_bitset_read) + ._M_iterator(*this)); + return *static_cast<const _Base_ref*>(this); + } + + reference& + flip() + { + _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), + _M_message(__gnu_debug::__msg_bad_bitset_flip) + ._M_iterator(*this)); + _Base_ref::flip(); + return *this; + } + }; +#endif + + // 23.3.5.1 constructors: + _GLIBCXX_CONSTEXPR bitset() : _Base() { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + constexpr bitset(unsigned long long __val) +#else + bitset(unsigned long __val) +#endif + : _Base(__val) { } + + template<typename _CharT, typename _Traits, typename _Alloc> + explicit + bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str, + typename std::basic_string<_CharT, _Traits, _Alloc>::size_type + __pos = 0, + typename std::basic_string<_CharT, _Traits, _Alloc>::size_type + __n = (std::basic_string<_CharT, _Traits, _Alloc>::npos)) + : _Base(__str, __pos, __n) { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 396. what are characters zero and one. + template<class _CharT, class _Traits, class _Alloc> + bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str, + typename std::basic_string<_CharT, _Traits, _Alloc>::size_type + __pos, + typename std::basic_string<_CharT, _Traits, _Alloc>::size_type + __n, + _CharT __zero, _CharT __one = _CharT('1')) + : _Base(__str, __pos, __n, __zero, __one) { } + + bitset(const _Base& __x) : _Base(__x) { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _CharT> + explicit + bitset(const _CharT* __str, + typename std::basic_string<_CharT>::size_type __n + = std::basic_string<_CharT>::npos, + _CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) + : _Base(__str, __n, __zero, __one) { } +#endif + + // 23.3.5.2 bitset operations: + bitset<_Nb>& + operator&=(const bitset<_Nb>& __rhs) + { + _M_base() &= __rhs; + return *this; + } + + bitset<_Nb>& + operator|=(const bitset<_Nb>& __rhs) + { + _M_base() |= __rhs; + return *this; + } + + bitset<_Nb>& + operator^=(const bitset<_Nb>& __rhs) + { + _M_base() ^= __rhs; + return *this; + } + + bitset<_Nb>& + operator<<=(size_t __pos) + { + _M_base() <<= __pos; + return *this; + } + + bitset<_Nb>& + operator>>=(size_t __pos) + { + _M_base() >>= __pos; + return *this; + } + + bitset<_Nb>& + set() + { + _Base::set(); + return *this; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 186. bitset::set() second parameter should be bool + bitset<_Nb>& + set(size_t __pos, bool __val = true) + { + _Base::set(__pos, __val); + return *this; + } + + bitset<_Nb>& + reset() + { + _Base::reset(); + return *this; + } + + bitset<_Nb>& + reset(size_t __pos) + { + _Base::reset(__pos); + return *this; + } + + bitset<_Nb> operator~() const { return bitset(~_M_base()); } + + bitset<_Nb>& + flip() + { + _Base::flip(); + return *this; + } + + bitset<_Nb>& + flip(size_t __pos) + { + _Base::flip(__pos); + return *this; + } + + // element access: + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 11. Bitset minor problems + reference + operator[](size_t __pos) + { + __glibcxx_check_subscript(__pos); +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + return _M_base()[__pos]; +#else + return reference(_M_base()[__pos], this); +#endif + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 11. Bitset minor problems + bool + operator[](size_t __pos) const + { + __glibcxx_check_subscript(__pos); + return _M_base()[__pos]; + } + + using _Base::to_ulong; +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + using _Base::to_ullong; +#endif + + template <typename _CharT, typename _Traits, typename _Alloc> + std::basic_string<_CharT, _Traits, _Alloc> + to_string() const + { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 396. what are characters zero and one. + template<class _CharT, class _Traits, class _Alloc> + std::basic_string<_CharT, _Traits, _Alloc> + to_string(_CharT __zero, _CharT __one = _CharT('1')) const + { + return _M_base().template + to_string<_CharT, _Traits, _Alloc>(__zero, __one); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 434. bitset::to_string() hard to use. + template<typename _CharT, typename _Traits> + std::basic_string<_CharT, _Traits, std::allocator<_CharT> > + to_string() const + { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 853. to_string needs updating with zero and one. + template<class _CharT, class _Traits> + std::basic_string<_CharT, _Traits, std::allocator<_CharT> > + to_string(_CharT __zero, _CharT __one = _CharT('1')) const + { return to_string<_CharT, _Traits, + std::allocator<_CharT> >(__zero, __one); } + + template<typename _CharT> + std::basic_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> > + to_string() const + { + return to_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> >(); + } + + template<class _CharT> + std::basic_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> > + to_string(_CharT __zero, _CharT __one = _CharT('1')) const + { + return to_string<_CharT, std::char_traits<_CharT>, + std::allocator<_CharT> >(__zero, __one); + } + + std::basic_string<char, std::char_traits<char>, std::allocator<char> > + to_string() const + { + return to_string<char,std::char_traits<char>,std::allocator<char> >(); + } + + std::basic_string<char, std::char_traits<char>, std::allocator<char> > + to_string(char __zero, char __one = '1') const + { + return to_string<char, std::char_traits<char>, + std::allocator<char> >(__zero, __one); + } + + using _Base::count; + using _Base::size; + + bool + operator==(const bitset<_Nb>& __rhs) const + { return _M_base() == __rhs; } + + bool + operator!=(const bitset<_Nb>& __rhs) const + { return _M_base() != __rhs; } + + using _Base::test; + using _Base::all; + using _Base::any; + using _Base::none; + + bitset<_Nb> + operator<<(size_t __pos) const + { return bitset<_Nb>(_M_base() << __pos); } + + bitset<_Nb> + operator>>(size_t __pos) const + { return bitset<_Nb>(_M_base() >> __pos); } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + }; + + template<size_t _Nb> + bitset<_Nb> + operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) + { return bitset<_Nb>(__x) &= __y; } + + template<size_t _Nb> + bitset<_Nb> + operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) + { return bitset<_Nb>(__x) |= __y; } + + template<size_t _Nb> + bitset<_Nb> + operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) + { return bitset<_Nb>(__x) ^= __y; } + + template<typename _CharT, typename _Traits, size_t _Nb> + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x) + { return __is >> __x._M_base(); } + + template<typename _CharT, typename _Traits, size_t _Nb> + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const bitset<_Nb>& __x) + { return __os << __x._M_base(); } + +} // namespace __debug + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + // DR 1182. + /// std::hash specialization for bitset. + template<size_t _Nb> + struct hash<__debug::bitset<_Nb>> + : public __hash_base<size_t, __debug::bitset<_Nb>> + { + size_t + operator()(const __debug::bitset<_Nb>& __b) const + { return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); } + }; +#endif + +} // namespace std + +#endif diff --git a/libstdc++-v3/include/debug/debug.h b/libstdc++-v3/include/debug/debug.h new file mode 100644 index 000000000..6ea8e2add --- /dev/null +++ b/libstdc++-v3/include/debug/debug.h @@ -0,0 +1,129 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/debug.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MACRO_SWITCH_H +#define _GLIBCXX_DEBUG_MACRO_SWITCH_H 1 + +/** Macros and namespaces used by the implementation outside of debug + * wrappers to verify certain properties. The __glibcxx_requires_xxx + * macros are merely wrappers around the __glibcxx_check_xxx wrappers + * when we are compiling with debug mode, but disappear when we are + * in release mode so that there is no checking performed in, e.g., + * the standard library algorithms. +*/ + +// Debug mode namespaces. + +/** + * @namespace std::__debug + * @brief GNU debug code, replaces standard behavior with debug behavior. + */ +namespace std +{ + namespace __debug { } +} + +/** @namespace __gnu_debug + * @brief GNU debug classes for public use. +*/ +namespace __gnu_debug +{ + using namespace std::__debug; +} + +#ifndef _GLIBCXX_DEBUG + +# define _GLIBCXX_DEBUG_ASSERT(_Condition) +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +# define _GLIBCXX_DEBUG_ONLY(_Statement) ; +# define __glibcxx_requires_cond(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) +# define __glibcxx_requires_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) +# define __glibcxx_requires_nonempty() +# define __glibcxx_requires_string(_String) +# define __glibcxx_requires_string_len(_String,_Len) +# define __glibcxx_requires_subscript(_N) + +#else + +# include <debug/macros.h> + +#define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition) + +#ifdef _GLIBCXX_DEBUG_PEDANTIC +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition) +#else +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +#endif + +# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement + +# define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) \ + __glibcxx_check_valid_range(_First,_Last) +# define __glibcxx_requires_sorted(_First,_Last) \ + __glibcxx_check_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) \ + __glibcxx_check_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) \ + __glibcxx_check_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ + __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) \ + __glibcxx_check_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) \ + __glibcxx_check_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) \ + __glibcxx_check_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \ + __glibcxx_check_heap_pred(_First,_Last,_Pred) +# define __glibcxx_requires_nonempty() __glibcxx_check_nonempty() +# define __glibcxx_requires_string(_String) __glibcxx_check_string(_String) +# define __glibcxx_requires_string_len(_String,_Len) \ + __glibcxx_check_string_len(_String,_Len) +# define __glibcxx_requires_subscript(_N) __glibcxx_check_subscript(_N) + +# include <debug/functions.h> + +#endif + +#endif // _GLIBCXX_DEBUG_MACRO_SWITCH_H diff --git a/libstdc++-v3/include/debug/deque b/libstdc++-v3/include/debug/deque new file mode 100644 index 000000000..fc4d8cb61 --- /dev/null +++ b/libstdc++-v3/include/debug/deque @@ -0,0 +1,560 @@ +// Debugging deque implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/deque + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_DEQUE +#define _GLIBCXX_DEBUG_DEQUE 1 + +#include <deque> +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::deque with safety/checking/debug instrumentation. + template<typename _Tp, typename _Allocator = std::allocator<_Tp> > + class deque + : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>, + public __gnu_debug::_Safe_sequence<deque<_Tp, _Allocator> > + { + typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<deque> _Safe_base; + + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + public: + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque> + iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque> + const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + + typedef _Tp value_type; + typedef _Allocator allocator_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + // 23.2.1.1 construct/copy/destroy: + explicit + deque(const _Allocator& __a = _Allocator()) + : _Base(__a) { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + explicit + deque(size_type __n) + : _Base(__n) { } + + deque(size_type __n, const _Tp& __value, + const _Allocator& __a = _Allocator()) + : _Base(__n, __value, __a) { } +#else + explicit + deque(size_type __n, const _Tp& __value = _Tp(), + const _Allocator& __a = _Allocator()) + : _Base(__n, __value, __a) { } +#endif + + template<class _InputIterator> + deque(_InputIterator __first, _InputIterator __last, + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __a) + { } + + deque(const deque& __x) + : _Base(__x), _Safe_base() { } + + deque(const _Base& __x) + : _Base(__x), _Safe_base() { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + deque(deque&& __x) + : _Base(std::move(__x)), _Safe_base() + { this->_M_swap(__x); } + + deque(initializer_list<value_type> __l, + const allocator_type& __a = allocator_type()) + : _Base(__l, __a), _Safe_base() { } +#endif + + ~deque() { } + + deque& + operator=(const deque& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + deque& + operator=(deque&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + deque& + operator=(initializer_list<value_type> __l) + { + *static_cast<_Base*>(this) = __l; + this->_M_invalidate_all(); + return *this; + } +#endif + + template<class _InputIterator> + void + assign(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::assign(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + } + + void + assign(size_type __n, const _Tp& __t) + { + _Base::assign(__n, __t); + this->_M_invalidate_all(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + assign(initializer_list<value_type> __l) + { + _Base::assign(__l); + this->_M_invalidate_all(); + } +#endif + + using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + + private: + void + _M_invalidate_after_nth(difference_type __n) + { + typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth; + this->_M_invalidate_if(_After_nth(__n, _Base::begin())); + } + + public: + // 23.2.1.2 capacity: + using _Base::size; + using _Base::max_size; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + resize(size_type __sz) + { + bool __invalidate_all = __sz > this->size(); + if (__sz < this->size()) + this->_M_invalidate_after_nth(__sz); + + _Base::resize(__sz); + + if (__invalidate_all) + this->_M_invalidate_all(); + } + + void + resize(size_type __sz, const _Tp& __c) + { + bool __invalidate_all = __sz > this->size(); + if (__sz < this->size()) + this->_M_invalidate_after_nth(__sz); + + _Base::resize(__sz, __c); + + if (__invalidate_all) + this->_M_invalidate_all(); + } +#else + void + resize(size_type __sz, _Tp __c = _Tp()) + { + bool __invalidate_all = __sz > this->size(); + if (__sz < this->size()) + this->_M_invalidate_after_nth(__sz); + + _Base::resize(__sz, __c); + + if (__invalidate_all) + this->_M_invalidate_all(); + } +#endif + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + using _Base::shrink_to_fit; +#endif + + using _Base::empty; + + // element access: + reference + operator[](size_type __n) + { + __glibcxx_check_subscript(__n); + return _M_base()[__n]; + } + + const_reference + operator[](size_type __n) const + { + __glibcxx_check_subscript(__n); + return _M_base()[__n]; + } + + using _Base::at; + + reference + front() + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + const_reference + front() const + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + reference + back() + { + __glibcxx_check_nonempty(); + return _Base::back(); + } + + const_reference + back() const + { + __glibcxx_check_nonempty(); + return _Base::back(); + } + + // 23.2.1.3 modifiers: + void + push_front(const _Tp& __x) + { + _Base::push_front(__x); + this->_M_invalidate_all(); + } + + void + push_back(const _Tp& __x) + { + _Base::push_back(__x); + this->_M_invalidate_all(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + push_front(_Tp&& __x) + { emplace_front(std::move(__x)); } + + void + push_back(_Tp&& __x) + { emplace_back(std::move(__x)); } + + template<typename... _Args> + void + emplace_front(_Args&&... __args) + { + _Base::emplace_front(std::forward<_Args>(__args)...); + this->_M_invalidate_all(); + } + + template<typename... _Args> + void + emplace_back(_Args&&... __args) + { + _Base::emplace_back(std::forward<_Args>(__args)...); + this->_M_invalidate_all(); + } + + template<typename... _Args> + iterator + emplace(iterator __position, _Args&&... __args) + { + __glibcxx_check_insert(__position); + _Base_iterator __res = _Base::emplace(__position.base(), + std::forward<_Args>(__args)...); + this->_M_invalidate_all(); + return iterator(__res, this); + } +#endif + + iterator + insert(iterator __position, const _Tp& __x) + { + __glibcxx_check_insert(__position); + _Base_iterator __res = _Base::insert(__position.base(), __x); + this->_M_invalidate_all(); + return iterator(__res, this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + insert(iterator __position, _Tp&& __x) + { return emplace(__position, std::move(__x)); } + + void + insert(iterator __p, initializer_list<value_type> __l) + { + _Base::insert(__p, __l); + this->_M_invalidate_all(); + } +#endif + + void + insert(iterator __position, size_type __n, const _Tp& __x) + { + __glibcxx_check_insert(__position); + _Base::insert(__position.base(), __n, __x); + this->_M_invalidate_all(); + } + + template<class _InputIterator> + void + insert(iterator __position, + _InputIterator __first, _InputIterator __last) + { + __glibcxx_check_insert_range(__position, __first, __last); + _Base::insert(__position.base(), __gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + } + + void + pop_front() + { + __glibcxx_check_nonempty(); + this->_M_invalidate_if(_Equal(_Base::begin())); + _Base::pop_front(); + } + + void + pop_back() + { + __glibcxx_check_nonempty(); + this->_M_invalidate_if(_Equal(--_Base::end())); + _Base::pop_back(); + } + + iterator + erase(iterator __position) + { + __glibcxx_check_erase(__position); + _Base_iterator __victim = __position.base(); + if (__victim == _Base::begin() || __victim == _Base::end()-1) + { + this->_M_invalidate_if(_Equal(__victim)); + return iterator(_Base::erase(__victim), this); + } + else + { + _Base_iterator __res = _Base::erase(__victim); + this->_M_invalidate_all(); + return iterator(__res, this); + } + } + + iterator + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + + if (__first.base() == __last.base()) + return __first; + else if (__first.base() == _Base::begin() + || __last.base() == _Base::end()) + { + this->_M_detach_singular(); + for (_Base_iterator __position = __first.base(); + __position != __last.base(); ++__position) + { + this->_M_invalidate_if(_Equal(__position)); + } + __try + { + return iterator(_Base::erase(__first.base(), __last.base()), + this); + } + __catch(...) + { + this->_M_revalidate_singular(); + __throw_exception_again; + } + } + else + { + _Base_iterator __res = _Base::erase(__first.base(), + __last.base()); + this->_M_invalidate_all(); + return iterator(__res, this); + } + } + + void + swap(deque& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + }; + + template<typename _Tp, typename _Alloc> + inline bool + operator==(const deque<_Tp, _Alloc>& __lhs, + const deque<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const deque<_Tp, _Alloc>& __lhs, + const deque<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<(const deque<_Tp, _Alloc>& __lhs, + const deque<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<=(const deque<_Tp, _Alloc>& __lhs, + const deque<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>=(const deque<_Tp, _Alloc>& __lhs, + const deque<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>(const deque<_Tp, _Alloc>& __lhs, + const deque<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline void + swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs) + { __lhs.swap(__rhs); } + +} // namespace __debug +} // namespace std + +#endif diff --git a/libstdc++-v3/include/debug/formatter.h b/libstdc++-v3/include/debug/formatter.h new file mode 100644 index 000000000..065a50274 --- /dev/null +++ b/libstdc++-v3/include/debug/formatter.h @@ -0,0 +1,415 @@ +// Debug-mode error formatting implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/formatter.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_FORMATTER_H +#define _GLIBCXX_DEBUG_FORMATTER_H 1 + +#include <bits/c++config.h> +#include <bits/cpp_type_traits.h> +#include <typeinfo> + +namespace __gnu_debug +{ + using std::type_info; + + template<typename _Iterator> + bool __check_singular(_Iterator&); + + class _Safe_sequence_base; + + template<typename _Iterator, typename _Sequence> + class _Safe_iterator; + + template<typename _Sequence> + class _Safe_sequence; + + enum _Debug_msg_id + { + // General checks + __msg_valid_range, + __msg_insert_singular, + __msg_insert_different, + __msg_erase_bad, + __msg_erase_different, + __msg_subscript_oob, + __msg_empty, + __msg_unpartitioned, + __msg_unpartitioned_pred, + __msg_unsorted, + __msg_unsorted_pred, + __msg_not_heap, + __msg_not_heap_pred, + // std::bitset checks + __msg_bad_bitset_write, + __msg_bad_bitset_read, + __msg_bad_bitset_flip, + // std::list checks + __msg_self_splice, + __msg_splice_alloc, + __msg_splice_bad, + __msg_splice_other, + __msg_splice_overlap, + // iterator checks + __msg_init_singular, + __msg_init_copy_singular, + __msg_init_const_singular, + __msg_copy_singular, + __msg_bad_deref, + __msg_bad_inc, + __msg_bad_dec, + __msg_iter_subscript_oob, + __msg_advance_oob, + __msg_retreat_oob, + __msg_iter_compare_bad, + __msg_compare_different, + __msg_iter_order_bad, + __msg_order_different, + __msg_distance_bad, + __msg_distance_different, + // istream_iterator + __msg_deref_istream, + __msg_inc_istream, + // ostream_iterator + __msg_output_ostream, + // istreambuf_iterator + __msg_deref_istreambuf, + __msg_inc_istreambuf, + // forward_list + __msg_insert_after_end, + __msg_erase_after_bad, + __msg_valid_range2 + }; + + class _Error_formatter + { + /// Whether an iterator is constant, mutable, or unknown + enum _Constness + { + __unknown_constness, + __const_iterator, + __mutable_iterator, + __last_constness + }; + + // The state of the iterator (fine-grained), if we know it. + enum _Iterator_state + { + __unknown_state, + __singular, // singular, may still be attached to a sequence + __begin, // dereferenceable, and at the beginning + __middle, // dereferenceable, not at the beginning + __end, // past-the-end, may be at beginning if sequence empty + __before_begin, // before begin + __last_state + }; + + // Tags denoting the type of parameter for construction + struct _Is_iterator { }; + struct _Is_sequence { }; + + // A parameter that may be referenced by an error message + struct _Parameter + { + enum + { + __unused_param, + __iterator, + __sequence, + __integer, + __string + } _M_kind; + + union + { + // When _M_kind == __iterator + struct + { + const char* _M_name; + const void* _M_address; + const type_info* _M_type; + _Constness _M_constness; + _Iterator_state _M_state; + const void* _M_sequence; + const type_info* _M_seq_type; + } _M_iterator; + + // When _M_kind == __sequence + struct + { + const char* _M_name; + const void* _M_address; + const type_info* _M_type; + } _M_sequence; + + // When _M_kind == __integer + struct + { + const char* _M_name; + long _M_value; + } _M_integer; + + // When _M_kind == __string + struct + { + const char* _M_name; + const char* _M_value; + } _M_string; + } _M_variant; + + _Parameter() : _M_kind(__unused_param), _M_variant() { } + + _Parameter(long __value, const char* __name) + : _M_kind(__integer), _M_variant() + { + _M_variant._M_integer._M_name = __name; + _M_variant._M_integer._M_value = __value; + } + + _Parameter(const char* __value, const char* __name) + : _M_kind(__string), _M_variant() + { + _M_variant._M_string._M_name = __name; + _M_variant._M_string._M_value = __value; + } + + template<typename _Iterator, typename _Sequence> + _Parameter(const _Safe_iterator<_Iterator, _Sequence>& __it, + const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = &__it; +#ifdef __GXX_RTTI + _M_variant._M_iterator._M_type = &typeid(__it); +#else + _M_variant._M_iterator._M_type = 0; +#endif + _M_variant._M_iterator._M_constness = + std::__are_same<_Safe_iterator<_Iterator, _Sequence>, + typename _Sequence::iterator>:: + __value ? __mutable_iterator : __const_iterator; + _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); +#ifdef __GXX_RTTI + _M_variant._M_iterator._M_seq_type = &typeid(_Sequence); +#else + _M_variant._M_iterator._M_seq_type = 0; +#endif + + if (__it._M_singular()) + _M_variant._M_iterator._M_state = __singular; + else + { + if (__it._M_is_before_begin()) + _M_variant._M_iterator._M_state = __before_begin; + else if (__it._M_is_end()) + _M_variant._M_iterator._M_state = __end; + else if (__it._M_is_begin()) + _M_variant._M_iterator._M_state = __begin; + else + _M_variant._M_iterator._M_state = __middle; + } + } + + template<typename _Type> + _Parameter(const _Type*& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = &__it; +#ifdef __GXX_RTTI + _M_variant._M_iterator._M_type = &typeid(__it); +#else + _M_variant._M_iterator._M_type = 0; +#endif + _M_variant._M_iterator._M_constness = __mutable_iterator; + _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + + template<typename _Type> + _Parameter(_Type*& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = &__it; +#ifdef __GXX_RTTI + _M_variant._M_iterator._M_type = &typeid(__it); +#else + _M_variant._M_iterator._M_type = 0; +#endif + _M_variant._M_iterator._M_constness = __const_iterator; + _M_variant._M_iterator._M_state = __it? __unknown_state : __singular; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + + template<typename _Iterator> + _Parameter(const _Iterator& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = &__it; +#ifdef __GXX_RTTI + _M_variant._M_iterator._M_type = &typeid(__it); +#else + _M_variant._M_iterator._M_type = 0; +#endif + _M_variant._M_iterator._M_constness = __unknown_constness; + _M_variant._M_iterator._M_state = + __gnu_debug::__check_singular(__it)? __singular : __unknown_state; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + + template<typename _Sequence> + _Parameter(const _Safe_sequence<_Sequence>& __seq, + const char* __name, _Is_sequence) + : _M_kind(__sequence), _M_variant() + { + _M_variant._M_sequence._M_name = __name; + _M_variant._M_sequence._M_address = + static_cast<const _Sequence*>(&__seq); +#ifdef __GXX_RTTI + _M_variant._M_sequence._M_type = &typeid(_Sequence); +#else + _M_variant._M_sequence._M_type = 0; +#endif + } + + template<typename _Sequence> + _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) + : _M_kind(__sequence), _M_variant() + { + _M_variant._M_sequence._M_name = __name; + _M_variant._M_sequence._M_address = &__seq; +#ifdef __GXX_RTTI + _M_variant._M_sequence._M_type = &typeid(_Sequence); +#else + _M_variant._M_sequence._M_type = 0; +#endif + } + + void + _M_print_field(const _Error_formatter* __formatter, + const char* __name) const; + + void + _M_print_description(const _Error_formatter* __formatter) const; + }; + + friend struct _Parameter; + + public: + template<typename _Iterator> + const _Error_formatter& + _M_iterator(const _Iterator& __it, const char* __name = 0) const + { + if (_M_num_parameters < std::size_t(__max_parameters)) + _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, + _Is_iterator()); + return *this; + } + + const _Error_formatter& + _M_integer(long __value, const char* __name = 0) const + { + if (_M_num_parameters < std::size_t(__max_parameters)) + _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); + return *this; + } + + const _Error_formatter& + _M_string(const char* __value, const char* __name = 0) const + { + if (_M_num_parameters < std::size_t(__max_parameters)) + _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); + return *this; + } + + template<typename _Sequence> + const _Error_formatter& + _M_sequence(const _Sequence& __seq, const char* __name = 0) const + { + if (_M_num_parameters < std::size_t(__max_parameters)) + _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, + _Is_sequence()); + return *this; + } + + const _Error_formatter& + _M_message(const char* __text) const + { _M_text = __text; return *this; } + + const _Error_formatter& + _M_message(_Debug_msg_id __id) const throw (); + + _GLIBCXX_NORETURN void + _M_error() const; + + private: + _Error_formatter(const char* __file, std::size_t __line) + : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0), + _M_max_length(78), _M_column(1), _M_first_line(true), _M_wordwrap(false) + { _M_get_max_length(); } + + template<typename _Tp> + void + _M_format_word(char*, int, const char*, _Tp) const throw (); + + void + _M_print_word(const char* __word) const; + + void + _M_print_string(const char* __string) const; + + void + _M_get_max_length() const throw (); + + enum { __max_parameters = 9 }; + + const char* _M_file; + std::size_t _M_line; + mutable _Parameter _M_parameters[__max_parameters]; + mutable std::size_t _M_num_parameters; + mutable const char* _M_text; + mutable std::size_t _M_max_length; + enum { _M_indent = 4 } ; + mutable std::size_t _M_column; + mutable bool _M_first_line; + mutable bool _M_wordwrap; + + public: + static _Error_formatter + _M_at(const char* __file, std::size_t __line) + { return _Error_formatter(__file, __line); } + }; +} // namespace __gnu_debug + +#endif diff --git a/libstdc++-v3/include/debug/forward_list b/libstdc++-v3/include/debug/forward_list new file mode 100644 index 000000000..70bd75a86 --- /dev/null +++ b/libstdc++-v3/include/debug/forward_list @@ -0,0 +1,741 @@ +// <forward_list> -*- C++ -*- + +// Copyright (C) 2010 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/forward_list + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_FORWARD_LIST +#define _GLIBCXX_DEBUG_FORWARD_LIST 1 + +#pragma GCC system_header + +#include <forward_list> +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::forward_list with safety/checking/debug instrumentation. + template<typename _Tp, typename _Alloc = std::allocator<_Tp> > + class forward_list + : public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>, + public __gnu_debug::_Safe_sequence<forward_list<_Tp, _Alloc> > + { + typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base; + typedef __gnu_debug::_Safe_sequence<forward_list> _Safe_base; + + typedef typename _Base::iterator _Base_iterator; + typedef typename _Base::const_iterator _Base_const_iterator; + public: + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, + forward_list> iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, + forward_list> const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + + typedef _Tp value_type; + typedef _Alloc allocator_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + + // 23.2.3.1 construct/copy/destroy: + explicit + forward_list(const _Alloc& __al = _Alloc()) + : _Base(__al) { } + + forward_list(const forward_list& __list, const _Alloc& __al) + : _Base(__list, __al) + { } + + forward_list(forward_list&& __list, const _Alloc& __al) + : _Base(std::move(__list._M_base()), __al) + { + this->_M_swap(__list); + } + + explicit + forward_list(size_type __n) + : _Base(__n) + { } + + forward_list(size_type __n, const _Tp& __value, + const _Alloc& __al = _Alloc()) + : _Base(__n, __value, __al) + { } + + template<typename _InputIterator> + forward_list(_InputIterator __first, _InputIterator __last, + const _Alloc& __al = _Alloc()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __al) + { } + + forward_list(const forward_list& __list) + : _Base(__list) + { } + + forward_list(forward_list&& __list) + : _Base(std::move(__list._M_base())) + { + this->_M_swap(__list); + } + + forward_list(std::initializer_list<_Tp> __il, + const _Alloc& __al = _Alloc()) + : _Base(__il, __al) + { } + + ~forward_list() + { } + + forward_list& + operator=(const forward_list& __list) + { + static_cast<_Base&>(*this) = __list; + this->_M_invalidate_all(); + return *this; + } + + forward_list& + operator=(forward_list&& __list) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__list); + return *this; + } + + forward_list& + operator=(std::initializer_list<_Tp> __il) + { + static_cast<_Base&>(*this) = __il; + this->_M_invalidate_all(); + return *this; + } + + template<typename _InputIterator> + void + assign(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::assign(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + } + + void + assign(size_type __n, const _Tp& __val) + { + _Base::assign(__n, __val); + this->_M_invalidate_all(); + } + + void + assign(std::initializer_list<_Tp> __il) + { + _Base::assign(__il); + this->_M_invalidate_all(); + } + + using _Base::get_allocator; + + // iterators: + + iterator + before_begin() + { return iterator(_Base::before_begin(), this); } + + const_iterator + before_begin() const + { return const_iterator(_Base::before_begin(), this); } + + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + const_iterator + cbegin() const + { return const_iterator(_Base::cbegin(), this); } + + const_iterator + cbefore_begin() const + { return const_iterator(_Base::cbefore_begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::cend(), this); } + + using _Base::empty; + using _Base::max_size; + + // element access: + + reference + front() + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + const_reference + front() const + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + // modifiers: + + using _Base::emplace_front; + using _Base::push_front; + + void + pop_front() + { + __glibcxx_check_nonempty(); + this->_M_invalidate_if([this](_Base_const_iterator __it) + { return __it == this->_M_base().cbegin(); }); + _Base::pop_front(); + } + + template<typename... _Args> + iterator + emplace_after(const_iterator __pos, _Args&&... __args) + { + __glibcxx_check_insert_after(__pos); + return iterator(_Base::emplace_after(__pos.base(), + std::forward<_Args>(__args)...), + this); + } + + iterator + insert_after(const_iterator __pos, const _Tp& __val) + { + __glibcxx_check_insert_after(__pos); + return iterator(_Base::insert_after(__pos.base(), __val), this); + } + + iterator + insert_after(const_iterator __pos, _Tp&& __val) + { + __glibcxx_check_insert_after(__pos); + return iterator(_Base::insert_after(__pos.base(), std::move(__val)), + this); + } + + iterator + insert_after(const_iterator __pos, size_type __n, const _Tp& __val) + { + __glibcxx_check_insert_after(__pos); + return iterator(_Base::insert_after(__pos.base(), __n, __val), + this); + } + + template<typename _InputIterator> + iterator + insert_after(const_iterator __pos, + _InputIterator __first, _InputIterator __last) + { + __glibcxx_check_insert_range_after(__pos, __first, __last); + return iterator(_Base::insert_after(__pos.base(), + __gnu_debug::__base(__first), + __gnu_debug::__base(__last)), + this); + } + + iterator + insert_after(const_iterator __pos, std::initializer_list<_Tp> __il) + { + __glibcxx_check_insert_after(__pos); + return iterator(_Base::insert_after(__pos.base(), __il), this); + } + + private: + _Base_iterator + _M_erase_after(_Base_const_iterator __pos) + { + _Base_const_iterator __next = std::next(__pos); + this->_M_invalidate_if([__next](_Base_const_iterator __it) + { return __it == __next; }); + return _Base::erase_after(__pos); + } + public: + iterator + erase_after(const_iterator __pos) + { + __glibcxx_check_erase_after(__pos); + return iterator(_M_erase_after(__pos.base()), this); + } + + iterator + erase_after(const_iterator __pos, const_iterator __last) + { + __glibcxx_check_erase_range_after(__pos, __last); + for (_Base_const_iterator __victim = std::next(__pos.base()); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range2) + ._M_sequence(*this, "this") + ._M_iterator(__pos, "pos") + ._M_iterator(__last, "last")); + this->_M_invalidate_if([__victim](_Base_const_iterator __it) + { return __it == __victim; }); + } + return iterator(_Base::erase_after(__pos.base(), __last.base()), this); + } + + void + swap(forward_list& __list) + { + _Base::swap(__list); + this->_M_swap(__list); + } + + void + resize(size_type __sz) + { + this->_M_detach_singular(); + + // if __sz < size(), invalidate all iterators in [begin+__sz, end() + _Base_iterator __victim = _Base::begin(); + _Base_iterator __end = _Base::end(); + for (size_type __i = __sz; __victim != __end && __i > 0; --__i) + ++__victim; + + for (; __victim != __end; ++__victim) + { + this->_M_invalidate_if([__victim](_Base_const_iterator __it) + { return __it == __victim; }); + } + + __try + { + _Base::resize(__sz); + } + __catch(...) + { + this->_M_revalidate_singular(); + __throw_exception_again; + } + } + + void + resize(size_type __sz, const value_type& __val) + { + this->_M_detach_singular(); + + // if __sz < size(), invalidate all iterators in [begin+__sz, end()) + _Base_iterator __victim = _Base::begin(); + _Base_iterator __end = _Base::end(); + for (size_type __i = __sz; __victim != __end && __i > 0; --__i) + ++__victim; + + for (; __victim != __end; ++__victim) + { + this->_M_invalidate_if([__victim](_Base_const_iterator __it) + { return __it == __victim; }); + } + + __try + { + _Base::resize(__sz, __val); + } + __catch(...) + { + this->_M_revalidate_singular(); + __throw_exception_again; + } + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + // 23.2.3.5 forward_list operations: + void + splice_after(const_iterator __pos, forward_list&& __list) + { + __glibcxx_check_insert_after(__pos); + _GLIBCXX_DEBUG_VERIFY(&__list != this, + _M_message(__gnu_debug::__msg_self_splice) + ._M_sequence(*this, "this")); + this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it) + { + return __it != __list._M_base().cbefore_begin() + && __it != __list._M_base().end(); + }); + _Base::splice_after(__pos.base(), std::move(__list._M_base())); + } + + void + splice_after(const_iterator __pos, forward_list&& __list, + const_iterator __i) + { + __glibcxx_check_insert_after(__pos); + _GLIBCXX_DEBUG_VERIFY(__i._M_before_dereferenceable(), + _M_message(__gnu_debug::__msg_splice_bad) + ._M_iterator(__i, "__i")); + _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__list), + _M_message(__gnu_debug::__msg_splice_other) + ._M_iterator(__i, "__i") + ._M_sequence(__list, "__list")); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 250. splicing invalidates iterators + _Base_const_iterator __next = std::next(__i.base()); + this->_M_transfer_from_if(__list, [__next](_Base_const_iterator __it) + { return __it == __next; }); + _Base::splice_after(__pos.base(), std::move(__list._M_base()), + __i.base()); + } + + void + splice_after(const_iterator __pos, forward_list&& __list, + const_iterator __before, const_iterator __last) + { + __glibcxx_check_insert_after(__pos); + __glibcxx_check_valid_range(__before, __last); + _GLIBCXX_DEBUG_VERIFY(__before._M_attached_to(&__list), + _M_message(__gnu_debug::__msg_splice_other) + ._M_sequence(__list, "list") + ._M_iterator(__before, "before")); + _GLIBCXX_DEBUG_VERIFY(__before._M_dereferenceable() + || __before._M_is_before_begin(), + _M_message(__gnu_debug::__msg_valid_range2) + ._M_sequence(__list, "list") + ._M_iterator(__before, "before") + ._M_iterator(__last, "last")); + _GLIBCXX_DEBUG_VERIFY(__before != __last, + _M_message(__gnu_debug::__msg_valid_range2) + ._M_sequence(__list, "list") + ._M_iterator(__before, "before") + ._M_iterator(__last, "last")); + + for (_Base_const_iterator __tmp = std::next(__before.base()); + __tmp != __last.base(); ++__tmp) + { + _GLIBCXX_DEBUG_VERIFY(__tmp != __list._M_base().end(), + _M_message(__gnu_debug::__msg_valid_range2) + ._M_sequence(__list, "list") + ._M_iterator(__before, "before") + ._M_iterator(__last, "last")); + _GLIBCXX_DEBUG_VERIFY(&__list != this || __tmp != __pos.base(), + _M_message(__gnu_debug::__msg_splice_overlap) + ._M_iterator(__tmp, "position") + ._M_iterator(__before, "before") + ._M_iterator(__last, "last")); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 250. splicing invalidates iterators + this->_M_transfer_from_if(__list, [__tmp](_Base_const_iterator __it) + { return __it == __tmp; }); + } + + _Base::splice_after(__pos.base(), std::move(__list._M_base()), + __before.base(), __last.base()); + } + + void + remove(const _Tp& __val) + { + _Base_iterator __x = _Base::before_begin(); + _Base_iterator __old = __x++; + while (__x != _Base::end()) + { + if (*__x == __val) + __x = _M_erase_after(__old); + else + __old = __x++; + } + } + + template<typename _Pred> + void + remove_if(_Pred __pred) + { + _Base_iterator __x = _Base::before_begin(); + _Base_iterator __old = __x++; + while (__x != _Base::end()) + { + if (__pred(*__x)) + __x = _M_erase_after(__old); + else + __old = __x++; + } + } + + void + unique() + { + _Base_iterator __first = _Base::begin(); + _Base_iterator __last = _Base::end(); + if (__first == __last) + return; + _Base_iterator __next = std::next(__first); + while (__next != __last) + { + if (*__first == *__next) + __next = _M_erase_after(__first); + else + __first = __next++; + } + } + + template<typename _BinPred> + void + unique(_BinPred __binary_pred) + { + _Base_iterator __first = _Base::begin(); + _Base_iterator __last = _Base::end(); + if (__first == __last) + return; + _Base_iterator __next = std::next(__first); + while (__next != __last) + { + if (__binary_pred(*__first, *__next)) + __next = _M_erase_after(__first); + else + __first = __next++; + } + } + + void + merge(forward_list&& __list) + { + if (this != &__list) + { + __glibcxx_check_sorted(_Base::begin(), _Base::end()); + __glibcxx_check_sorted(__list._M_base().begin(), + __list._M_base().end()); + this->_M_transfer_from_if(__list, [&__list](_Base_const_iterator __it) + { + return __it != __list._M_base().cbefore_begin() + && __it != __list._M_base().cend(); + }); + _Base::merge(std::move(__list._M_base())); + } + } + + template<typename _Comp> + void + merge(forward_list&& __list, _Comp __comp) + { + if (this != &__list) + { + __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), __comp); + __glibcxx_check_sorted_pred(__list._M_base().begin(), + __list._M_base().end(), __comp); + this->_M_transfer_from_if(__list, + [&__list](_Base_const_iterator __it) + { + return __it != __list._M_base().cbefore_begin() + && __it != __list._M_base().cend(); + }); + _Base::merge(std::move(__list._M_base()), __comp); + } + } + + using _Base::sort; + using _Base::reverse; + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + this->_M_invalidate_if([this](_Base_const_iterator __it) + { + return __it != this->_M_base().cbefore_begin() + && __it != this->_M_base().cend(); + }); + } + typedef __gnu_debug::_Safe_iterator_base _Safe_iterator_base; + static void + _M_swap_aux(forward_list& __lhs, + _Safe_iterator_base*& __lhs_iterators, + forward_list& __rhs, + _Safe_iterator_base*& __rhs_iterators); + void _M_swap(forward_list& __list); + }; + + template<typename _Tp, typename _Alloc> + void + forward_list<_Tp, _Alloc>:: + _M_swap_aux(forward_list<_Tp, _Alloc>& __lhs, + __gnu_debug::_Safe_iterator_base*& __lhs_iterators, + forward_list<_Tp, _Alloc>& __rhs, + __gnu_debug::_Safe_iterator_base*& __rhs_iterators) + { + using __gnu_debug::_Safe_iterator_base; + _Safe_iterator_base* __bbegin_its = 0; + _Safe_iterator_base* __last_bbegin = 0; + for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;) + { + // Even iterator are casted to const_iterator, not a problem. + const_iterator* __victim = static_cast<const_iterator*>(__iter); + __iter = __iter->_M_next; + if (__victim->base() == __rhs._M_base().cbefore_begin()) + { + __victim->_M_unlink(); + if (__lhs_iterators == __victim) + __lhs_iterators = __victim->_M_next; + if (__bbegin_its) + { + __victim->_M_next = __bbegin_its; + __bbegin_its->_M_prior = __victim; + } + else + __last_bbegin = __victim; + __bbegin_its = __victim; + } + else + __victim->_M_sequence = &__lhs; + } + + if (__bbegin_its) + { + if (__rhs_iterators) + { + __rhs_iterators->_M_prior = __last_bbegin; + __last_bbegin->_M_next = __rhs_iterators; + } + __rhs_iterators = __bbegin_its; + } + } + + /* Special forward_list _M_swap version that do not swap the + * before-begin ownership.*/ + template<typename _Tp, typename _Alloc> + void + forward_list<_Tp, _Alloc>:: + _M_swap(forward_list<_Tp, _Alloc>& __list) + { + __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + std::swap(this->_M_iterators, __list._M_iterators); + std::swap(this->_M_const_iterators, __list._M_const_iterators); + // Useless, always 1 on forward_list + //std::swap(this->_M_version, __list._M_version); + _Safe_iterator_base* __this_its = this->_M_iterators; + _M_swap_aux(__list, __list._M_iterators, *this, this->_M_iterators); + _Safe_iterator_base* __this_const_its = this->_M_const_iterators; + _M_swap_aux(__list, __list._M_const_iterators, *this, this->_M_const_iterators); + _M_swap_aux(*this, __this_its, __list, __list._M_iterators); + _M_swap_aux(*this, __this_const_its, __list, __list._M_const_iterators); + } + + template<typename _Tp, typename _Alloc> + bool + operator==(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return __lx._M_base() == __ly._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return __lx._M_base() < __ly._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__lx == __ly); } + + /// Based on operator< + template<typename _Tp, typename _Alloc> + inline bool + operator>(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return (__ly < __lx); } + + /// Based on operator< + template<typename _Tp, typename _Alloc> + inline bool + operator>=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__lx < __ly); } + + /// Based on operator< + template<typename _Tp, typename _Alloc> + inline bool + operator<=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__ly < __lx); } + + /// See std::forward_list::swap(). + template<typename _Tp, typename _Alloc> + inline void + swap(forward_list<_Tp, _Alloc>& __lx, + forward_list<_Tp, _Alloc>& __ly) + { __lx.swap(__ly); } + +} // namespace __debug +} // namespace std + +namespace __gnu_debug +{ + template<class _Tp, class _Alloc> + struct _BeforeBeginHelper<std::__debug::forward_list<_Tp, _Alloc> > + { + typedef std::__debug::forward_list<_Tp, _Alloc> _Sequence; + typedef typename _Sequence::const_iterator _It; + typedef typename _It::iterator_type _BaseIt; + + static bool + _M_Is(_BaseIt __it, const _Sequence* __seq) + { return __it == __seq->_M_base().cbefore_begin(); } + }; +} + +#endif diff --git a/libstdc++-v3/include/debug/functions.h b/libstdc++-v3/include/debug/functions.h new file mode 100644 index 000000000..75ed9ef05 --- /dev/null +++ b/libstdc++-v3/include/debug/functions.h @@ -0,0 +1,383 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/functions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H +#define _GLIBCXX_DEBUG_FUNCTIONS_H 1 + +#include <bits/c++config.h> +#include <bits/stl_iterator_base_types.h> // for iterator_traits, categories +#include <bits/cpp_type_traits.h> // for __is_integer +#include <debug/formatter.h> + +namespace __gnu_debug +{ + template<typename _Iterator, typename _Sequence> + class _Safe_iterator; + + // An arbitrary iterator pointer is not singular. + inline bool + __check_singular_aux(const void*) { return false; } + + // We may have an iterator that derives from _Safe_iterator_base but isn't + // a _Safe_iterator. + template<typename _Iterator> + inline bool + __check_singular(_Iterator& __x) + { return __check_singular_aux(&__x); } + + /** Non-NULL pointers are nonsingular. */ + template<typename _Tp> + inline bool + __check_singular(const _Tp* __ptr) + { return __ptr == 0; } + + /** Safe iterators know if they are singular. */ + template<typename _Iterator, typename _Sequence> + inline bool + __check_singular(const _Safe_iterator<_Iterator, _Sequence>& __x) + { return __x._M_singular(); } + + /** Assume that some arbitrary iterator is dereferenceable, because we + can't prove that it isn't. */ + template<typename _Iterator> + inline bool + __check_dereferenceable(_Iterator&) + { return true; } + + /** Non-NULL pointers are dereferenceable. */ + template<typename _Tp> + inline bool + __check_dereferenceable(const _Tp* __ptr) + { return __ptr; } + + /** Safe iterators know if they are singular. */ + template<typename _Iterator, typename _Sequence> + inline bool + __check_dereferenceable(const _Safe_iterator<_Iterator, _Sequence>& __x) + { return __x._M_dereferenceable(); } + + /** If the distance between two random access iterators is + * nonnegative, assume the range is valid. + */ + template<typename _RandomAccessIterator> + inline bool + __valid_range_aux2(const _RandomAccessIterator& __first, + const _RandomAccessIterator& __last, + std::random_access_iterator_tag) + { return __last - __first >= 0; } + + /** Can't test for a valid range with input iterators, because + * iteration may be destructive. So we just assume that the range + * is valid. + */ + template<typename _InputIterator> + inline bool + __valid_range_aux2(const _InputIterator&, const _InputIterator&, + std::input_iterator_tag) + { return true; } + + /** We say that integral types for a valid range, and defer to other + * routines to realize what to do with integral types instead of + * iterators. + */ + template<typename _Integral> + inline bool + __valid_range_aux(const _Integral&, const _Integral&, std::__true_type) + { return true; } + + /** We have iterators, so figure out what kind of iterators that are + * to see if we can check the range ahead of time. + */ + template<typename _InputIterator> + inline bool + __valid_range_aux(const _InputIterator& __first, + const _InputIterator& __last, std::__false_type) + { + typedef typename std::iterator_traits<_InputIterator>::iterator_category + _Category; + return __valid_range_aux2(__first, __last, _Category()); + } + + /** Don't know what these iterators are, or if they are even + * iterators (we may get an integral type for InputIterator), so + * see if they are integral and pass them on to the next phase + * otherwise. + */ + template<typename _InputIterator> + inline bool + __valid_range(const _InputIterator& __first, const _InputIterator& __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __valid_range_aux(__first, __last, _Integral()); + } + + /** Safe iterators know how to check if they form a valid range. */ + template<typename _Iterator, typename _Sequence> + inline bool + __valid_range(const _Safe_iterator<_Iterator, _Sequence>& __first, + const _Safe_iterator<_Iterator, _Sequence>& __last) + { return __first._M_valid_range(__last); } + + /* Checks that [first, last) is a valid range, and then returns + * __first. This routine is useful when we can't use a separate + * assertion statement because, e.g., we are in a constructor. + */ + template<typename _InputIterator> + inline _InputIterator + __check_valid_range(const _InputIterator& __first, + const _InputIterator& __last + __attribute__((__unused__))) + { + __glibcxx_check_valid_range(__first, __last); + return __first; + } + + /** Checks that __s is non-NULL or __n == 0, and then returns __s. */ + template<typename _CharT, typename _Integer> + inline const _CharT* + __check_string(const _CharT* __s, + const _Integer& __n __attribute__((__unused__))) + { +#ifdef _GLIBCXX_DEBUG_PEDANTIC + __glibcxx_assert(__s != 0 || __n == 0); +#endif + return __s; + } + + /** Checks that __s is non-NULL and then returns __s. */ + template<typename _CharT> + inline const _CharT* + __check_string(const _CharT* __s) + { +#ifdef _GLIBCXX_DEBUG_PEDANTIC + __glibcxx_assert(__s != 0); +#endif + return __s; + } + + // Can't check if an input iterator sequence is sorted, because we + // can't step through the sequence. + template<typename _InputIterator> + inline bool + __check_sorted_aux(const _InputIterator&, const _InputIterator&, + std::input_iterator_tag) + { return true; } + + // Can verify if a forward iterator sequence is in fact sorted using + // std::__is_sorted + template<typename _ForwardIterator> + inline bool + __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, ++__next) + if (*__next < *__first) + return false; + + return true; + } + + // Can't check if an input iterator sequence is sorted, because we can't step + // through the sequence. + template<typename _InputIterator, typename _Predicate> + inline bool + __check_sorted_aux(const _InputIterator&, const _InputIterator&, + _Predicate, std::input_iterator_tag) + { return true; } + + // Can verify if a forward iterator sequence is in fact sorted using + // std::__is_sorted + template<typename _ForwardIterator, typename _Predicate> + inline bool + __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, std::forward_iterator_tag) + { + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, ++__next) + if (__pred(*__next, *__first)) + return false; + + return true; + } + + // Determine if a sequence is sorted. + template<typename _InputIterator> + inline bool + __check_sorted(const _InputIterator& __first, const _InputIterator& __last) + { + typedef typename std::iterator_traits<_InputIterator>::iterator_category + _Category; + + // Verify that the < operator for elements in the sequence is a + // StrictWeakOrdering by checking that it is irreflexive. + __glibcxx_assert(__first == __last || !(*__first < *__first)); + + return __check_sorted_aux(__first, __last, _Category()); + } + + template<typename _InputIterator, typename _Predicate> + inline bool + __check_sorted(const _InputIterator& __first, const _InputIterator& __last, + _Predicate __pred) + { + typedef typename std::iterator_traits<_InputIterator>::iterator_category + _Category; + + // Verify that the predicate is StrictWeakOrdering by checking that it + // is irreflexive. + __glibcxx_assert(__first == __last || !__pred(*__first, *__first)); + + return __check_sorted_aux(__first, __last, __pred, _Category()); + } + + template<typename _InputIterator> + inline bool + __check_sorted_set_aux(const _InputIterator& __first, + const _InputIterator& __last, + std::__true_type) + { return __check_sorted(__first, __last); } + + template<typename _InputIterator> + inline bool + __check_sorted_set_aux(const _InputIterator&, + const _InputIterator&, + std::__false_type) + { return true; } + + template<typename _InputIterator, typename _Predicate> + inline bool + __check_sorted_set_aux(const _InputIterator& __first, + const _InputIterator& __last, + _Predicate __pred, std::__true_type) + { return __check_sorted(__first, __last, __pred); } + + template<typename _InputIterator, typename _Predicate> + inline bool + __check_sorted_set_aux(const _InputIterator&, + const _InputIterator&, _Predicate, + std::__false_type) + { return true; } + + // ... special variant used in std::merge, std::includes, std::set_*. + template<typename _InputIterator1, typename _InputIterator2> + inline bool + __check_sorted_set(const _InputIterator1& __first, + const _InputIterator1& __last, + const _InputIterator2&) + { + typedef typename std::iterator_traits<_InputIterator1>::value_type + _ValueType1; + typedef typename std::iterator_traits<_InputIterator2>::value_type + _ValueType2; + + typedef typename std::__are_same<_ValueType1, _ValueType2>::__type + _SameType; + return __check_sorted_set_aux(__first, __last, _SameType()); + } + + template<typename _InputIterator1, typename _InputIterator2, + typename _Predicate> + inline bool + __check_sorted_set(const _InputIterator1& __first, + const _InputIterator1& __last, + const _InputIterator2&, _Predicate __pred) + { + typedef typename std::iterator_traits<_InputIterator1>::value_type + _ValueType1; + typedef typename std::iterator_traits<_InputIterator2>::value_type + _ValueType2; + + typedef typename std::__are_same<_ValueType1, _ValueType2>::__type + _SameType; + return __check_sorted_set_aux(__first, __last, __pred, _SameType()); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 270. Binary search requirements overly strict + // Determine if a sequence is partitioned w.r.t. this element. + template<typename _ForwardIterator, typename _Tp> + inline bool + __check_partitioned_lower(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value) + { + while (__first != __last && *__first < __value) + ++__first; + while (__first != __last && !(*__first < __value)) + ++__first; + return __first == __last; + } + + template<typename _ForwardIterator, typename _Tp> + inline bool + __check_partitioned_upper(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value) + { + while (__first != __last && !(__value < *__first)) + ++__first; + while (__first != __last && __value < *__first) + ++__first; + return __first == __last; + } + + // Determine if a sequence is partitioned w.r.t. this element. + template<typename _ForwardIterator, typename _Tp, typename _Pred> + inline bool + __check_partitioned_lower(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value, + _Pred __pred) + { + while (__first != __last && bool(__pred(*__first, __value))) + ++__first; + while (__first != __last && !bool(__pred(*__first, __value))) + ++__first; + return __first == __last; + } + + template<typename _ForwardIterator, typename _Tp, typename _Pred> + inline bool + __check_partitioned_upper(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value, + _Pred __pred) + { + while (__first != __last && !bool(__pred(__value, *__first))) + ++__first; + while (__first != __last && bool(__pred(__value, *__first))) + ++__first; + return __first == __last; + } +} // namespace __gnu_debug + +#endif diff --git a/libstdc++-v3/include/debug/list b/libstdc++-v3/include/debug/list new file mode 100644 index 000000000..a7a2c5499 --- /dev/null +++ b/libstdc++-v3/include/debug/list @@ -0,0 +1,744 @@ +// Debugging list implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/list + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_LIST +#define _GLIBCXX_DEBUG_LIST 1 + +#include <list> +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::list with safety/checking/debug instrumentation. + template<typename _Tp, typename _Allocator = std::allocator<_Tp> > + class list + : public _GLIBCXX_STD_C::list<_Tp, _Allocator>, + public __gnu_debug::_Safe_sequence<list<_Tp, _Allocator> > + { + typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<list> _Safe_base; + + typedef typename _Base::iterator _Base_iterator; + typedef typename _Base::const_iterator _Base_const_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + public: + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, list> + iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, list> + const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + + typedef _Tp value_type; + typedef _Allocator allocator_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + // 23.2.2.1 construct/copy/destroy: + explicit + list(const _Allocator& __a = _Allocator()) + : _Base(__a) { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + explicit + list(size_type __n) + : _Base(__n) { } + + list(size_type __n, const _Tp& __value, + const _Allocator& __a = _Allocator()) + : _Base(__n, __value, __a) { } +#else + explicit + list(size_type __n, const _Tp& __value = _Tp(), + const _Allocator& __a = _Allocator()) + : _Base(__n, __value, __a) { } +#endif + + template<class _InputIterator> + list(_InputIterator __first, _InputIterator __last, + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __a) + { } + + + list(const list& __x) + : _Base(__x), _Safe_base() { } + + list(const _Base& __x) + : _Base(__x), _Safe_base() { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + list(list&& __x) + : _Base(std::move(__x)), _Safe_base() + { this->_M_swap(__x); } + + list(initializer_list<value_type> __l, + const allocator_type& __a = allocator_type()) + : _Base(__l, __a), _Safe_base() { } +#endif + + ~list() { } + + list& + operator=(const list& __x) + { + static_cast<_Base&>(*this) = __x; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + list& + operator=(list&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + list& + operator=(initializer_list<value_type> __l) + { + static_cast<_Base&>(*this) = __l; + this->_M_invalidate_all(); + return *this; + } + + void + assign(initializer_list<value_type> __l) + { + _Base::assign(__l); + this->_M_invalidate_all(); + } +#endif + + template<class _InputIterator> + void + assign(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::assign(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + } + + void + assign(size_type __n, const _Tp& __t) + { + _Base::assign(__n, __t); + this->_M_invalidate_all(); + } + + using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + + // 23.2.2.2 capacity: + using _Base::empty; + using _Base::size; + using _Base::max_size; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + resize(size_type __sz) + { + this->_M_detach_singular(); + + // if __sz < size(), invalidate all iterators in [begin+__sz, end()) + _Base_iterator __victim = _Base::begin(); + _Base_iterator __end = _Base::end(); + for (size_type __i = __sz; __victim != __end && __i > 0; --__i) + ++__victim; + + for (; __victim != __end; ++__victim) + { + this->_M_invalidate_if(_Equal(__victim)); + } + + __try + { + _Base::resize(__sz); + } + __catch(...) + { + this->_M_revalidate_singular(); + __throw_exception_again; + } + } + + void + resize(size_type __sz, const _Tp& __c) + { + this->_M_detach_singular(); + + // if __sz < size(), invalidate all iterators in [begin+__sz, end()) + _Base_iterator __victim = _Base::begin(); + _Base_iterator __end = _Base::end(); + for (size_type __i = __sz; __victim != __end && __i > 0; --__i) + ++__victim; + + for (; __victim != __end; ++__victim) + { + this->_M_invalidate_if(_Equal(__victim)); + } + + __try + { + _Base::resize(__sz, __c); + } + __catch(...) + { + this->_M_revalidate_singular(); + __throw_exception_again; + } + } +#else + void + resize(size_type __sz, _Tp __c = _Tp()) + { + this->_M_detach_singular(); + + // if __sz < size(), invalidate all iterators in [begin+__sz, end()) + _Base_iterator __victim = _Base::begin(); + _Base_iterator __end = _Base::end(); + for (size_type __i = __sz; __victim != __end && __i > 0; --__i) + ++__victim; + + for (; __victim != __end; ++__victim) + { + this->_M_invalidate_if(_Equal(__victim)); + } + + __try + { + _Base::resize(__sz, __c); + } + __catch(...) + { + this->_M_revalidate_singular(); + __throw_exception_again; + } + } +#endif + + // element access: + reference + front() + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + const_reference + front() const + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + reference + back() + { + __glibcxx_check_nonempty(); + return _Base::back(); + } + + const_reference + back() const + { + __glibcxx_check_nonempty(); + return _Base::back(); + } + + // 23.2.2.3 modifiers: + using _Base::push_front; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + using _Base::emplace_front; +#endif + + void + pop_front() + { + __glibcxx_check_nonempty(); + this->_M_invalidate_if(_Equal(_Base::begin())); + _Base::pop_front(); + } + + using _Base::push_back; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + using _Base::emplace_back; +#endif + + void + pop_back() + { + __glibcxx_check_nonempty(); + this->_M_invalidate_if(_Equal(--_Base::end())); + _Base::pop_back(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename... _Args> + iterator + emplace(iterator __position, _Args&&... __args) + { + __glibcxx_check_insert(__position); + return iterator(_Base::emplace(__position.base(), + std::forward<_Args>(__args)...), this); + } +#endif + + iterator + insert(iterator __position, const _Tp& __x) + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), __x), this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + insert(iterator __position, _Tp&& __x) + { return emplace(__position, std::move(__x)); } + + void + insert(iterator __p, initializer_list<value_type> __l) + { + __glibcxx_check_insert(__p); + _Base::insert(__p, __l); + } +#endif + + void + insert(iterator __position, size_type __n, const _Tp& __x) + { + __glibcxx_check_insert(__position); + _Base::insert(__position.base(), __n, __x); + } + + template<class _InputIterator> + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + __glibcxx_check_insert_range(__position, __first, __last); + _Base::insert(__position.base(), __gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + + private: + _Base_iterator + _M_erase(_Base_iterator __position) + { + this->_M_invalidate_if(_Equal(__position)); + return _Base::erase(__position); + } + public: + iterator + erase(iterator __position) + { + __glibcxx_check_erase(__position); + return iterator(_M_erase(__position.base()), this); + } + + iterator + erase(iterator __position, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__position, __last); + for (_Base_iterator __victim = __position.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__position, "position") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + return iterator(_Base::erase(__position.base(), __last.base()), this); + } + + void + swap(list& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + // 23.2.2.4 list operations: + void +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + splice(iterator __position, list&& __x) +#else + splice(iterator __position, list& __x) +#endif + { + _GLIBCXX_DEBUG_VERIFY(&__x != this, + _M_message(__gnu_debug::__msg_self_splice) + ._M_sequence(*this, "this")); + this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end())); + _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base())); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + splice(iterator __position, list& __x) + { splice(__position, std::move(__x)); } +#endif + + void +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + splice(iterator __position, list&& __x, iterator __i) +#else + splice(iterator __position, list& __x, iterator __i) +#endif + { + __glibcxx_check_insert(__position); + + // We used to perform the splice_alloc check: not anymore, redundant + // after implementing the relevant bits of N1599. + + _GLIBCXX_DEBUG_VERIFY(__i._M_dereferenceable(), + _M_message(__gnu_debug::__msg_splice_bad) + ._M_iterator(__i, "__i")); + _GLIBCXX_DEBUG_VERIFY(__i._M_attached_to(&__x), + _M_message(__gnu_debug::__msg_splice_other) + ._M_iterator(__i, "__i")._M_sequence(__x, "__x")); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 250. splicing invalidates iterators + this->_M_transfer_from_if(__x, _Equal(__i.base())); + _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), + __i.base()); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + splice(iterator __position, list& __x, iterator __i) + { splice(__position, std::move(__x), __i); } +#endif + + void +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + splice(iterator __position, list&& __x, iterator __first, + iterator __last) +#else + splice(iterator __position, list& __x, iterator __first, + iterator __last) +#endif + { + __glibcxx_check_insert(__position); + __glibcxx_check_valid_range(__first, __last); + _GLIBCXX_DEBUG_VERIFY(__first._M_attached_to(&__x), + _M_message(__gnu_debug::__msg_splice_other) + ._M_sequence(__x, "x") + ._M_iterator(__first, "first")); + + // We used to perform the splice_alloc check: not anymore, redundant + // after implementing the relevant bits of N1599. + + for (_Base_iterator __tmp = __first.base(); + __tmp != __last.base(); ++__tmp) + { + _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + _GLIBCXX_DEBUG_VERIFY(&__x != this || __tmp != __position, + _M_message(__gnu_debug::__msg_splice_overlap) + ._M_iterator(__tmp, "position") + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 250. splicing invalidates iterators + this->_M_transfer_from_if(__x, _Equal(__tmp)); + } + + _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), + __first.base(), __last.base()); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + splice(iterator __position, list& __x, iterator __first, iterator __last) + { splice(__position, std::move(__x), __first, __last); } +#endif + + void + remove(const _Tp& __value) + { + for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) + { + if (*__x == __value) + __x = _M_erase(__x); + else + ++__x; + } + } + + template<class _Predicate> + void + remove_if(_Predicate __pred) + { + for (_Base_iterator __x = _Base::begin(); __x != _Base::end(); ) + { + if (__pred(*__x)) + __x = _M_erase(__x); + else + ++__x; + } + } + + void + unique() + { + _Base_iterator __first = _Base::begin(); + _Base_iterator __last = _Base::end(); + if (__first == __last) + return; + _Base_iterator __next = __first; ++__next; + while (__next != __last) + { + if (*__first == *__next) + __next = _M_erase(__next); + else + __first = __next++; + } + } + + template<class _BinaryPredicate> + void + unique(_BinaryPredicate __binary_pred) + { + _Base_iterator __first = _Base::begin(); + _Base_iterator __last = _Base::end(); + if (__first == __last) + return; + _Base_iterator __next = __first; ++__next; + while (__next != __last) + { + if (__binary_pred(*__first, *__next)) + __next = _M_erase(__next); + else + __first = __next++; + } + } + + void +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + merge(list&& __x) +#else + merge(list& __x) +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 300. list::merge() specification incomplete + if (this != &__x) + { + __glibcxx_check_sorted(_Base::begin(), _Base::end()); + __glibcxx_check_sorted(__x.begin().base(), __x.end().base()); + this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end())); + _Base::merge(_GLIBCXX_MOVE(__x._M_base())); + } + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + merge(list& __x) + { merge(std::move(__x)); } +#endif + + template<class _Compare> + void +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + merge(list&& __x, _Compare __comp) +#else + merge(list& __x, _Compare __comp) +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 300. list::merge() specification incomplete + if (this != &__x) + { + __glibcxx_check_sorted_pred(_Base::begin(), _Base::end(), + __comp); + __glibcxx_check_sorted_pred(__x.begin().base(), __x.end().base(), + __comp); + this->_M_transfer_from_if(__x, _Not_equal(__x._M_base().end())); + _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); + } + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Compare> + void + merge(list& __x, _Compare __comp) + { merge(std::move(__x), __comp); } +#endif + + void + sort() { _Base::sort(); } + + template<typename _StrictWeakOrdering> + void + sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); } + + using _Base::reverse; + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + this->_M_invalidate_if(_Not_equal(_Base::end())); + } + }; + + template<typename _Tp, typename _Alloc> + inline bool + operator==(const list<_Tp, _Alloc>& __lhs, + const list<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const list<_Tp, _Alloc>& __lhs, + const list<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<(const list<_Tp, _Alloc>& __lhs, + const list<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<=(const list<_Tp, _Alloc>& __lhs, + const list<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>=(const list<_Tp, _Alloc>& __lhs, + const list<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>(const list<_Tp, _Alloc>& __lhs, + const list<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline void + swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs) + { __lhs.swap(__rhs); } + +} // namespace __debug +} // namespace std + +#endif diff --git a/libstdc++-v3/include/debug/macros.h b/libstdc++-v3/include/debug/macros.h new file mode 100644 index 000000000..c90bec5cf --- /dev/null +++ b/libstdc++-v3/include/debug/macros.h @@ -0,0 +1,312 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/macros.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MACROS_H +#define _GLIBCXX_DEBUG_MACROS_H 1 + +/** + * Macros used by the implementation to verify certain + * properties. These macros may only be used directly by the debug + * wrappers. Note that these are macros (instead of the more obviously + * @a correct choice of making them functions) because we need line and + * file information at the call site, to minimize the distance between + * the user error and where the error is reported. + * + */ +#define _GLIBCXX_DEBUG_VERIFY(_Condition,_ErrorMessage) \ + do \ + { \ + if (! (_Condition)) \ + __gnu_debug::_Error_formatter::_M_at(__FILE__, __LINE__) \ + ._ErrorMessage._M_error(); \ + } while (false) + +// Verify that [_First, _Last) forms a valid iterator range. +#define __glibcxx_check_valid_range(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last), \ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that we can insert into *this with the iterator _Position. + * Insertion into a container at a specific position requires that + * the iterator be nonsingular, either dereferenceable or past-the-end, + * and that it reference the sequence we are inserting into. Note that + * this macro is only valid when the container is a_Safe_sequence and + * the iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert(_Position) \ +_GLIBCXX_DEBUG_VERIFY(!_Position._M_singular(), \ + _M_message(__gnu_debug::__msg_insert_singular) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_insert_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can insert into *this after the iterator _Position. + * Insertion into a container after a specific position requires that + * the iterator be nonsingular, either dereferenceable or before-begin, + * and that it reference the sequence we are inserting into. Note that + * this macro is only valid when the container is a_Safe_sequence and + * the iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert_after(_Position) \ +__glibcxx_check_insert(_Position); \ +_GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \ + _M_message(__gnu_debug::__msg_insert_after_end) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can insert the values in the iterator range + * [_First, _Last) into *this with the iterator _Position. Insertion + * into a container at a specific position requires that the iterator + * be nonsingular (i.e., either dereferenceable or past-the-end), + * that it reference the sequence we are inserting into, and that the + * iterator range [_First, Last) is a valid (possibly empty) + * range. Note that this macro is only valid when the container is a + * _Safe_sequence and the iterator is a _Safe_iterator. + * + * @todo We would like to be able to check for noninterference of + * _Position and the range [_First, _Last), but that can't (in + * general) be done. +*/ +#define __glibcxx_check_insert_range(_Position,_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_insert(_Position) + +/** Verify that we can insert the values in the iterator range + * [_First, _Last) into *this after the iterator _Position. Insertion + * into a container after a specific position requires that the iterator + * be nonsingular (i.e., either dereferenceable or past-the-end), + * that it reference the sequence we are inserting into, and that the + * iterator range [_First, Last) is a valid (possibly empty) + * range. Note that this macro is only valid when the container is a + * _Safe_sequence and the iterator is a _Safe_iterator. + * + * @todo We would like to be able to check for noninterference of + * _Position and the range [_First, _Last), but that can't (in + * general) be done. +*/ +#define __glibcxx_check_insert_range_after(_Position,_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_insert_after(_Position) + +/** Verify that we can erase the element referenced by the iterator + * _Position. We can erase the element if the _Position iterator is + * dereferenceable and references this sequence. +*/ +#define __glibcxx_check_erase(_Position) \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_dereferenceable(), \ + _M_message(__gnu_debug::__msg_erase_bad) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can erase the element after the iterator + * _Position. We can erase the element if the _Position iterator is + * before a dereferenceable one and references this sequence. +*/ +#define __glibcxx_check_erase_after(_Position) \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_before_dereferenceable(), \ + _M_message(__gnu_debug::__msg_erase_after_bad) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can erase the elements in the iterator range + * [_First, _Last). We can erase the elements if [_First, _Last) is a + * valid iterator range within this sequence. +*/ +#define __glibcxx_check_erase_range(_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that we can erase the elements in the iterator range + * (_First, _Last). We can erase the elements if (_First, _Last) is a + * valid iterator range within this sequence. +*/ +#define __glibcxx_check_erase_range_after(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(_First._M_can_compare(_Last), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First)); \ +_GLIBCXX_DEBUG_VERIFY(_First != _Last, \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_incrementable(), \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(!_Last._M_is_before_begin(), \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) \ + +// Verify that the subscript _N is less than the container's size. +#define __glibcxx_check_subscript(_N) \ +_GLIBCXX_DEBUG_VERIFY(_N < this->size(), \ + _M_message(__gnu_debug::__msg_subscript_oob) \ + ._M_sequence(*this, "this") \ + ._M_integer(_N, #_N) \ + ._M_integer(this->size(), "size")) + +// Verify that the container is nonempty +#define __glibcxx_check_nonempty() \ +_GLIBCXX_DEBUG_VERIFY(! this->empty(), \ + _M_message(__gnu_debug::__msg_empty) \ + ._M_sequence(*this, "this")) + +// Verify that the iterator range [_First, _Last) is sorted +#define __glibcxx_check_sorted(_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted(_First, _Last), \ + _M_message(__gnu_debug::__msg_unsorted) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that the iterator range [_First, _Last) is sorted by the + predicate _Pred. */ +#define __glibcxx_check_sorted_pred(_First,_Last,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted(_First, _Last, _Pred), \ + _M_message(__gnu_debug::__msg_unsorted_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred)) + +// Special variant for std::merge, std::includes, std::set_* +#define __glibcxx_check_sorted_set(_First1,_Last1,_First2) \ +__glibcxx_check_valid_range(_First1,_Last1); \ +_GLIBCXX_DEBUG_VERIFY( \ + __gnu_debug::__check_sorted_set(_First1, _Last1, _First2), \ + _M_message(__gnu_debug::__msg_unsorted) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1)) + +// Likewise with a _Pred. +#define __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ +__glibcxx_check_valid_range(_First1,_Last1); \ +_GLIBCXX_DEBUG_VERIFY( \ + __gnu_debug::__check_sorted_set(_First1, _Last1, _First2, _Pred), \ + _M_message(__gnu_debug::__msg_unsorted_pred) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1) \ + ._M_string(#_Pred)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value. */ +#define __glibcxx_check_partitioned_lower(_First,_Last,_Value) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower(_First, _Last, \ + _Value), \ + _M_message(__gnu_debug::__msg_unpartitioned) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Value)) + +#define __glibcxx_check_partitioned_upper(_First,_Last,_Value) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper(_First, _Last, \ + _Value), \ + _M_message(__gnu_debug::__msg_unpartitioned) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Value)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value and predicate _Pred. */ +#define __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower(_First, _Last, \ + _Value, _Pred), \ + _M_message(__gnu_debug::__msg_unpartitioned_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred) \ + ._M_string(#_Value)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value and predicate _Pred. */ +#define __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper(_First, _Last, \ + _Value, _Pred), \ + _M_message(__gnu_debug::__msg_unpartitioned_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred) \ + ._M_string(#_Value)) + +// Verify that the iterator range [_First, _Last) is a heap +#define __glibcxx_check_heap(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(std::__is_heap(_First, _Last), \ + _M_message(__gnu_debug::__msg_not_heap) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that the iterator range [_First, _Last) is a heap + w.r.t. the predicate _Pred. */ +#define __glibcxx_check_heap_pred(_First,_Last,_Pred) \ +_GLIBCXX_DEBUG_VERIFY(std::__is_heap(_First, _Last, _Pred), \ + _M_message(__gnu_debug::__msg_not_heap_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred)) + +#ifdef _GLIBCXX_DEBUG_PEDANTIC +# define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0) +# define __glibcxx_check_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_ASSERT(_String != 0 || _Len == 0) +#else +# define __glibcxx_check_string(_String) +# define __glibcxx_check_string_len(_String,_Len) +#endif + +#endif diff --git a/libstdc++-v3/include/debug/map b/libstdc++-v3/include/debug/map new file mode 100644 index 000000000..2d16b71d3 --- /dev/null +++ b/libstdc++-v3/include/debug/map @@ -0,0 +1,37 @@ +// Debugging map/multimap implementation -*- C++ -*- + +// Copyright (C) 2003, 2006, 2009 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/map + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MAP +#define _GLIBCXX_DEBUG_MAP 1 + +#include <map> +#include <debug/map.h> +#include <debug/multimap.h> + +#endif diff --git a/libstdc++-v3/include/debug/map.h b/libstdc++-v3/include/debug/map.h new file mode 100644 index 000000000..177797d73 --- /dev/null +++ b/libstdc++-v3/include/debug/map.h @@ -0,0 +1,475 @@ +// Debugging map implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/map.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MAP_H +#define _GLIBCXX_DEBUG_MAP_H 1 + +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> +#include <utility> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::map with safety/checking/debug instrumentation. + template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>, + typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > > + class map + : public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>, + public __gnu_debug::_Safe_sequence<map<_Key, _Tp, _Compare, _Allocator> > + { + typedef _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<map> _Safe_base; + + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + public: + // types: + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair<const _Key, _Tp> value_type; + typedef _Compare key_compare; + typedef _Allocator allocator_type; + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, map> + iterator; + typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, map> + const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + // 23.3.1.1 construct/copy/destroy: + explicit map(const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + + template<typename _InputIterator> + map(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a), _Safe_base() { } + + map(const map& __x) + : _Base(__x), _Safe_base() { } + + map(const _Base& __x) + : _Base(__x), _Safe_base() { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + map(map&& __x) + : _Base(std::move(__x)), _Safe_base() + { this->_M_swap(__x); } + + map(initializer_list<value_type> __l, + const _Compare& __c = _Compare(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __c, __a), _Safe_base() { } +#endif + + ~map() { } + + map& + operator=(const map& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + map& + operator=(map&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + map& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 133. map missing get_allocator() + using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + + // capacity: + using _Base::empty; + using _Base::size; + using _Base::max_size; + + // 23.3.1.2 element access: + using _Base::operator[]; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + using _Base::at; + + // modifiers: + std::pair<iterator, bool> + insert(const value_type& __x) + { + typedef typename _Base::iterator _Base_iterator; + std::pair<_Base_iterator, bool> __res = _Base::insert(__x); + return std::pair<iterator, bool>(iterator(__res.first, this), + __res.second); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + std::pair<iterator, bool> + insert(_Pair&& __x) + { + typedef typename _Base::iterator _Base_iterator; + std::pair<_Base_iterator, bool> __res + = _Base::insert(std::forward<_Pair>(__x)); + return std::pair<iterator, bool>(iterator(__res.first, this), + __res.second); + } +#endif + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + insert(std::initializer_list<value_type> __list) + { _Base::insert(__list); } +#endif + + iterator +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), __x), this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + iterator + insert(const_iterator __position, _Pair&& __x) + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), + std::forward<_Pair>(__x)), this); + } +#endif + + template<typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + return iterator(_Base::erase(__position.base()), this); + } + + iterator + erase(iterator __position) + { return erase(const_iterator(__position)); } +#else + void + erase(iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + _Base::erase(__position.base()); + } +#endif + + size_type + erase(const key_type& __x) + { + _Base_iterator __victim = _Base::find(__x); + if (__victim == _Base::end()) + return 0; + else + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim); + return 1; + } + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __first, const_iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + return iterator(_Base::erase(__first.base(), __last.base()), this); + } +#else + void + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + _Base::erase(__first.base(), __last.base()); + } +#endif + + void + swap(map& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + } + + void + clear() + { + this->_M_invalidate_all(); + _Base::clear(); + } + + // observers: + using _Base::key_comp; + using _Base::value_comp; + + // 23.3.1.3 map operations: + iterator + find(const key_type& __x) + { return iterator(_Base::find(__x), this); } + + const_iterator + find(const key_type& __x) const + { return const_iterator(_Base::find(__x), this); } + + using _Base::count; + + iterator + lower_bound(const key_type& __x) + { return iterator(_Base::lower_bound(__x), this); } + + const_iterator + lower_bound(const key_type& __x) const + { return const_iterator(_Base::lower_bound(__x), this); } + + iterator + upper_bound(const key_type& __x) + { return iterator(_Base::upper_bound(__x), this); } + + const_iterator + upper_bound(const key_type& __x) const + { return const_iterator(_Base::upper_bound(__x), this); } + + std::pair<iterator,iterator> + equal_range(const key_type& __x) + { + typedef typename _Base::iterator _Base_iterator; + std::pair<_Base_iterator, _Base_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + std::pair<const_iterator,const_iterator> + equal_range(const key_type& __x) const + { + typedef typename _Base::const_iterator _Base_const_iterator; + std::pair<_Base_const_iterator, _Base_const_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef typename _Base::const_iterator _Base_const_iterator; + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_M_base().end())); + } + }; + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator==(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, + const map<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, + const map<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator<(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, + const map<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, + const map<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator>=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, + const map<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator>(const map<_Key, _Tp, _Compare, _Allocator>& __lhs, + const map<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline void + swap(map<_Key, _Tp, _Compare, _Allocator>& __lhs, + map<_Key, _Tp, _Compare, _Allocator>& __rhs) + { __lhs.swap(__rhs); } + +} // namespace __debug +} // namespace std + +#endif diff --git a/libstdc++-v3/include/debug/multimap.h b/libstdc++-v3/include/debug/multimap.h new file mode 100644 index 000000000..d2e197699 --- /dev/null +++ b/libstdc++-v3/include/debug/multimap.h @@ -0,0 +1,455 @@ +// Debugging multimap implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/multimap.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MULTIMAP_H +#define _GLIBCXX_DEBUG_MULTIMAP_H 1 + +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> +#include <utility> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::multimap with safety/checking/debug instrumentation. + template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>, + typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > > + class multimap + : public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>, + public __gnu_debug::_Safe_sequence<multimap<_Key, _Tp, + _Compare, _Allocator> > + { + typedef _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<multimap> _Safe_base; + + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + public: + // types: + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair<const _Key, _Tp> value_type; + typedef _Compare key_compare; + typedef _Allocator allocator_type; + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, multimap> + iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, + multimap> const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + // 23.3.1.1 construct/copy/destroy: + explicit multimap(const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + + template<typename _InputIterator> + multimap(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a) { } + + multimap(const multimap& __x) + : _Base(__x), _Safe_base() { } + + multimap(const _Base& __x) + : _Base(__x), _Safe_base() { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + multimap(multimap&& __x) + : _Base(std::move(__x)), _Safe_base() + { this->_M_swap(__x); } + + multimap(initializer_list<value_type> __l, + const _Compare& __c = _Compare(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __c, __a), _Safe_base() { } +#endif + + ~multimap() { } + + multimap& + operator=(const multimap& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + multimap& + operator=(multimap&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + multimap& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } +#endif + + using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + + // capacity: + using _Base::empty; + using _Base::size; + using _Base::max_size; + + // modifiers: + iterator + insert(const value_type& __x) + { return iterator(_Base::insert(__x), this); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + iterator + insert(_Pair&& __x) + { return iterator(_Base::insert(std::forward<_Pair>(__x)), this); } +#endif + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + insert(std::initializer_list<value_type> __list) + { _Base::insert(__list); } +#endif + + iterator +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), __x), this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + iterator + insert(const_iterator __position, _Pair&& __x) + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), + std::forward<_Pair>(__x)), this); + } +#endif + + template<typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + return iterator(_Base::erase(__position.base()), this); + } + + iterator + erase(iterator __position) + { return erase(const_iterator(__position)); } +#else + void + erase(iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + _Base::erase(__position.base()); + } +#endif + + size_type + erase(const key_type& __x) + { + std::pair<_Base_iterator, _Base_iterator> __victims = + _Base::equal_range(__x); + size_type __count = 0; + _Base_iterator __victim = __victims.first; + while (__victim != __victims.second) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__count; + } + return __count; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __first, const_iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + return iterator(_Base::erase(__first.base(), __last.base()), this); + } +#else + void + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + _Base::erase(__first.base(), __last.base()); + } +#endif + + void + swap(multimap& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + } + + void + clear() + { + this->_M_invalidate_all(); + _Base::clear(); + } + + // observers: + using _Base::key_comp; + using _Base::value_comp; + + // 23.3.1.3 multimap operations: + iterator + find(const key_type& __x) + { return iterator(_Base::find(__x), this); } + + const_iterator + find(const key_type& __x) const + { return const_iterator(_Base::find(__x), this); } + + using _Base::count; + + iterator + lower_bound(const key_type& __x) + { return iterator(_Base::lower_bound(__x), this); } + + const_iterator + lower_bound(const key_type& __x) const + { return const_iterator(_Base::lower_bound(__x), this); } + + iterator + upper_bound(const key_type& __x) + { return iterator(_Base::upper_bound(__x), this); } + + const_iterator + upper_bound(const key_type& __x) const + { return const_iterator(_Base::upper_bound(__x), this); } + + std::pair<iterator,iterator> + equal_range(const key_type& __x) + { + std::pair<_Base_iterator, _Base_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + std::pair<const_iterator,const_iterator> + equal_range(const key_type& __x) const + { + std::pair<_Base_const_iterator, _Base_const_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_Base::end())); + } + }; + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator==(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, + const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator!=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, + const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator<(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, + const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator<=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, + const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator>=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, + const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline bool + operator>(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, + const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Key, typename _Tp, + typename _Compare, typename _Allocator> + inline void + swap(multimap<_Key, _Tp, _Compare, _Allocator>& __lhs, + multimap<_Key, _Tp, _Compare, _Allocator>& __rhs) + { __lhs.swap(__rhs); } + +} // namespace __debug +} // namespace std + +#endif diff --git a/libstdc++-v3/include/debug/multiset.h b/libstdc++-v3/include/debug/multiset.h new file mode 100644 index 000000000..6808fb804 --- /dev/null +++ b/libstdc++-v3/include/debug/multiset.h @@ -0,0 +1,441 @@ +// Debugging multiset implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/multiset.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MULTISET_H +#define _GLIBCXX_DEBUG_MULTISET_H 1 + +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> +#include <utility> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::multiset with safety/checking/debug instrumentation. + template<typename _Key, typename _Compare = std::less<_Key>, + typename _Allocator = std::allocator<_Key> > + class multiset + : public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>, + public __gnu_debug::_Safe_sequence<multiset<_Key, _Compare, _Allocator> > + { + typedef _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<multiset> _Safe_base; + + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + public: + // types: + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + typedef _Allocator allocator_type; + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, multiset> + iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, + multiset> const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + // 23.3.3.1 construct/copy/destroy: + explicit multiset(const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + + template<typename _InputIterator> + multiset(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a) { } + + multiset(const multiset& __x) + : _Base(__x), _Safe_base() { } + + multiset(const _Base& __x) + : _Base(__x), _Safe_base() { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + multiset(multiset&& __x) + : _Base(std::move(__x)), _Safe_base() + { this->_M_swap(__x); } + + multiset(initializer_list<value_type> __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __comp, __a), _Safe_base() { } +#endif + + ~multiset() { } + + multiset& + operator=(const multiset& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + multiset& + operator=(multiset&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + multiset& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } +#endif + + using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + + // capacity: + using _Base::empty; + using _Base::size; + using _Base::max_size; + + // modifiers: + iterator + insert(const value_type& __x) + { return iterator(_Base::insert(__x), this); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + insert(value_type&& __x) + { return iterator(_Base::insert(std::move(__x)), this); } +#endif + + iterator + insert(const_iterator __position, const value_type& __x) + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), __x), this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + insert(const_iterator __position, value_type&& __x) + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), std::move(__x)), + this); + } +#endif + + template<typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + insert(initializer_list<value_type> __l) + { _Base::insert(__l); } +#endif + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + return iterator(_Base::erase(__position.base()), this); + } +#else + void + erase(iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + _Base::erase(__position.base()); + } +#endif + + size_type + erase(const key_type& __x) + { + std::pair<_Base_iterator, _Base_iterator> __victims = + _Base::equal_range(__x); + size_type __count = 0; + _Base_iterator __victim = __victims.first; + while (__victim != __victims.second) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__count; + } + return __count; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __first, const_iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + return iterator(_Base::erase(__first.base(), __last.base()), this); + } +#else + void + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + _Base::erase(__first.base(), __last.base()); + } +#endif + + void + swap(multiset& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + } + + void + clear() + { + this->_M_invalidate_all(); + _Base::clear(); + } + + // observers: + using _Base::key_comp; + using _Base::value_comp; + + // multiset operations: + iterator + find(const key_type& __x) + { return iterator(_Base::find(__x), this); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + const_iterator + find(const key_type& __x) const + { return const_iterator(_Base::find(__x), this); } + + using _Base::count; + + iterator + lower_bound(const key_type& __x) + { return iterator(_Base::lower_bound(__x), this); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + const_iterator + lower_bound(const key_type& __x) const + { return const_iterator(_Base::lower_bound(__x), this); } + + iterator + upper_bound(const key_type& __x) + { return iterator(_Base::upper_bound(__x), this); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + const_iterator + upper_bound(const key_type& __x) const + { return const_iterator(_Base::upper_bound(__x), this); } + + std::pair<iterator,iterator> + equal_range(const key_type& __x) + { + std::pair<_Base_iterator, _Base_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + std::pair<const_iterator,const_iterator> + equal_range(const key_type& __x) const + { + std::pair<_Base_const_iterator, _Base_const_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_Base::end())); + } + }; + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator==(const multiset<_Key, _Compare, _Allocator>& __lhs, + const multiset<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator!=(const multiset<_Key, _Compare, _Allocator>& __lhs, + const multiset<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator<(const multiset<_Key, _Compare, _Allocator>& __lhs, + const multiset<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator<=(const multiset<_Key, _Compare, _Allocator>& __lhs, + const multiset<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator>=(const multiset<_Key, _Compare, _Allocator>& __lhs, + const multiset<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator>(const multiset<_Key, _Compare, _Allocator>& __lhs, + const multiset<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + void + swap(multiset<_Key, _Compare, _Allocator>& __x, + multiset<_Key, _Compare, _Allocator>& __y) + { return __x.swap(__y); } + +} // namespace __debug +} // namespace std + +#endif diff --git a/libstdc++-v3/include/debug/safe_base.h b/libstdc++-v3/include/debug/safe_base.h new file mode 100644 index 000000000..1348004cb --- /dev/null +++ b/libstdc++-v3/include/debug/safe_base.h @@ -0,0 +1,255 @@ +// Safe sequence/iterator base implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/safe_base.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SAFE_BASE_H +#define _GLIBCXX_DEBUG_SAFE_BASE_H 1 + +#include <ext/concurrence.h> + +namespace __gnu_debug +{ + class _Safe_sequence_base; + + /** \brief Basic functionality for a @a safe iterator. + * + * The %_Safe_iterator_base base class implements the functionality + * of a safe iterator that is not specific to a particular iterator + * type. It contains a pointer back to the sequence it references + * along with iterator version information and pointers to form a + * doubly-linked list of iterators referenced by the container. + * + * This class must not perform any operations that can throw an + * exception, or the exception guarantees of derived iterators will + * be broken. + */ + class _Safe_iterator_base + { + public: + /** The sequence this iterator references; may be NULL to indicate + a singular iterator. */ + _Safe_sequence_base* _M_sequence; + + /** The version number of this iterator. The sentinel value 0 is + * used to indicate an invalidated iterator (i.e., one that is + * singular because of an operation on the container). This + * version number must equal the version number in the sequence + * referenced by _M_sequence for the iterator to be + * non-singular. + */ + unsigned int _M_version; + + /** Pointer to the previous iterator in the sequence's list of + iterators. Only valid when _M_sequence != NULL. */ + _Safe_iterator_base* _M_prior; + + /** Pointer to the next iterator in the sequence's list of + iterators. Only valid when _M_sequence != NULL. */ + _Safe_iterator_base* _M_next; + + protected: + /** Initializes the iterator and makes it singular. */ + _Safe_iterator_base() + : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) + { } + + /** Initialize the iterator to reference the sequence pointed to + * by @p__seq. @p __constant is true when we are initializing a + * constant iterator, and false if it is a mutable iterator. Note + * that @p __seq may be NULL, in which case the iterator will be + * singular. Otherwise, the iterator will reference @p __seq and + * be nonsingular. + */ + _Safe_iterator_base(const _Safe_sequence_base* __seq, bool __constant) + : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) + { this->_M_attach(const_cast<_Safe_sequence_base*>(__seq), __constant); } + + /** Initializes the iterator to reference the same sequence that + @p __x does. @p __constant is true if this is a constant + iterator, and false if it is mutable. */ + _Safe_iterator_base(const _Safe_iterator_base& __x, bool __constant) + : _M_sequence(0), _M_version(0), _M_prior(0), _M_next(0) + { this->_M_attach(__x._M_sequence, __constant); } + + _Safe_iterator_base& + operator=(const _Safe_iterator_base&); + + explicit + _Safe_iterator_base(const _Safe_iterator_base&); + + ~_Safe_iterator_base() { this->_M_detach(); } + + /** For use in _Safe_iterator. */ + __gnu_cxx::__mutex& _M_get_mutex() throw (); + + public: + /** Attaches this iterator to the given sequence, detaching it + * from whatever sequence it was attached to originally. If the + * new sequence is the NULL pointer, the iterator is left + * unattached. + */ + void _M_attach(_Safe_sequence_base* __seq, bool __constant); + + /** Likewise, but not thread-safe. */ + void _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw (); + + /** Detach the iterator for whatever sequence it is attached to, + * if any. + */ + void _M_detach(); + + /** Likewise, but not thread-safe. */ + void _M_detach_single() throw (); + + /** Determines if we are attached to the given sequence. */ + bool _M_attached_to(const _Safe_sequence_base* __seq) const + { return _M_sequence == __seq; } + + /** Is this iterator singular? */ + _GLIBCXX_PURE bool _M_singular() const throw (); + + /** Can we compare this iterator to the given iterator @p __x? + Returns true if both iterators are nonsingular and reference + the same sequence. */ + _GLIBCXX_PURE bool _M_can_compare(const _Safe_iterator_base& __x) const throw (); + + /** Invalidate the iterator, making it singular. */ + void + _M_invalidate() + { _M_version = 0; } + + /** Reset all member variables */ + void + _M_reset() throw (); + + /** Unlink itself */ + void + _M_unlink() throw () + { + if (_M_prior) + _M_prior->_M_next = _M_next; + if (_M_next) + _M_next->_M_prior = _M_prior; + } + }; + + /** + * @brief Base class that supports tracking of iterators that + * reference a sequence. + * + * The %_Safe_sequence_base class provides basic support for + * tracking iterators into a sequence. Sequences that track + * iterators must derived from %_Safe_sequence_base publicly, so + * that safe iterators (which inherit _Safe_iterator_base) can + * attach to them. This class contains two linked lists of + * iterators, one for constant iterators and one for mutable + * iterators, and a version number that allows very fast + * invalidation of all iterators that reference the container. + * + * This class must ensure that no operation on it may throw an + * exception, otherwise @a safe sequences may fail to provide the + * exception-safety guarantees required by the C++ standard. + */ + class _Safe_sequence_base + { + public: + /// The list of mutable iterators that reference this container + _Safe_iterator_base* _M_iterators; + + /// The list of constant iterators that reference this container + _Safe_iterator_base* _M_const_iterators; + + /// The container version number. This number may never be 0. + mutable unsigned int _M_version; + + protected: + // Initialize with a version number of 1 and no iterators + _Safe_sequence_base() + : _M_iterators(0), _M_const_iterators(0), _M_version(1) + { } + + /** Notify all iterators that reference this sequence that the + sequence is being destroyed. */ + ~_Safe_sequence_base() + { this->_M_detach_all(); } + + /** Detach all iterators, leaving them singular. */ + void + _M_detach_all(); + + /** Detach all singular iterators. + * @post for all iterators i attached to this sequence, + * i->_M_version == _M_version. + */ + void + _M_detach_singular(); + + /** Revalidates all attached singular iterators. This method may + * be used to validate iterators that were invalidated before + * (but for some reason, such as an exception, need to become + * valid again). + */ + void + _M_revalidate_singular(); + + /** Swap this sequence with the given sequence. This operation + * also swaps ownership of the iterators, so that when the + * operation is complete all iterators that originally referenced + * one container now reference the other container. + */ + void + _M_swap(_Safe_sequence_base& __x); + + /** For use in _Safe_sequence. */ + __gnu_cxx::__mutex& _M_get_mutex() throw (); + + public: + /** Invalidates all iterators. */ + void + _M_invalidate_all() const + { if (++_M_version == 0) _M_version = 1; } + + /** Attach an iterator to this sequence. */ + void + _M_attach(_Safe_iterator_base* __it, bool __constant); + + /** Likewise but not thread safe. */ + void + _M_attach_single(_Safe_iterator_base* __it, bool __constant) throw (); + + /** Detach an iterator from this sequence */ + void + _M_detach(_Safe_iterator_base* __it); + + /** Likewise but not thread safe. */ + void + _M_detach_single(_Safe_iterator_base* __it) throw (); + }; +} // namespace __gnu_debug + +#endif diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h new file mode 100644 index 000000000..8d1996b4b --- /dev/null +++ b/libstdc++-v3/include/debug/safe_iterator.h @@ -0,0 +1,730 @@ +// Safe iterator implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011, 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 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/safe_iterator.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_H +#define _GLIBCXX_DEBUG_SAFE_ITERATOR_H 1 + +#include <debug/debug.h> +#include <debug/macros.h> +#include <debug/functions.h> +#include <debug/safe_base.h> +#include <bits/stl_pair.h> +#include <bits/stl_iterator_base_types.h> // for _Iter_base +#include <ext/type_traits.h> + +namespace __gnu_debug +{ + /** Helper struct to deal with sequence offering a before_begin + * iterator. + **/ + template <typename _Sequence> + struct _BeforeBeginHelper + { + typedef typename _Sequence::const_iterator _It; + typedef typename _It::iterator_type _BaseIt; + + static bool + _M_Is(_BaseIt __it, const _Sequence* __seq) + { return false; } + }; + + /** Iterators that derive from _Safe_iterator_base but that aren't + * _Safe_iterators can be determined singular or non-singular via + * _Safe_iterator_base. + */ + inline bool + __check_singular_aux(const _Safe_iterator_base* __x) + { return __x->_M_singular(); } + + /** \brief Safe iterator wrapper. + * + * The class template %_Safe_iterator is a wrapper around an + * iterator that tracks the iterator's movement among sequences and + * checks that operations performed on the "safe" iterator are + * legal. In additional to the basic iterator operations (which are + * validated, and then passed to the underlying iterator), + * %_Safe_iterator has member functions for iterator invalidation, + * attaching/detaching the iterator from sequences, and querying + * the iterator's state. + */ + template<typename _Iterator, typename _Sequence> + class _Safe_iterator : public _Safe_iterator_base + { + typedef _Safe_iterator _Self; + + /** The precision to which we can calculate the distance between + * two iterators. + */ + enum _Distance_precision + { + __dp_equality, //< Can compare iterator equality, only + __dp_sign, //< Can determine equality and ordering + __dp_exact //< Can determine distance precisely + }; + + /// The underlying iterator + _Iterator _M_current; + + /// Determine if this is a constant iterator. + bool + _M_constant() const + { + typedef typename _Sequence::const_iterator const_iterator; + return std::__are_same<const_iterator, _Safe_iterator>::__value; + } + + typedef std::iterator_traits<_Iterator> _Traits; + + public: + typedef _Iterator iterator_type; + typedef typename _Traits::iterator_category iterator_category; + typedef typename _Traits::value_type value_type; + typedef typename _Traits::difference_type difference_type; + typedef typename _Traits::reference reference; + typedef typename _Traits::pointer pointer; + + /// @post the iterator is singular and unattached + _Safe_iterator() : _M_current() { } + + /** + * @brief Safe iterator construction from an unsafe iterator and + * its sequence. + * + * @pre @p seq is not NULL + * @post this is not singular + */ + _Safe_iterator(const _Iterator& __i, const _Sequence* __seq) + : _Safe_iterator_base(__seq, _M_constant()), _M_current(__i) + { + _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(), + _M_message(__msg_init_singular) + ._M_iterator(*this, "this")); + } + + /** + * @brief Copy construction. + */ + _Safe_iterator(const _Safe_iterator& __x) + : _Safe_iterator_base(__x, _M_constant()), _M_current(__x._M_current) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 408. Is vector<reverse_iterator<char*> > forbidden? + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() + || __x._M_current == _Iterator(), + _M_message(__msg_init_copy_singular) + ._M_iterator(*this, "this") + ._M_iterator(__x, "other")); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + /** + * @brief Move construction. + * @post __x is singular and unattached + */ + _Safe_iterator(_Safe_iterator&& __x) : _M_current() + { + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() + || __x._M_current == _Iterator(), + _M_message(__msg_init_copy_singular) + ._M_iterator(*this, "this") + ._M_iterator(__x, "other")); + std::swap(_M_current, __x._M_current); + this->_M_attach(__x._M_sequence); + __x._M_detach(); + } +#endif + + /** + * @brief Converting constructor from a mutable iterator to a + * constant iterator. + */ + template<typename _MutableIterator> + _Safe_iterator( + const _Safe_iterator<_MutableIterator, + typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, + typename _Sequence::iterator::iterator_type>::__value), + _Sequence>::__type>& __x) + : _Safe_iterator_base(__x, _M_constant()), _M_current(__x.base()) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 408. Is vector<reverse_iterator<char*> > forbidden? + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() + || __x.base() == _Iterator(), + _M_message(__msg_init_const_singular) + ._M_iterator(*this, "this") + ._M_iterator(__x, "other")); + } + + /** + * @brief Copy assignment. + */ + _Safe_iterator& + operator=(const _Safe_iterator& __x) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 408. Is vector<reverse_iterator<char*> > forbidden? + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() + || __x._M_current == _Iterator(), + _M_message(__msg_copy_singular) + ._M_iterator(*this, "this") + ._M_iterator(__x, "other")); + _M_current = __x._M_current; + this->_M_attach(__x._M_sequence); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + /** + * @brief Move assignment. + * @post __x is singular and unattached + */ + _Safe_iterator& + operator=(_Safe_iterator&& __x) + { + _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() + || __x._M_current == _Iterator(), + _M_message(__msg_copy_singular) + ._M_iterator(*this, "this") + ._M_iterator(__x, "other")); + _M_current = __x._M_current; + _M_attach(__x._M_sequence); + __x._M_detach(); + __x._M_current = _Iterator(); + return *this; + } +#endif + + /** + * @brief Iterator dereference. + * @pre iterator is dereferenceable + */ + reference + operator*() const + { + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), + _M_message(__msg_bad_deref) + ._M_iterator(*this, "this")); + return *_M_current; + } + + /** + * @brief Iterator dereference. + * @pre iterator is dereferenceable + * @todo Make this correct w.r.t. iterators that return proxies + * @todo Use addressof() instead of & operator + */ + pointer + operator->() const + { + _GLIBCXX_DEBUG_VERIFY(this->_M_dereferenceable(), + _M_message(__msg_bad_deref) + ._M_iterator(*this, "this")); + return &*_M_current; + } + + // ------ Input iterator requirements ------ + /** + * @brief Iterator preincrement + * @pre iterator is incrementable + */ + _Safe_iterator& + operator++() + { + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), + _M_message(__msg_bad_inc) + ._M_iterator(*this, "this")); + ++_M_current; + return *this; + } + + /** + * @brief Iterator postincrement + * @pre iterator is incrementable + */ + _Safe_iterator + operator++(int) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(), + _M_message(__msg_bad_inc) + ._M_iterator(*this, "this")); + _Safe_iterator __tmp(*this); + ++_M_current; + return __tmp; + } + + // ------ Bidirectional iterator requirements ------ + /** + * @brief Iterator predecrement + * @pre iterator is decrementable + */ + _Safe_iterator& + operator--() + { + _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), + _M_message(__msg_bad_dec) + ._M_iterator(*this, "this")); + --_M_current; + return *this; + } + + /** + * @brief Iterator postdecrement + * @pre iterator is decrementable + */ + _Safe_iterator + operator--(int) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_decrementable(), + _M_message(__msg_bad_dec) + ._M_iterator(*this, "this")); + _Safe_iterator __tmp(*this); + --_M_current; + return __tmp; + } + + // ------ Random access iterator requirements ------ + reference + operator[](const difference_type& __n) const + { + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n) + && this->_M_can_advance(__n+1), + _M_message(__msg_iter_subscript_oob) + ._M_iterator(*this)._M_integer(__n)); + + return _M_current[__n]; + } + + _Safe_iterator& + operator+=(const difference_type& __n) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(__n), + _M_message(__msg_advance_oob) + ._M_iterator(*this)._M_integer(__n)); + _M_current += __n; + return *this; + } + + _Safe_iterator + operator+(const difference_type& __n) const + { + _Safe_iterator __tmp(*this); + __tmp += __n; + return __tmp; + } + + _Safe_iterator& + operator-=(const difference_type& __n) + { + _GLIBCXX_DEBUG_VERIFY(this->_M_can_advance(-__n), + _M_message(__msg_retreat_oob) + ._M_iterator(*this)._M_integer(__n)); + _M_current += -__n; + return *this; + } + + _Safe_iterator + operator-(const difference_type& __n) const + { + _Safe_iterator __tmp(*this); + __tmp -= __n; + return __tmp; + } + + // ------ Utilities ------ + /** + * @brief Return the underlying iterator + */ + _Iterator + base() const { return _M_current; } + + /** + * @brief Conversion to underlying non-debug iterator to allow + * better interaction with non-debug containers. + */ + operator _Iterator() const { return _M_current; } + + /** Attach iterator to the given sequence. */ + void + _M_attach(_Safe_sequence_base* __seq) + { + _Safe_iterator_base::_M_attach(__seq, _M_constant()); + } + + /** Likewise, but not thread-safe. */ + void + _M_attach_single(_Safe_sequence_base* __seq) + { + _Safe_iterator_base::_M_attach_single(__seq, _M_constant()); + } + + /// Is the iterator dereferenceable? + bool + _M_dereferenceable() const + { return !this->_M_singular() && !_M_is_end() && !_M_is_before_begin(); } + + /// Is the iterator before a dereferenceable one? + bool + _M_before_dereferenceable() const + { + _Self __it = *this; + return __it._M_incrementable() && (++__it)._M_dereferenceable(); + } + + /// Is the iterator incrementable? + bool + _M_incrementable() const + { return !this->_M_singular() && !_M_is_end(); } + + // Is the iterator decrementable? + bool + _M_decrementable() const { return !_M_singular() && !_M_is_begin(); } + + // Can we advance the iterator @p __n steps (@p __n may be negative) + bool + _M_can_advance(const difference_type& __n) const; + + // Is the iterator range [*this, __rhs) valid? + template<typename _Other> + bool + _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const; + + // The sequence this iterator references. + const _Sequence* + _M_get_sequence() const + { return static_cast<const _Sequence*>(_M_sequence); } + + /** Determine the distance between two iterators with some known + * precision. + */ + template<typename _Iterator1, typename _Iterator2> + static std::pair<difference_type, _Distance_precision> + _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs) + { + typedef typename std::iterator_traits<_Iterator1>::iterator_category + _Category; + return _M_get_distance(__lhs, __rhs, _Category()); + } + + template<typename _Iterator1, typename _Iterator2> + static std::pair<difference_type, _Distance_precision> + _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, + std::random_access_iterator_tag) + { return std::make_pair(__rhs - __lhs, __dp_exact); } + + template<typename _Iterator1, typename _Iterator2> + static std::pair<difference_type, _Distance_precision> + _M_get_distance(const _Iterator1& __lhs, const _Iterator2& __rhs, + std::forward_iterator_tag) + { return std::make_pair(__lhs == __rhs? 0 : 1, __dp_equality); } + + /// Is this iterator equal to the sequence's begin() iterator? + bool _M_is_begin() const + { return base() == _M_get_sequence()->_M_base().begin(); } + + /// Is this iterator equal to the sequence's end() iterator? + bool _M_is_end() const + { return base() == _M_get_sequence()->_M_base().end(); } + + /// Is this iterator equal to the sequence's before_begin() iterator if + /// any? + bool _M_is_before_begin() const + { + return _BeforeBeginHelper<_Sequence>::_M_Is(base(), _M_get_sequence()); + } + }; + + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline bool + operator==(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_compare_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_compare_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() == __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline bool + operator==(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_compare_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_compare_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() == __rhs.base(); + } + + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline bool + operator!=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_compare_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_compare_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() != __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline bool + operator!=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_compare_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_compare_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() != __rhs.base(); + } + + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline bool + operator<(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() < __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline bool + operator<(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() < __rhs.base(); + } + + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline bool + operator<=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() <= __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline bool + operator<=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() <= __rhs.base(); + } + + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline bool + operator>(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() > __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline bool + operator>(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() > __rhs.base(); + } + + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline bool + operator>=(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() >= __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline bool + operator>=(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_iter_order_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_order_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() >= __rhs.base(); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline typename _Safe_iterator<_IteratorL, _Sequence>::difference_type + operator-(const _Safe_iterator<_IteratorL, _Sequence>& __lhs, + const _Safe_iterator<_IteratorR, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_distance_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_distance_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() - __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline typename _Safe_iterator<_Iterator, _Sequence>::difference_type + operator-(const _Safe_iterator<_Iterator, _Sequence>& __lhs, + const _Safe_iterator<_Iterator, _Sequence>& __rhs) + { + _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _M_message(__msg_distance_bad) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), + _M_message(__msg_distance_different) + ._M_iterator(__lhs, "lhs") + ._M_iterator(__rhs, "rhs")); + return __lhs.base() - __rhs.base(); + } + + template<typename _Iterator, typename _Sequence> + inline _Safe_iterator<_Iterator, _Sequence> + operator+(typename _Safe_iterator<_Iterator,_Sequence>::difference_type __n, + const _Safe_iterator<_Iterator, _Sequence>& __i) + { return __i + __n; } + + // Helper struct to detect random access safe iterators. + template<typename _Iterator> + struct __is_safe_random_iterator + { + enum { __value = 0 }; + typedef std::__false_type __type; + }; + + template<typename _Iterator, typename _Sequence> + struct __is_safe_random_iterator<_Safe_iterator<_Iterator, _Sequence> > + : std::__are_same<std::random_access_iterator_tag, + typename std::iterator_traits<_Iterator>:: + iterator_category> + { }; + + template<typename _Iterator> + struct _Siter_base + : std::_Iter_base<_Iterator, __is_safe_random_iterator<_Iterator>::__value> + { }; + + /** Helper function to extract base iterator of random access safe iterator + in order to reduce performance impact of debug mode. Limited to random + access iterator because it is the only category for which it is possible + to check for correct iterators order in the __valid_range function + thanks to the < operator. + */ + template<typename _Iterator> + inline typename _Siter_base<_Iterator>::iterator_type + __base(_Iterator __it) + { return _Siter_base<_Iterator>::_S_base(__it); } +} // namespace __gnu_debug + +#include <debug/safe_iterator.tcc> + +#endif diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc b/libstdc++-v3/include/debug/safe_iterator.tcc new file mode 100644 index 000000000..942640c65 --- /dev/null +++ b/libstdc++-v3/include/debug/safe_iterator.tcc @@ -0,0 +1,106 @@ +// Debugging iterator implementation (out of line) -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/safe_iterator.tcc + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC +#define _GLIBCXX_DEBUG_SAFE_ITERATOR_TCC 1 + +namespace __gnu_debug +{ + template<typename _Iterator, typename _Sequence> + bool + _Safe_iterator<_Iterator, _Sequence>:: + _M_can_advance(const difference_type& __n) const + { + typedef typename _Sequence::const_iterator const_debug_iterator; + typedef typename const_debug_iterator::iterator_type const_iterator; + + if (this->_M_singular()) + return false; + if (__n == 0) + return true; + if (__n < 0) + { + const_iterator __begin = _M_get_sequence()->_M_base().begin(); + std::pair<difference_type, _Distance_precision> __dist = + this->_M_get_distance(__begin, base()); + bool __ok = ((__dist.second == __dp_exact && __dist.first >= -__n) + || (__dist.second != __dp_exact && __dist.first > 0)); + return __ok; + } + else + { + const_iterator __end = _M_get_sequence()->_M_base().end(); + std::pair<difference_type, _Distance_precision> __dist = + this->_M_get_distance(base(), __end); + bool __ok = ((__dist.second == __dp_exact && __dist.first >= __n) + || (__dist.second != __dp_exact && __dist.first > 0)); + return __ok; + } + } + + template<typename _Iterator, typename _Sequence> + template<typename _Other> + bool + _Safe_iterator<_Iterator, _Sequence>:: + _M_valid_range(const _Safe_iterator<_Other, _Sequence>& __rhs) const + { + if (!_M_can_compare(__rhs)) + return false; + + /* Determine if we can order the iterators without the help of + the container */ + std::pair<difference_type, _Distance_precision> __dist = + this->_M_get_distance(base(), __rhs.base()); + switch (__dist.second) { + case __dp_equality: + if (__dist.first == 0) + return true; + break; + + case __dp_sign: + case __dp_exact: + return __dist.first >= 0; + } + + /* We can only test for equality, but check if one of the + iterators is at an extreme. */ + /* Optim for classic [begin, it) or [it, end) ranges, limit checks + * when code is valid. */ + if (_M_is_begin() || __rhs._M_is_end()) + return true; + if (_M_is_end() || __rhs._M_is_begin()) + return false; + + // Assume that this is a valid range; we can't check anything else + return true; + } +} // namespace __gnu_debug + +#endif + diff --git a/libstdc++-v3/include/debug/safe_sequence.h b/libstdc++-v3/include/debug/safe_sequence.h new file mode 100644 index 000000000..cc1f4c10d --- /dev/null +++ b/libstdc++-v3/include/debug/safe_sequence.h @@ -0,0 +1,135 @@ +// Safe sequence implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/safe_sequence.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_H +#define _GLIBCXX_DEBUG_SAFE_SEQUENCE_H 1 + +#include <debug/debug.h> +#include <debug/macros.h> +#include <debug/functions.h> +#include <debug/safe_base.h> + +namespace __gnu_debug +{ + template<typename _Iterator, typename _Sequence> + class _Safe_iterator; + + /** A simple function object that returns true if the passed-in + * value is not equal to the stored value. It saves typing over + * using both bind1st and not_equal. + */ + template<typename _Type> + class _Not_equal_to + { + _Type __value; + + public: + explicit _Not_equal_to(const _Type& __v) : __value(__v) { } + + bool + operator()(const _Type& __x) const + { return __value != __x; } + }; + + /** A simple function object that returns true if the passed-in + * value is equal to the stored value. */ + template <typename _Type> + class _Equal_to + { + _Type __value; + + public: + explicit _Equal_to(const _Type& __v) : __value(__v) { } + + bool + operator()(const _Type& __x) const + { return __value == __x; } + }; + + /** A function object that returns true when the given random access + iterator is at least @c n steps away from the given iterator. */ + template<typename _Iterator> + class _After_nth_from + { + typedef typename std::iterator_traits<_Iterator>::difference_type + difference_type; + + _Iterator _M_base; + difference_type _M_n; + + public: + _After_nth_from(const difference_type& __n, const _Iterator& __base) + : _M_base(__base), _M_n(__n) { } + + bool + operator()(const _Iterator& __x) const + { return __x - _M_base >= _M_n; } + }; + + /** + * @brief Base class for constructing a @a safe sequence type that + * tracks iterators that reference it. + * + * The class template %_Safe_sequence simplifies the construction of + * @a safe sequences that track the iterators that reference the + * sequence, so that the iterators are notified of changes in the + * sequence that may affect their operation, e.g., if the container + * invalidates its iterators or is destructed. This class template + * may only be used by deriving from it and passing the name of the + * derived class as its template parameter via the curiously + * recurring template pattern. The derived class must have @c + * iterator and @const_iterator types that are instantiations of + * class template _Safe_iterator for this sequence. Iterators will + * then be tracked automatically. + */ + template<typename _Sequence> + class _Safe_sequence : public _Safe_sequence_base + { + public: + /** Invalidates all iterators @c x that reference this sequence, + are not singular, and for which @c pred(x) returns @c + true. @c pred will be invoked with the normal iterators nested + in the safe ones. */ + template<typename _Predicate> + void + _M_invalidate_if(_Predicate __pred); + + /** Transfers all iterators @c x that reference @c from sequence, + are not singular, and for which @c pred(x) returns @c + true. @c pred will be invoked with the normal iterators nested + in the safe ones. */ + template<typename _Predicate> + void + _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred); + }; +} // namespace __gnu_debug + +#include <debug/safe_sequence.tcc> + +#endif diff --git a/libstdc++-v3/include/debug/safe_sequence.tcc b/libstdc++-v3/include/debug/safe_sequence.tcc new file mode 100644 index 000000000..bf0295cfd --- /dev/null +++ b/libstdc++-v3/include/debug/safe_sequence.tcc @@ -0,0 +1,150 @@ +// Safe sequence implementation -*- C++ -*- + +// Copyright (C) 2010 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/safe_sequence.tcc + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SAFE_SEQUENCE_TCC +#define _GLIBCXX_DEBUG_SAFE_SEQUENCE_TCC 1 + +namespace __gnu_debug +{ + template<typename _Sequence> + template<typename _Predicate> + void + _Safe_sequence<_Sequence>:: + _M_invalidate_if(_Predicate __pred) + { + typedef typename _Sequence::iterator iterator; + typedef typename _Sequence::const_iterator const_iterator; + + __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + for (_Safe_iterator_base* __iter = _M_iterators; __iter;) + { + iterator* __victim = static_cast<iterator*>(__iter); + __iter = __iter->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_invalidate(); + } + } + + for (_Safe_iterator_base* __iter2 = _M_const_iterators; __iter2;) + { + const_iterator* __victim = static_cast<const_iterator*>(__iter2); + __iter2 = __iter2->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_invalidate(); + } + } + } + + template<typename _Sequence> + template<typename _Predicate> + void + _Safe_sequence<_Sequence>:: + _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred) + { + typedef typename _Sequence::iterator iterator; + typedef typename _Sequence::const_iterator const_iterator; + + _Safe_iterator_base* __transfered_iterators = 0; + _Safe_iterator_base* __transfered_const_iterators = 0; + _Safe_iterator_base* __last_iterator = 0; + _Safe_iterator_base* __last_const_iterator = 0; + { + // We lock __from first and detach iterator(s) to transfer + __gnu_cxx::__scoped_lock sentry(__from._M_get_mutex()); + + for (_Safe_iterator_base* __iter = __from._M_iterators; __iter;) + { + iterator* __victim = static_cast<iterator*>(__iter); + __iter = __iter->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_detach_single(); + if (__transfered_iterators) + { + __victim->_M_next = __transfered_iterators; + __transfered_iterators->_M_prior = __victim; + } + else + __last_iterator = __victim; + __victim->_M_sequence = this; + __victim->_M_version = this->_M_version; + __transfered_iterators = __victim; + } + } + + for (_Safe_iterator_base* __iter2 = __from._M_const_iterators; + __iter2;) + { + const_iterator* __victim = static_cast<const_iterator*>(__iter2); + __iter2 = __iter2->_M_next; + if (!__victim->_M_singular() && __pred(__victim->base())) + { + __victim->_M_detach_single(); + if (__transfered_const_iterators) + { + __victim->_M_next = __transfered_const_iterators; + __transfered_const_iterators->_M_prior = __victim; + } + else + __last_const_iterator = __victim; + __victim->_M_sequence = this; + __victim->_M_version = this->_M_version; + __transfered_const_iterators = __victim; + } + } + } + + // Now we can lock *this and add the transfered iterators if any + if (__last_iterator || __last_const_iterator) + { + __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); + if (__last_iterator) + { + if (this->_M_iterators) + { + this->_M_iterators->_M_prior = __last_iterator; + __last_iterator->_M_next = this->_M_iterators; + } + this->_M_iterators = __transfered_iterators; + } + if (__last_const_iterator) + { + if (this->_M_const_iterators) + { + this->_M_const_iterators->_M_prior = __last_const_iterator; + __last_const_iterator->_M_next = this->_M_const_iterators; + } + this->_M_const_iterators = __transfered_const_iterators; + } + } + } +} // namespace __gnu_debug + +#endif diff --git a/libstdc++-v3/include/debug/set b/libstdc++-v3/include/debug/set new file mode 100644 index 000000000..34f3ea5e4 --- /dev/null +++ b/libstdc++-v3/include/debug/set @@ -0,0 +1,37 @@ +// Debugging set/multiset implementation -*- C++ -*- + +// Copyright (C) 2003, 2009 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/set + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SET +#define _GLIBCXX_DEBUG_SET 1 + +#include <set> +#include <debug/set.h> +#include <debug/multiset.h> + +#endif diff --git a/libstdc++-v3/include/debug/set.h b/libstdc++-v3/include/debug/set.h new file mode 100644 index 000000000..7ca4c7788 --- /dev/null +++ b/libstdc++-v3/include/debug/set.h @@ -0,0 +1,449 @@ +// Debugging set implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/set.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SET_H +#define _GLIBCXX_DEBUG_SET_H 1 + +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> +#include <utility> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::set with safety/checking/debug instrumentation. + template<typename _Key, typename _Compare = std::less<_Key>, + typename _Allocator = std::allocator<_Key> > + class set + : public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>, + public __gnu_debug::_Safe_sequence<set<_Key, _Compare, _Allocator> > + { + typedef _GLIBCXX_STD_C::set<_Key, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<set> _Safe_base; + + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + public: + // types: + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + typedef _Allocator allocator_type; + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, set> + iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, set> + const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + // 23.3.3.1 construct/copy/destroy: + explicit set(const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + + template<typename _InputIterator> + set(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a) { } + + set(const set& __x) + : _Base(__x), _Safe_base() { } + + set(const _Base& __x) + : _Base(__x), _Safe_base() { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + set(set&& __x) + : _Base(std::move(__x)), _Safe_base() + { this->_M_swap(__x); } + + set(initializer_list<value_type> __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __comp, __a), _Safe_base() { } +#endif + + ~set() { } + + set& + operator=(const set& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + set& + operator=(set&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + set& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } +#endif + + using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + + // capacity: + using _Base::empty; + using _Base::size; + using _Base::max_size; + + // modifiers: + std::pair<iterator, bool> + insert(const value_type& __x) + { + std::pair<_Base_iterator, bool> __res = _Base::insert(__x); + return std::pair<iterator, bool>(iterator(__res.first, this), + __res.second); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + std::pair<iterator, bool> + insert(value_type&& __x) + { + typedef typename _Base::iterator _Base_iterator; + std::pair<_Base_iterator, bool> __res + = _Base::insert(std::move(__x)); + return std::pair<iterator, bool>(iterator(__res.first, this), + __res.second); + } +#endif + + iterator + insert(const_iterator __position, const value_type& __x) + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), __x), this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + insert(const_iterator __position, value_type&& __x) + { + __glibcxx_check_insert(__position); + return iterator(_Base::insert(__position.base(), std::move(__x)), + this); + } +#endif + + template <typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + insert(initializer_list<value_type> __l) + { _Base::insert(__l); } +#endif + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + return iterator(_Base::erase(__position.base()), this); + } +#else + void + erase(iterator __position) + { + __glibcxx_check_erase(__position); + this->_M_invalidate_if(_Equal(__position.base())); + _Base::erase(__position.base()); + } +#endif + + size_type + erase(const key_type& __x) + { + _Base_iterator __victim = _Base::find(__x); + if (__victim == _Base::end()) + return 0; + else + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim); + return 1; + } + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + erase(const_iterator __first, const_iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + return iterator(_Base::erase(__first.base(), __last.base()), this); + } +#else + void + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + for (_Base_iterator __victim = __first.base(); + __victim != __last.base(); ++__victim) + { + _GLIBCXX_DEBUG_VERIFY(__victim != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__victim)); + } + _Base::erase(__first.base(), __last.base()); + } +#endif + + void + swap(set& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + } + + void + clear() + { + this->_M_invalidate_all(); + _Base::clear(); + } + + // observers: + using _Base::key_comp; + using _Base::value_comp; + + // set operations: + iterator + find(const key_type& __x) + { return iterator(_Base::find(__x), this); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + const_iterator + find(const key_type& __x) const + { return const_iterator(_Base::find(__x), this); } + + using _Base::count; + + iterator + lower_bound(const key_type& __x) + { return iterator(_Base::lower_bound(__x), this); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + const_iterator + lower_bound(const key_type& __x) const + { return const_iterator(_Base::lower_bound(__x), this); } + + iterator + upper_bound(const key_type& __x) + { return iterator(_Base::upper_bound(__x), this); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + const_iterator + upper_bound(const key_type& __x) const + { return const_iterator(_Base::upper_bound(__x), this); } + + std::pair<iterator,iterator> + equal_range(const key_type& __x) + { + std::pair<_Base_iterator, _Base_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + std::pair<const_iterator,const_iterator> + equal_range(const key_type& __x) const + { + std::pair<_Base_iterator, _Base_iterator> __res = + _Base::equal_range(__x); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_M_base().end())); + } + }; + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator==(const set<_Key, _Compare, _Allocator>& __lhs, + const set<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator!=(const set<_Key, _Compare, _Allocator>& __lhs, + const set<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator<(const set<_Key, _Compare, _Allocator>& __lhs, + const set<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator<=(const set<_Key, _Compare, _Allocator>& __lhs, + const set<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator>=(const set<_Key, _Compare, _Allocator>& __lhs, + const set<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + inline bool + operator>(const set<_Key, _Compare, _Allocator>& __lhs, + const set<_Key, _Compare, _Allocator>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Key, typename _Compare, typename _Allocator> + void + swap(set<_Key, _Compare, _Allocator>& __x, + set<_Key, _Compare, _Allocator>& __y) + { return __x.swap(__y); } + +} // namespace __debug +} // namespace std + +#endif diff --git a/libstdc++-v3/include/debug/string b/libstdc++-v3/include/debug/string new file mode 100644 index 000000000..fe073f21c --- /dev/null +++ b/libstdc++-v3/include/debug/string @@ -0,0 +1,1113 @@ +// Debugging string implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/string + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_STRING +#define _GLIBCXX_DEBUG_STRING 1 + +#include <string> +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace __gnu_debug +{ + /// Class std::basic_string with safety/checking/debug instrumentation. + template<typename _CharT, typename _Traits = std::char_traits<_CharT>, + typename _Allocator = std::allocator<_CharT> > + class basic_string + : public std::basic_string<_CharT, _Traits, _Allocator>, + public __gnu_debug::_Safe_sequence<basic_string<_CharT, _Traits, + _Allocator> > + { + typedef std::basic_string<_CharT, _Traits, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<basic_string> _Safe_base; + + public: + // types: + typedef _Traits traits_type; + typedef typename _Traits::char_type value_type; + typedef _Allocator allocator_type; + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + + typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, basic_string> + iterator; + typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, + basic_string> const_iterator; + + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + using _Base::npos; + + // 21.3.1 construct/copy/destroy: + explicit basic_string(const _Allocator& __a = _Allocator()) + : _Base(__a) + { } + + // Provides conversion from a release-mode string to a debug-mode string + basic_string(const _Base& __base) : _Base(__base), _Safe_base() { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 42. string ctors specify wrong default allocator + basic_string(const basic_string& __str) + : _Base(__str, 0, _Base::npos, __str.get_allocator()), _Safe_base() + { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 42. string ctors specify wrong default allocator + basic_string(const basic_string& __str, size_type __pos, + size_type __n = _Base::npos, + const _Allocator& __a = _Allocator()) + : _Base(__str, __pos, __n, __a) + { } + + basic_string(const _CharT* __s, size_type __n, + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__check_string(__s, __n), __n, __a) + { } + + basic_string(const _CharT* __s, const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__check_string(__s), __a) + { this->assign(__s); } + + basic_string(size_type __n, _CharT __c, + const _Allocator& __a = _Allocator()) + : _Base(__n, __c, __a) + { } + + template<typename _InputIterator> + basic_string(_InputIterator __begin, _InputIterator __end, + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__begin, + __end)), + __gnu_debug::__base(__end), __a) + { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + basic_string(basic_string&& __str) + : _Base(std::move(__str)) + { } + + basic_string(std::initializer_list<_CharT> __l, + const _Allocator& __a = _Allocator()) + : _Base(__l, __a) + { } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + + ~basic_string() { } + + basic_string& + operator=(const basic_string& __str) + { + *static_cast<_Base*>(this) = __str; + this->_M_invalidate_all(); + return *this; + } + + basic_string& + operator=(const _CharT* __s) + { + __glibcxx_check_string(__s); + *static_cast<_Base*>(this) = __s; + this->_M_invalidate_all(); + return *this; + } + + basic_string& + operator=(_CharT __c) + { + *static_cast<_Base*>(this) = __c; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + basic_string& + operator=(basic_string&& __str) + { + *static_cast<_Base*>(this) = std::move(__str); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + operator=(std::initializer_list<_CharT> __l) + { + *static_cast<_Base*>(this) = __l; + this->_M_invalidate_all(); + return *this; + } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + + // 21.3.2 iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + + // 21.3.3 capacity: + using _Base::size; + using _Base::length; + using _Base::max_size; + + void + resize(size_type __n, _CharT __c) + { + _Base::resize(__n, __c); + this->_M_invalidate_all(); + } + + void + resize(size_type __n) + { this->resize(__n, _CharT()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + using _Base::shrink_to_fit; +#endif + + using _Base::capacity; + using _Base::reserve; + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + using _Base::empty; + + // 21.3.4 element access: + const_reference + operator[](size_type __pos) const + { + _GLIBCXX_DEBUG_VERIFY(__pos <= this->size(), + _M_message(__gnu_debug::__msg_subscript_oob) + ._M_sequence(*this, "this") + ._M_integer(__pos, "__pos") + ._M_integer(this->size(), "size")); + return _M_base()[__pos]; + } + + reference + operator[](size_type __pos) + { +#ifdef _GLIBCXX_DEBUG_PEDANTIC + __glibcxx_check_subscript(__pos); +#else + // as an extension v3 allows s[s.size()] when s is non-const. + _GLIBCXX_DEBUG_VERIFY(__pos <= this->size(), + _M_message(__gnu_debug::__msg_subscript_oob) + ._M_sequence(*this, "this") + ._M_integer(__pos, "__pos") + ._M_integer(this->size(), "size")); +#endif + return _M_base()[__pos]; + } + + using _Base::at; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + using _Base::front; + using _Base::back; +#endif + + // 21.3.5 modifiers: + basic_string& + operator+=(const basic_string& __str) + { + _M_base() += __str; + this->_M_invalidate_all(); + return *this; + } + + basic_string& + operator+=(const _CharT* __s) + { + __glibcxx_check_string(__s); + _M_base() += __s; + this->_M_invalidate_all(); + return *this; + } + + basic_string& + operator+=(_CharT __c) + { + _M_base() += __c; + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + basic_string& + operator+=(std::initializer_list<_CharT> __l) + { + _M_base() += __l; + this->_M_invalidate_all(); + return *this; + } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + + basic_string& + append(const basic_string& __str) + { + _Base::append(__str); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + append(const basic_string& __str, size_type __pos, size_type __n) + { + _Base::append(__str, __pos, __n); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + append(const _CharT* __s, size_type __n) + { + __glibcxx_check_string_len(__s, __n); + _Base::append(__s, __n); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + append(const _CharT* __s) + { + __glibcxx_check_string(__s); + _Base::append(__s); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + append(size_type __n, _CharT __c) + { + _Base::append(__n, __c); + this->_M_invalidate_all(); + return *this; + } + + template<typename _InputIterator> + basic_string& + append(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::append(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + return *this; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 7. string clause minor problems + void + push_back(_CharT __c) + { + _Base::push_back(__c); + this->_M_invalidate_all(); + } + + basic_string& + assign(const basic_string& __x) + { + _Base::assign(__x); + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + basic_string& + assign(basic_string&& __x) + { + _Base::assign(std::move(__x)); + this->_M_invalidate_all(); + return *this; + } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + + basic_string& + assign(const basic_string& __str, size_type __pos, size_type __n) + { + _Base::assign(__str, __pos, __n); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + assign(const _CharT* __s, size_type __n) + { + __glibcxx_check_string_len(__s, __n); + _Base::assign(__s, __n); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + assign(const _CharT* __s) + { + __glibcxx_check_string(__s); + _Base::assign(__s); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + assign(size_type __n, _CharT __c) + { + _Base::assign(__n, __c); + this->_M_invalidate_all(); + return *this; + } + + template<typename _InputIterator> + basic_string& + assign(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::assign(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + basic_string& + assign(std::initializer_list<_CharT> __l) + { + _Base::assign(__l); + this->_M_invalidate_all(); + return *this; + } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + + basic_string& + insert(size_type __pos1, const basic_string& __str) + { + _Base::insert(__pos1, __str); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + insert(size_type __pos1, const basic_string& __str, + size_type __pos2, size_type __n) + { + _Base::insert(__pos1, __str, __pos2, __n); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + insert(size_type __pos, const _CharT* __s, size_type __n) + { + __glibcxx_check_string(__s); + _Base::insert(__pos, __s, __n); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + insert(size_type __pos, const _CharT* __s) + { + __glibcxx_check_string(__s); + _Base::insert(__pos, __s); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + insert(size_type __pos, size_type __n, _CharT __c) + { + _Base::insert(__pos, __n, __c); + this->_M_invalidate_all(); + return *this; + } + + iterator + insert(iterator __p, _CharT __c) + { + __glibcxx_check_insert(__p); + typename _Base::iterator __res = _Base::insert(__p.base(), __c); + this->_M_invalidate_all(); + return iterator(__res, this); + } + + void + insert(iterator __p, size_type __n, _CharT __c) + { + __glibcxx_check_insert(__p); + _Base::insert(__p.base(), __n, __c); + this->_M_invalidate_all(); + } + + template<typename _InputIterator> + void + insert(iterator __p, _InputIterator __first, _InputIterator __last) + { + __glibcxx_check_insert_range(__p, __first, __last); + _Base::insert(__p.base(), __gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + insert(iterator __p, std::initializer_list<_CharT> __l) + { + __glibcxx_check_insert(__p); + _Base::insert(__p.base(), __l); + this->_M_invalidate_all(); + } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + + basic_string& + erase(size_type __pos = 0, size_type __n = _Base::npos) + { + _Base::erase(__pos, __n); + this->_M_invalidate_all(); + return *this; + } + + iterator + erase(iterator __position) + { + __glibcxx_check_erase(__position); + typename _Base::iterator __res = _Base::erase(__position.base()); + this->_M_invalidate_all(); + return iterator(__res, this); + } + + iterator + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + typename _Base::iterator __res = _Base::erase(__first.base(), + __last.base()); + this->_M_invalidate_all(); + return iterator(__res, this); + } + + basic_string& + replace(size_type __pos1, size_type __n1, const basic_string& __str) + { + _Base::replace(__pos1, __n1, __str); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(size_type __pos1, size_type __n1, const basic_string& __str, + size_type __pos2, size_type __n2) + { + _Base::replace(__pos1, __n1, __str, __pos2, __n2); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(size_type __pos, size_type __n1, const _CharT* __s, + size_type __n2) + { + __glibcxx_check_string_len(__s, __n2); + _Base::replace(__pos, __n1, __s, __n2); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(size_type __pos, size_type __n1, const _CharT* __s) + { + __glibcxx_check_string(__s); + _Base::replace(__pos, __n1, __s); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c) + { + _Base::replace(__pos, __n1, __n2, __c); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(iterator __i1, iterator __i2, const basic_string& __str) + { + __glibcxx_check_erase_range(__i1, __i2); + _Base::replace(__i1.base(), __i2.base(), __str); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n) + { + __glibcxx_check_erase_range(__i1, __i2); + __glibcxx_check_string_len(__s, __n); + _Base::replace(__i1.base(), __i2.base(), __s, __n); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(iterator __i1, iterator __i2, const _CharT* __s) + { + __glibcxx_check_erase_range(__i1, __i2); + __glibcxx_check_string(__s); + _Base::replace(__i1.base(), __i2.base(), __s); + this->_M_invalidate_all(); + return *this; + } + + basic_string& + replace(iterator __i1, iterator __i2, size_type __n, _CharT __c) + { + __glibcxx_check_erase_range(__i1, __i2); + _Base::replace(__i1.base(), __i2.base(), __n, __c); + this->_M_invalidate_all(); + return *this; + } + + template<typename _InputIterator> + basic_string& + replace(iterator __i1, iterator __i2, + _InputIterator __j1, _InputIterator __j2) + { + __glibcxx_check_erase_range(__i1, __i2); + __glibcxx_check_valid_range(__j1, __j2); + _Base::replace(__i1.base(), __i2.base(), __j1, __j2); + this->_M_invalidate_all(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + basic_string& replace(iterator __i1, iterator __i2, + std::initializer_list<_CharT> __l) + { + __glibcxx_check_erase_range(__i1, __i2); + _Base::replace(__i1.base(), __i2.base(), __l); + this->_M_invalidate_all(); + return *this; + } +#endif // __GXX_EXPERIMENTAL_CXX0X__ + + size_type + copy(_CharT* __s, size_type __n, size_type __pos = 0) const + { + __glibcxx_check_string_len(__s, __n); + return _Base::copy(__s, __n, __pos); + } + + void + swap(basic_string<_CharT,_Traits,_Allocator>& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + this->_M_invalidate_all(); + __x._M_invalidate_all(); + } + + // 21.3.6 string operations: + const _CharT* + c_str() const + { + const _CharT* __res = _Base::c_str(); + this->_M_invalidate_all(); + return __res; + } + + const _CharT* + data() const + { + const _CharT* __res = _Base::data(); + this->_M_invalidate_all(); + return __res; + } + + using _Base::get_allocator; + + size_type + find(const basic_string& __str, size_type __pos = 0) const + { return _Base::find(__str, __pos); } + + size_type + find(const _CharT* __s, size_type __pos, size_type __n) const + { + __glibcxx_check_string(__s); + return _Base::find(__s, __pos, __n); + } + + size_type + find(const _CharT* __s, size_type __pos = 0) const + { + __glibcxx_check_string(__s); + return _Base::find(__s, __pos); + } + + size_type + find(_CharT __c, size_type __pos = 0) const + { return _Base::find(__c, __pos); } + + size_type + rfind(const basic_string& __str, size_type __pos = _Base::npos) const + { return _Base::rfind(__str, __pos); } + + size_type + rfind(const _CharT* __s, size_type __pos, size_type __n) const + { + __glibcxx_check_string_len(__s, __n); + return _Base::rfind(__s, __pos, __n); + } + + size_type + rfind(const _CharT* __s, size_type __pos = _Base::npos) const + { + __glibcxx_check_string(__s); + return _Base::rfind(__s, __pos); + } + + size_type + rfind(_CharT __c, size_type __pos = _Base::npos) const + { return _Base::rfind(__c, __pos); } + + size_type + find_first_of(const basic_string& __str, size_type __pos = 0) const + { return _Base::find_first_of(__str, __pos); } + + size_type + find_first_of(const _CharT* __s, size_type __pos, size_type __n) const + { + __glibcxx_check_string(__s); + return _Base::find_first_of(__s, __pos, __n); + } + + size_type + find_first_of(const _CharT* __s, size_type __pos = 0) const + { + __glibcxx_check_string(__s); + return _Base::find_first_of(__s, __pos); + } + + size_type + find_first_of(_CharT __c, size_type __pos = 0) const + { return _Base::find_first_of(__c, __pos); } + + size_type + find_last_of(const basic_string& __str, + size_type __pos = _Base::npos) const + { return _Base::find_last_of(__str, __pos); } + + size_type + find_last_of(const _CharT* __s, size_type __pos, size_type __n) const + { + __glibcxx_check_string(__s); + return _Base::find_last_of(__s, __pos, __n); + } + + size_type + find_last_of(const _CharT* __s, size_type __pos = _Base::npos) const + { + __glibcxx_check_string(__s); + return _Base::find_last_of(__s, __pos); + } + + size_type + find_last_of(_CharT __c, size_type __pos = _Base::npos) const + { return _Base::find_last_of(__c, __pos); } + + size_type + find_first_not_of(const basic_string& __str, size_type __pos = 0) const + { return _Base::find_first_not_of(__str, __pos); } + + size_type + find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const + { + __glibcxx_check_string_len(__s, __n); + return _Base::find_first_not_of(__s, __pos, __n); + } + + size_type + find_first_not_of(const _CharT* __s, size_type __pos = 0) const + { + __glibcxx_check_string(__s); + return _Base::find_first_not_of(__s, __pos); + } + + size_type + find_first_not_of(_CharT __c, size_type __pos = 0) const + { return _Base::find_first_not_of(__c, __pos); } + + size_type + find_last_not_of(const basic_string& __str, + size_type __pos = _Base::npos) const + { return _Base::find_last_not_of(__str, __pos); } + + size_type + find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const + { + __glibcxx_check_string(__s); + return _Base::find_last_not_of(__s, __pos, __n); + } + + size_type + find_last_not_of(const _CharT* __s, size_type __pos = _Base::npos) const + { + __glibcxx_check_string(__s); + return _Base::find_last_not_of(__s, __pos); + } + + size_type + find_last_not_of(_CharT __c, size_type __pos = _Base::npos) const + { return _Base::find_last_not_of(__c, __pos); } + + basic_string + substr(size_type __pos = 0, size_type __n = _Base::npos) const + { return basic_string(_Base::substr(__pos, __n)); } + + int + compare(const basic_string& __str) const + { return _Base::compare(__str); } + + int + compare(size_type __pos1, size_type __n1, + const basic_string& __str) const + { return _Base::compare(__pos1, __n1, __str); } + + int + compare(size_type __pos1, size_type __n1, const basic_string& __str, + size_type __pos2, size_type __n2) const + { return _Base::compare(__pos1, __n1, __str, __pos2, __n2); } + + int + compare(const _CharT* __s) const + { + __glibcxx_check_string(__s); + return _Base::compare(__s); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 5. string::compare specification questionable + int + compare(size_type __pos1, size_type __n1, const _CharT* __s) const + { + __glibcxx_check_string(__s); + return _Base::compare(__pos1, __n1, __s); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 5. string::compare specification questionable + int + compare(size_type __pos1, size_type __n1,const _CharT* __s, + size_type __n2) const + { + __glibcxx_check_string_len(__s, __n2); + return _Base::compare(__pos1, __n1, __s, __n2); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + using _Safe_base::_M_invalidate_all; + }; + + template<typename _CharT, typename _Traits, typename _Allocator> + inline basic_string<_CharT,_Traits,_Allocator> + operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline basic_string<_CharT,_Traits,_Allocator> + operator+(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { + __glibcxx_check_string(__lhs); + return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline basic_string<_CharT,_Traits,_Allocator> + operator+(_CharT __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return basic_string<_CharT,_Traits,_Allocator>(1, __lhs) += __rhs; } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline basic_string<_CharT,_Traits,_Allocator> + operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const _CharT* __rhs) + { + __glibcxx_check_string(__rhs); + return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline basic_string<_CharT,_Traits,_Allocator> + operator+(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + _CharT __rhs) + { return basic_string<_CharT,_Traits,_Allocator>(__lhs) += __rhs; } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator==(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { + __glibcxx_check_string(__lhs); + return __lhs == __rhs._M_base(); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator==(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const _CharT* __rhs) + { + __glibcxx_check_string(__rhs); + return __lhs._M_base() == __rhs; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator!=(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { + __glibcxx_check_string(__lhs); + return __lhs != __rhs._M_base(); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator!=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const _CharT* __rhs) + { + __glibcxx_check_string(__rhs); + return __lhs._M_base() != __rhs; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator<(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator<(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { + __glibcxx_check_string(__lhs); + return __lhs < __rhs._M_base(); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator<(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const _CharT* __rhs) + { + __glibcxx_check_string(__rhs); + return __lhs._M_base() < __rhs; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator<=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator<=(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { + __glibcxx_check_string(__lhs); + return __lhs <= __rhs._M_base(); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator<=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const _CharT* __rhs) + { + __glibcxx_check_string(__rhs); + return __lhs._M_base() <= __rhs; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator>=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator>=(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { + __glibcxx_check_string(__lhs); + return __lhs >= __rhs._M_base(); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator>=(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const _CharT* __rhs) + { + __glibcxx_check_string(__rhs); + return __lhs._M_base() >= __rhs; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator>(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator>(const _CharT* __lhs, + const basic_string<_CharT,_Traits,_Allocator>& __rhs) + { + __glibcxx_check_string(__lhs); + return __lhs > __rhs._M_base(); + } + + template<typename _CharT, typename _Traits, typename _Allocator> + inline bool + operator>(const basic_string<_CharT,_Traits,_Allocator>& __lhs, + const _CharT* __rhs) + { + __glibcxx_check_string(__rhs); + return __lhs._M_base() > __rhs; + } + + // 21.3.7.8: + template<typename _CharT, typename _Traits, typename _Allocator> + inline void + swap(basic_string<_CharT,_Traits,_Allocator>& __lhs, + basic_string<_CharT,_Traits,_Allocator>& __rhs) + { __lhs.swap(__rhs); } + + template<typename _CharT, typename _Traits, typename _Allocator> + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const basic_string<_CharT, _Traits, _Allocator>& __str) + { return __os << __str._M_base(); } + + template<typename _CharT, typename _Traits, typename _Allocator> + std::basic_istream<_CharT,_Traits>& + operator>>(std::basic_istream<_CharT,_Traits>& __is, + basic_string<_CharT,_Traits,_Allocator>& __str) + { + std::basic_istream<_CharT,_Traits>& __res = __is >> __str._M_base(); + __str._M_invalidate_all(); + return __res; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + std::basic_istream<_CharT,_Traits>& + getline(std::basic_istream<_CharT,_Traits>& __is, + basic_string<_CharT,_Traits,_Allocator>& __str, _CharT __delim) + { + std::basic_istream<_CharT,_Traits>& __res = getline(__is, + __str._M_base(), + __delim); + __str._M_invalidate_all(); + return __res; + } + + template<typename _CharT, typename _Traits, typename _Allocator> + std::basic_istream<_CharT,_Traits>& + getline(std::basic_istream<_CharT,_Traits>& __is, + basic_string<_CharT,_Traits,_Allocator>& __str) + { + std::basic_istream<_CharT,_Traits>& __res = getline(__is, + __str._M_base()); + __str._M_invalidate_all(); + return __res; + } + + typedef basic_string<char> string; + +#ifdef _GLIBCXX_USE_WCHAR_T + typedef basic_string<wchar_t> wstring; +#endif + +} // namespace __gnu_debug + +#endif diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map new file mode 100644 index 000000000..43b1e9c29 --- /dev/null +++ b/libstdc++-v3/include/debug/unordered_map @@ -0,0 +1,626 @@ +// Debugging unordered_map/unordered_multimap implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/unordered_map + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_UNORDERED_MAP +#define _GLIBCXX_DEBUG_UNORDERED_MAP 1 + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +# include <bits/c++0x_warning.h> +#else +# include <unordered_map> + +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::unordered_map with safety/checking/debug instrumentation. + template<typename _Key, typename _Tp, + typename _Hash = std::hash<_Key>, + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator<_Key> > + class unordered_map + : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, + public __gnu_debug::_Safe_sequence<unordered_map<_Key, _Tp, _Hash, + _Pred, _Alloc> > + { + typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, + _Pred, _Alloc> _Base; + typedef __gnu_debug::_Safe_sequence<unordered_map> _Safe_base; + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + + public: + typedef typename _Base::size_type size_type; + typedef typename _Base::hasher hasher; + typedef typename _Base::key_equal key_equal; + typedef typename _Base::allocator_type allocator_type; + + typedef typename _Base::key_type key_type; + typedef typename _Base::value_type value_type; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, + unordered_map> iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, + unordered_map> const_iterator; + + explicit + unordered_map(size_type __n = 10, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__n, __hf, __eql, __a) { } + + template<typename _InputIterator> + unordered_map(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __n, + __hf, __eql, __a), _Safe_base() { } + + unordered_map(const unordered_map& __x) + : _Base(__x), _Safe_base() { } + + unordered_map(const _Base& __x) + : _Base(__x), _Safe_base() { } + + unordered_map(unordered_map&& __x) + : _Base(std::move(__x)), _Safe_base() { } + + unordered_map(initializer_list<value_type> __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { } + + unordered_map& + operator=(const unordered_map& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + + unordered_map& + operator=(unordered_map&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + unordered_map& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } + + void + swap(unordered_map& __x) + { + _Base::swap(__x); + _Safe_base::_M_swap(__x); + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + // local versions + using _Base::begin; + using _Base::end; + using _Base::cbegin; + using _Base::cend; + + std::pair<iterator, bool> + insert(const value_type& __obj) + { + std::pair<_Base_iterator, bool> __res = _Base::insert(__obj); + return std::make_pair(iterator(__res.first, this), __res.second); + } + + iterator + insert(const_iterator __hint, const value_type& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), __obj), this); + } + + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + std::pair<iterator, bool> + insert(_Pair&& __obj) + { + std::pair<_Base_iterator, bool> __res = + _Base::insert(std::forward<_Pair>(__obj)); + return std::make_pair(iterator(__res.first, this), __res.second); + } + + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + iterator + insert(const_iterator __hint, _Pair&& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), + std::forward<_Pair>(__obj)), + this); + } + + void + insert(std::initializer_list<value_type> __l) + { _Base::insert(__l); } + + template<typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + + iterator + find(const key_type& __key) + { return iterator(_Base::find(__key), this); } + + const_iterator + find(const key_type& __key) const + { return const_iterator(_Base::find(__key), this); } + + std::pair<iterator, iterator> + equal_range(const key_type& __key) + { + std::pair<_Base_iterator, _Base_iterator> __res = + _Base::equal_range(__key); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + std::pair<const_iterator, const_iterator> + equal_range(const key_type& __key) const + { + std::pair<_Base_const_iterator, _Base_const_iterator> __res = + _Base::equal_range(__key); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + size_type + erase(const key_type& __key) + { + size_type __ret(0); + _Base_iterator __victim(_Base::find(__key)); + if (__victim != _Base::end()) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim); + __ret = 1; + } + return __ret; + } + + iterator + erase(const_iterator __it) + { + __glibcxx_check_erase(__it); + this->_M_invalidate_if(_Equal(__it.base())); + return iterator(_Base::erase(__it.base()), this); + } + + iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator + erase(const_iterator __first, const_iterator __last) + { + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __tmp = __first.base(); + __tmp != __last.base(); ++__tmp) + { + _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__tmp)); + } + return iterator(_Base::erase(__first.base(), + __last.base()), this); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_Base::end())); + } + }; + + template<typename _Key, typename _Tp, typename _Hash, + typename _Pred, typename _Alloc> + inline void + swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { __x.swap(__y); } + + template<typename _Key, typename _Tp, typename _Hash, + typename _Pred, typename _Alloc> + inline bool + operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return __x._M_equal(__y); } + + template<typename _Key, typename _Tp, typename _Hash, + typename _Pred, typename _Alloc> + inline bool + operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } + + + /// Class std::unordered_multimap with safety/checking/debug instrumentation. + template<typename _Key, typename _Tp, + typename _Hash = std::hash<_Key>, + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator<_Key> > + class unordered_multimap + : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, + _Pred, _Alloc>, + public __gnu_debug::_Safe_sequence<unordered_multimap<_Key, _Tp, _Hash, + _Pred, _Alloc> > + { + typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, + _Pred, _Alloc> _Base; + typedef __gnu_debug::_Safe_sequence<unordered_multimap> _Safe_base; + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + + public: + typedef typename _Base::size_type size_type; + typedef typename _Base::hasher hasher; + typedef typename _Base::key_equal key_equal; + typedef typename _Base::allocator_type allocator_type; + + typedef typename _Base::key_type key_type; + typedef typename _Base::value_type value_type; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, + unordered_multimap> iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, + unordered_multimap> const_iterator; + + explicit + unordered_multimap(size_type __n = 10, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__n, __hf, __eql, __a) { } + + template<typename _InputIterator> + unordered_multimap(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __n, + __hf, __eql, __a), _Safe_base() { } + + unordered_multimap(const unordered_multimap& __x) + : _Base(__x), _Safe_base() { } + + unordered_multimap(const _Base& __x) + : _Base(__x), _Safe_base() { } + + unordered_multimap(unordered_multimap&& __x) + : _Base(std::move(__x)), _Safe_base() { } + + unordered_multimap(initializer_list<value_type> __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { } + + unordered_multimap& + operator=(const unordered_multimap& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + + unordered_multimap& + operator=(unordered_multimap&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + unordered_multimap& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } + + void + swap(unordered_multimap& __x) + { + _Base::swap(__x); + _Safe_base::_M_swap(__x); + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + // local versions + using _Base::begin; + using _Base::end; + using _Base::cbegin; + using _Base::cend; + + iterator + insert(const value_type& __obj) + { return iterator(_Base::insert(__obj), this); } + + iterator + insert(const_iterator __hint, const value_type& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), __obj), this); + } + + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + iterator + insert(_Pair&& __obj) + { return iterator(_Base::insert(std::forward<_Pair>(__obj)), this); } + + template<typename _Pair, typename = typename + std::enable_if<std::is_convertible<_Pair, + value_type>::value>::type> + iterator + insert(const_iterator __hint, _Pair&& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), + std::forward<_Pair>(__obj)), + this); + } + + void + insert(std::initializer_list<value_type> __l) + { _Base::insert(__l); } + + template<typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + + iterator + find(const key_type& __key) + { return iterator(_Base::find(__key), this); } + + const_iterator + find(const key_type& __key) const + { return const_iterator(_Base::find(__key), this); } + + std::pair<iterator, iterator> + equal_range(const key_type& __key) + { + std::pair<_Base_iterator, _Base_iterator> __res = + _Base::equal_range(__key); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + std::pair<const_iterator, const_iterator> + equal_range(const key_type& __key) const + { + std::pair<_Base_const_iterator, _Base_const_iterator> __res = + _Base::equal_range(__key); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + size_type + erase(const key_type& __key) + { + size_type __ret(0); + std::pair<_Base_iterator, _Base_iterator> __pair = + _Base::equal_range(__key); + for (_Base_iterator __victim = __pair.first; __victim != __pair.second;) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__ret; + } + return __ret; + } + + iterator + erase(const_iterator __it) + { + __glibcxx_check_erase(__it); + this->_M_invalidate_if(_Equal(__it.base())); + return iterator(_Base::erase(__it.base()), this); + } + + iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator + erase(const_iterator __first, const_iterator __last) + { + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __tmp = __first.base(); + __tmp != __last.base(); ++__tmp) + { + _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__tmp)); + } + return iterator(_Base::erase(__first.base(), + __last.base()), this); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_Base::end())); + } + }; + + template<typename _Key, typename _Tp, typename _Hash, + typename _Pred, typename _Alloc> + inline void + swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { __x.swap(__y); } + + template<typename _Key, typename _Tp, typename _Hash, + typename _Pred, typename _Alloc> + inline bool + operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return __x._M_equal(__y); } + + template<typename _Key, typename _Tp, typename _Hash, + typename _Pred, typename _Alloc> + inline bool + operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } + +} // namespace __debug +} // namespace std + +#endif // __GXX_EXPERIMENTAL_CXX0X__ + +#endif diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set new file mode 100644 index 000000000..cf21a3c15 --- /dev/null +++ b/libstdc++-v3/include/debug/unordered_set @@ -0,0 +1,604 @@ +// Debugging unordered_set/unordered_multiset implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/unordered_set + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_UNORDERED_SET +#define _GLIBCXX_DEBUG_UNORDERED_SET 1 + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +# include <bits/c++0x_warning.h> +#else +# include <unordered_set> + +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::unordered_set with safety/checking/debug instrumentation. + template<typename _Value, + typename _Hash = std::hash<_Value>, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value> > + class unordered_set + : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>, + public __gnu_debug::_Safe_sequence<unordered_set<_Value, _Hash, + _Pred, _Alloc> > + { + typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash, + _Pred, _Alloc> _Base; + typedef __gnu_debug::_Safe_sequence<unordered_set> _Safe_base; + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + + public: + typedef typename _Base::size_type size_type; + typedef typename _Base::hasher hasher; + typedef typename _Base::key_equal key_equal; + typedef typename _Base::allocator_type allocator_type; + + typedef typename _Base::key_type key_type; + typedef typename _Base::value_type value_type; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, + unordered_set> iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, + unordered_set> const_iterator; + + explicit + unordered_set(size_type __n = 10, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__n, __hf, __eql, __a) { } + + template<typename _InputIterator> + unordered_set(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __n, + __hf, __eql, __a), _Safe_base() { } + + unordered_set(const unordered_set& __x) + : _Base(__x), _Safe_base() { } + + unordered_set(const _Base& __x) + : _Base(__x), _Safe_base() { } + + unordered_set(unordered_set&& __x) + : _Base(std::move(__x)), _Safe_base() { } + + unordered_set(initializer_list<value_type> __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { } + + unordered_set& + operator=(const unordered_set& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + + unordered_set& + operator=(unordered_set&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + unordered_set& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } + + void + swap(unordered_set& __x) + { + _Base::swap(__x); + _Safe_base::_M_swap(__x); + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + // local versions + using _Base::begin; + using _Base::end; + using _Base::cbegin; + using _Base::cend; + + std::pair<iterator, bool> + insert(const value_type& __obj) + { + typedef std::pair<_Base_iterator, bool> __pair_type; + __pair_type __res = _Base::insert(__obj); + return std::make_pair(iterator(__res.first, this), __res.second); + } + + iterator + insert(const_iterator __hint, const value_type& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), __obj), this); + } + + std::pair<iterator, bool> + insert(value_type&& __obj) + { + typedef std::pair<typename _Base::iterator, bool> __pair_type; + __pair_type __res = _Base::insert(std::move(__obj)); + return std::make_pair(iterator(__res.first, this), __res.second); + } + + iterator + insert(const_iterator __hint, value_type&& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), std::move(__obj)), this); + } + + void + insert(std::initializer_list<value_type> __l) + { _Base::insert(__l); } + + template<typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + + iterator + find(const key_type& __key) + { return iterator(_Base::find(__key), this); } + + const_iterator + find(const key_type& __key) const + { return const_iterator(_Base::find(__key), this); } + + std::pair<iterator, iterator> + equal_range(const key_type& __key) + { + typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; + __pair_type __res = _Base::equal_range(__key); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + std::pair<const_iterator, const_iterator> + equal_range(const key_type& __key) const + { + std::pair<_Base_const_iterator, _Base_const_iterator> + __res = _Base::equal_range(__key); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + size_type + erase(const key_type& __key) + { + size_type __ret(0); + _Base_iterator __victim(_Base::find(__key)); + if (__victim != _Base::end()) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim); + __ret = 1; + } + return __ret; + } + + iterator + erase(const_iterator __it) + { + __glibcxx_check_erase(__it); + this->_M_invalidate_if(_Equal(__it.base())); + return iterator(_Base::erase(__it.base()), this); + } + + iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator + erase(const_iterator __first, const_iterator __last) + { + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __tmp = __first.base(); + __tmp != __last.base(); ++__tmp) + { + _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__tmp)); + } + return iterator(_Base::erase(__first.base(), + __last.base()), this); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_Base::end())); + } + }; + + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> + inline void + swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + { __x.swap(__y); } + + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> + inline bool + operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + { return __x._M_equal(__y); } + + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> + inline bool + operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } + + + /// Class std::unordered_multiset with safety/checking/debug instrumentation. + template<typename _Value, + typename _Hash = std::hash<_Value>, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value> > + class unordered_multiset + : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>, + public __gnu_debug::_Safe_sequence<unordered_multiset<_Value, _Hash, + _Pred, _Alloc> > + { + typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, + _Pred, _Alloc> _Base; + typedef __gnu_debug::_Safe_sequence<unordered_multiset> _Safe_base; + typedef typename _Base::const_iterator _Base_const_iterator; + typedef typename _Base::iterator _Base_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + + public: + typedef typename _Base::size_type size_type; + typedef typename _Base::hasher hasher; + typedef typename _Base::key_equal key_equal; + typedef typename _Base::allocator_type allocator_type; + + typedef typename _Base::key_type key_type; + typedef typename _Base::value_type value_type; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator, + unordered_multiset> iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, + unordered_multiset> const_iterator; + + explicit + unordered_multiset(size_type __n = 10, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__n, __hf, __eql, __a) { } + + template<typename _InputIterator> + unordered_multiset(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __n, + __hf, __eql, __a), _Safe_base() { } + + unordered_multiset(const unordered_multiset& __x) + : _Base(__x), _Safe_base() { } + + unordered_multiset(const _Base& __x) + : _Base(__x), _Safe_base() { } + + unordered_multiset(unordered_multiset&& __x) + : _Base(std::move(__x)), _Safe_base() { } + + unordered_multiset(initializer_list<value_type> __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { } + + unordered_multiset& + operator=(const unordered_multiset& __x) + { + *static_cast<_Base*>(this) = __x; + this->_M_invalidate_all(); + return *this; + } + + unordered_multiset& + operator=(unordered_multiset&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + unordered_multiset& + operator=(initializer_list<value_type> __l) + { + this->clear(); + this->insert(__l); + return *this; + } + + void + swap(unordered_multiset& __x) + { + _Base::swap(__x); + _Safe_base::_M_swap(__x); + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + } + + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + // local versions + using _Base::begin; + using _Base::end; + using _Base::cbegin; + using _Base::cend; + + iterator + insert(const value_type& __obj) + { return iterator(_Base::insert(__obj), this); } + + iterator + insert(const_iterator __hint, const value_type& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), __obj), this); + } + + iterator + insert(value_type&& __obj) + { return iterator(_Base::insert(std::move(__obj)), this); } + + iterator + insert(const_iterator __hint, value_type&& __obj) + { + __glibcxx_check_insert(__hint); + return iterator(_Base::insert(__hint.base(), std::move(__obj)), this); + } + + void + insert(std::initializer_list<value_type> __l) + { _Base::insert(__l); } + + template<typename _InputIterator> + void + insert(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::insert(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + } + + iterator + find(const key_type& __key) + { return iterator(_Base::find(__key), this); } + + const_iterator + find(const key_type& __key) const + { return const_iterator(_Base::find(__key), this); } + + std::pair<iterator, iterator> + equal_range(const key_type& __key) + { + typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; + __pair_type __res = _Base::equal_range(__key); + return std::make_pair(iterator(__res.first, this), + iterator(__res.second, this)); + } + + std::pair<const_iterator, const_iterator> + equal_range(const key_type& __key) const + { + std::pair<_Base_const_iterator, _Base_const_iterator> + __res = _Base::equal_range(__key); + return std::make_pair(const_iterator(__res.first, this), + const_iterator(__res.second, this)); + } + + size_type + erase(const key_type& __key) + { + size_type __ret(0); + std::pair<_Base_iterator, _Base_iterator> __pair = + _Base::equal_range(__key); + for (_Base_iterator __victim = __pair.first; __victim != __pair.second;) + { + this->_M_invalidate_if(_Equal(__victim)); + _Base::erase(__victim++); + ++__ret; + } + return __ret; + } + + iterator + erase(const_iterator __it) + { + __glibcxx_check_erase(__it); + this->_M_invalidate_if(_Equal(__it.base())); + return iterator(_Base::erase(__it.base()), this); + } + + iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + iterator + erase(const_iterator __first, const_iterator __last) + { + __glibcxx_check_erase_range(__first, __last); + for (_Base_const_iterator __tmp = __first.base(); + __tmp != __last.base(); ++__tmp) + { + _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), + _M_message(__gnu_debug::__msg_valid_range) + ._M_iterator(__first, "first") + ._M_iterator(__last, "last")); + this->_M_invalidate_if(_Equal(__tmp)); + } + return iterator(_Base::erase(__first.base(), + __last.base()), this); + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + void + _M_invalidate_all() + { + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + this->_M_invalidate_if(_Not_equal(_Base::end())); + } + }; + + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> + inline void + swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + { __x.swap(__y); } + + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> + inline bool + operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + { return __x._M_equal(__y); } + + template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> + inline bool + operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } + +} // namespace __debug +} // namespace std + +#endif // __GXX_EXPERIMENTAL_CXX0X__ + +#endif diff --git a/libstdc++-v3/include/debug/vector b/libstdc++-v3/include/debug/vector new file mode 100644 index 000000000..b5daaa46f --- /dev/null +++ b/libstdc++-v3/include/debug/vector @@ -0,0 +1,610 @@ +// Debugging vector implementation -*- C++ -*- + +// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file debug/vector + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_VECTOR +#define _GLIBCXX_DEBUG_VECTOR 1 + +#include <vector> +#include <utility> +#include <debug/safe_sequence.h> +#include <debug/safe_iterator.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace __debug +{ + /// Class std::vector with safety/checking/debug instrumentation. + template<typename _Tp, + typename _Allocator = std::allocator<_Tp> > + class vector + : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>, + public __gnu_debug::_Safe_sequence<vector<_Tp, _Allocator> > + { + typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base; + typedef __gnu_debug::_Safe_sequence<vector> _Safe_base; + + typedef typename _Base::iterator _Base_iterator; + typedef typename _Base::const_iterator _Base_const_iterator; + typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + + public: + typedef typename _Base::reference reference; + typedef typename _Base::const_reference const_reference; + + typedef __gnu_debug::_Safe_iterator<_Base_iterator,vector> + iterator; + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,vector> + const_iterator; + + typedef typename _Base::size_type size_type; + typedef typename _Base::difference_type difference_type; + + typedef _Tp value_type; + typedef _Allocator allocator_type; + typedef typename _Base::pointer pointer; + typedef typename _Base::const_pointer const_pointer; + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + + // 23.2.4.1 construct/copy/destroy: + explicit + vector(const _Allocator& __a = _Allocator()) + : _Base(__a), _M_guaranteed_capacity(0) { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + explicit + vector(size_type __n) + : _Base(__n), _M_guaranteed_capacity(__n) { } + + vector(size_type __n, const _Tp& __value, + const _Allocator& __a = _Allocator()) + : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { } +#else + explicit + vector(size_type __n, const _Tp& __value = _Tp(), + const _Allocator& __a = _Allocator()) + : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { } +#endif + + template<class _InputIterator> + vector(_InputIterator __first, _InputIterator __last, + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), __a), + _M_guaranteed_capacity(0) + { _M_update_guaranteed_capacity(); } + + vector(const vector& __x) + : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { } + + /// Construction from a release-mode vector + vector(const _Base& __x) + : _Base(__x), _Safe_base(), _M_guaranteed_capacity(__x.size()) { } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + vector(vector&& __x) + : _Base(std::move(__x)), _Safe_base(), + _M_guaranteed_capacity(this->size()) + { + this->_M_swap(__x); + __x._M_guaranteed_capacity = 0; + } + + vector(initializer_list<value_type> __l, + const allocator_type& __a = allocator_type()) + : _Base(__l, __a), _Safe_base(), + _M_guaranteed_capacity(__l.size()) { } +#endif + + ~vector() { } + + vector& + operator=(const vector& __x) + { + static_cast<_Base&>(*this) = __x; + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + vector& + operator=(vector&& __x) + { + // NB: DR 1204. + // NB: DR 675. + clear(); + swap(__x); + return *this; + } + + vector& + operator=(initializer_list<value_type> __l) + { + static_cast<_Base&>(*this) = __l; + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + return *this; + } +#endif + + template<typename _InputIterator> + void + assign(_InputIterator __first, _InputIterator __last) + { + __glibcxx_check_valid_range(__first, __last); + _Base::assign(__gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } + + void + assign(size_type __n, const _Tp& __u) + { + _Base::assign(__n, __u); + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + assign(initializer_list<value_type> __l) + { + _Base::assign(__l); + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } +#endif + + using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + + // 23.2.4.2 capacity: + using _Base::size; + using _Base::max_size; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + resize(size_type __sz) + { + bool __realloc = _M_requires_reallocation(__sz); + if (__sz < this->size()) + this->_M_invalidate_after_nth(__sz); + _Base::resize(__sz); + if (__realloc) + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } + + void + resize(size_type __sz, const _Tp& __c) + { + bool __realloc = _M_requires_reallocation(__sz); + if (__sz < this->size()) + this->_M_invalidate_after_nth(__sz); + _Base::resize(__sz, __c); + if (__realloc) + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } +#else + void + resize(size_type __sz, _Tp __c = _Tp()) + { + bool __realloc = _M_requires_reallocation(__sz); + if (__sz < this->size()) + this->_M_invalidate_after_nth(__sz); + _Base::resize(__sz, __c); + if (__realloc) + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } +#endif + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + using _Base::shrink_to_fit; +#endif + + size_type + capacity() const + { +#ifdef _GLIBCXX_DEBUG_PEDANTIC + return _M_guaranteed_capacity; +#else + return _Base::capacity(); +#endif + } + + using _Base::empty; + + void + reserve(size_type __n) + { + bool __realloc = _M_requires_reallocation(__n); + _Base::reserve(__n); + if (__n > _M_guaranteed_capacity) + _M_guaranteed_capacity = __n; + if (__realloc) + this->_M_invalidate_all(); + } + + // element access: + reference + operator[](size_type __n) + { + __glibcxx_check_subscript(__n); + return _M_base()[__n]; + } + + const_reference + operator[](size_type __n) const + { + __glibcxx_check_subscript(__n); + return _M_base()[__n]; + } + + using _Base::at; + + reference + front() + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + const_reference + front() const + { + __glibcxx_check_nonempty(); + return _Base::front(); + } + + reference + back() + { + __glibcxx_check_nonempty(); + return _Base::back(); + } + + const_reference + back() const + { + __glibcxx_check_nonempty(); + return _Base::back(); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + using _Base::data; + + // 23.2.4.3 modifiers: + void + push_back(const _Tp& __x) + { + bool __realloc = _M_requires_reallocation(this->size() + 1); + _Base::push_back(__x); + if (__realloc) + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Up = _Tp> + typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, + void>::__type + push_back(_Tp&& __x) + { emplace_back(std::move(__x)); } + + template<typename... _Args> + void + emplace_back(_Args&&... __args) + { + bool __realloc = _M_requires_reallocation(this->size() + 1); + _Base::emplace_back(std::forward<_Args>(__args)...); + if (__realloc) + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + } +#endif + + void + pop_back() + { + __glibcxx_check_nonempty(); + this->_M_invalidate_if(_Equal(--_Base::end())); + _Base::pop_back(); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename... _Args> + iterator + emplace(iterator __position, _Args&&... __args) + { + __glibcxx_check_insert(__position); + bool __realloc = _M_requires_reallocation(this->size() + 1); + difference_type __offset = __position.base() - _Base::begin(); + _Base_iterator __res = _Base::emplace(__position.base(), + std::forward<_Args>(__args)...); + if (__realloc) + this->_M_invalidate_all(); + else + this->_M_invalidate_after_nth(__offset); + _M_update_guaranteed_capacity(); + return iterator(__res, this); + } +#endif + + iterator + insert(iterator __position, const _Tp& __x) + { + __glibcxx_check_insert(__position); + bool __realloc = _M_requires_reallocation(this->size() + 1); + difference_type __offset = __position.base() - _Base::begin(); + _Base_iterator __res = _Base::insert(__position.base(), __x); + if (__realloc) + this->_M_invalidate_all(); + else + this->_M_invalidate_after_nth(__offset); + _M_update_guaranteed_capacity(); + return iterator(__res, this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Up = _Tp> + typename __gnu_cxx::__enable_if<!std::__are_same<_Up, bool>::__value, + iterator>::__type + insert(iterator __position, _Tp&& __x) + { return emplace(__position, std::move(__x)); } + + void + insert(iterator __position, initializer_list<value_type> __l) + { this->insert(__position, __l.begin(), __l.end()); } +#endif + + void + insert(iterator __position, size_type __n, const _Tp& __x) + { + __glibcxx_check_insert(__position); + bool __realloc = _M_requires_reallocation(this->size() + __n); + difference_type __offset = __position.base() - _Base::begin(); + _Base::insert(__position.base(), __n, __x); + if (__realloc) + this->_M_invalidate_all(); + else + this->_M_invalidate_after_nth(__offset); + _M_update_guaranteed_capacity(); + } + + template<class _InputIterator> + void + insert(iterator __position, + _InputIterator __first, _InputIterator __last) + { + __glibcxx_check_insert_range(__position, __first, __last); + + /* Hard to guess if invalidation will occur, because __last + - __first can't be calculated in all cases, so we just + punt here by checking if it did occur. */ + _Base_iterator __old_begin = _M_base().begin(); + difference_type __offset = __position.base() - _Base::begin(); + _Base::insert(__position.base(), __gnu_debug::__base(__first), + __gnu_debug::__base(__last)); + + if (_M_base().begin() != __old_begin) + this->_M_invalidate_all(); + else + this->_M_invalidate_after_nth(__offset); + _M_update_guaranteed_capacity(); + } + + iterator + erase(iterator __position) + { + __glibcxx_check_erase(__position); + difference_type __offset = __position.base() - _Base::begin(); + _Base_iterator __res = _Base::erase(__position.base()); + this->_M_invalidate_after_nth(__offset); + return iterator(__res, this); + } + + iterator + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + __glibcxx_check_erase_range(__first, __last); + + if (__first.base() != __last.base()) + { + difference_type __offset = __first.base() - _Base::begin(); + _Base_iterator __res = _Base::erase(__first.base(), + __last.base()); + this->_M_invalidate_after_nth(__offset); + return iterator(__res, this); + } + else + return __first; + } + + void + swap(vector& __x) + { + _Base::swap(__x); + this->_M_swap(__x); + std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity); + } + + void + clear() + { + _Base::clear(); + this->_M_invalidate_all(); + _M_guaranteed_capacity = 0; + } + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + private: + size_type _M_guaranteed_capacity; + + bool + _M_requires_reallocation(size_type __elements) + { return __elements > this->capacity(); } + + void + _M_update_guaranteed_capacity() + { + if (this->size() > _M_guaranteed_capacity) + _M_guaranteed_capacity = this->size(); + } + + void + _M_invalidate_after_nth(difference_type __n) + { + typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth; + this->_M_invalidate_if(_After_nth(__n, _Base::begin())); + } + }; + + template<typename _Tp, typename _Alloc> + inline bool + operator==(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<=(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>=(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline void + swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs) + { __lhs.swap(__rhs); } + +} // namespace __debug + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + // DR 1182. + /// std::hash specialization for vector<bool>. + template<typename _Alloc> + struct hash<__debug::vector<bool, _Alloc>> + : public __hash_base<size_t, __debug::vector<bool, _Alloc>> + { + size_t + operator()(const __debug::vector<bool, _Alloc>& __b) const + { return std::hash<_GLIBCXX_STD_C::vector<bool, _Alloc>>() + (__b._M_base()); } + }; +#endif + +} // namespace std + +#endif |