re PR libstdc++/40518 (data races when calling std::string::erase() on empty string)

2009-06-23  Paolo Carlini  <paolo.carlini@oracle.com>

	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
This commit is contained in:
Paolo Carlini 2009-06-23 12:36:43 +00:00 committed by Paolo Carlini
parent 2724e58f96
commit 7309083f99
3 changed files with 45 additions and 16 deletions

View File

@ -1,3 +1,12 @@
2009-06-23 Paolo Carlini <paolo.carlini@oracle.com>
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.
2009-06-22 Paolo Carlini <paolo.carlini@oracle.com> 2009-06-22 Paolo Carlini <paolo.carlini@oracle.com>
* testsuite/util/testsuite_common_types.h (bitwise_operators, * testsuite/util/testsuite_common_types.h (bitwise_operators,

View File

@ -197,12 +197,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
void void
_M_set_length_and_sharable(size_type __n) _M_set_length_and_sharable(size_type __n)
{ {
this->_M_set_sharable(); // One reference. #ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
this->_M_length = __n; if (__builtin_expect(this != &_S_empty_rep(), false))
traits_type::assign(this->_M_refdata()[__n], _S_terminal); #endif
// grrr. (per 21.3.4) {
// You cannot leave those LWG people alone for a second. 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* _CharT*
@ -1226,16 +1231,8 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
* The value of the string doesn't change if an error is thrown. * The value of the string doesn't change if an error is thrown.
*/ */
iterator iterator
erase(iterator __first, iterator __last) 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);
}
/** /**
* @brief Replace characters with value from another string. * @brief Replace characters with value from another string.
* @param pos Index of first character to replace. * @param pos Index of first character to replace.

View File

@ -385,6 +385,29 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
} }
} }
template<typename _CharT, typename _Traits, typename _Alloc>
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<typename _CharT, typename _Traits, typename _Alloc> template<typename _CharT, typename _Traits, typename _Alloc>
basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>&
basic_string<_CharT, _Traits, _Alloc>:: basic_string<_CharT, _Traits, _Alloc>::