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 =

>             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
>
>

Reply via email to