diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2025-05-21 15:29:02 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-05-27 12:15:41 +0100 |
commit | ae1c59c8de43a2cae494ce2212f44be08a629216 (patch) | |
tree | 2c120f1a5492868698aa7b2d6bd15c4909e8cdec | |
parent | a0e365b7361f685655cd45edd424804423bb6931 (diff) | |
download | gcc-ae1c59c8de43a2cae494ce2212f44be08a629216.zip gcc-ae1c59c8de43a2cae494ce2212f44be08a629216.tar.gz gcc-ae1c59c8de43a2cae494ce2212f44be08a629216.tar.bz2 |
libstdc++: Fix vector(from_range_t, R&&) for exceptions [PR120367]
Because this constructor delegates to vector(a) the object has been
fully constructed and the destructor will run if an exception happens.
That means we need to set _M_finish == _M_start so that the destructor
doesn't try to destroy any elements.
libstdc++-v3/ChangeLog:
PR libstdc++/120367
* include/bits/stl_vector.h (_M_range_initialize): Initialize
_M_impl._M_finish.
* testsuite/23_containers/vector/cons/from_range.cc: Check with
a type that throws on construction.
exceptions during construction.
Reviewed-by: Patrick Palka <ppalka@redhat.com>
(cherry picked from commit 04f2be72b1deecd6c6d454e000cfc0cb16db957c)
-rw-r--r-- | libstdc++-v3/include/bits/stl_vector.h | 3 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc | 22 |
2 files changed, 24 insertions, 1 deletions
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index aff9d5d..4861edb 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -1981,8 +1981,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_range_initialize_n(_Iterator __first, _Sentinel __last, size_type __n) { - pointer __start = this->_M_impl._M_start = + pointer __start = this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator())); + this->_M_impl._M_start = this->_M_impl._M_finish = __start; this->_M_impl._M_end_of_storage = __start + __n; this->_M_impl._M_finish = std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last, diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc index 7a62645..3784b9c 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc @@ -106,8 +106,30 @@ test_constexpr() return true; } +void +test_pr120367() +{ +#ifdef __cpp_exceptions + struct X + { + X(int) { throw 1; } // Cannot successfully construct an X. + ~X() { VERIFY(false); } // So should never need to destroy one. + }; + + try + { + int i[1]{}; + std::vector<X> v(std::from_range, i); + } + catch (int) + { + } +#endif +} + int main() { test_ranges(); static_assert( test_constexpr() ); + test_pr120367(); } |