Skip to content

Commit

Permalink
Implement N4258 noexcept for std::basic_string.
Browse files Browse the repository at this point in the history
	PR libstdc++/58265
	* doc/xml/manual/intro.xml: Document LWG 2063 and 2064 resolutions.
	* doc/html/manual/bugs.html: Regenerate.
	* include/bits/basic_string.h (basic_string): Implement N4258. Add
	correct exception-specifications and propagate allocators correctly.
	* include/bits/basic_string.tcc (basic_string::swap): Propagate
	allocators correctly.
	* include/debug/string (__gnu_debug::basic_string): Add correct
	exceptions-specifications and allcoator-extended constructors.
	* testsuite/21_strings/basic_string/allocator/char/copy.cc: New.
	* testsuite/21_strings/basic_string/allocator/char/copy_assign.cc:
	New.
	* testsuite/21_strings/basic_string/allocator/char/minimal.cc: New.
	* testsuite/21_strings/basic_string/allocator/char/move.cc: New.
	* testsuite/21_strings/basic_string/allocator/char/move_assign.cc:
	New.
	* testsuite/21_strings/basic_string/allocator/char/noexcept.cc: New.
	* testsuite/21_strings/basic_string/allocator/char/swap.cc: New.
	* testsuite/21_strings/basic_string/allocator/wchar_t/copy.cc: New.
	* testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc:
	New.
	* testsuite/21_strings/basic_string/allocator/wchar_t/minimal.cc: New.
	* testsuite/21_strings/basic_string/allocator/wchar_t/move.cc: New.
	* testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc:
	New.
	* testsuite/21_strings/basic_string/allocator/wchar_t/noexcept.cc: New.
	* testsuite/21_strings/basic_string/allocator/wchar_t/swap.cc: New.
	* testsuite/util/testsuite_allocator.h (tracker_allocator): Define
	defaulted assignment operators.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@227681 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
redi committed Sep 11, 2015
1 parent c5dc0aa commit b7aaabf
Show file tree
Hide file tree
Showing 21 changed files with 1,450 additions and 33 deletions.
30 changes: 30 additions & 0 deletions libstdc++-v3/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
2015-09-11 Jonathan Wakely <jwakely@redhat.com>

PR libstdc++/58265
* doc/xml/manual/intro.xml: Document LWG 2063 and 2064 resolutions.
* doc/html/manual/bugs.html: Regenerate.
* include/bits/basic_string.h (basic_string): Implement N4258. Add
correct exception-specifications and propagate allocators correctly.
* include/bits/basic_string.tcc (basic_string::swap): Propagate
allocators correctly.
* include/debug/string (__gnu_debug::basic_string): Add correct
exceptions-specifications and allcoator-extended constructors.
* testsuite/21_strings/basic_string/allocator/char/copy.cc: New.
* testsuite/21_strings/basic_string/allocator/char/copy_assign.cc:
New.
* testsuite/21_strings/basic_string/allocator/char/minimal.cc: New.
* testsuite/21_strings/basic_string/allocator/char/move.cc: New.
* testsuite/21_strings/basic_string/allocator/char/move_assign.cc:
New.
* testsuite/21_strings/basic_string/allocator/char/noexcept.cc: New.
* testsuite/21_strings/basic_string/allocator/char/swap.cc: New.
* testsuite/21_strings/basic_string/allocator/wchar_t/copy.cc: New.
* testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc:
New.
* testsuite/21_strings/basic_string/allocator/wchar_t/minimal.cc: New.
* testsuite/21_strings/basic_string/allocator/wchar_t/move.cc: New.
* testsuite/21_strings/basic_string/allocator/wchar_t/move_assign.cc:
New.
* testsuite/21_strings/basic_string/allocator/wchar_t/noexcept.cc: New.
* testsuite/21_strings/basic_string/allocator/wchar_t/swap.cc: New.
* testsuite/util/testsuite_allocator.h (tracker_allocator): Define
defaulted assignment operators.

PR libstdc++/65092
* include/bits/stl_queue.h (queue, priority_queue): Add
allocator-extended constructors.
Expand Down
6 changes: 6 additions & 0 deletions libstdc++-v3/doc/html/manual/bugs.html
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,12 @@
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2059" target="_top">2059</a>:
<span class="emphasis"><em>C++0x ambiguity problem with map::erase</em></span>
</span></dt><dd><p>Add additional overloads.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2063" target="_top">2063</a>:
<span class="emphasis"><em>Contradictory requirements for string move assignment</em></span>
</span></dt><dd><p>Respect propagation trait for move assignment.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2064" target="_top">2064</a>:
<span class="emphasis"><em>More noexcept issues in basic_string</em></span>
</span></dt><dd><p>Add noexcept to the comparison operators.
</p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2067" target="_top">2067</a>:
<span class="emphasis"><em>packaged_task should have deleted copy c'tor with const parameter</em></span>
</span></dt><dd><p>Fix signatures.
Expand Down
12 changes: 12 additions & 0 deletions libstdc++-v3/doc/xml/manual/intro.xml
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,18 @@ requirements of the license of GCC.
<listitem><para>Add additional overloads.
</para></listitem></varlistentry>

<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2063">2063</link>:
<emphasis>Contradictory requirements for string move assignment</emphasis>
</term>
<listitem><para>Respect propagation trait for move assignment.
</para></listitem></varlistentry>

<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2064">2064</link>:
<emphasis>More noexcept issues in basic_string</emphasis>
</term>
<listitem><para>Add noexcept to the comparison operators.
</para></listitem></varlistentry>

<varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2067">2067</link>:
<emphasis>packaged_task should have deleted copy c'tor with const parameter</emphasis>
</term>
Expand Down
101 changes: 91 additions & 10 deletions libstdc++-v3/include/bits/basic_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -379,17 +379,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @brief Default constructor creates an empty string.
*/
basic_string()
#if __cplusplus >= 201103L
noexcept(is_nothrow_default_constructible<_Alloc>::value)
#endif
_GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value)
: _M_dataplus(_M_local_data())
{ _M_set_length(0); }

/**
* @brief Construct an empty string using allocator @a a.
*/
explicit
basic_string(const _Alloc& __a)
basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPT
: _M_dataplus(_M_local_data(), __a)
{ _M_set_length(0); }

Expand All @@ -398,7 +396,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @param __str Source string.
*/
basic_string(const basic_string& __str)
: _M_dataplus(_M_local_data(), __str._M_get_allocator()) // TODO A traits
: _M_dataplus(_M_local_data(),
_Alloc_traits::_S_select_on_copy(__str._M_get_allocator()))
{ _M_construct(__str._M_data(), __str._M_data() + __str.length()); }

/**
Expand Down Expand Up @@ -511,10 +510,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ _M_construct(__str.begin(), __str.end()); }

basic_string(basic_string&& __str, const _Alloc& __a)
noexcept(_Alloc_traits::_S_always_equal())
: _M_dataplus(_M_local_data(), __a)
{
if (__str.get_allocator() == __a)
*this = std::move(__str);
if (__str._M_is_local())
{
traits_type::copy(_M_local_buf, __str._M_local_buf,
_S_local_capacity + 1);
_M_length(__str.length());
__str._M_set_length(0);
}
else if (_Alloc_traits::_S_always_equal()
|| __str.get_allocator() == __a)
{
_M_data(__str._M_data());
_M_length(__str.length());
_M_capacity(__str._M_allocated_capacity);
__str._M_data(__str._M_local_buf);
__str._M_set_length(0);
}
else
_M_construct(__str.begin(), __str.end());
}
Expand Down Expand Up @@ -550,7 +564,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_string&
operator=(const basic_string& __str)
{ return this->assign(__str); }
{
#if __cplusplus >= 201103L
if (_Alloc_traits::_S_propagate_on_copy_assign())
{
if (!_Alloc_traits::_S_always_equal() && !_M_is_local()
&& _M_get_allocator() != __str._M_get_allocator())
{
// replacement allocator cannot free existing storage
_M_destroy(_M_allocated_capacity);
_M_data(_M_local_data());
_M_set_length(0);
}
std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
}
#endif
return this->assign(__str);
}

/**
* @brief Copy contents of @a s into this string.
Expand Down Expand Up @@ -587,8 +617,51 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
// 2063. Contradictory requirements for string move assignment
basic_string&
operator=(basic_string&& __str)
noexcept(_Alloc_traits::_S_nothrow_move())
{
this->swap(__str);
if (!_M_is_local() && _Alloc_traits::_S_propagate_on_move_assign()
&& !_Alloc_traits::_S_always_equal()
&& _M_get_allocator() != __str._M_get_allocator())
{
// Destroy existing storage before replacing allocator.
_M_destroy(_M_allocated_capacity);
_M_data(_M_local_data());
_M_set_length(0);
}
// Replace allocator if POCMA is true.
std::__alloc_on_move(_M_get_allocator(), __str._M_get_allocator());

if (!__str._M_is_local()
&& (_Alloc_traits::_S_propagate_on_move_assign()
|| _Alloc_traits::_S_always_equal()))
{
pointer __data = nullptr;
size_type __capacity;
if (!_M_is_local())
{
if (_Alloc_traits::_S_always_equal())
{
__data = _M_data();
__capacity = _M_allocated_capacity;
}
else
_M_destroy(_M_allocated_capacity);
}

_M_data(__str._M_data());
_M_length(__str.length());
_M_capacity(__str._M_allocated_capacity);
if (__data)
{
__str._M_data(__data);
__str._M_capacity(__capacity);
}
else
__str._M_data(__str._M_local_buf);
}
else
assign(__str);
__str.clear();
return *this;
}

Expand Down Expand Up @@ -1119,6 +1192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
*/
basic_string&
assign(basic_string&& __str)
noexcept(_Alloc_traits::_S_nothrow_move())
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2063. Contradictory requirements for string move assignment
Expand Down Expand Up @@ -4961,13 +5035,14 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline bool
operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
_GLIBCXX_NOEXCEPT
{ return __lhs.compare(__rhs) == 0; }

template<typename _CharT>
inline
typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type
operator==(const basic_string<_CharT>& __lhs,
const basic_string<_CharT>& __rhs)
const basic_string<_CharT>& __rhs) _GLIBCXX_NOEXCEPT
{ return (__lhs.size() == __rhs.size()
&& !std::char_traits<_CharT>::compare(__lhs.data(), __rhs.data(),
__lhs.size())); }
Expand Down Expand Up @@ -5007,6 +5082,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline bool
operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
_GLIBCXX_NOEXCEPT
{ return !(__lhs == __rhs); }

/**
Expand Down Expand Up @@ -5044,6 +5120,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline bool
operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
_GLIBCXX_NOEXCEPT
{ return __lhs.compare(__rhs) < 0; }

/**
Expand Down Expand Up @@ -5081,6 +5158,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline bool
operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
_GLIBCXX_NOEXCEPT
{ return __lhs.compare(__rhs) > 0; }

/**
Expand Down Expand Up @@ -5118,6 +5196,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline bool
operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
_GLIBCXX_NOEXCEPT
{ return __lhs.compare(__rhs) <= 0; }

/**
Expand Down Expand Up @@ -5155,6 +5234,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline bool
operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
const basic_string<_CharT, _Traits, _Alloc>& __rhs)
_GLIBCXX_NOEXCEPT
{ return __lhs.compare(__rhs) >= 0; }

/**
Expand Down Expand Up @@ -5192,6 +5272,7 @@ _GLIBCXX_END_NAMESPACE_CXX11
inline void
swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
basic_string<_CharT, _Traits, _Alloc>& __rhs)
_GLIBCXX_NOEXCEPT_IF(noexcept(__lhs.swap(__rhs)))
{ __lhs.swap(__rhs); }


Expand Down
10 changes: 3 additions & 7 deletions libstdc++-v3/include/bits/basic_string.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (this == &__s)
return;

// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 431. Swapping containers with unequal allocators.
// TODO propagation traits
std::__alloc_swap<allocator_type>::_S_do_it(_M_get_allocator(),
__s._M_get_allocator());
_Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator());

if (_M_is_local())
if (__s._M_is_local())
Expand Down Expand Up @@ -404,7 +400,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

if (__new_size <= this->capacity())
{
_CharT* __p = this->_M_data() + __pos1;
pointer __p = this->_M_data() + __pos1;

const size_type __how_much = __old_size - __pos1 - __n1;
if (__how_much && __n1 != __n2)
Expand Down Expand Up @@ -433,7 +429,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

if (__new_size <= this->capacity())
{
_CharT* __p = this->_M_data() + __pos;
pointer __p = this->_M_data() + __pos;

const size_type __how_much = __old_size - __pos - __len1;
if (_M_disjunct(__s))
Expand Down

0 comments on commit b7aaabf

Please sign in to comment.