https://gcc.gnu.org/g:ae1c59c8de43a2cae494ce2212f44be08a629216

commit r15-9735-gae1c59c8de43a2cae494ce2212f44be08a629216
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed May 21 15:29:02 2025 +0100

    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 <ppa...@redhat.com>
    (cherry picked from commit 04f2be72b1deecd6c6d454e000cfc0cb16db957c)

Diff:
---
 libstdc++-v3/include/bits/stl_vector.h             |  3 ++-
 .../23_containers/vector/cons/from_range.cc        | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/stl_vector.h 
b/libstdc++-v3/include/bits/stl_vector.h
index aff9d5d9ca5b..4861edb21465 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 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();
 }

Reply via email to