Hello,I did not touch the regular basic_string because Paulo usually says not to touch it, but I could do it as well if wanted. I didn't add noexcept to the debug string swap (and move assignments) because the regular basic_string swap can currently throw if the allocators are distinct.
bootstrap+testsuite ok. 2013-09-19 Marc Glisse <marc.gli...@inria.fr> PR libstdc++/58338 * include/bits/stl_tree.h (_Rb_tree_node_base) [_S_minimum, _S_maximum]: Mark as noexcept. (_Rb_tree_iterator) [_Rb_tree_iterator, operator*, operator->, operator++, operator--, operator==, operator!=]: Likewise. (_Rb_tree_const_iterator) [_Rb_tree_const_iterator, _M_const_cast, operator*, operator->, operator++, operator--, operator==, operator!=]: Likewise. (operator==(const _Rb_tree_iterator&, const _Rb_tree_const_iterator&), operator!=(const _Rb_tree_iterator&, const _Rb_tree_const_iterator&)): Likewise. (_Rb_tree) [_M_put_node, _M_destroy_node, _M_root, _M_leftmost, _M_rightmost, _M_begin, _M_end, _S_left, _S_right, _S_minimum, _S_maximum]: Likewise. * include/debug/string (basic_string) [basic_string(const _Allocator&), shrink_to_fit, operator[], pop_back]: Likewise. * include/ext/vstring.h (__versa_string) [_M_limit, _M_disjunct, _M_ibegin, _M_iend, __versa_string(const _Alloc&), operator=(__versa_string&&), shrink_to_fit, operator[], front, back, assign(__versa_string&&), swap]: Likewise. (__versa_string) [__versa_string(), __versa_string(const _Alloc&)]: Merge. -- Marc Glisse
Index: include/bits/stl_tree.h =================================================================== --- include/bits/stl_tree.h (revision 202722) +++ include/bits/stl_tree.h (working copy) @@ -92,42 +92,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef _Rb_tree_node_base* _Base_ptr; typedef const _Rb_tree_node_base* _Const_Base_ptr; _Rb_tree_color _M_color; _Base_ptr _M_parent; _Base_ptr _M_left; _Base_ptr _M_right; static _Base_ptr - _S_minimum(_Base_ptr __x) + _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT { while (__x->_M_left != 0) __x = __x->_M_left; return __x; } static _Const_Base_ptr - _S_minimum(_Const_Base_ptr __x) + _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT { while (__x->_M_left != 0) __x = __x->_M_left; return __x; } static _Base_ptr - _S_maximum(_Base_ptr __x) + _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT { while (__x->_M_right != 0) __x = __x->_M_right; return __x; } static _Const_Base_ptr - _S_maximum(_Const_Base_ptr __x) + _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT { while (__x->_M_right != 0) __x = __x->_M_right; return __x; } }; template<typename _Val> struct _Rb_tree_node : public _Rb_tree_node_base { typedef _Rb_tree_node<_Val>* _Link_type; @@ -160,72 +160,72 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Tp& reference; typedef _Tp* pointer; typedef bidirectional_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef _Rb_tree_iterator<_Tp> _Self; typedef _Rb_tree_node_base::_Base_ptr _Base_ptr; typedef _Rb_tree_node<_Tp>* _Link_type; - _Rb_tree_iterator() + _Rb_tree_iterator() _GLIBCXX_NOEXCEPT : _M_node() { } explicit - _Rb_tree_iterator(_Link_type __x) + _Rb_tree_iterator(_Link_type __x) _GLIBCXX_NOEXCEPT : _M_node(__x) { } reference - operator*() const + operator*() const _GLIBCXX_NOEXCEPT { return static_cast<_Link_type>(_M_node)->_M_value_field; } pointer - operator->() const + operator->() const _GLIBCXX_NOEXCEPT { return std::__addressof(static_cast<_Link_type> (_M_node)->_M_value_field); } _Self& - operator++() + operator++() _GLIBCXX_NOEXCEPT { _M_node = _Rb_tree_increment(_M_node); return *this; } _Self - operator++(int) + operator++(int) _GLIBCXX_NOEXCEPT { _Self __tmp = *this; _M_node = _Rb_tree_increment(_M_node); return __tmp; } _Self& - operator--() + operator--() _GLIBCXX_NOEXCEPT { _M_node = _Rb_tree_decrement(_M_node); return *this; } _Self - operator--(int) + operator--(int) _GLIBCXX_NOEXCEPT { _Self __tmp = *this; _M_node = _Rb_tree_decrement(_M_node); return __tmp; } bool - operator==(const _Self& __x) const + operator==(const _Self& __x) const _GLIBCXX_NOEXCEPT { return _M_node == __x._M_node; } bool - operator!=(const _Self& __x) const + operator!=(const _Self& __x) const _GLIBCXX_NOEXCEPT { return _M_node != __x._M_node; } _Base_ptr _M_node; }; template<typename _Tp> struct _Rb_tree_const_iterator { typedef _Tp value_type; typedef const _Tp& reference; @@ -233,95 +233,95 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef _Rb_tree_iterator<_Tp> iterator; typedef bidirectional_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef _Rb_tree_const_iterator<_Tp> _Self; typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr; typedef const _Rb_tree_node<_Tp>* _Link_type; - _Rb_tree_const_iterator() + _Rb_tree_const_iterator() _GLIBCXX_NOEXCEPT : _M_node() { } explicit - _Rb_tree_const_iterator(_Link_type __x) + _Rb_tree_const_iterator(_Link_type __x) _GLIBCXX_NOEXCEPT : _M_node(__x) { } - _Rb_tree_const_iterator(const iterator& __it) + _Rb_tree_const_iterator(const iterator& __it) _GLIBCXX_NOEXCEPT : _M_node(__it._M_node) { } iterator - _M_const_cast() const + _M_const_cast() const _GLIBCXX_NOEXCEPT { return iterator(static_cast<typename iterator::_Link_type> (const_cast<typename iterator::_Base_ptr>(_M_node))); } reference - operator*() const + operator*() const _GLIBCXX_NOEXCEPT { return static_cast<_Link_type>(_M_node)->_M_value_field; } pointer - operator->() const + operator->() const _GLIBCXX_NOEXCEPT { return std::__addressof(static_cast<_Link_type> (_M_node)->_M_value_field); } _Self& - operator++() + operator++() _GLIBCXX_NOEXCEPT { _M_node = _Rb_tree_increment(_M_node); return *this; } _Self - operator++(int) + operator++(int) _GLIBCXX_NOEXCEPT { _Self __tmp = *this; _M_node = _Rb_tree_increment(_M_node); return __tmp; } _Self& - operator--() + operator--() _GLIBCXX_NOEXCEPT { _M_node = _Rb_tree_decrement(_M_node); return *this; } _Self - operator--(int) + operator--(int) _GLIBCXX_NOEXCEPT { _Self __tmp = *this; _M_node = _Rb_tree_decrement(_M_node); return __tmp; } bool - operator==(const _Self& __x) const + operator==(const _Self& __x) const _GLIBCXX_NOEXCEPT { return _M_node == __x._M_node; } bool - operator!=(const _Self& __x) const + operator!=(const _Self& __x) const _GLIBCXX_NOEXCEPT { return _M_node != __x._M_node; } _Base_ptr _M_node; }; template<typename _Val> inline bool operator==(const _Rb_tree_iterator<_Val>& __x, - const _Rb_tree_const_iterator<_Val>& __y) + const _Rb_tree_const_iterator<_Val>& __y) _GLIBCXX_NOEXCEPT { return __x._M_node == __y._M_node; } template<typename _Val> inline bool operator!=(const _Rb_tree_iterator<_Val>& __x, - const _Rb_tree_const_iterator<_Val>& __y) + const _Rb_tree_const_iterator<_Val>& __y) _GLIBCXX_NOEXCEPT { return __x._M_node != __y._M_node; } void _Rb_tree_insert_and_rebalance(const bool __insert_left, _Rb_tree_node_base* __x, _Rb_tree_node_base* __p, _Rb_tree_node_base& __header) throw (); _Rb_tree_node_base* _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z, @@ -363,21 +363,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return allocator_type(_M_get_Node_allocator()); } protected: _Link_type _M_get_node() { return _M_impl._Node_allocator::allocate(1); } void - _M_put_node(_Link_type __p) + _M_put_node(_Link_type __p) _GLIBCXX_NOEXCEPT { _M_impl._Node_allocator::deallocate(__p, 1); } #if __cplusplus < 201103L _Link_type _M_create_node(const value_type& __x) { _Link_type __tmp = _M_get_node(); __try { get_allocator().construct (std::__addressof(__tmp->_M_value_field), __x); } @@ -409,21 +409,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } __catch(...) { _M_put_node(__tmp); __throw_exception_again; } return __tmp; } void - _M_destroy_node(_Link_type __p) + _M_destroy_node(_Link_type __p) noexcept { _M_get_Node_allocator().destroy(__p); _M_put_node(__p); } #endif _Link_type _M_clone_node(_Const_Link_type __x) { _Link_type __tmp = _M_create_node(__x->_M_value_field); @@ -467,108 +467,108 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION this->_M_header._M_parent = 0; this->_M_header._M_left = &this->_M_header; this->_M_header._M_right = &this->_M_header; } }; _Rb_tree_impl<_Compare> _M_impl; protected: _Base_ptr& - _M_root() + _M_root() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_parent; } _Const_Base_ptr - _M_root() const + _M_root() const _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_parent; } _Base_ptr& - _M_leftmost() + _M_leftmost() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_left; } _Const_Base_ptr - _M_leftmost() const + _M_leftmost() const _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_left; } _Base_ptr& - _M_rightmost() + _M_rightmost() _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_right; } _Const_Base_ptr - _M_rightmost() const + _M_rightmost() const _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_right; } _Link_type - _M_begin() + _M_begin() _GLIBCXX_NOEXCEPT { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } _Const_Link_type - _M_begin() const + _M_begin() const _GLIBCXX_NOEXCEPT { return static_cast<_Const_Link_type> (this->_M_impl._M_header._M_parent); } _Link_type - _M_end() + _M_end() _GLIBCXX_NOEXCEPT { return static_cast<_Link_type>(&this->_M_impl._M_header); } _Const_Link_type - _M_end() const + _M_end() const _GLIBCXX_NOEXCEPT { return static_cast<_Const_Link_type>(&this->_M_impl._M_header); } static const_reference _S_value(_Const_Link_type __x) { return __x->_M_value_field; } static const _Key& _S_key(_Const_Link_type __x) { return _KeyOfValue()(_S_value(__x)); } static _Link_type - _S_left(_Base_ptr __x) + _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT { return static_cast<_Link_type>(__x->_M_left); } static _Const_Link_type - _S_left(_Const_Base_ptr __x) + _S_left(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT { return static_cast<_Const_Link_type>(__x->_M_left); } static _Link_type - _S_right(_Base_ptr __x) + _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT { return static_cast<_Link_type>(__x->_M_right); } static _Const_Link_type - _S_right(_Const_Base_ptr __x) + _S_right(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT { return static_cast<_Const_Link_type>(__x->_M_right); } static const_reference _S_value(_Const_Base_ptr __x) { return static_cast<_Const_Link_type>(__x)->_M_value_field; } static const _Key& _S_key(_Const_Base_ptr __x) { return _KeyOfValue()(_S_value(__x)); } static _Base_ptr - _S_minimum(_Base_ptr __x) + _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT { return _Rb_tree_node_base::_S_minimum(__x); } static _Const_Base_ptr - _S_minimum(_Const_Base_ptr __x) + _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT { return _Rb_tree_node_base::_S_minimum(__x); } static _Base_ptr - _S_maximum(_Base_ptr __x) + _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT { return _Rb_tree_node_base::_S_maximum(__x); } static _Const_Base_ptr - _S_maximum(_Const_Base_ptr __x) + _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT { return _Rb_tree_node_base::_S_maximum(__x); } public: typedef _Rb_tree_iterator<value_type> iterator; typedef _Rb_tree_const_iterator<value_type> const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; private: Index: include/debug/string =================================================================== --- include/debug/string (revision 202722) +++ include/debug/string (working copy) @@ -63,20 +63,21 @@ namespace __gnu_debug 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()) + _GLIBCXX_NOEXCEPT : _Base(__a) { } // Provides conversion from a release-mode string to a debug-mode string basic_string(const _Base& __base) : _Base(__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()) @@ -231,21 +232,21 @@ namespace __gnu_debug _Base::resize(__n, __c); this->_M_invalidate_all(); } void resize(size_type __n) { this->resize(__n, _CharT()); } #if __cplusplus >= 201103L void - shrink_to_fit() + shrink_to_fit() noexcept { if (capacity() > size()) { __try { reserve(0); this->_M_invalidate_all(); } __catch(...) { } @@ -260,32 +261,32 @@ namespace __gnu_debug clear() _GLIBCXX_NOEXCEPT { _Base::clear(); this->_M_invalidate_all(); } using _Base::empty; // 21.3.4 element access: const_reference - operator[](size_type __pos) const + operator[](size_type __pos) const _GLIBCXX_NOEXCEPT { _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) + operator[](size_type __pos) _GLIBCXX_NOEXCEPT { #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")); @@ -575,21 +576,21 @@ namespace __gnu_debug // 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); } #if __cplusplus >= 201103L void - pop_back() + pop_back() noexcept { __glibcxx_check_nonempty(); _Base::pop_back(); this->_M_invalidate_all(); } #endif // C++11 basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str) { Index: include/ext/vstring.h =================================================================== --- include/ext/vstring.h (revision 202722) +++ include/ext/vstring.h (working copy) @@ -91,61 +91,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void _M_check_length(size_type __n1, size_type __n2, const char* __s) const { if (this->max_size() - (this->size() - __n1) < __n2) std::__throw_length_error(__N(__s)); } // NB: _M_limit doesn't check for a bad __pos value. size_type - _M_limit(size_type __pos, size_type __off) const + _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPT { const bool __testoff = __off < this->size() - __pos; return __testoff ? __off : this->size() - __pos; } // True if _Rep and source do not overlap. bool - _M_disjunct(const _CharT* __s) const + _M_disjunct(const _CharT* __s) const _GLIBCXX_NOEXCEPT { return (std::less<const _CharT*>()(__s, this->_M_data()) || std::less<const _CharT*>()(this->_M_data() + this->size(), __s)); } // For the internal use we have functions similar to `begin'/`end' // but they do not call _M_leak. iterator - _M_ibegin() const + _M_ibegin() const _GLIBCXX_NOEXCEPT { return iterator(this->_M_data()); } iterator - _M_iend() const + _M_iend() const _GLIBCXX_NOEXCEPT { return iterator(this->_M_data() + this->_M_length()); } public: // Construct/copy/destroy: // NB: We overload ctors in some cases instead of using default // arguments, per 17.4.4.4 para. 2 item 2. /** - * @brief Default constructor creates an empty string. - */ - __versa_string() - : __vstring_base() { } - - /** * @brief Construct an empty string using allocator @a a. */ explicit - __versa_string(const _Alloc& __a) + __versa_string(const _Alloc& __a = _Alloc()) _GLIBCXX_NOEXCEPT : __vstring_base(__a) { } // NB: per LWG issue 42, semantics different from IS: /** * @brief Construct string with copy of value of @a __str. * @param __str Source string. */ __versa_string(const __versa_string& __str) : __vstring_base(__str) { } @@ -262,21 +256,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L /** * @brief String move assignment operator. * @param __str Source string. * * The contents of @a __str are moved into this string (without * copying). @a __str is a valid, but unspecified string. */ __versa_string& - operator=(__versa_string&& __str) + operator=(__versa_string&& __str) noexcept { // NB: DR 1204. this->swap(__str); return *this; } /** * @brief Set value to string constructed from initializer list. * @param __l std::initializer_list. */ @@ -463,21 +457,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * is extended and new characters are default-constructed. For * basic types such as char, this means setting them to 0. */ void resize(size_type __n) { this->resize(__n, _CharT()); } #if __cplusplus >= 201103L /// A non-binding request to reduce capacity() to size(). void - shrink_to_fit() + shrink_to_fit() noexcept { if (capacity() > size()) { __try { this->reserve(0); } __catch(...) { } } } #endif @@ -531,38 +525,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @brief Subscript access to the data contained in the %string. * @param __pos The index of the character to access. * @return Read-only (constant) reference to the character. * * This operator allows for easy, array-style, data access. * Note that data access with this operator is unchecked and * out_of_range lookups are not defined. (For checked lookups * see at().) */ const_reference - operator[] (size_type __pos) const + operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT { _GLIBCXX_DEBUG_ASSERT(__pos <= this->size()); return this->_M_data()[__pos]; } /** * @brief Subscript access to the data contained in the %string. * @param __pos The index of the character to access. * @return Read/write reference to the character. * * This operator allows for easy, array-style, data access. * Note that data access with this operator is unchecked and * out_of_range lookups are not defined. (For checked lookups * see at().) Unshares the string. */ reference - operator[](size_type __pos) + operator[](size_type __pos) _GLIBCXX_NOEXCEPT { // Allow pos == size() both in C++98 mode, as v3 extension, // and in C++11 mode. _GLIBCXX_DEBUG_ASSERT(__pos <= this->size()); // In pedantic mode be strict in C++98 mode. _GLIBCXX_DEBUG_PEDASSERT(__cplusplus >= 201103L || __pos < this->size()); this->_M_leak(); return this->_M_data()[__pos]; } @@ -604,45 +598,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION this->_M_leak(); return this->_M_data()[__n]; } #if __cplusplus >= 201103L /** * Returns a read/write reference to the data at the first * element of the %string. */ reference - front() + front() _GLIBCXX_NOEXCEPT { return operator[](0); } /** * Returns a read-only (constant) reference to the data at the first * element of the %string. */ const_reference - front() const + front() const _GLIBCXX_NOEXCEPT { return operator[](0); } /** * Returns a read/write reference to the data at the last * element of the %string. */ reference - back() + back() _GLIBCXX_NOEXCEPT { return operator[](this->size() - 1); } /** * Returns a read-only (constant) reference to the data at the * last element of the %string. */ const_reference - back() const + back() const _GLIBCXX_NOEXCEPT { return operator[](this->size() - 1); } #endif // Modifiers: /** * @brief Append a string to this string. * @param __str The string to append. * @return Reference to this string. */ __versa_string& @@ -807,21 +801,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L /** * @brief Set value to contents of another string. * @param __str Source string to use. * @return Reference to this string. * * This function sets this string to the exact contents of @a __str. * @a __str is a valid, but unspecified string. */ __versa_string& - assign(__versa_string&& __str) + assign(__versa_string&& __str) noexcept { this->swap(__str); return *this; } #endif // C++11 /** * @brief Set value to a substring of a string. * @param __str The string to use. * @param __pos Index of the first character of str. @@ -1624,21 +1618,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION copy(_CharT* __s, size_type __n, size_type __pos = 0) const; /** * @brief Swap contents with another string. * @param __s String to swap with. * * Exchanges the contents of this string with that of @a __s in * constant time. */ void - swap(__versa_string& __s) + swap(__versa_string& __s) _GLIBCXX_NOEXCEPT { this->_M_swap(__s); } // String operations: /** * @brief Return const pointer to null-terminated contents. * * This is a handle to internal data. Do not modify or dire things may * happen. */ const _CharT*