Jelajahi Sumber

The exception recovery mechanism for the uninitialized_* algorithms did not work for iterators into discontiguous memory.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@147343 91177308-0d34-0410-b5e6-96231b3b80d8
Howard Hinnant 13 tahun lalu
induk
melakukan
8292d74270
2 mengubah file dengan 66 tambahan dan 20 penghapusan
  1. 2 0
      include/algorithm
  2. 64 20
      include/memory

+ 2 - 0
include/algorithm

@@ -4751,6 +4751,8 @@ __nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, _Rando
     while (true)
     {
     __restart:
+        if (__nth == __last)
+            return;
         difference_type __len = __last - __first;
         switch (__len)
         {

+ 64 - 20
include/memory

@@ -3215,12 +3215,23 @@ template <class _InputIterator, class _ForwardIterator>
 _ForwardIterator
 uninitialized_copy(_InputIterator __f, _InputIterator __l, _ForwardIterator __r)
 {
-    __destruct_n __d(0);
     typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
-    unique_ptr<value_type, __destruct_n&> __h(&*__r, __d);
-    for (; __f != __l; ++__f, ++__r, __d.__incr((value_type*)0))
-        ::new(&*__r) value_type(*__f);
-    __h.release();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    _ForwardIterator __s = __r;
+    try
+    {
+#endif
+        for (; __f != __l; ++__f, ++__r)
+            ::new(&*__r) value_type(*__f);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        for (; __s != __r; ++__s)
+            __s->~value_type();
+        throw;
+    }
+#endif
     return __r;
 }
 
@@ -3228,12 +3239,23 @@ template <class _InputIterator, class _Size, class _ForwardIterator>
 _ForwardIterator
 uninitialized_copy_n(_InputIterator __f, _Size __n, _ForwardIterator __r)
 {
-    __destruct_n __d(0);
     typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
-    unique_ptr<value_type, __destruct_n&> __h(&*__r, __d);
-    for (; __n > 0; ++__f, ++__r, __d.__incr((value_type*)0), --__n)
-        ::new(&*__r) value_type(*__f);
-    __h.release();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    _ForwardIterator __s = __r;
+    try
+    {
+#endif
+        for (; __n > 0; ++__f, ++__r, --__n)
+            ::new(&*__r) value_type(*__f);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        for (; __s != __r; ++__s)
+            __s->~value_type();
+        throw;
+    }
+#endif
     return __r;
 }
 
@@ -3241,24 +3263,46 @@ template <class _ForwardIterator, class _Tp>
 void
 uninitialized_fill(_ForwardIterator __f, _ForwardIterator __l, const _Tp& __x)
 {
-    __destruct_n __d(0);
     typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
-    unique_ptr<value_type, __destruct_n&> __h(&*__f, __d);
-    for (; __f != __l; ++__f, __d.__incr((value_type*)0))
-        ::new(&*__f) value_type(__x);
-    __h.release();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    _ForwardIterator __s = __f;
+    try
+    {
+#endif
+        for (; __f != __l; ++__f)
+            ::new(&*__f) value_type(__x);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        for (; __s != __f; ++__s)
+            __s->~value_type();
+        throw;
+    }
+#endif
 }
 
 template <class _ForwardIterator, class _Size, class _Tp>
 _ForwardIterator
 uninitialized_fill_n(_ForwardIterator __f, _Size __n, const _Tp& __x)
 {
-    __destruct_n __d(0);
     typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
-    unique_ptr<value_type, __destruct_n&> __h(&*__f, __d);
-    for (; __n > 0; ++__f, --__n, __d.__incr((value_type*)0))
-        ::new(&*__f) value_type(__x);
-    __h.release();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    _ForwardIterator __s = __f;
+    try
+    {
+#endif
+        for (; __n > 0; ++__f, --__n)
+            ::new(&*__f) value_type(__x);
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    }
+    catch (...)
+    {
+        for (; __s != __f; ++__s)
+            __s->~value_type();
+        throw;
+    }
+#endif
     return __f;
 }