aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2023-06-20 13:39:29 +0100
committerJonathan Wakely <jwakely@redhat.com>2023-07-05 07:39:04 +0100
commit4870a18ac2d5e0bd8515ea473006071e65622e52 (patch)
tree90ece059749794a8be93b43deaa9457f161ebe96
parent49f2b325ec7a49e41fc107239542eae0eb6d364e (diff)
downloadgcc-4870a18ac2d5e0bd8515ea473006071e65622e52.zip
gcc-4870a18ac2d5e0bd8515ea473006071e65622e52.tar.gz
gcc-4870a18ac2d5e0bd8515ea473006071e65622e52.tar.bz2
libstdc++: Use RAII in std::vector::_M_default_append
Similar to r14-2052-gdd2eb972a5b063, replace the try-block with RAII types for deallocating storage and destroying elements. libstdc++-v3/ChangeLog: * include/bits/vector.tcc (_M_default_append): Replace try-block with RAII types.
-rw-r--r--libstdc++-v3/include/bits/vector.tcc91
1 files changed, 59 insertions, 32 deletions
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index cda52fb..f592c72 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -704,47 +704,74 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
const size_type __len =
_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);
+
+ std::__uninitialized_default_n_a(__new_start + __size, __n,
+ _M_get_Tp_allocator());
+
if _GLIBCXX17_CONSTEXPR (_S_use_relocate())
{
- __try
- {
- std::__uninitialized_default_n_a(__new_start + __size,
- __n, _M_get_Tp_allocator());
- }
- __catch(...)
- {
- _M_deallocate(__new_start, __len);
- __throw_exception_again;
- }
_S_relocate(__old_start, __old_finish,
__new_start, _M_get_Tp_allocator());
}
else
{
- pointer __destroy_from = pointer();
- __try
- {
- std::__uninitialized_default_n_a(__new_start + __size,
- __n, _M_get_Tp_allocator());
- __destroy_from = __new_start + __size;
- std::__uninitialized_move_if_noexcept_a(
- __old_start, __old_finish,
- __new_start, _M_get_Tp_allocator());
- }
- __catch(...)
- {
- if (__destroy_from)
- std::_Destroy(__destroy_from, __destroy_from + __n,
- _M_get_Tp_allocator());
- _M_deallocate(__new_start, __len);
- __throw_exception_again;
- }
- std::_Destroy(__old_start, __old_finish,
- _M_get_Tp_allocator());
+ // RAII type to destroy initialized elements.
+ struct _Guard_elts
+ {
+ pointer _M_first, _M_last; // Elements to destroy
+ _Tp_alloc_type& _M_alloc;
+
+ _GLIBCXX20_CONSTEXPR
+ _Guard_elts(pointer __first, size_type __n,
+ _Tp_alloc_type& __a)
+ : _M_first(__first), _M_last(__first + __n), _M_alloc(__a)
+ { }
+
+ _GLIBCXX20_CONSTEXPR
+ ~_Guard_elts()
+ { std::_Destroy(_M_first, _M_last, _M_alloc); }
+
+ private:
+ _Guard_elts(const _Guard_elts&);
+ };
+ _Guard_elts __guard_elts(__new_start + __size, __n, _M_impl);
+
+ std::__uninitialized_move_if_noexcept_a(
+ __old_start, __old_finish, __new_start,
+ _M_get_Tp_allocator());
+
+ __guard_elts._M_first = __old_start;
+ __guard_elts._M_last = __old_finish;
}
_GLIBCXX_ASAN_ANNOTATE_REINIT;
- _M_deallocate(__old_start,
- this->_M_impl._M_end_of_storage - __old_start);
+ __guard._M_storage = __old_start;
+ __guard._M_len = this->_M_impl._M_end_of_storage - __old_start;
+
this->_M_impl._M_start = __new_start;
this->_M_impl._M_finish = __new_start + __size + __n;
this->_M_impl._M_end_of_storage = __new_start + __len;