libstdc++: Use RAII to replace try/catch blocks

Move _Guard into std::vector declaration and use it to guard all calls to
vector _M_allocate.

Doing so the compiler has more visibility on what is done with the pointers
and do not raise anymore the -Wfree-nonheap-object warning.

libstdc++-v3/ChangeLog:

	* include/bits/vector.tcc (_Guard): Move all the nested duplicated class...
	* include/bits/stl_vector.h (_Guard_alloc): ...here and rename.
	(_M_allocate_and_copy): Use latter.
	(_M_initialize_dispatch): Small code simplification.
	(_M_range_initialize): Likewise and set _M_finish first from the result
	of __uninitialize_fill_n_a that can throw.
This commit is contained in:
François Dumont
2024-05-16 06:59:50 +02:00
committed by François Dumont
parent b24b081113
commit d22eaeca76
2 changed files with 55 additions and 100 deletions

View File

@@ -1607,6 +1607,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
clear() _GLIBCXX_NOEXCEPT
{ _M_erase_at_end(this->_M_impl._M_start); }
private:
// RAII guard for allocated storage.
struct _Guard_alloc
{
pointer _M_storage; // Storage to deallocate
size_type _M_len;
_Base& _M_vect;
_GLIBCXX20_CONSTEXPR
_Guard_alloc(pointer __s, size_type __l, _Base& __vect)
: _M_storage(__s), _M_len(__l), _M_vect(__vect)
{ }
_GLIBCXX20_CONSTEXPR
~_Guard_alloc()
{
if (_M_storage)
_M_vect._M_deallocate(_M_storage, _M_len);
}
_GLIBCXX20_CONSTEXPR
pointer
_M_release()
{
pointer __res = _M_storage;
_M_storage = pointer();
return __res;
}
private:
_Guard_alloc(const _Guard_alloc&);
};
protected:
/**
* Memory expansion handler. Uses the member allocation function to
@@ -1618,18 +1651,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_allocate_and_copy(size_type __n,
_ForwardIterator __first, _ForwardIterator __last)
{
pointer __result = this->_M_allocate(__n);
__try
{
std::__uninitialized_copy_a(__first, __last, __result,
_M_get_Tp_allocator());
return __result;
}
__catch(...)
{
_M_deallocate(__result, __n);
__throw_exception_again;
}
_Guard_alloc __guard(this->_M_allocate(__n), __n, *this);
std::__uninitialized_copy_a
(__first, __last, __guard._M_storage, _M_get_Tp_allocator());
return __guard._M_release();
}
@@ -1642,13 +1667,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
// 438. Ambiguity in the "do the right thing" clause
template<typename _Integer>
void
_M_initialize_dispatch(_Integer __n, _Integer __value, __true_type)
_M_initialize_dispatch(_Integer __int_n, _Integer __value, __true_type)
{
this->_M_impl._M_start = _M_allocate(_S_check_init_len(
static_cast<size_type>(__n), _M_get_Tp_allocator()));
this->_M_impl._M_end_of_storage =
this->_M_impl._M_start + static_cast<size_type>(__n);
_M_fill_initialize(static_cast<size_type>(__n), __value);
const size_type __n = static_cast<size_type>(__int_n);
pointer __start =
_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
this->_M_impl._M_start = __start;
this->_M_impl._M_end_of_storage = __start + __n;
_M_fill_initialize(__n, __value);
}
// Called by the range constructor to implement [23.1.1]/9
@@ -1690,13 +1716,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::forward_iterator_tag)
{
const size_type __n = std::distance(__first, __last);
this->_M_impl._M_start
= this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
this->_M_impl._M_finish =
std::__uninitialized_copy_a(__first, __last,
this->_M_impl._M_start,
_M_get_Tp_allocator());
pointer __start =
this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
_Guard_alloc __guard(__start, __n, *this);
this->_M_impl._M_finish = std::__uninitialized_copy_a
(__first, __last, __start, _M_get_Tp_allocator());
this->_M_impl._M_start = __start;
(void) __guard._M_release();
this->_M_impl._M_end_of_storage = __start + __n;
}
// Called by the first initialize_dispatch above and by the

View File

@@ -467,32 +467,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __new_start(this->_M_allocate(__len));
pointer __new_finish(__new_start);
// RAII guard for allocated storage.
struct _Guard
{
pointer _M_storage; // Storage to deallocate
size_type _M_len;
_Tp_alloc_type& _M_alloc;
_GLIBCXX20_CONSTEXPR
_Guard(pointer __s, size_type __l, _Tp_alloc_type& __a)
: _M_storage(__s), _M_len(__l), _M_alloc(__a)
{ }
_GLIBCXX20_CONSTEXPR
~_Guard()
{
if (_M_storage)
__gnu_cxx::__alloc_traits<_Tp_alloc_type>::
deallocate(_M_alloc, _M_storage, _M_len);
}
private:
_Guard(const _Guard&);
};
{
_Guard __guard(__new_start, __len, _M_impl);
_Guard_alloc __guard(__new_start, __len, *this);
// The order of the three operations is dictated by the C++11
// case, where the moves could alter a new element belonging
@@ -596,32 +572,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer __new_start(this->_M_allocate(__len));
pointer __new_finish(__new_start);
// RAII guard for allocated storage.
struct _Guard
{
pointer _M_storage; // Storage to deallocate
size_type _M_len;
_Tp_alloc_type& _M_alloc;
_GLIBCXX20_CONSTEXPR
_Guard(pointer __s, size_type __l, _Tp_alloc_type& __a)
: _M_storage(__s), _M_len(__l), _M_alloc(__a)
{ }
_GLIBCXX20_CONSTEXPR
~_Guard()
{
if (_M_storage)
__gnu_cxx::__alloc_traits<_Tp_alloc_type>::
deallocate(_M_alloc, _M_storage, _M_len);
}
private:
_Guard(const _Guard&);
};
{
_Guard __guard(__new_start, __len, _M_impl);
_Guard_alloc __guard(__new_start, __len, *this);
// The order of the three operations is dictated by the C++11
// case, where the moves could alter a new element belonging
@@ -833,32 +785,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_check_len(__n, "vector::_M_default_append");
pointer __new_start(this->_M_allocate(__len));
// RAII guard for allocated storage.
struct _Guard
{
pointer _M_storage; // Storage to deallocate
size_type _M_len;
_Tp_alloc_type& _M_alloc;
_GLIBCXX20_CONSTEXPR
_Guard(pointer __s, size_type __l, _Tp_alloc_type& __a)
: _M_storage(__s), _M_len(__l), _M_alloc(__a)
{ }
_GLIBCXX20_CONSTEXPR
~_Guard()
{
if (_M_storage)
__gnu_cxx::__alloc_traits<_Tp_alloc_type>::
deallocate(_M_alloc, _M_storage, _M_len);
}
private:
_Guard(const _Guard&);
};
{
_Guard __guard(__new_start, __len, _M_impl);
_Guard_alloc __guard(__new_start, __len, *this);
std::__uninitialized_default_n_a(__new_start + __size, __n,
_M_get_Tp_allocator());