diff mbox

LWG DR 1339: uninitialized_fill_n should return the end of its range

Message ID 20140925152745.GG2669@redhat.com
State New
Headers show

Commit Message

Jonathan Wakely Sept. 25, 2014, 3:27 p.m. UTC
http://cplusplus.github.io/LWG/lwg-defects.html#1339

Also make the same change to our __uninitialized_xxx_n_a extensions
and change std::vector to make use of the returned iterator instead of
recalculating it.

Tested x86_64-linux, committed to trunk.
diff mbox

Patch

commit 81456b32a7991351d40ca45c276892fdab5d91ab
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Sep 23 00:13:14 2014 +0100

    	DR 1339
    	* doc/xml/manual/status_cxx2011.xml: Update.
    	* include/bits/stl_uninitialized.h (uninitialized_fill_n): Return
    	an iterator.
    	(__uninitialized_fill_n_a, __uninitialized_default_n_a): Likewise.
    	* include/bits/stl_vector.h (vector::_M_fill_initialize,
    	vector::_M_default_initialize): Use returned iterator.
    	* include/bits/vector.tcc (vector::_M_fill_assign,
    	vector::_M_fill_insert, vector::_M_default_append): Likewise.
    	* testsuite/20_util/specialized_algorithms/uninitialized_fill_n/
    	16505.cc: Adjust return type.
    	* testsuite/20_util/specialized_algorithms/uninitialized_fill_n/
    	dr1339.cc: New.

diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
index 4433c89..36630ce 100644
--- a/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
+++ b/libstdc++-v3/doc/xml/manual/status_cxx2011.xml
@@ -600,11 +600,10 @@  particular release.
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#B0B0B0" ?>
       <entry>20.6.12.3</entry>
       <entry><code>uninitialized_fill</code></entry>
-      <entry>Partial</entry>
-      <entry>Returns <code>void</code>..</entry>
+      <entry>Y</entry>
+      <entry/>
     </row>
     <row>
       <?dbhtml bgcolor="#B0B0B0" ?>
diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h
index cd2a482..c864fa14 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -190,7 +190,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __uninitialized_fill_n
     {
       template<typename _ForwardIterator, typename _Size, typename _Tp>
-        static void
+        static _ForwardIterator
         __uninit_fill_n(_ForwardIterator __first, _Size __n,
 			const _Tp& __x)
         {
@@ -199,6 +199,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    {
 	      for (; __n > 0; --__n, ++__cur)
 		std::_Construct(std::__addressof(*__cur), __x);
+	      return __cur;
 	    }
 	  __catch(...)
 	    {
@@ -212,12 +213,14 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __uninitialized_fill_n<true>
     {
       template<typename _ForwardIterator, typename _Size, typename _Tp>
-        static void
+        static _ForwardIterator
         __uninit_fill_n(_ForwardIterator __first, _Size __n,
 			const _Tp& __x)
-        { std::fill_n(__first, __n, __x); }
+        { return std::fill_n(__first, __n, __x); }
     };
 
+   // _GLIBCXX_RESOLVE_LIB_DEFECTS
+   // DR 1339. uninitialized_fill_n should return the end of its range
   /**
    *  @brief Copies the value x into the range [first,first+n).
    *  @param  __first  An input iterator.
@@ -228,7 +231,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  Like fill_n(), but does not require an initialized output range.
   */
   template<typename _ForwardIterator, typename _Size, typename _Tp>
-    inline void
+    inline _ForwardIterator
     uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x)
     {
       typedef typename iterator_traits<_ForwardIterator>::value_type
@@ -239,8 +242,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // trivial types can have deleted assignment
       const bool __assignable = is_copy_assignable<_ValueType>::value;
 #endif
-
-      std::__uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>::
+      return __uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>::
 	__uninit_fill_n(__first, __n, __x);
     }
 
@@ -328,7 +330,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _ForwardIterator, typename _Size, typename _Tp,
 	   typename _Allocator>
-    void
+    _ForwardIterator
     __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, 
 			     const _Tp& __x, _Allocator& __alloc)
     {
@@ -338,6 +340,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
 	  for (; __n > 0; --__n, ++__cur)
 	    __traits::construct(__alloc, std::__addressof(*__cur), __x);
+	  return __cur;
 	}
       __catch(...)
 	{
@@ -348,10 +351,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _ForwardIterator, typename _Size, typename _Tp,
 	   typename _Tp2>
-    inline void
+    inline _ForwardIterator
     __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, 
 			     const _Tp& __x, allocator<_Tp2>&)
-    { std::uninitialized_fill_n(__first, __n, __x); }
+    { return std::uninitialized_fill_n(__first, __n, __x); }
 
 
   // Extensions: __uninitialized_copy_move, __uninitialized_move_copy,
@@ -505,7 +508,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __uninitialized_default_n_1
     {
       template<typename _ForwardIterator, typename _Size>
-        static void
+        static _ForwardIterator
         __uninit_default_n(_ForwardIterator __first, _Size __n)
         {
 	  _ForwardIterator __cur = __first;
@@ -513,6 +516,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	    {
 	      for (; __n > 0; --__n, ++__cur)
 		std::_Construct(std::__addressof(*__cur));
+	      return __cur;
 	    }
 	  __catch(...)
 	    {
@@ -526,13 +530,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __uninitialized_default_n_1<true>
     {
       template<typename _ForwardIterator, typename _Size>
-        static void
+        static _ForwardIterator
         __uninit_default_n(_ForwardIterator __first, _Size __n)
         {
 	  typedef typename iterator_traits<_ForwardIterator>::value_type
 	    _ValueType;
 
-	  std::fill_n(__first, __n, _ValueType());
+	  return std::fill_n(__first, __n, _ValueType());
 	}
     };
 
@@ -557,7 +561,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // __uninitialized_default_n
   // Fills [first, first + n) with n default constructed value_type(s).
   template<typename _ForwardIterator, typename _Size>
-    inline void
+    inline _ForwardIterator
     __uninitialized_default_n(_ForwardIterator __first, _Size __n)
     {
       typedef typename iterator_traits<_ForwardIterator>::value_type
@@ -565,7 +569,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // trivial types can have deleted assignment
       const bool __assignable = is_copy_assignable<_ValueType>::value;
 
-      std::__uninitialized_default_n_1<__is_trivial(_ValueType)
+      return __uninitialized_default_n_1<__is_trivial(_ValueType)
 				       && __assignable>::
 	__uninit_default_n(__first, __n);
     }
@@ -606,7 +610,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // Fills [first, first + n) with n default constructed value_types(s),
   // constructed with the allocator alloc.
   template<typename _ForwardIterator, typename _Size, typename _Allocator>
-    void
+    _ForwardIterator
     __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, 
 				_Allocator& __alloc)
     {
@@ -616,6 +620,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  typedef __gnu_cxx::__alloc_traits<_Allocator> __traits;
 	  for (; __n > 0; --__n, ++__cur)
 	    __traits::construct(__alloc, std::__addressof(*__cur));
+	  return __cur;
 	}
       __catch(...)
 	{
@@ -625,10 +630,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
   template<typename _ForwardIterator, typename _Size, typename _Tp>
-    inline void
+    inline _ForwardIterator
     __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, 
 				allocator<_Tp>&)
-    { std::__uninitialized_default_n(__first, __n); }
+    { return std::__uninitialized_default_n(__first, __n); }
 
 
   template<typename _InputIterator, typename _Size,
diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h
index 0a56c65..dd2d433 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1297,9 +1297,9 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       _M_fill_initialize(size_type __n, const value_type& __value)
       {
-	std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value, 
-				      _M_get_Tp_allocator());
-	this->_M_impl._M_finish = this->_M_impl._M_end_of_storage;
+	this->_M_impl._M_finish =
+	  std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value,
+					_M_get_Tp_allocator());
       }
 
 #if __cplusplus >= 201103L
@@ -1307,9 +1307,9 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       void
       _M_default_initialize(size_type __n)
       {
-	std::__uninitialized_default_n_a(this->_M_impl._M_start, __n, 
-					 _M_get_Tp_allocator());
-	this->_M_impl._M_finish = this->_M_impl._M_end_of_storage;
+	this->_M_impl._M_finish =
+	  std::__uninitialized_default_n_a(this->_M_impl._M_start, __n,
+					   _M_get_Tp_allocator());
       }
 #endif
 
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index 4eacec3..19784c0 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -233,10 +233,10 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       else if (__n > size())
 	{
 	  std::fill(begin(), end(), __val);
-	  std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
-					__n - size(), __val,
-					_M_get_Tp_allocator());
-	  this->_M_impl._M_finish += __n - size();
+	  this->_M_impl._M_finish =
+	    std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
+					  __n - size(), __val,
+					  _M_get_Tp_allocator());
 	}
       else
         _M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val));
@@ -471,11 +471,11 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		}
 	      else
 		{
-		  std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
-						__n - __elems_after,
-						__x_copy,
-						_M_get_Tp_allocator());
-		  this->_M_impl._M_finish += __n - __elems_after;
+		  this->_M_impl._M_finish =
+		    std::__uninitialized_fill_n_a(this->_M_impl._M_finish,
+						  __n - __elems_after,
+						  __x_copy,
+						  _M_get_Tp_allocator());
 		  std::__uninitialized_move_a(__position.base(), __old_finish,
 					      this->_M_impl._M_finish,
 					      _M_get_Tp_allocator());
@@ -545,9 +545,9 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 	  if (size_type(this->_M_impl._M_end_of_storage
 			- this->_M_impl._M_finish) >= __n)
 	    {
-	      std::__uninitialized_default_n_a(this->_M_impl._M_finish,
-					       __n, _M_get_Tp_allocator());
-	      this->_M_impl._M_finish += __n;
+	      this->_M_impl._M_finish =
+		std::__uninitialized_default_n_a(this->_M_impl._M_finish,
+						 __n, _M_get_Tp_allocator());
 	    }
 	  else
 	    {
@@ -562,9 +562,9 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 		    = std::__uninitialized_move_if_noexcept_a
 		    (this->_M_impl._M_start, this->_M_impl._M_finish,
 		     __new_start, _M_get_Tp_allocator());
-		  std::__uninitialized_default_n_a(__new_finish, __n,
-						   _M_get_Tp_allocator());
-		  __new_finish += __n;
+		  __new_finish =
+		    std::__uninitialized_default_n_a(__new_finish, __n,
+						     _M_get_Tp_allocator());
 		}
 	      __catch(...)
 		{
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/16505.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/16505.cc
index cfe01ca..72c93a5 100644
--- a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/16505.cc
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/16505.cc
@@ -26,5 +26,5 @@ 
 struct S { };
 
 template
-  void
+  S*
   std::uninitialized_fill_n<S*, int, S>(S*, int, const S&);
diff --git a/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/dr1339.cc b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/dr1339.cc
new file mode 100644
index 0000000..d3ba204
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_fill_n/dr1339.cc
@@ -0,0 +1,64 @@ 
+// Copyright (C) 2014 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+// test specialization for trivial types
+void
+test01()
+{
+  const int N = 10;
+  int arr[N] = { };
+  const int n = 5;
+  const int over9000 = 9001;
+  int* end = std::uninitialized_fill_n(arr, n, over9000);
+  VERIFY( end = arr + n );
+  for (int i = 0; i < n; ++i)
+    VERIFY( arr[i] == over9000 );
+  for (int i = n; i < N; ++i)
+    VERIFY( arr[i] == 0 );
+}
+
+struct T
+{
+  T() { }
+  T(const T&) { ++counter; }
+  static int counter;
+};
+
+int T::counter;
+
+// test non-trivial
+void
+test02()
+{
+  const int n = 5;
+  char* mem = new char[sizeof(T)*n];
+  T* p = reinterpret_cast<T*>(mem);
+  T* end = std::uninitialized_fill_n(p, n, T());
+  VERIFY( end = p + n );
+  VERIFY( T::counter == n );
+  delete[] mem;
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}