aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorPaolo Carlini <paolo.carlini@oracle.com>2009-06-23 12:36:43 +0000
committerPaolo Carlini <paolo@gcc.gnu.org>2009-06-23 12:36:43 +0000
commit7309083f99e306bd9f8512be3c7f4093cbbb13d0 (patch)
treee75e40c13a65e7f0449922ee1c3c4606a42e111a /libstdc++-v3
parent2724e58f9632352aecea376a0fdbbae54c4a2895 (diff)
downloadgcc-7309083f99e306bd9f8512be3c7f4093cbbb13d0.zip
gcc-7309083f99e306bd9f8512be3c7f4093cbbb13d0.tar.gz
gcc-7309083f99e306bd9f8512be3c7f4093cbbb13d0.tar.bz2
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
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog9
-rw-r--r--libstdc++-v3/include/bits/basic_string.h29
-rw-r--r--libstdc++-v3/include/bits/basic_string.tcc23
3 files changed, 45 insertions, 16 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index fc14048..a92920e 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -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>
* testsuite/util/testsuite_common_types.h (bitwise_operators,
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 _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>
basic_string<_CharT, _Traits, _Alloc>&
basic_string<_CharT, _Traits, _Alloc>::
replace(size_type __pos, size_type __n1, const _CharT* __s,