]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR libstdc++/40518 (data races when calling std::string::erase() on empty string)
authorPaolo Carlini <paolo.carlini@oracle.com>
Tue, 23 Jun 2009 12:36:43 +0000 (12:36 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 23 Jun 2009 12:36:43 +0000 (12:36 +0000)
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

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/basic_string.h
libstdc++-v3/include/bits/basic_string.tcc

index fc140487c81b8a75b5469e01234ba23dac96029a..a92920efdb84500e75d4a3e5b026943a1fb42cbf 100644 (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>
 
        * testsuite/util/testsuite_common_types.h (bitwise_operators,
index 1e8300dabfac3db61abf9c124c1b8be3ed258374..085aea463b6fb69d95060f2c126ea1e3ebaa26a2 100644 (file)
@@ -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.
index ec771c66859f7846672e9cc44ef9c2816f79f415..d450a4717de8ff75e24b283f1fd60aeff7379987 100644 (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>
      basic_string<_CharT, _Traits, _Alloc>&
      basic_string<_CharT, _Traits, _Alloc>::