From patchwork Sun Jul 23 17:41:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Fran=C3=A7ois_Dumont?= X-Patchwork-Id: 792577 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-458728-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="xR3ntldR"; dkim-atps=neutral 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 3xFsJ12HR5z9s81 for ; Mon, 24 Jul 2017 03:41:34 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=wGmCwEObHR1Maigl2CyOY+mv9DMmarAu6xah5d2dudG0CQ/RKo B4dQaeyD7bqC35YY1J5m61TUfLVOB4iP8Ov5FaoGIFi1JttPV/kSR07zW9anJNFh yeq6rSB7agn/2ivApRA3SnPfsSFg4AYlX59Hb5Uq3/XQhBkERziDZuMz0= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=lQXHtM0RNS32YBmA37mH+Jy7PIM=; b=xR3ntldRalOhiDAcsdAj R245Vgh+YcxDeBDTzZbYADtb4ONcjyLFQF7JQwGcICe1fyrxSja+rlTGO88l6p9F l/e0XvaIv2BiV9Voyc2OgwQAvyfIp793t9CZIX5JwjSi0TswH6EqELL2lfodJwkj 0TQOYvzzbc8uq0Yz2g4DHeQ= Received: (qmail 52323 invoked by alias); 23 Jul 2017 17:41:25 -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 52255 invoked by uid 89); 23 Jul 2017 17:41:23 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.2 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=H*r:rev.sfr.net X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-wm0-f44.google.com Received: from mail-wm0-f44.google.com (HELO mail-wm0-f44.google.com) (74.125.82.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sun, 23 Jul 2017 17:41:20 +0000 Received: by mail-wm0-f44.google.com with SMTP id c184so15754634wmd.0; Sun, 23 Jul 2017 10:41:20 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=oT/K6BuCjt64wKUzqXcMMApTw/7Ipm3BteqbRqcouEY=; b=tbW3RKkOk4qC9wnWswT4A4E6qNpRPof3rzG+0qISM9Z8vwzXip6g2z+GU+cq8Ddo5K E5YB+poRLOnO+hCodvKROxksM5AviXdZr8EymLi/JOng23rXGYk7QuB+lqr1uqbgCKL5 ZKY4ZW/Aynjqhm+5F1UXD1qynZDVUChGrmbNOUSv3D1ZXRbvuD57WnaeXIdGub644bkn dW6NcNfg9tF4qHqnSNt9G6ReSJ1tpm2azHJwrfSvW5u9/tyr2/3jA3EULMco9ObGAoRh 1hMKQXQ+CdqGrSN75JnCIETpBVgoywhGALEflOHPeacxP7CscFDCe2Hy3tXqSWAb+amY JMRw== X-Gm-Message-State: AIVw110YKurRBa35FOKs63+RGOjDjn//SPZH2HZy7PJLCJwtcOUVYjOr WYXWk57xaPQfbOX1 X-Received: by 10.28.20.67 with SMTP id 64mr3353671wmu.60.1500831678109; Sun, 23 Jul 2017 10:41:18 -0700 (PDT) Received: from [192.168.1.75] (54.153.102.84.rev.sfr.net. [84.102.153.54]) by smtp.googlemail.com with ESMTPSA id v8sm10611296wrv.16.2017.07.23.10.41.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 23 Jul 2017 10:41:16 -0700 (PDT) To: "libstdc++@gcc.gnu.org" , gcc-patches From: =?UTF-8?Q?Fran=c3=a7ois_Dumont?= Subject: std::vector default default and move constructors Message-ID: <2b48d135-7b0f-f8ec-73f5-15932c2a8581@gmail.com> Date: Sun, 23 Jul 2017 19:41:15 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.1 MIME-Version: 1.0 Hi Is it time now to consider this patch ? * include/bits/stl_vector.h (_Vector_impl_data): New. (_Vector_impl): Inherit from latter. (_Vertor_impl(_Vector_impl&&, _Tp_alloc_type&&)): New. (_Vector_base(_Vector_base&&, const allocator_type&)): Use latter. (_Vector_base()): Default. (_Vector_base(size_t)): Delete. (_Vector_base(_Tp_alloc_type&&)): Delete. (_Vector_base(_Vector_base&&)): Default. (vector()): Default. (vector(vector&&, const allocator_type&, true_type)): New. (vector(vector&&, const allocator_type&, false_type)): New. (vector(vector&&, const allocator_type&)): Use latters. Tested under linux x86_64. François diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 69cb803..d1abaf4 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -85,29 +85,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer pointer; - struct _Vector_impl - : public _Tp_alloc_type + struct _Vector_impl_data { pointer _M_start; pointer _M_finish; pointer _M_end_of_storage; - _Vector_impl() - : _Tp_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage() - { } - - _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT - : _Tp_alloc_type(__a), _M_start(), _M_finish(), _M_end_of_storage() + _Vector_impl_data() _GLIBCXX_NOEXCEPT + : _M_start(), _M_finish(), _M_end_of_storage() { } #if __cplusplus >= 201103L - _Vector_impl(_Tp_alloc_type&& __a) noexcept - : _Tp_alloc_type(std::move(__a)), - _M_start(), _M_finish(), _M_end_of_storage() - { } + _Vector_impl_data(_Vector_impl_data&& __x) noexcept + : _M_start(__x._M_start), _M_finish(__x._M_finish), + _M_end_of_storage(__x._M_end_of_storage) + { __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); } #endif - void _M_swap_data(_Vector_impl& __x) _GLIBCXX_NOEXCEPT + void + _M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPT { std::swap(_M_start, __x._M_start); std::swap(_M_finish, __x._M_finish); @@ -230,54 +226,64 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR }; + struct _Vector_impl + : public _Tp_alloc_type, public _Vector_impl_data + { + _Vector_impl() _GLIBCXX_NOEXCEPT_IF( noexcept(_Tp_alloc_type()) ) + : _Tp_alloc_type() + { } + + _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT + : _Tp_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _Vector_impl(_Vector_impl&&) = default; + + _Vector_impl(_Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)) + { } + + _Vector_impl(_Vector_impl&& __rv, _Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv)) + { } +#endif + }; + public: typedef _Alloc allocator_type; _Tp_alloc_type& _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT - { return *static_cast<_Tp_alloc_type*>(&this->_M_impl); } + { return this->_M_impl; } const _Tp_alloc_type& _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT - { return *static_cast(&this->_M_impl); } + { return this->_M_impl; } allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return allocator_type(_M_get_Tp_allocator()); } - _Vector_base() - : _M_impl() { } +#if __cplusplus >= 201103L + _Vector_base() = default; +#else + _Vector_base() { } +#endif _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT : _M_impl(__a) { } - _Vector_base(size_t __n) - : _M_impl() - { _M_create_storage(__n); } - _Vector_base(size_t __n, const allocator_type& __a) : _M_impl(__a) { _M_create_storage(__n); } #if __cplusplus >= 201103L - _Vector_base(_Tp_alloc_type&& __a) noexcept - : _M_impl(std::move(__a)) { } - - _Vector_base(_Vector_base&& __x) noexcept - : _M_impl(std::move(__x._M_get_Tp_allocator())) - { this->_M_impl._M_swap_data(__x._M_impl); } + _Vector_base(_Vector_base&&) = default; _Vector_base(_Vector_base&& __x, const allocator_type& __a) - : _M_impl(__a) - { - if (__x.get_allocator() == __a) - this->_M_impl._M_swap_data(__x._M_impl); - else - { - size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start; - _M_create_storage(__n); - } - } + : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) + { } #endif ~_Vector_base() _GLIBCXX_NOEXCEPT @@ -379,11 +385,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Creates a %vector with no elements. */ - vector() #if __cplusplus >= 201103L - noexcept(is_nothrow_default_constructible<_Alloc>::value) + vector() = default; +#else + vector() { } #endif - : _Base() { } /** * @brief Creates a %vector with no elements. @@ -459,13 +465,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L /** * @brief %Vector move constructor. - * @param __x A %vector of identical element and allocator types. * - * The newly-created %vector contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %vector. + * The newly-created %vector contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %vector. */ - vector(vector&& __x) noexcept - : _Base(std::move(__x)) { } + vector(vector&&) = default; /// Copy constructor with alternative allocator vector(const vector& __x, const allocator_type& __a) @@ -477,13 +483,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_get_Tp_allocator()); } - /// Move constructor with alternative allocator - vector(vector&& __rv, const allocator_type& __m) - noexcept(_Alloc_traits::_S_always_equal()) + private: + vector(vector&& __rv, const allocator_type& __m, std::true_type) noexcept : _Base(std::move(__rv), __m) + { } + + vector(vector&& __rv, const allocator_type& __m, std::false_type) + : _Base(__m) { - if (__rv.get_allocator() != __m) + if (__rv.get_allocator() == __m) + this->_M_impl._M_swap_data(__rv._M_impl); + else if (!__rv.empty()) { + this->_M_create_storage(__rv.size()); this->_M_impl._M_finish = std::__uninitialized_move_a(__rv.begin(), __rv.end(), this->_M_impl._M_start, @@ -492,6 +504,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } + public: + /// Move constructor with alternative allocator + vector(vector&& __rv, const allocator_type& __m) + noexcept(_Alloc_traits::_S_always_equal()) + : vector(std::move(__rv), __m, typename _Alloc_traits::is_always_equal{}) + { } + /** * @brief Builds a %vector from an initializer list. * @param __l An initializer_list. @@ -534,7 +553,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector(_InputIterator __first, _InputIterator __last, const allocator_type& __a = allocator_type()) : _Base(__a) - { _M_initialize_dispatch(__first, __last, __false_type()); } + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } #else template vector(_InputIterator __first, _InputIterator __last, @@ -1405,6 +1427,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Called by the range constructor to implement [23.1.1]/9 +#if __cplusplus < 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template @@ -1423,10 +1446,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, __false_type) { - typedef typename std::iterator_traits<_InputIterator>:: - iterator_category _IterCategory; - _M_range_initialize(__first, __last, _IterCategory()); + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); } +#endif // Called by the second initialize_dispatch above template diff --git a/libstdc++-v3/testsuite/23_containers/vector/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/vector/allocator/default_init.cc new file mode 100644 index 0000000..1f0719d --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/allocator/default_init.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2017 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 run { target c++11 } } +// { dg-options "-O0" } +// { dg-xfail-run-if "PR c++/65816" { *-*-* } } + +#include +#include +#include + +#include + +using T = int; + +using __gnu_test::default_init_allocator; + +void test01() +{ + typedef default_init_allocator alloc_type; + typedef std::vector test_type; + + __gnu_cxx::__aligned_buffer buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type; + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +void test02() +{ + typedef default_init_allocator alloc_type; + typedef std::vector test_type; + + __gnu_cxx::__aligned_buffer buf; + __builtin_memset(buf._M_addr(), ~0, sizeof(test_type)); + + test_type *tmp = ::new(buf._M_addr()) test_type(); + + VERIFY( tmp->get_allocator().state == 0 ); + + tmp->~test_type(); +} + +int main() +{ + test01(); + test02(); + return 0; +}