From patchwork Thu Sep 25 15:27:45 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 393370 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 7A31B1400DD for ; Fri, 26 Sep 2014 01:28:00 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=dr6gvsMzbpzRmFEDLrz3z1F8RI+UjUrjqGoTvf5aks8Ro7HT0lEk4 /g6+OpFaFkZK1yImYmBoUUSvDJFsWZBbzLy+3vR3HE+XFbxSS9GxTfB4S8ienUDE T8A6b/Qq5sDlPQ75Uv3jdiBEAh2/wrbiUUrATyF8EQA6md9U63qkRc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=J7g/ERiH8ibVfEh6bOM1rIpEvA0=; b=lLlsoZrqoDn3lFZUa1P9 s2Vcd6WWkt7t3qckgZqb6BkDsdYk1k43atpuX/5TZzMnP7EthBI9Kg5sYzWBIM4y 8BbX1xuXwBZvUEiSL8tLctdkwwBxb4/4R5XihlxuwsqkRkhDmxh7GSOx7qUPmsIf YyllQb/BdgOBpdXSLBA2Ucw= Received: (qmail 10555 invoked by alias); 25 Sep 2014 15:27:53 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 10527 invoked by uid 89); 25 Sep 2014 15:27:52 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Thu, 25 Sep 2014 15:27:50 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s8PFRlcJ009536 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 25 Sep 2014 11:27:48 -0400 Received: from localhost (ovpn-116-40.ams2.redhat.com [10.36.116.40]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s8PFRjTH020551; Thu, 25 Sep 2014 11:27:46 -0400 Date: Thu, 25 Sep 2014 16:27:45 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [patch] LWG DR 1339: uninitialized_fill_n should return the end of its range Message-ID: <20140925152745.GG2669@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) 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. commit 81456b32a7991351d40ca45c276892fdab5d91ab Author: Jonathan Wakely 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. - 20.6.12.3 uninitialized_fill - Partial - Returns void.. + Y + 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 - 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 { template - 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 - 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 - 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 - 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 - 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 { template - 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 - 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 - 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 - 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_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, 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 +// . + +#include +#include + +// 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(mem); + T* end = std::uninitialized_fill_n(p, n, T()); + VERIFY( end = p + n ); + VERIFY( T::counter == n ); + delete[] mem; +} + +int +main() +{ + test01(); + test02(); +}