Re: [v3 PATCH] PR libstdc++/77619

2016-09-20 Thread Jonathan Wakely

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(__p)) _T1(__value);
}
#endif


Blank line here please.


+  template
+inline void
+_Construct_novalue(_T1* __p)
+{ ::new(static_cast(__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
+struct __uninitialized_default_novalue_1
+{
+  template
+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
+{
+  template
+static void
+__uninit_default_novalue(_ForwardIterator __first,
+_ForwardIterator __last)
+{
+   }


Ditto.


+};
+
+  template
+struct __uninitialized_default_novalue_n_1
+{
+  template
+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
+{
+  template
+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
+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
+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
@@ -669,6 +771,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   random_access_iterator_tag)
{ return std::uninitialized_copy(__first, __first + __n, __result); }

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

[v3 PATCH] PR libstdc++/77619

2016-09-18 Thread Ville Voutilainen
Tested on Linux-x64.

2016-09-19  Ville Voutilainen  

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.
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(__p)) _T1(__value);
 }
 #endif
+  template
+inline void
+_Construct_novalue(_T1* __p)
+{ ::new(static_cast(__p)) _T1; }
 
   /**
* Destroy the object pointed to by a pointer type.
@@ -127,6 +131,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__destroy(__first, __last);
 }
 
+  template
+struct _Destroy_n_aux
+{
+  template
+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
+{
+  template
+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
+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 
 #endif
 
+#if __cplusplus >= 201103L
+#include 
+#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
+struct __uninitialized_default_novalue_1
+{
+  template
+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
+{
+  template
+static void
+__uninit_default_novalue(_ForwardIterator __first,
+_ForwardIterator __last)
+{
+   }
+};
+
+  template
+struct __uninitialized_default_novalue_n_1
+{
+  template
+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_