diff mbox

[v3] PR libstdc++/77619

Message ID CAFk2RUaw=L0aB8WPyOM1TbR3bCTXqGKEDUVJd=zYkzTMCN1Q9Q@mail.gmail.com
State New
Headers show

Commit Message

Ville Voutilainen Sept. 18, 2016, 6:07 p.m. UTC
Tested on Linux-x64.

2016-09-19  Ville Voutilainen  <ville.voutilainen@gmail.com>

    PR libstdc++/77619
    * include/bits/stl_construct.h: (_Construct_novalue): New.
    (_Destroy_n_aux, _Destroy_n): New.
    * include/bits/stl_uninitialized.h: (type_traits):
    New include in C++11 mode.
    (__uninitialized_default_novalue_1): New.
    (__uninitialized_default_novalue_n_1): Likewise.
    (__uninitialized_default_novalue): Likewise.
    (__uninitialized_default_novalue_n): Likewise.
    (__uninitialized_copy_n_pair): Likewise.
    (uninitialized_default_construct):
    Use __uninitialized_default_novalue.
    (uninitialized_default_construct_n):
    Use __uninitialized_default_novalue_n.
    (uninitialized_value_construct): Use __uninitialized_default.
    (uninitialized_value_construct_n): Use __uninitialized_default_n.
    (uninitialized_move): Use uninitialized_copy.
    (uninitialized_move_n): Use __uninitialized_copy_n_pair.
    (destroy_at): Use _Destroy.
    (destroy): Likewise.
    (destroy_n): Likewise.
    * testsuite/20_util/specialized_algorithms/
    memory_management_tools/1.cc: Add tests for exceptions,
    add tests for trivial cases for construct and move.

Comments

Jonathan Wakely Sept. 20, 2016, 2:07 p.m. UTC | #1
On 18/09/16 21:07 +0300, Ville Voutilainen wrote:
>diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h
>index 3d12628..c7ca1f8 100644
>--- a/libstdc++-v3/include/bits/stl_construct.h
>+++ b/libstdc++-v3/include/bits/stl_construct.h
>@@ -83,6 +83,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>       ::new(static_cast<void*>(__p)) _T1(__value);
>     }
> #endif

Blank line here please.

>+  template<typename _T1>
>+    inline void
>+    _Construct_novalue(_T1* __p)
>+    { ::new(static_cast<void*>(__p)) _T1; }
>
>   /**
>    * Destroy the object pointed to by a pointer type.


>diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
>index c5c81fb..b4213d5 100644
>--- a/libstdc++-v3/include/bits/stl_uninitialized.h
>+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
>@@ -640,6 +644,104 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> 				allocator<_Tp>&)
>     { return std::__uninitialized_default_n(__first, __n); }
>
>+  template<bool _TrivialValueType>
>+    struct __uninitialized_default_novalue_1
>+    {
>+      template<typename _ForwardIterator>
>+        static void
>+        __uninit_default_novalue(_ForwardIterator __first,
>+				 _ForwardIterator __last)
>+        {
          ...
>+	}

The left brace is indented with spaces and the right one with a tab,
might as well make them the same.

>+    };
>+
>+  template<>
>+    struct __uninitialized_default_novalue_1<true>
>+    {
>+      template<typename _ForwardIterator>
>+        static void
>+        __uninit_default_novalue(_ForwardIterator __first,
>+				 _ForwardIterator __last)
>+        {
>+	}

Ditto.

>+    };
>+
>+  template<bool _TrivialValueType>
>+    struct __uninitialized_default_novalue_n_1
>+    {
>+      template<typename _ForwardIterator, typename _Size>
>+        static _ForwardIterator
>+        __uninit_default_novalue_n(_ForwardIterator __first, _Size __n)
>+        {
>+	  _ForwardIterator __cur = __first;
>+	  __try
>+	    {
>+	      for (; __n > 0; --__n, ++__cur)
>+		std::_Construct_novalue(std::__addressof(*__cur));
>+	      return __cur;
>+	    }
>+	  __catch(...)
>+	    {
>+	      std::_Destroy(__first, __cur);
>+	      __throw_exception_again;
>+	    }
>+	}

Ditto.

>+    };
>+
>+  template<>
>+    struct __uninitialized_default_novalue_n_1<true>
>+    {
>+      template<typename _ForwardIterator, typename _Size>
>+        static _ForwardIterator
>+        __uninit_default_novalue_n(_ForwardIterator __first, _Size __n)
>+        {
>+	}

Ditto.

>+    };
>+
>+  // __uninitialized_default_novalue
>+  // Fills [first, last) with std::distance(first, last) default-initialized
>+  // value_types(s).
>+  template<typename _ForwardIterator>
>+    inline void
>+    __uninitialized_default_novalue(_ForwardIterator __first,
>+				    _ForwardIterator __last)
>+    {
>+      typedef typename iterator_traits<_ForwardIterator>::value_type
>+	_ValueType;
>+      // trivial types can have deleted assignment
>+      const bool __assignable = is_copy_assignable<_ValueType>::value;

Aha! A non-whitespace comment ... __assignable isn't used. If it's not
needed it can be removed.

>+      std::__uninitialized_default_novalue_1<
>+	is_trivially_default_constructible<_ValueType>::value>::
>+	__uninit_default_novalue(__first, __last);
>+    }
>+
>+  // __uninitialized_default_n
>+  // Fills [first, first + n) with n default-initialized value_type(s).
>+  template<typename _ForwardIterator, typename _Size>
>+    inline _ForwardIterator
>+    __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n)
>+    {
>+      typedef typename iterator_traits<_ForwardIterator>::value_type
>+	_ValueType;
>+      // trivial types can have deleted assignment
>+      const bool __assignable = is_copy_assignable<_ValueType>::value;

Ditto.

>+      return __uninitialized_default_novalue_n_1<
>+	is_trivially_default_constructible<_ValueType>::value>::
>+	__uninit_default_novalue_n(__first, __n);
>+    }
>
>   template<typename _InputIterator, typename _Size,
> 	   typename _ForwardIterator>
>@@ -669,6 +771,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> 			   random_access_iterator_tag)
>     { return std::uninitialized_copy(__first, __first + __n, __result); }
>
>+  template<typename _InputIterator, typename _Size,
>+	   typename _ForwardIterator>
>+    pair<_InputIterator, _ForwardIterator>
>+    __uninitialized_copy_n_pair(_InputIterator __first, _Size __n,
>+			   _ForwardIterator __result, input_iterator_tag)
>+    {
>+      _ForwardIterator __cur = __result;
>+      __try
>+	{
>+	  for (; __n > 0; --__n, ++__first, ++__cur)
>+	    std::_Construct(std::__addressof(*__cur), *__first);
>+	  return {__first, __cur};
>+	}
>+      __catch(...)
>+	{
>+	  std::_Destroy(__result, __cur);
>+	  __throw_exception_again;
>+	}
>+    }
>+
>+  template<typename _RandomAccessIterator, typename _Size,
>+	   typename _ForwardIterator>
>+    inline pair<_RandomAccessIterator, _ForwardIterator>
>+    __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n,
>+			   _ForwardIterator __result,
>+			   random_access_iterator_tag)
>+    {
>+      auto second = uninitialized_copy(__first, __first + __n, __result);
>+      auto first = std::next(__first, __n);
>+      return {first, second};

I was going to say these names need to be uglified, but they can't be
macros due to std::pair. Carry on.

>@@ -744,35 +877,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>     uninitialized_move_n(_InputIterator __first, _Size __count,
> 			 _ForwardIterator __result)
>   {
>-    for (; __count > 0; ++__result, (void) ++__first, --__count)
>-      ::new (static_cast<void*>(std::__addressof(*__result)))
>-	  typename
>-	  iterator_traits<_ForwardIterator>::value_type(std::move(*__first));
>-    return {__first, __result};
>+    auto res = std::__uninitialized_copy_n_pair
>+      (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
>+       __count, __result);
>+    return {res.first.base(), res.second};

However, res isn't a reserved name AFAIK, so should be __res.

OK for trunk with that change, and the whitespace changes if you would
be so kind. Thanks.
diff mbox

Patch

diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h
index 3d12628..c7ca1f8 100644
--- a/libstdc++-v3/include/bits/stl_construct.h
+++ b/libstdc++-v3/include/bits/stl_construct.h
@@ -83,6 +83,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       ::new(static_cast<void*>(__p)) _T1(__value);
     }
 #endif
+  template<typename _T1>
+    inline void
+    _Construct_novalue(_T1* __p)
+    { ::new(static_cast<void*>(__p)) _T1; }
 
   /**
    * Destroy the object pointed to by a pointer type.
@@ -127,6 +131,46 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__destroy(__first, __last);
     }
 
+  template<bool>
+    struct _Destroy_n_aux
+    {
+      template<typename _ForwardIterator, typename _Size>
+        static _ForwardIterator
+        __destroy_n(_ForwardIterator __first, _Size __count)
+	{
+	  for (; __count > 0; (void)++__first, --__count)
+	    std::_Destroy(std::__addressof(*__first));
+	  return __first;
+	}
+    };
+
+  template<>
+    struct _Destroy_n_aux<true>
+    {
+      template<typename _ForwardIterator, typename _Size>
+        static _ForwardIterator
+        __destroy_n(_ForwardIterator __first, _Size __count)
+      {
+	 std::advance(__first, __count);
+	 return __first;
+      }
+    };
+
+  /**
+   * Destroy a range of objects.  If the value_type of the object has
+   * a trivial destructor, the compiler should optimize all of this
+   * away, otherwise the objects' destructors must be invoked.
+   */
+  template<typename _ForwardIterator, typename _Size>
+    inline _ForwardIterator
+    _Destroy_n(_ForwardIterator __first, _Size __count)
+    {
+      typedef typename iterator_traits<_ForwardIterator>::value_type
+                       _Value_type;
+      return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>::
+	__destroy_n(__first, __count);
+    }
+
   /**
    * Destroy a range of objects using the supplied allocator.  For
    * nondefault allocators we do not optimize away invocation of 
diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
index c5c81fb..b4213d5 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -60,6 +60,10 @@ 
 #include <utility>
 #endif
 
+#if __cplusplus >= 201103L
+#include <type_traits>
+#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -640,6 +644,104 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				allocator<_Tp>&)
     { return std::__uninitialized_default_n(__first, __n); }
 
+  template<bool _TrivialValueType>
+    struct __uninitialized_default_novalue_1
+    {
+      template<typename _ForwardIterator>
+        static void
+        __uninit_default_novalue(_ForwardIterator __first,
+				 _ForwardIterator __last)
+        {
+	  _ForwardIterator __cur = __first;
+	  __try
+	    {
+	      for (; __cur != __last; ++__cur)
+		std::_Construct_novalue(std::__addressof(*__cur));
+	    }
+	  __catch(...)
+	    {
+	      std::_Destroy(__first, __cur);
+	      __throw_exception_again;
+	    }
+	}
+    };
+
+  template<>
+    struct __uninitialized_default_novalue_1<true>
+    {
+      template<typename _ForwardIterator>
+        static void
+        __uninit_default_novalue(_ForwardIterator __first,
+				 _ForwardIterator __last)
+        {
+	}
+    };
+
+  template<bool _TrivialValueType>
+    struct __uninitialized_default_novalue_n_1
+    {
+      template<typename _ForwardIterator, typename _Size>
+        static _ForwardIterator
+        __uninit_default_novalue_n(_ForwardIterator __first, _Size __n)
+        {
+	  _ForwardIterator __cur = __first;
+	  __try
+	    {
+	      for (; __n > 0; --__n, ++__cur)
+		std::_Construct_novalue(std::__addressof(*__cur));
+	      return __cur;
+	    }
+	  __catch(...)
+	    {
+	      std::_Destroy(__first, __cur);
+	      __throw_exception_again;
+	    }
+	}
+    };
+
+  template<>
+    struct __uninitialized_default_novalue_n_1<true>
+    {
+      template<typename _ForwardIterator, typename _Size>
+        static _ForwardIterator
+        __uninit_default_novalue_n(_ForwardIterator __first, _Size __n)
+        {
+	}
+    };
+
+  // __uninitialized_default_novalue
+  // Fills [first, last) with std::distance(first, last) default-initialized
+  // value_types(s).
+  template<typename _ForwardIterator>
+    inline void
+    __uninitialized_default_novalue(_ForwardIterator __first,
+				    _ForwardIterator __last)
+    {
+      typedef typename iterator_traits<_ForwardIterator>::value_type
+	_ValueType;
+      // trivial types can have deleted assignment
+      const bool __assignable = is_copy_assignable<_ValueType>::value;
+
+      std::__uninitialized_default_novalue_1<
+	is_trivially_default_constructible<_ValueType>::value>::
+	__uninit_default_novalue(__first, __last);
+    }
+
+  // __uninitialized_default_n
+  // Fills [first, first + n) with n default-initialized value_type(s).
+  template<typename _ForwardIterator, typename _Size>
+    inline _ForwardIterator
+    __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n)
+    {
+      typedef typename iterator_traits<_ForwardIterator>::value_type
+	_ValueType;
+      // trivial types can have deleted assignment
+      const bool __assignable = is_copy_assignable<_ValueType>::value;
+
+      return __uninitialized_default_novalue_n_1<
+	is_trivially_default_constructible<_ValueType>::value>::
+	__uninit_default_novalue_n(__first, __n);
+    }
 
   template<typename _InputIterator, typename _Size,
 	   typename _ForwardIterator>
@@ -669,6 +771,38 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			   random_access_iterator_tag)
     { return std::uninitialized_copy(__first, __first + __n, __result); }
 
+  template<typename _InputIterator, typename _Size,
+	   typename _ForwardIterator>
+    pair<_InputIterator, _ForwardIterator>
+    __uninitialized_copy_n_pair(_InputIterator __first, _Size __n,
+			   _ForwardIterator __result, input_iterator_tag)
+    {
+      _ForwardIterator __cur = __result;
+      __try
+	{
+	  for (; __n > 0; --__n, ++__first, ++__cur)
+	    std::_Construct(std::__addressof(*__cur), *__first);
+	  return {__first, __cur};
+	}
+      __catch(...)
+	{
+	  std::_Destroy(__result, __cur);
+	  __throw_exception_again;
+	}
+    }
+
+  template<typename _RandomAccessIterator, typename _Size,
+	   typename _ForwardIterator>
+    inline pair<_RandomAccessIterator, _ForwardIterator>
+    __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n,
+			   _ForwardIterator __result,
+			   random_access_iterator_tag)
+    {
+      auto second = uninitialized_copy(__first, __first + __n, __result);
+      auto first = std::next(__first, __n);
+      return {first, second};
+    }
+
   /**
    *  @brief Copies the range [first,first+n) into result.
    *  @param  __first  An input iterator.
@@ -684,6 +818,17 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			 _ForwardIterator __result)
     { return std::__uninitialized_copy_n(__first, __n, __result,
 					 std::__iterator_category(__first)); }
+
+  template<typename _InputIterator, typename _Size, typename _ForwardIterator>
+    inline pair<_InputIterator, _ForwardIterator>
+    __uninitialized_copy_n_pair(_InputIterator __first, _Size __n,
+			      _ForwardIterator __result)
+    {
+      return
+	std::__uninitialized_copy_n_pair(__first, __n, __result,
+					 std::__iterator_category(__first));
+    }
+
 #endif
 
 #if __cplusplus > 201402L
@@ -692,19 +837,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     uninitialized_default_construct(_ForwardIterator __first,
 				    _ForwardIterator __last)
   {
-    for (; __first != __last; ++__first)
-      ::new (static_cast<void*>(std::__addressof(*__first)))
-	  typename iterator_traits<_ForwardIterator>::value_type;
+    __uninitialized_default_novalue(__first, __last);
   }
 
   template <typename _ForwardIterator, typename _Size>
     inline _ForwardIterator
     uninitialized_default_construct_n(_ForwardIterator __first, _Size __count)
   {
-    for (; __count > 0; (void)++__first, --__count)
-      ::new (static_cast<void*>(std::__addressof(*__first)))
-	  typename iterator_traits<_ForwardIterator>::value_type;
-    return __first;
+    return __uninitialized_default_novalue_n(__first, __count);
   }
 
   template <typename _ForwardIterator>
@@ -712,19 +852,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     uninitialized_value_construct(_ForwardIterator __first,
 				  _ForwardIterator __last)
   {
-    for (; __first != __last; ++__first)
-      ::new (static_cast<void*>(std::__addressof(*__first)))
-	  typename iterator_traits<_ForwardIterator>::value_type();
+    return __uninitialized_default(__first, __last);
   }
 
   template <typename _ForwardIterator, typename _Size>
     inline _ForwardIterator
     uninitialized_value_construct_n(_ForwardIterator __first, _Size __count)
   {
-    for (; __count > 0; (void)++__first, --__count)
-      ::new (static_cast<void*>(std::__addressof(*__first)))
-	  typename iterator_traits<_ForwardIterator>::value_type();
-    return __first;
+    return __uninitialized_default_n(__first, __count);
   }
 
   template <typename _InputIterator, typename _ForwardIterator>
@@ -732,11 +867,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     uninitialized_move(_InputIterator __first, _InputIterator __last,
 		       _ForwardIterator __result)
   {
-    for (; __first != __last; (void)++__result, ++__first)
-      ::new (static_cast<void*>(std::__addressof(*__result)))
-	  typename
-	  iterator_traits<_ForwardIterator>::value_type(std::move(*__first));
-    return __result;
+    return std::uninitialized_copy
+      (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
+       _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result);
   }
 
   template <typename _InputIterator, typename _Size, typename _ForwardIterator>
@@ -744,35 +877,31 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     uninitialized_move_n(_InputIterator __first, _Size __count,
 			 _ForwardIterator __result)
   {
-    for (; __count > 0; ++__result, (void) ++__first, --__count)
-      ::new (static_cast<void*>(std::__addressof(*__result)))
-	  typename
-	  iterator_traits<_ForwardIterator>::value_type(std::move(*__first));
-    return {__first, __result};
+    auto res = std::__uninitialized_copy_n_pair
+      (_GLIBCXX_MAKE_MOVE_ITERATOR(__first),
+       __count, __result);
+    return {res.first.base(), res.second};
   }
 
   template <typename _Tp>
     inline void
     destroy_at(_Tp* __location)
   {
-    __location->~_Tp();
+    std::_Destroy(__location);
   }
 
   template <typename _ForwardIterator>
     inline void
     destroy(_ForwardIterator __first, _ForwardIterator __last)
   {
-    for (; __first != __last; ++__first)
-      std::destroy_at(std::__addressof(*__first));
+    std::_Destroy(__first, __last);
   }
 
   template <typename _ForwardIterator, typename _Size>
     inline _ForwardIterator
     destroy_n(_ForwardIterator __first, _Size __count)
   {
-    for (; __count > 0; (void)++__first, --__count)
-      std::destroy_at(std::__addressof(*__first));
-    return __first;
+    return std::_Destroy_n(__first, __count);
   }
 
 #endif
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc
index ec72b82..84a6857 100644
--- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/memory_management_tools/1.cc
@@ -21,14 +21,40 @@ 
 #include <testsuite_hooks.h>
 #include <string>
 #include <array>
+#include <sstream>
 
 int del_count = 0;
+int ctor_count = 0;
+int throw_after = 0;
 
 struct DelCount
 {
   ~DelCount() { ++del_count; }
 };
 
+struct ThrowAfterN
+{
+  ThrowAfterN()
+  {
+    if (++ctor_count == throw_after) {
+      std::ostringstream os;
+      os << "ThrowAfterN(), ctor_count: " << ctor_count
+	 << " throw_after: " << throw_after << std::endl;
+      throw std::runtime_error(os.str());
+    }
+  }
+  ThrowAfterN(ThrowAfterN&&)
+  {
+    if (++ctor_count == throw_after) {
+      std::ostringstream os;
+      os << "ThrowAfterN(), ctor_count: " << ctor_count
+	 << " throw_after: " << throw_after << std::endl;
+      throw std::runtime_error(os.str());
+    }
+  }
+  DelCount dc;
+};
+
 void test01()
 {
   char test_data[] = "123456";
@@ -118,6 +144,153 @@  void test09()
   free(target);
 }
 
+void test10()
+{
+  char* x = (char*)malloc(sizeof(char)*10);
+  for (int i = 0; i < 10; ++i) new (x+i) char;
+  std::destroy(x, x+10);
+  free(x);
+}
+
+void test11()
+{
+  char* x = (char*)malloc(sizeof(char)*10);
+  for (int i = 0; i < 10; ++i) new (x+i) char;
+  std::destroy_n(x, 10);
+  free(x);
+}
+
+void test12()
+{
+  throw_after = 5;
+  del_count = 0;
+  ctor_count = 0;
+  ThrowAfterN* target =
+    (ThrowAfterN*)malloc(sizeof(ThrowAfterN)*10);
+  try {
+    std::uninitialized_default_construct(target, target+10);
+  } catch (...) {
+  }
+  VERIFY(ctor_count == 5);
+  VERIFY(del_count == 5);
+  throw_after = 0;
+  del_count = 0;
+  ctor_count = 0;
+}
+
+void test13()
+{
+  throw_after = 5;
+  del_count = 0;
+  ctor_count = 0;
+  ThrowAfterN* target =
+    (ThrowAfterN*)malloc(sizeof(ThrowAfterN)*10);
+  try {
+    std::uninitialized_value_construct(target, target+10);
+  } catch (...) {
+  }
+  VERIFY(ctor_count == 5);
+  VERIFY(del_count == 5);
+  throw_after = 0;
+  del_count = 0;
+  ctor_count = 0;
+}
+
+void test14()
+{
+  throw_after = 5;
+  del_count = 0;
+  ctor_count = 0;
+  ThrowAfterN* target =
+    (ThrowAfterN*)malloc(sizeof(ThrowAfterN)*10);
+  try {
+    std::uninitialized_default_construct_n(target, 10);
+  } catch (...) {
+  }
+  VERIFY(ctor_count == 5);
+  VERIFY(del_count == 5);
+  throw_after = 0;
+  del_count = 0;
+  ctor_count = 0;
+}
+
+void test15()
+{
+  throw_after = 5;
+  del_count = 0;
+  ctor_count = 0;
+  ThrowAfterN* target =
+    (ThrowAfterN*)malloc(sizeof(ThrowAfterN)*10);
+  try {
+    std::uninitialized_value_construct_n(target, 10);
+  } catch (...) {
+  }
+  VERIFY(ctor_count == 5);
+  VERIFY(del_count == 5);
+  throw_after = 0;
+  del_count = 0;
+  ctor_count = 0;
+}
+
+void test16()
+{
+  std::vector<ThrowAfterN> source(10);
+  del_count = 0;
+  ctor_count = 0;
+  throw_after = 5;
+  throw_after = 5;
+  ThrowAfterN* target =
+    (ThrowAfterN*)malloc(sizeof(ThrowAfterN)*10);
+  try {
+    std::uninitialized_move(source.begin(), source.end(), target);
+  } catch (...) {
+  }
+  VERIFY(ctor_count == 5);
+  VERIFY(del_count == 5);
+  throw_after = 0;
+  del_count = 0;
+  ctor_count = 0;
+}
+
+void test17()
+{
+  std::vector<ThrowAfterN> source(10);
+  del_count = 0;
+  ctor_count = 0;
+  throw_after = 5;
+  ThrowAfterN* target =
+    (ThrowAfterN*)malloc(sizeof(ThrowAfterN)*10);
+  try {
+    std::uninitialized_move_n(source.begin(), 10, target);
+  } catch (...) {
+  }
+  VERIFY(ctor_count == 5);
+  VERIFY(del_count == 5);
+  throw_after = 0;
+  del_count = 0;
+  ctor_count = 0;
+}
+
+void test18()
+{
+  char test_source[] = "123456";
+  char test_target[] = "000000";
+  std::uninitialized_move(std::begin(test_source),
+			  std::end(test_source),
+			  test_target);
+  VERIFY(std::string(test_target) == "123456");
+}
+
+void test19()
+{
+  char test_source[] = "123456";
+  char test_target[] = "000000";
+  std::uninitialized_move_n(std::begin(test_source),
+			    6,
+			    test_target);
+  VERIFY(std::string(test_target) == "123456");
+}
+
 int main()
 {
   test01();
@@ -129,4 +302,14 @@  int main()
   test07();
   test08();
   test09();
+  test10();
+  test11();
+  test12();
+  test13();
+  test14();
+  test15();
+  test16();
+  test17();
+  test18();
+  test19();
 }