Inconsistency wrt Allocators in basic_string assignment (LWG2579)

2019-05-14  Nina Dinka Ranns  <dinka.ranns@gmail.com>

	Inconsistency wrt Allocators in basic_string assignment (LWG2579)
	* include/bits/basic_string.h: (operator=(const basic_string&):
	Move allocator decision to assign.
	(assign(const basic_string&)): Move allocator decision here.
	* testsuite/21_strings/basic_string/allocator/char/copy_assign.cc:
	Add tests.
	* testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc:
	Add tests.

From-SVN: r271165
This commit is contained in:
Nina Dinka Ranns 2019-05-14 11:48:31 +00:00 committed by Jonathan Wakely
parent 4593483f15
commit db33efde17
4 changed files with 113 additions and 29 deletions

View File

@ -1,3 +1,14 @@
2019-05-14 Nina Dinka Ranns <dinka.ranns@gmail.com>
Inconsistency wrt Allocators in basic_string assignment (LWG2579)
* include/bits/basic_string.h: (operator=(const basic_string&):
Move allocator decision to assign.
(assign(const basic_string&)): Move allocator decision here.
* testsuite/21_strings/basic_string/allocator/char/copy_assign.cc:
Add tests.
* testsuite/21_strings/basic_string/allocator/wchar_t/copy_assign.cc:
Add tests.
2019-05-14 Jonathan Wakely <jwakely@redhat.com>
* testsuite/util/testsuite_allocator.h (memory_resource)

View File

@ -664,35 +664,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_string&
operator=(const basic_string& __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())
{
// Propagating allocator cannot free existing storage so must
// deallocate it before replacing current allocator.
if (__str.size() <= _S_local_capacity)
{
_M_destroy(_M_allocated_capacity);
_M_data(_M_local_data());
_M_set_length(0);
}
else
{
const auto __len = __str.size();
auto __alloc = __str._M_get_allocator();
// If this allocation throws there are no effects:
auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
_M_destroy(_M_allocated_capacity);
_M_data(__ptr);
_M_capacity(__len);
_M_set_length(__len);
}
}
std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
}
#endif
return this->assign(__str);
}
@ -1363,6 +1334,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_string&
assign(const basic_string& __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())
{
// Propagating allocator cannot free existing storage so must
// deallocate it before replacing current allocator.
if (__str.size() <= _S_local_capacity)
{
_M_destroy(_M_allocated_capacity);
_M_data(_M_local_data());
_M_set_length(0);
}
else
{
const auto __len = __str.size();
auto __alloc = __str._M_get_allocator();
// If this allocation throws there are no effects:
auto __ptr = _Alloc_traits::allocate(__alloc, __len + 1);
_M_destroy(_M_allocated_capacity);
_M_data(__ptr);
_M_capacity(__len);
_M_set_length(__len);
}
}
std::__alloc_on_copy(_M_get_allocator(), __str._M_get_allocator());
}
#endif
this->_M_assign(__str);
return *this;
}

View File

@ -133,10 +133,47 @@ void test03()
VERIFY( v1.get_allocator() == a2 );
}
void test04()
{
// LWG2579
typedef propagating_allocator<C, true> alloc_type;
typedef std::basic_string<C, traits, alloc_type> test_type;
test_type v1("tralalala",alloc_type(1));
test_type v2("content", alloc_type(2));
test_type v3("content2", alloc_type(3));
v1.assign(v2);
v3 = v2;
VERIFY(2 == v1.get_allocator().get_personality());
VERIFY(2 == v3.get_allocator().get_personality());
}
void test05()
{
// LWG2579
typedef propagating_allocator<C, false> alloc_type;
typedef std::basic_string<C, traits, alloc_type> test_type;
test_type v1("tralalala",alloc_type(1));
test_type v2("content", alloc_type(2));
test_type v3("content2", alloc_type(3));
v1.assign(v2);
v3 = v2;
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(3 == v3.get_allocator().get_personality());
}
int main()
{
test01();
test02();
test03();
test04();
test05();
return 0;
}

View File

@ -133,10 +133,46 @@ void test03()
VERIFY( v1.get_allocator() == a2 );
}
void test04()
{
// LWG2579
typedef propagating_allocator<C, true> alloc_type;
typedef std::basic_string<C, traits, alloc_type> test_type;
test_type v1(L"tralalala",alloc_type(1));
test_type v2(L"content", alloc_type(2));
test_type v3(L"content2", alloc_type(3));
v1.assign(v2);
v3 = v2;
VERIFY(2 == v1.get_allocator().get_personality());
VERIFY(2 == v3.get_allocator().get_personality());
}
void test05()
{
// LWG2579
typedef propagating_allocator<C, false> alloc_type;
typedef std::basic_string<C, traits, alloc_type> test_type;
test_type v1(L"tralalala",alloc_type(1));
test_type v2(L"content", alloc_type(2));
test_type v3(L"content2", alloc_type(3));
v1.assign(v2);
v3 = v2;
VERIFY(1 == v1.get_allocator().get_personality());
VERIFY(3 == v3.get_allocator().get_personality());
}
int main()
{
test01();
test02();
test03();
test04();
test05();
return 0;
}