From patchwork Wed Nov 9 01:28:11 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 124465 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]) by ozlabs.org (Postfix) with SMTP id 981E51007D6 for ; Wed, 9 Nov 2011 12:28:40 +1100 (EST) Received: (qmail 22884 invoked by alias); 9 Nov 2011 01:28:34 -0000 Received: (qmail 22866 invoked by uid 22791); 9 Nov 2011 01:28:31 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SARE_SUB_OBFU_Q1 X-Spam-Check-By: sourceware.org Received: from mail-wy0-f175.google.com (HELO mail-wy0-f175.google.com) (74.125.82.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 09 Nov 2011 01:28:13 +0000 Received: by wyh5 with SMTP id 5so1288423wyh.20 for ; Tue, 08 Nov 2011 17:28:11 -0800 (PST) MIME-Version: 1.0 Received: by 10.216.229.14 with SMTP id g14mr53083weq.6.1320802091187; Tue, 08 Nov 2011 17:28:11 -0800 (PST) Received: by 10.216.63.83 with HTTP; Tue, 8 Nov 2011 17:28:11 -0800 (PST) Date: Wed, 9 Nov 2011 01:28:11 +0000 Message-ID: Subject: [v3] C++11 allocator reqs for vector in debug & profile mode From: Jonathan Wakely To: "libstdc++" , gcc-patches 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 This adds C++11 allocator support to vector in debug mode and profile mode. It also fixes an unrelated bug in __profile::vector::push_back(_Tp&&) * include/bits/stl_vector.h (vector::_Alloc_traits): Make private. * include/debug/vector: Add allocator-extended constructors, ensure move assignment and swap have same allocator propagation semantics and exceptions specification as base class. * include/profile/vector: Likewise. (vector::push_back(_Tp&&)): Forward argument as rvalue. * testsuite/23_containers/vector/debug/alloc_prop.cc: New. * doc/xml/manual/status_cxx2011.xml: Clarify status of container requirements with respect to allocators. (status.iso.200x): Add anchor for old ID to preserve existing links. (Sorry this took so long to do, Paolo!) Tested on x86_64-linux with make check, and for most of the testsuite with check-debug check-profile. Committed to trunk. Index: include/bits/stl_vector.h =================================================================== --- include/bits/stl_vector.h (revision 181166) +++ include/bits/stl_vector.h (working copy) @@ -214,11 +214,11 @@ typedef _Vector_base<_Tp, _Alloc> _Base; typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; public: typedef _Tp value_type; typedef typename _Base::pointer pointer; - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; typedef typename _Alloc_traits::const_pointer const_pointer; typedef typename _Alloc_traits::reference reference; typedef typename _Alloc_traits::const_reference const_reference; Index: include/debug/vector =================================================================== --- include/debug/vector (revision 181166) +++ include/debug/vector (working copy) @@ -52,6 +52,10 @@ typedef typename _Base::const_iterator _Base_const_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits; +#endif + public: typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; @@ -116,6 +120,17 @@ __x._M_guaranteed_capacity = 0; } + vector(const vector& __x, const allocator_type& __a) + : _Base(__x, __a), _M_guaranteed_capacity(__x.size()) { } + + vector(vector&& __x, const allocator_type& __a) + : _Base(std::move(__x), __a), + _M_guaranteed_capacity(this->size()) + { + __x._M_invalidate_all(); + __x._M_guaranteed_capacity = 0; + } + vector(initializer_list __l, const allocator_type& __a = allocator_type()) : _Base(__l, __a), @@ -135,12 +150,13 @@ #ifdef __GXX_EXPERIMENTAL_CXX0X__ vector& - operator=(vector&& __x) + operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move()) { - // NB: DR 1204. - // NB: DR 675. - clear(); - swap(__x); + _Base::operator=(std::move(__x)); + this->_M_invalidate_all(); + _M_update_guaranteed_capacity(); + __x._M_invalidate_all(); + __x._M_guaranteed_capacity = 0; return *this; } @@ -513,6 +529,9 @@ void swap(vector& __x) +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + noexcept(_Alloc_traits::_S_nothrow_swap()) +#endif { _Base::swap(__x); this->_M_swap(__x); Index: include/profile/vector =================================================================== --- include/profile/vector (revision 181166) +++ include/profile/vector (working copy) @@ -50,6 +50,10 @@ { typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base; +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits; +#endif + public: typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; @@ -143,6 +147,20 @@ __profcxx_vector_construct2(this); } + vector(const _Base& __x, const _Allocator& __a) + : _Base(__x) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + + vector(vector&& __x, const _Allocator& __a) noexcept + : _Base(std::move(__x), __a) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + vector(initializer_list __l, const allocator_type& __a = allocator_type()) : _Base(__l, __a) { } @@ -163,12 +181,11 @@ #ifdef __GXX_EXPERIMENTAL_CXX0X__ vector& - operator=(vector&& __x) + operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move()) { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); + __profcxx_vector_destruct(this, this->capacity(), this->size()); + __profcxx_vector_destruct2(this); + static_cast<_Base&>(*this) = std::move(__x); return *this; } @@ -329,7 +346,7 @@ push_back(_Tp&& __x) { size_type __old_size = this->capacity(); - _Base::push_back(__x); + _Base::push_back(std::move(__x)); _M_profile_resize(this, __old_size, this->capacity()); } @@ -373,6 +390,9 @@ void swap(vector& __x) +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + noexcept(_Alloc_traits::_S_nothrow_swap()) +#endif { _Base::swap(__x); } Index: testsuite/23_containers/vector/debug/alloc_prop.cc =================================================================== --- testsuite/23_containers/vector/debug/alloc_prop.cc (revision 0) +++ testsuite/23_containers/vector/debug/alloc_prop.cc (revision 0) @@ -0,0 +1,89 @@ +// Copyright (C) 2011 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 +// . +// +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +#include +#include +#include + +template + void + test() + { + typedef std::vector base; + typedef __gnu_debug::vector debug; + + using std::is_nothrow_default_constructible; + using std::is_nothrow_copy_constructible; + using std::is_nothrow_move_constructible; + using std::is_nothrow_copy_assignable; + using std::is_nothrow_move_assignable; + + static_assert( + is_nothrow_default_constructible::value + == is_nothrow_default_constructible::value, + "nothrow default constructible"); + + static_assert( + is_nothrow_copy_constructible::value + == is_nothrow_copy_constructible::value, + "nothrow copy constructible"); + + static_assert( + is_nothrow_move_constructible::value + == is_nothrow_move_constructible::value, + "nothrow move constructible"); + + static_assert( + is_nothrow_copy_assignable::value + == is_nothrow_copy_assignable::value, + "nothrow move assignable"); + + static_assert( + is_nothrow_move_assignable::value + == is_nothrow_move_assignable::value, + "nothrow move assignable"); + } + +struct X +{ + X() { } + ~X() { } + X(const X&) { } + X(X&&) { } + X& operator=(const X&) { } + X& operator=(X&&) { } +}; + +int main() +{ + using __gnu_test::propagating_allocator; + using __gnu_test::SimpleAllocator; + + test>(); + test>(); + test>(); + test>(); + test>(); + test>(); + test>(); + test>(); + + return 0; +} Index: doc/xml/manual/status_cxx2011.xml =================================================================== --- doc/xml/manual/status_cxx2011.xml (revision 181166) +++ doc/xml/manual/status_cxx2011.xml (working copy) @@ -14,6 +14,7 @@ + This table is based on the table of contents of ISO/IEC JTC1 SC22 WG21 Doc No: N3290 Date: 2011-04-11 Final Draft International Standard, Standard for Programming Language C++ @@ -1373,10 +1374,12 @@ + 23.2.1 General container requirements - Y - + Partial + Only vector meets the requirements + relating to allocator use and propagation. 23.2.2