On Mon, 23 Sep 2013, Paolo Carlini wrote:

On 9/23/13 10:55 AM, Marc Glisse wrote:
Hello,

this patch was tested on x86_64 with a bootstrap and a simple make -k check, without regression. Note that it doesn't completely fix 56166, it
merely admits that we may currently throw and avoids turning that into
std::terminate.
Of course.

Patch basically Ok, can you be a little less terse in the comments before the noexcepts which you are removing and in fact must be there for conformance, aren't just QoI? Point to an existing bug, when it exists, like 56166, add a FIXME C++11 at least.

Like this?

It is funny that with fully dynamic strings, the copy constructor is "better" than the move constructor: faster, doesn't throw, etc. I think we should remove the move constructor in that case, or at least make it act the same as the copy constructor. I didn't mark the copy constructor as noexcept, but without checking the code it seems likely we could.

Also, __versa_string actually has the same issues as basic_string, if you choose the reference counted base... I guess I have to do a patch to remove noexcept there now :-( Has someone started work on some branch to get a real C++11 basic_string, or are we waiting until the "lack of manpower" argument convinces everyone to forget about trying to preserve any ABI compatibility?

2013-09-24  Marc Glisse  <marc.gli...@inria.fr>

        PR libstdc++/58338
        PR libstdc++/56166
        * include/bits/basic_string.h (basic_string)
        [basic_string(basic_string&&)]: Make the noexcept conditional.
        [operator=(basic_string&&), assign(basic_string&&)]: Link to PR 58265.
        [begin(), end(), rbegin(), rend(), clear]: Remove noexcept.
        [pop_back]: Comment on the lack of noexcept.
        * include/debug/string (basic_string) [basic_string(const _Allocator&),
        basic_string(basic_string&&), begin(), end(), rbegin(), rend(), clear,
        operator[](size_type), pop_back]: Comment out noexcept, until vstring
        replaces basic_string.

--
Marc Glisse
Index: include/bits/basic_string.h
===================================================================
--- include/bits/basic_string.h (revision 202838)
+++ include/bits/basic_string.h (working copy)
@@ -502,21 +502,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc());
 
 #if __cplusplus >= 201103L
       /**
        *  @brief  Move construct string.
        *  @param  __str  Source string.
        *
        *  The newly-created string contains the exact contents of @a __str.
        *  @a __str is a valid, but unspecified string.
        **/
-      basic_string(basic_string&& __str) noexcept
+      basic_string(basic_string&& __str)
+#if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
+      noexcept // FIXME C++11: should always be noexcept.
+#endif
       : _M_dataplus(__str._M_dataplus)
       {
 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
        __str._M_data(_S_empty_rep()._M_refdata());
 #else
        __str._M_data(_S_construct(size_type(), _CharT(), get_allocator()));
 #endif
       }
 
       /**
@@ -574,20 +577,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
 #if __cplusplus >= 201103L
       /**
        *  @brief  Move assign the value of @a str to this string.
        *  @param  __str  Source string.
        *
        *  The contents of @a str are moved into this string (without copying).
        *  @a str is a valid, but unspecified string.
        **/
+      // PR 58265, this should be noexcept.
       basic_string&
       operator=(basic_string&& __str)
       {
        // NB: DR 1204.
        this->swap(__str);
        return *this;
       }
 
       /**
        *  @brief  Set value to string constructed from initializer %list.
@@ -600,78 +604,78 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return *this;
       }
 #endif // C++11
 
       // Iterators:
       /**
        *  Returns a read/write iterator that points to the first character in
        *  the %string.  Unshares the string.
        */
       iterator
-      begin() _GLIBCXX_NOEXCEPT
+      begin() // FIXME C++11: should be noexcept.
       {
        _M_leak();
        return iterator(_M_data());
       }
 
       /**
        *  Returns a read-only (constant) iterator that points to the first
        *  character in the %string.
        */
       const_iterator
       begin() const _GLIBCXX_NOEXCEPT
       { return const_iterator(_M_data()); }
 
       /**
        *  Returns a read/write iterator that points one past the last
        *  character in the %string.  Unshares the string.
        */
       iterator
-      end() _GLIBCXX_NOEXCEPT
+      end() // FIXME C++11: should be noexcept.
       {
        _M_leak();
        return iterator(_M_data() + this->size());
       }
 
       /**
        *  Returns a read-only (constant) iterator that points one past the
        *  last character in the %string.
        */
       const_iterator
       end() const _GLIBCXX_NOEXCEPT
       { return const_iterator(_M_data() + this->size()); }
 
       /**
        *  Returns a read/write reverse iterator that points to the last
        *  character in the %string.  Iteration is done in reverse element
        *  order.  Unshares the string.
        */
       reverse_iterator
-      rbegin() _GLIBCXX_NOEXCEPT
+      rbegin() // FIXME C++11: should be noexcept.
       { return reverse_iterator(this->end()); }
 
       /**
        *  Returns a read-only (constant) reverse iterator that points
        *  to the last character in the %string.  Iteration is done in
        *  reverse element order.
        */
       const_reverse_iterator
       rbegin() const _GLIBCXX_NOEXCEPT
       { return const_reverse_iterator(this->end()); }
 
       /**
        *  Returns a read/write reverse iterator that points to one before the
        *  first character in the %string.  Iteration is done in reverse
        *  element order.  Unshares the string.
        */
       reverse_iterator
-      rend() _GLIBCXX_NOEXCEPT
+      rend() // FIXME C++11: should be noexcept.
       { return reverse_iterator(this->begin()); }
 
       /**
        *  Returns a read-only (constant) reverse iterator that points
        *  to one before the first character in the %string.  Iteration
        *  is done in reverse element order.
        */
       const_reverse_iterator
       rend() const _GLIBCXX_NOEXCEPT
       { return const_reverse_iterator(this->begin()); }
@@ -799,21 +803,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  data.
        */
       void
       reserve(size_type __res_arg = 0);
 
       /**
        *  Erases the string, making it empty.
        */
       // PR 56166: this should not throw.
       void
-      clear() _GLIBCXX_NOEXCEPT
+      clear()
       { _M_mutate(0, this->size(), 0); }
 
       /**
        *  Returns true if the %string is empty.  Equivalent to 
        *  <code>*this == ""</code>.
        */
       bool
       empty() const _GLIBCXX_NOEXCEPT
       { return this->size() == 0; }
 
@@ -1081,20 +1085,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.
        */
+      // PR 58265, this should be noexcept.
       basic_string&
       assign(basic_string&& __str)
       {
        this->swap(__str);
        return *this;
       }
 #endif // C++11
 
       /**
        *  @brief  Set value to a substring of a string.
@@ -1410,21 +1415,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       iterator
       erase(iterator __first, iterator __last);
  
 #if __cplusplus >= 201103L
       /**
        *  @brief  Remove the last character.
        *
        *  The string must be non-empty.
        */
       void
-      pop_back()
+      pop_back() // FIXME C++11: should be noexcept.
       { erase(size()-1, 1); }
 #endif // C++11
 
       /**
        *  @brief  Replace characters with value from another string.
        *  @param __pos  Index of first character to replace.
        *  @param __n  Number of characters to be replaced.
        *  @param __str  String to insert.
        *  @return  Reference to this string.
        *  @throw  std::out_of_range  If @a pos is beyond the end of this
Index: include/debug/string
===================================================================
--- include/debug/string        (revision 202838)
+++ include/debug/string        (working copy)
@@ -63,21 +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
+    // _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())
@@ -107,21 +107,21 @@ namespace __gnu_debug
 
     template<typename _InputIterator>
       basic_string(_InputIterator __begin, _InputIterator __end,
                   const _Allocator& __a = _Allocator())
       : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__begin,
                                                                   __end)),
              __gnu_debug::__base(__end), __a)
       { }
 
 #if __cplusplus >= 201103L
-    basic_string(basic_string&& __str) noexcept
+    basic_string(basic_string&& __str) // noexcept
     : _Base(std::move(__str))
     { }
 
     basic_string(std::initializer_list<_CharT> __l,
                 const _Allocator& __a = _Allocator())
     : _Base(__l, __a)
     { }
 #endif // C++11
 
     ~basic_string() _GLIBCXX_NOEXCEPT { }
@@ -165,45 +165,45 @@ namespace __gnu_debug
     operator=(std::initializer_list<_CharT> __l)
     {
       *static_cast<_Base*>(this) = __l;
       this->_M_invalidate_all();
       return *this;
     }
 #endif // C++11
 
     // 21.3.2 iterators:
     iterator
-    begin() _GLIBCXX_NOEXCEPT
+    begin() // _GLIBCXX_NOEXCEPT
     { return iterator(_Base::begin(), this); }
 
     const_iterator
     begin() const _GLIBCXX_NOEXCEPT
     { return const_iterator(_Base::begin(), this); }
 
     iterator
-    end() _GLIBCXX_NOEXCEPT
+    end() // _GLIBCXX_NOEXCEPT
     { return iterator(_Base::end(), this); }
 
     const_iterator
     end() const _GLIBCXX_NOEXCEPT
     { return const_iterator(_Base::end(), this); }
 
     reverse_iterator
-    rbegin() _GLIBCXX_NOEXCEPT
+    rbegin() // _GLIBCXX_NOEXCEPT
     { return reverse_iterator(end()); }
 
     const_reverse_iterator
     rbegin() const _GLIBCXX_NOEXCEPT
     { return const_reverse_iterator(end()); }
 
     reverse_iterator
-    rend() _GLIBCXX_NOEXCEPT
+    rend() // _GLIBCXX_NOEXCEPT
     { return reverse_iterator(begin()); }
 
     const_reverse_iterator
     rend() const _GLIBCXX_NOEXCEPT
     { return const_reverse_iterator(begin()); }
 
 #if __cplusplus >= 201103L
     const_iterator
     cbegin() const noexcept
     { return const_iterator(_Base::begin(), this); }
@@ -251,42 +251,42 @@ namespace __gnu_debug
          __catch(...)
            { }
        }
     }
 #endif
 
     using _Base::capacity;
     using _Base::reserve;
 
     void
-    clear() _GLIBCXX_NOEXCEPT
+    clear() // _GLIBCXX_NOEXCEPT
     {
       _Base::clear();
       this->_M_invalidate_all();
     }
 
     using _Base::empty;
 
     // 21.3.4 element access:
     const_reference
     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) _GLIBCXX_NOEXCEPT
+    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"));
@@ -576,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() noexcept
+    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)
     {

Reply via email to