[libcxx] r283941 - Fix incorrect exception handling behavior in the uninitialized algorithms

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 11 14:13:44 PDT 2016


Author: ericwf
Date: Tue Oct 11 16:13:44 2016
New Revision: 283941

URL: http://llvm.org/viewvc/llvm-project?rev=283941&view=rev
Log:
Fix incorrect exception handling behavior in the uninitialized algorithms

Modified:
    libcxx/trunk/include/memory
    libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp
    libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp
    libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp
    libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
    libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp

Modified: libcxx/trunk/include/memory
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/memory?rev=283941&r1=283940&r2=283941&view=diff
==============================================================================
--- libcxx/trunk/include/memory (original)
+++ libcxx/trunk/include/memory Tue Oct 11 16:13:44 2016
@@ -3709,21 +3709,63 @@ uninitialized_fill_n(_ForwardIterator __
 
 #if _LIBCPP_STD_VER > 14
 
+template <class _Tp>
+inline _LIBCPP_INLINE_VISIBILITY
+void destroy_at(_Tp* __loc) {
+    _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at");
+    __loc->~_Tp();
+}
+
+template <class _ForwardIterator>
+inline _LIBCPP_INLINE_VISIBILITY
+void destroy(_ForwardIterator __first, _ForwardIterator __last) {
+    for (; __first != __last; ++__first)
+        _VSTD::destroy_at(_VSTD::addressof(*__first));
+}
+
+template <class _ForwardIterator, class _Size>
+inline _LIBCPP_INLINE_VISIBILITY
+_ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) {
+    for (; __n > 0; (void)++__first, --__n)
+        _VSTD::destroy_at(_VSTD::addressof(*__first));
+    return __first;
+}
+
 template <class _ForwardIterator>
 inline _LIBCPP_INLINE_VISIBILITY
 void uninitialized_default_construct(_ForwardIterator __first, _ForwardIterator __last) {
     using _Vt = typename iterator_traits<_ForwardIterator>::value_type;
-    for (; __first != __last; ++__first)
-        ::new((void*)_VSTD::addressof(*__first)) _Vt;
+    auto __idx = __first;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try {
+#endif
+    for (; __idx != __last; ++__idx)
+        ::new((void*)_VSTD::addressof(*__idx)) _Vt;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    } catch (...) {
+        _VSTD::destroy(__first, __idx);
+        throw;
+    }
+#endif
 }
 
 template <class _ForwardIterator, class _Size>
 inline _LIBCPP_INLINE_VISIBILITY
 _ForwardIterator uninitialized_default_construct_n(_ForwardIterator __first, _Size __n) {
     using _Vt = typename iterator_traits<_ForwardIterator>::value_type;
-    for (; __n > 0; (void)++__first, --__n)
-        ::new((void*)_VSTD::addressof(*__first)) _Vt;
-    return __first;
+    auto __idx = __first;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try {
+#endif
+    for (; __n > 0; (void)++__idx, --__n)
+        ::new((void*)_VSTD::addressof(*__idx)) _Vt;
+    return __idx;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    } catch (...) {
+        _VSTD::destroy(__first, __idx);
+        throw;
+    }
+#endif
 }
 
 
@@ -3731,60 +3773,79 @@ template <class _ForwardIterator>
 inline _LIBCPP_INLINE_VISIBILITY
 void uninitialized_value_construct(_ForwardIterator __first, _ForwardIterator __last) {
     using _Vt = typename iterator_traits<_ForwardIterator>::value_type;
-    for (; __first != __last; ++__first)
-        ::new((void*)_VSTD::addressof(*__first)) _Vt();
+    auto __idx = __first;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try {
+#endif
+    for (; __idx != __last; ++__idx)
+        ::new((void*)_VSTD::addressof(*__idx)) _Vt();
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    } catch (...) {
+        _VSTD::destroy(__first, __idx);
+        throw;
+    }
+#endif
 }
 
 template <class _ForwardIterator, class _Size>
 inline _LIBCPP_INLINE_VISIBILITY
 _ForwardIterator uninitialized_value_construct_n(_ForwardIterator __first, _Size __n) {
     using _Vt = typename iterator_traits<_ForwardIterator>::value_type;
-    for (; __n > 0; (void)++__first, --__n)
-        ::new((void*)_VSTD::addressof(*__first)) _Vt();
-    return __first;
+    auto __idx = __first;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try {
+#endif
+    for (; __n > 0; (void)++__idx, --__n)
+        ::new((void*)_VSTD::addressof(*__idx)) _Vt();
+    return __idx;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    } catch (...) {
+        _VSTD::destroy(__first, __idx);
+        throw;
+    }
+#endif
 }
 
 
 template <class _InputIt, class _ForwardIt>
 inline _LIBCPP_INLINE_VISIBILITY
-_ForwardIt uninitialized_move(_InputIt __first, _InputIt __last, _ForwardIt __res) {
+_ForwardIt uninitialized_move(_InputIt __first, _InputIt __last, _ForwardIt __first_res) {
     using _Vt = typename iterator_traits<_ForwardIt>::value_type;
-    for (; __first != __last; (void)++__res, ++__first)
-        ::new((void*)_VSTD::addressof(*__res)) _Vt(std::move(*__first));
-    return __res;
+    auto __idx = __first_res;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try {
+#endif
+    for (; __first != __last; (void)++__idx, ++__first)
+        ::new((void*)_VSTD::addressof(*__idx)) _Vt(std::move(*__first));
+    return __idx;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    } catch (...) {
+        _VSTD::destroy(__first_res, __idx);
+        throw;
+    }
+#endif
 }
 
 template <class _InputIt, class _Size, class _ForwardIt>
 inline _LIBCPP_INLINE_VISIBILITY
 pair<_InputIt, _ForwardIt>
-uninitialized_move_n(_InputIt __first, _Size __n, _ForwardIt __res) {
+uninitialized_move_n(_InputIt __first, _Size __n, _ForwardIt __first_res) {
     using _Vt = typename iterator_traits<_ForwardIt>::value_type;
-    for (; __n > 0; ++__res, (void)++__first, --__n)
-        ::new((void*)_VSTD::addressof(*__res)) _Vt(std::move(*__first));
-    return {__first, __res};
-}
-
-template <class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
-void destroy_at(_Tp* __loc) {
-    _LIBCPP_ASSERT(__loc, "null pointer given to destroy_at");
-    __loc->~_Tp();
-}
-
-template <class _ForwardIterator>
-inline _LIBCPP_INLINE_VISIBILITY
-void destroy(_ForwardIterator __first, _ForwardIterator __last) {
-    for (; __first != __last; ++__first)
-        _VSTD::destroy_at(_VSTD::addressof(*__first));
+    auto __idx = __first_res;
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    try {
+#endif
+    for (; __n > 0; ++__idx, (void)++__first, --__n)
+        ::new((void*)_VSTD::addressof(*__idx)) _Vt(std::move(*__first));
+    return {__first, __idx};
+#ifndef _LIBCPP_NO_EXCEPTIONS
+    } catch (...) {
+        _VSTD::destroy(__first_res, __idx);
+        throw;
+    }
+#endif
 }
 
-template <class _ForwardIterator, class _Size>
-inline _LIBCPP_INLINE_VISIBILITY
-_ForwardIterator destroy_n(_ForwardIterator __first, _Size __n) {
-    for (; __n > 0; (void)++__first, --__n)
-        _VSTD::destroy_at(_VSTD::addressof(*__first));
-    return __first;
-}
 
 #endif // _LIBCPP_STD_VER > 14
 

Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct.pass.cpp Tue Oct 11 16:13:44 2016
@@ -47,7 +47,7 @@ struct ThrowsCounted {
       ++count;
   }
   ThrowsCounted(ThrowsCounted const&) { assert(false); }
-  ~ThrowsCounted() { --count; }
+  ~ThrowsCounted() { assert(count > 0); --count; }
   friend void operator&(ThrowsCounted) = delete;
 };
 int ThrowsCounted::count = 0;
@@ -67,10 +67,8 @@ void test_ctor_throws()
         std::uninitialized_default_construct(It(p), It(p+N));
         assert(false);
     } catch (...) {}
-    assert(ThrowsCounted::count == 3);
-    assert(ThrowsCounted::constructed == 4); // forth construction throws
-    std::destroy(p, p+3);
     assert(ThrowsCounted::count == 0);
+    assert(ThrowsCounted::constructed == 4); // forth construction throws
 #endif
 }
 

Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.default/uninitialized_default_construct_n.pass.cpp Tue Oct 11 16:13:44 2016
@@ -27,7 +27,7 @@ struct Counted {
   static void reset() { count = constructed =  0; }
   explicit Counted() { ++count; ++constructed; }
   Counted(Counted const&) { assert(false); }
-  ~Counted() { --count; }
+  ~Counted() { assert(count > 0); --count; }
   friend void operator&(Counted) = delete;
 };
 int Counted::count = 0;
@@ -47,7 +47,7 @@ struct ThrowsCounted {
       ++count;
   }
   ThrowsCounted(ThrowsCounted const&) { assert(false); }
-  ~ThrowsCounted() { --count; }
+  ~ThrowsCounted() { assert(count > 0); --count; }
   friend void operator&(ThrowsCounted) = delete;
 };
 int ThrowsCounted::count = 0;
@@ -66,10 +66,8 @@ void test_ctor_throws()
         std::uninitialized_default_construct_n(It(p), N);
         assert(false);
     } catch (...) {}
-    assert(ThrowsCounted::count == 3);
-    assert(ThrowsCounted::constructed == 4); // forth construction throws
-    std::destroy(p, p+3);
     assert(ThrowsCounted::count == 0);
+    assert(ThrowsCounted::constructed == 4); // forth construction throws
 #endif
 }
 

Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.construct.value/uninitialized_value_construct.pass.cpp Tue Oct 11 16:13:44 2016
@@ -27,7 +27,7 @@ struct Counted {
   static void reset() { count = constructed =  0; }
   explicit Counted() { ++count; ++constructed; }
   Counted(Counted const&) { assert(false); }
-  ~Counted() { --count; }
+  ~Counted() { assert(count > 0); --count; }
   friend void operator&(Counted) = delete;
 };
 int Counted::count = 0;
@@ -47,7 +47,7 @@ struct ThrowsCounted {
       ++count;
   }
   ThrowsCounted(ThrowsCounted const&) { assert(false); }
-  ~ThrowsCounted() { --count; }
+  ~ThrowsCounted() { assert(count > 0); --count; }
   friend void operator&(ThrowsCounted) = delete;
 };
 int ThrowsCounted::count = 0;
@@ -66,10 +66,8 @@ void test_ctor_throws()
         std::uninitialized_value_construct(It(p), It(p+N));
         assert(false);
     } catch (...) {}
-    assert(ThrowsCounted::count == 3);
-    assert(ThrowsCounted::constructed == 4); // forth construction throws
-    std::destroy(p, p+3);
     assert(ThrowsCounted::count == 0);
+    assert(ThrowsCounted::constructed == 4); // forth construction throws
 #endif
 }
 

Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move.pass.cpp Tue Oct 11 16:13:44 2016
@@ -27,7 +27,7 @@ struct Counted {
   static void reset() { count = constructed =  0; }
   explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; }
   Counted(Counted const&) { assert(false); }
-  ~Counted() { --count; }
+  ~Counted() { assert(count > 0); --count; }
   friend void operator&(Counted) = delete;
   int value;
 };
@@ -48,7 +48,7 @@ struct ThrowsCounted {
       x = 0;
   }
   ThrowsCounted(ThrowsCounted const&) { assert(false); }
-  ~ThrowsCounted() { --count; }
+  ~ThrowsCounted() { assert(count > 0); --count; }
   friend void operator&(ThrowsCounted) = delete;
 };
 int ThrowsCounted::count = 0;
@@ -68,15 +68,13 @@ void test_ctor_throws()
         std::uninitialized_move(values, values + N, It(p));
         assert(false);
     } catch (...) {}
-    assert(ThrowsCounted::count == 3);
+    assert(ThrowsCounted::count == 0);
     assert(ThrowsCounted::constructed == 4); // forth construction throws
     assert(values[0] == 0);
     assert(values[1] == 0);
     assert(values[2] == 0);
     assert(values[3] == 4);
     assert(values[4] == 5);
-    std::destroy(p, p+3);
-    assert(ThrowsCounted::count == 0);
 #endif
 }
 

Modified: libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp?rev=283941&r1=283940&r2=283941&view=diff
==============================================================================
--- libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp (original)
+++ libcxx/trunk/test/std/utilities/memory/specialized.algorithms/uninitialized.move/uninitialized_move_n.pass.cpp Tue Oct 11 16:13:44 2016
@@ -27,7 +27,7 @@ struct Counted {
   static void reset() { count = constructed =  0; }
   explicit Counted(int&& x) : value(x) { x = 0; ++count; ++constructed; }
   Counted(Counted const&) { assert(false); }
-  ~Counted() { --count; }
+  ~Counted() { assert(count > 0); --count; }
   friend void operator&(Counted) = delete;
   int value;
 };
@@ -48,7 +48,7 @@ struct ThrowsCounted {
       x = 0;
   }
   ThrowsCounted(ThrowsCounted const&) { assert(false); }
-  ~ThrowsCounted() { --count; }
+  ~ThrowsCounted() { assert(count > 0); --count; }
   friend void operator&(ThrowsCounted) = delete;
 };
 int ThrowsCounted::count = 0;
@@ -68,15 +68,13 @@ void test_ctor_throws()
         std::uninitialized_move_n(values, N, It(p));
         assert(false);
     } catch (...) {}
-    assert(ThrowsCounted::count == 3);
+    assert(ThrowsCounted::count == 0);
     assert(ThrowsCounted::constructed == 4); // forth construction throws
     assert(values[0] == 0);
     assert(values[1] == 0);
     assert(values[2] == 0);
     assert(values[3] == 4);
     assert(values[4] == 5);
-    std::destroy(p, p+3);
-    assert(ThrowsCounted::count == 0);
 #endif
 }
 




More information about the cfe-commits mailing list