On Wed, 21 May 2025, Jonathan Wakely 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.
LGTM (and TIL!) > > 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 = > 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 > >