On Thu, 22 May 2025, 07:21 Tomasz Kaminski, <tkami...@redhat.com> wrote:
> > > On Wed, May 21, 2025 at 5:41 PM Jonathan Wakely <jwak...@redhat.com> > wrote: > >> 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. >> --- >> >> Tested x86_64-linux. >> >> libstdc++-v3/include/bits/stl_vector.h | 1 + >> .../23_containers/vector/cons/from_range.cc | 22 +++++++++++++++++++ >> 2 files changed, 23 insertions(+) >> >> diff --git a/libstdc++-v3/include/bits/stl_vector.h >> b/libstdc++-v3/include/bits/stl_vector.h >> index 57680b7bbcf3..43b913da778d 100644 >> --- a/libstdc++-v3/include/bits/stl_vector.h >> +++ b/libstdc++-v3/include/bits/stl_vector.h >> @@ -1971,6 +1971,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER >> { >> pointer __start = this->_M_impl._M_start = >> > Not required change, but I was a bit confused where _M_start is set. > Maybe assign all pointers here? > pointer __start = this->_M_impl._M_start = > this->_M_impl._M_finish = > That's how I wrote it at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120367#c4 but it seemed a bit crowded so I did it on a separate line for the real patch. this->_M_allocate(_S_check_init_len(__n, >> _M_get_Tp_allocator())); >> + 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 7a62645283d2..3784b9cd66ad 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(); >> } >> -- >> 2.49.0 >> >>