From patchwork Fri Nov 2 01:34:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 196456 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 345B32C0323 for ; Fri, 2 Nov 2012 12:34:27 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1352424868; h=Comment: DomainKey-Signature:Received:Received:Received:Received: MIME-Version:Received:Received:Date:Message-ID:Subject:From:To: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=BX4Gi8O 4HaFhFjLuK3KTTT8FJa4=; b=JcXqpkCiSytLbelB32JLoup2pnR2rFdJ8zabY07 +fypFn0S++i64v6I7NmAEgdDxpNEyEiRCgfvGCMu7bqOs/yQaEsptOnOG56FDwGM oiyM8ZlFXXstrIJPJ68Yq+M/Ge5dpxRZIiVE8H6kBydYoxmuN4ZIBPqW+ZC5s1Pl 3+gU= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:MIME-Version:Received:Received:Date:Message-ID:Subject:From:To:Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=IWblbnM0RgQgTW96zuidlft/dHvZhWRRfBQ6IYhy38ZDTKHN24nuucSqlq0+X3 jrAyXdp35K9fSwyug4WrYGWdd8gLN4+Gh3g4Nk+3F3mUdpoDPGRx8QFKO15Jr0M+ EFQ+Uvp056vienIDwxsW77ACrcImQjU8swujp/PjozG1I=; Received: (qmail 9644 invoked by alias); 2 Nov 2012 01:34:20 -0000 Received: (qmail 9531 invoked by uid 22791); 2 Nov 2012 01:34:19 -0000 X-SWARE-Spam-Status: No, hits=-4.5 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, KHOP_RCVD_TRUST, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE X-Spam-Check-By: sourceware.org Received: from mail-ie0-f175.google.com (HELO mail-ie0-f175.google.com) (209.85.223.175) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 02 Nov 2012 01:34:09 +0000 Received: by mail-ie0-f175.google.com with SMTP id c13so4887493ieb.20 for ; Thu, 01 Nov 2012 18:34:09 -0700 (PDT) MIME-Version: 1.0 Received: by 10.50.140.3 with SMTP id rc3mr194018igb.35.1351820049009; Thu, 01 Nov 2012 18:34:09 -0700 (PDT) Received: by 10.42.158.202 with HTTP; Thu, 1 Nov 2012 18:34:08 -0700 (PDT) Date: Fri, 2 Nov 2012 01:34:08 +0000 Message-ID: Subject: [v3] Fix allocator-aware container requirements for forward_list 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 fixes the new LWG issue 2210 and only uses allocator::construct() for the elements not the nodes. 2012-11-02 Jonathan Wakely * include/bits/forward_list.h (forward_list(size_type)): Add missing allocator parameter. (_Fwd_list_node_base): Use NSDMI and define constructor as defaulted. (_Fwd_list_node::_M_value): Replace with uninitialized storage. (_Fwd_list_node::_M_valptr()): Define functions to access storage. (_Fwd_list_iterator, _Fwd_list_const_iterator): Use _M_valptr. (_Fwd_list_base::_M_create_node): Only use allocator to construct the element not the node. * include/bits/forward_list.tcc (_Fwd_list_base::_M_erase_after): Only use allocator to destroy the element not the node. * testsuite/23_containers/forward_list/cons/11.cc: Remove unused headers. * testsuite/23_containers/forward_list/cons/12.cc: Likewise. * testsuite/23_containers/forward_list/cons/13.cc: New. * testsuite/23_containers/forward_list/cons/14.cc: New. Tested x86_64-linux, committed to trunk. The pretty printers need an update, which I'll do asap. commit 751520cfc531da12190b93c12a208f83fec81e4e Author: Jonathan Wakely Date: Fri Nov 2 00:15:27 2012 +0000 * include/bits/forward_list.h (forward_list(size_type)): Add missing allocator parameter. (_Fwd_list_node_base): Use NSDMI and define constructor as defaulted. (_Fwd_list_node::_M_value): Replace with uninitialized storage. (_Fwd_list_node::_M_valptr()): Define functions to access storage. (_Fwd_list_iterator, _Fwd_list_const_iterator): Use _M_valptr. (_Fwd_list_base::_M_create_node): Only use allocator to construct the element not the node. * include/bits/forward_list.tcc (_Fwd_list_base::_M_erase_after): Only use allocator to destroy the element not the node. * testsuite/23_containers/forward_list/cons/11.cc: Remove unused headers. * testsuite/23_containers/forward_list/cons/12.cc: Likewise. * testsuite/23_containers/forward_list/cons/13.cc: New. * testsuite/23_containers/forward_list/cons/14.cc: New. diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index b40fe9b..9efabcf 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -48,9 +48,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ struct _Fwd_list_node_base { - _Fwd_list_node_base() : _M_next(0) { } + _Fwd_list_node_base() = default; - _Fwd_list_node_base* _M_next; + _Fwd_list_node_base* _M_next = nullptr; _Fwd_list_node_base* _M_transfer_after(_Fwd_list_node_base* __begin, @@ -86,19 +86,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief A helper node class for %forward_list. - * This is just a linked list with a data value in each node. + * This is just a linked list with uninitialized storage for a + * data value in each node. * There is a sorting utility method. */ template struct _Fwd_list_node : public _Fwd_list_node_base { - template - _Fwd_list_node(_Args&&... __args) - : _Fwd_list_node_base(), - _M_value(std::forward<_Args>(__args)...) { } + _Fwd_list_node() = default; + + typename aligned_storage::value>::type + _M_storage; + + _Tp* + _M_valptr() noexcept + { + return static_cast<_Tp*>(static_cast(&_M_storage)); + } - _Tp _M_value; + const _Tp* + _M_valptr() const noexcept + { + return static_cast(static_cast(&_M_storage)); + } }; /** @@ -127,12 +138,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER reference operator*() const - { return static_cast<_Node*>(this->_M_node)->_M_value; } + { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } pointer operator->() const - { return std::__addressof(static_cast<_Node*> - (this->_M_node)->_M_value); } + { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } _Self& operator++() @@ -199,12 +209,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER reference operator*() const - { return static_cast<_Node*>(this->_M_node)->_M_value; } + { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } pointer operator->() const - { return std::__addressof(static_cast<_Node*> - (this->_M_node)->_M_value); } + { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } _Self& operator++() @@ -339,9 +348,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Node* __node = this->_M_get_node(); __try { - _Node_alloc_traits::construct(_M_get_Node_allocator(), __node, - std::forward<_Args>(__args)...); - __node->_M_next = 0; + _Tp_alloc_type __a(_M_get_Node_allocator()); + typedef allocator_traits<_Tp_alloc_type> _Alloc_traits; + ::new ((void*)__node) _Node(); + _Alloc_traits::construct(__a, __node->_M_valptr(), + std::forward<_Args>(__args)...); } __catch(...) { @@ -457,8 +468,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * constructed elements. */ explicit - forward_list(size_type __n) - : _Base() + forward_list(size_type __n, const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) { _M_default_initialize(__n); } /** @@ -738,7 +749,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER front() { _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); - return __front->_M_value; + return *__front->_M_valptr(); } /** @@ -749,7 +760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER front() const { _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); - return __front->_M_value; + return *__front->_M_valptr(); } // 23.3.4.5 modiļ¬ers: diff --git a/libstdc++-v3/include/bits/forward_list.tcc b/libstdc++-v3/include/bits/forward_list.tcc index 7395b20..757f319 100644 --- a/libstdc++-v3/include/bits/forward_list.tcc +++ b/libstdc++-v3/include/bits/forward_list.tcc @@ -53,7 +53,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER while (__curr) { __to->_M_next = - _M_create_node(std::move_if_noexcept(__curr->_M_value)); + _M_create_node(std::move_if_noexcept(*__curr->_M_valptr())); __to = __to->_M_next; __curr = static_cast<_Node*>(__curr->_M_next); } @@ -81,7 +81,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Node* __curr = static_cast<_Node*>(__pos->_M_next); __pos->_M_next = __curr->_M_next; - _Node_alloc_traits::destroy(_M_get_Node_allocator(), __curr); + _Tp_alloc_type __a(_M_get_Node_allocator()); + allocator_traits<_Tp_alloc_type>::destroy(__a, __curr->_M_valptr()); + __curr->~_Node(); _M_put_node(__curr); return __pos->_M_next; } @@ -97,7 +99,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _Node* __temp = __curr; __curr = static_cast<_Node*>(__curr->_M_next); - _Node_alloc_traits::destroy(_M_get_Node_allocator(), __temp); + _Tp_alloc_type __a(_M_get_Node_allocator()); + allocator_traits<_Tp_alloc_type>::destroy(__a, __temp->_M_valptr()); + __temp->~_Node(); _M_put_node(__temp); } __pos->_M_next = __last; @@ -300,10 +304,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) { - if (__tmp->_M_value == __val) + if (*__tmp->_M_valptr() == __val) { - if (std::__addressof(__tmp->_M_value) - != std::__addressof(__val)) + if (__tmp->_M_valptr() != std::__addressof(__val)) { this->_M_erase_after(__curr); continue; @@ -327,7 +330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Node* __curr = static_cast<_Node*>(&this->_M_impl._M_head); while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) { - if (__pred(__tmp->_M_value)) + if (__pred(*__tmp->_M_valptr())) this->_M_erase_after(__curr); else __curr = static_cast<_Node*>(__curr->_M_next); @@ -364,10 +367,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Node_base* __node = &this->_M_impl._M_head; while (__node->_M_next && __list._M_impl._M_head._M_next) { - if (__comp(static_cast<_Node*> - (__list._M_impl._M_head._M_next)->_M_value, - static_cast<_Node*> - (__node->_M_next)->_M_value)) + if (__comp(*static_cast<_Node*> + (__list._M_impl._M_head._M_next)->_M_valptr(), + *static_cast<_Node*> + (__node->_M_next)->_M_valptr())) __node->_M_transfer_after(&__list._M_impl._M_head, __list._M_impl._M_head._M_next); __node = __node->_M_next; @@ -460,7 +463,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __p = static_cast<_Node*>(__p->_M_next); --__psize; } - else if (__comp(__p->_M_value, __q->_M_value)) + else if (__comp(*__p->_M_valptr(), *__q->_M_valptr())) { // First node of p is lower; e must come from p. __e = __p; diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc index 30ae3fc..fa8c8db 100644 --- a/libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc +++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/11.cc @@ -20,8 +20,6 @@ // 23.3.4.2 forward_list construction [forwardlist.cons] #include -#include -#include bool fail = false; diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc index 42889db..3e28735 100644 --- a/libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc +++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/12.cc @@ -21,8 +21,6 @@ // 23.3.4.2 forward_list construction [forwardlist.cons] #include -#include -#include bool fail = false; diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/13.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/13.cc new file mode 100644 index 0000000..e21e02e --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/13.cc @@ -0,0 +1,55 @@ +// { dg-options "-std=gnu++11" } + +// Copyright (C) 2012 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 +// . + +// 23.3.4.2 forward_list construction [forwardlist.cons] + +#include +#include +#include +#include + +struct A +{ + typedef std::allocator allocator_type; + + A() : ok(false) { } + A(const A&) : ok(false) { } + A(const allocator_type&) : ok(true) { } + A(const A&, const allocator_type&) : ok(true) { } + + bool ok; +}; + +void test01() +{ + typedef std::scoped_allocator_adaptor alloc_type; + typedef std::forward_list list; + + list l1(1); + VERIFY( l1.begin()->ok ); + + A a; + list l2(1, a); + VERIFY( l2.begin()->ok ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/cons/14.cc b/libstdc++-v3/testsuite/23_containers/forward_list/cons/14.cc new file mode 100644 index 0000000..8bb17ee --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/forward_list/cons/14.cc @@ -0,0 +1,35 @@ +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +// Copyright (C) 2012 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 +// . + +// 23.3.4.2 forward_list construction [forwardlist.cons] + +#include +#include + +void test01() +{ + using namespace std; + using list = forward_list; + forward_list> l; + + // Check for forward_list(size_type, const allocator_type&) + l.emplace_front(1u); +} +