From 7309083f99e306bd9f8512be3c7f4093cbbb13d0 Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 23 Jun 2009 12:36:43 +0000 Subject: re PR libstdc++/40518 (data races when calling std::string::erase() on empty string) 2009-06-23 Paolo Carlini PR libstdc++/40518 * include/bits/basic_string.h (basic_string<>::_Rep:: _M_set_length_and_sharable): Do not write the empty rep. (basic_string<>::erase(iterator, iterator)): Likewise, move out of line... * include/bits/basic_string.tcc: ... here. From-SVN: r148850 --- libstdc++-v3/include/bits/basic_string.h | 29 +++++++++++++---------------- libstdc++-v3/include/bits/basic_string.tcc | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 16 deletions(-) (limited to 'libstdc++-v3/include/bits') diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 1e8300d..085aea4 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -197,12 +197,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std) void _M_set_length_and_sharable(size_type __n) - { - this->_M_set_sharable(); // One reference. - this->_M_length = __n; - traits_type::assign(this->_M_refdata()[__n], _S_terminal); - // grrr. (per 21.3.4) - // You cannot leave those LWG people alone for a second. + { +#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING + if (__builtin_expect(this != &_S_empty_rep(), false)) +#endif + { + this->_M_set_sharable(); // One reference. + this->_M_length = __n; + traits_type::assign(this->_M_refdata()[__n], _S_terminal); + // grrr. (per 21.3.4) + // You cannot leave those LWG people alone for a second. + } } _CharT* @@ -1226,16 +1231,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std) * The value of the string doesn't change if an error is thrown. */ iterator - erase(iterator __first, iterator __last) - { - _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last - && __last <= _M_iend()); - const size_type __pos = __first - _M_ibegin(); - _M_mutate(__pos, __last - __first, size_type(0)); - _M_rep()->_M_set_leaked(); - return iterator(_M_data() + __pos); - } - + erase(iterator __first, iterator __last); + /** * @brief Replace characters with value from another string. * @param pos Index of first character to replace. diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index ec771c6..d450a47 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -386,6 +386,29 @@ _GLIBCXX_BEGIN_NAMESPACE(std) } template + typename basic_string<_CharT, _Traits, _Alloc>::iterator + basic_string<_CharT, _Traits, _Alloc>:: + erase(iterator __first, iterator __last) + { + _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last + && __last <= _M_iend()); + + // NB: This isn't just an optimization (bail out early when + // there is nothing to do, really), it's also a correctness + // issue vs MT, see libstdc++/40518. + const size_type __size = __last - __first; + if (__size) + { + const size_type __pos = __first - _M_ibegin(); + _M_mutate(__pos, __size, size_type(0)); + _M_rep()->_M_set_leaked(); + return iterator(_M_data() + __pos); + } + else + return __first; + } + + template basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>:: replace(size_type __pos, size_type __n1, const _CharT* __s, -- cgit v1.1