From patchwork Fri May 10 04:58:49 2019 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: 1097825 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-500397-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Tpq4KM3n"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="JnfoUoEj"; 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 450dKY6nzJz9sB8 for ; Fri, 10 May 2019 14:59:06 +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:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=IrsDzHZzAh2i8uWvg6OoDfIJxLPpch+nGV7QSqbTe3mc0RFSDFTSk wQyy4wkyGFPLT4cbKfPGDNRmb76zLsJpCfco4pxXkQaKcsTiY8Kjr22VKPOJYA1z lW5tQwBHOBzWT6p9l6Y4cpqTTlphkGpCTHkRhfSIrRmTf2mnQP/Fig= 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:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=uXTIz186XY0FqMt6W5JpfkUlOzI=; b=Tpq4KM3njUpip/rqNGAp KeHhW0jaVy0LJGU3q2qP8txANhQXMBAZzTvT1w8bCkvpqMrXJgxXOJKoIe/AUMF8 XVZVxbcV6nHV6aPzW3oKdOnRVxkg/9CrB/+PZcdwgkUkRew75FHSgpRDmQiwhxdc mdav6/FNGDDboV/H1cUZgig= Received: (qmail 120243 invoked by alias); 10 May 2019 04:58:59 -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 119974 invoked by uid 89); 10 May 2019 04:58:59 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=delegate, is_always_equal, qualification, 83011 X-HELO: mail-wm1-f49.google.com Received: from mail-wm1-f49.google.com (HELO mail-wm1-f49.google.com) (209.85.128.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 10 May 2019 04:58:55 +0000 Received: by mail-wm1-f49.google.com with SMTP id i3so39964wml.4; Thu, 09 May 2019 21:58:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:subject:to:message-id:date:user-agent:mime-version :content-language; bh=PbccjzjGn3zUl+hz2DIS6RG2UEHQKBPQWEP284pwuvU=; b=JnfoUoEjB4KwCui6H8qWFKrw3Ug8JUvgahc9w4nNq1VcAR4aDmJOxO/Uo2k5DNPfoM xBxmcQXcEXCx4oXiRABMX8jMpxgIdvSWM49wCtzvdClDrjwQ5S8cmJ3Td8u0vhQFUMM2 iVkMIb04LRxfi5jRMeySf8Snylua7k7R7OBS/x+6g89JdWrN50het6CQSIksF5f+fmao 7zGj/R7HyFg7sYNq9rBTjRjOxeBrgQIXxEc04O5yMqLXsYOt5rJb/4dYefbR1w269f3t es+f8qSyRY4ohQ6zqA7fpFYKdG+j0Ub9dJBaX6rAdiGmPCKtWlTqbuZ3iQS9WkXnZVw2 BImA== Received: from [10.1.8.69] ([109.190.253.11]) by smtp.googlemail.com with ESMTPSA id g3sm6383969wmh.27.2019.05.09.21.58.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 May 2019 21:58:52 -0700 (PDT) From: =?utf-8?q?Fran=C3=A7ois_Dumont?= Subject: Deque code cleanup and optimizations To: "libstdc++@gcc.gnu.org" , gcc-patches Message-ID: Date: Fri, 10 May 2019 06:58:49 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 Hi     This patch implements a number of simplifications and optimizations already done to other containers like std::vector - Default default and move constructors - The std::swap optimization - The construction always equal allocator optimization - Shortcuts on method calls.     I remove several _M_map != nullptr checks cause in current implementation it can't be null. I have several patches following this one to support it but in this case we will be using a different code path.     Now that we take shortcuts in several methods in C++11 there are some that are simply unused in C++11 mode. For the moment I kept them as long as we are not in versioned namespace scope in order to maintain abi compatibility, I wonder if I really need to consider abi backward-compatibility here ?     * include/bits/stl_deque.h (_Deque_base(_Deque_base&&, false_type)):     Make private.     (_Deque_base(_Deque_base&&, true_type)): Likewise. Remove _M_map check.     (_Deque_base(_Deque_base&&, const allocator_type&)): New.     (_Deque_base(_Deque_base&&, const allocator_type&, size_t)): Remove     _M_map check.     (_Deque_base::_Deque_impl_data): New.     (_Deque_base::_Deque_impl): Inherit latter.     (_Deque_base::_Deque_impl::_M_swap_data): Move...     (_Deque_base::_Deque_impl_data::_M_swap_data): ... here.     (_Deque_base::_Deque_impl()): Add noexcept qualification.     (_Deque_base::_Deque_impl(_Deque_impl&&, _Tp_alloc_type&&)): New.     (_Deque_base::_Deque_impl::_M_get_Tp_allocator()): Remove static_cast.     (_Deque_base::_Deque_impl::_M_move_impl()): Remove _M_impl._M_map check.     (deque<>::deque()): Default.     (deque<>::deque(deque&&)): Default.     (deque<>::deque(deque&&, const allocator_type&, false_type)): New.     (deque<>::deque(deque&&, const allocator_type&, true_type)): New.     (deque<>::deque(deque&&, const allocator_type&)): Delegate to latters.     (deque<>::deque<_It>(_It, _It, const allocator_type&)): Use     _M_range_initialize.     (deque<>::assign<_It>(_It, _It)): Use _M_assign_aux.     (deque<>::resize(size_type, const value_type&)): Share a single     implementation.     (deque<>::insert<_It>(const_iterator, _It, _It)): Use     _M_range_insert_aux.     [__cplusplus >= 201103L && _GLIBCXX_INLINE_VERSION](_M_initialize_dispatch):     Remove.     [__cplusplus >= 201103L && _GLIBCXX_INLINE_VERSION](_M_assign_dispatch):     Remove.     [__cplusplus >= 201103L && _GLIBCXX_INLINE_VERSION](_M_insert_dispatch):     Remove.     * testsuite/23_containers/deque/allocator/default_init.cc: New. Tested under Linux x86_64 normal and debug modes. Ok to commit ? François diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index c050d1bf023..92c34207baa 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -401,7 +401,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Map_alloc_type; typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits; - public: typedef _Alloc allocator_type; allocator_type @@ -428,6 +427,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { /* Caller must initialize map. */ } #if __cplusplus >= 201103L + private: _Deque_base(_Deque_base&& __x, false_type) : _M_impl(__x._M_move_impl()) { } @@ -436,84 +436,100 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _M_impl(std::move(__x._M_get_Tp_allocator())) { _M_initialize_map(0); - if (__x._M_impl._M_map) this->_M_impl._M_swap_data(__x._M_impl); } + protected: _Deque_base(_Deque_base&& __x) : _Deque_base(std::move(__x), typename _Alloc_traits::is_always_equal{}) { } + _Deque_base(_Deque_base&& __x, const allocator_type& __a) + : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) + { __x._M_initialize_map(0); } + _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_t __n) : _M_impl(__a) { if (__x.get_allocator() == __a) - { - if (__x._M_impl._M_map) { _M_initialize_map(0); this->_M_impl._M_swap_data(__x._M_impl); } - } else - { _M_initialize_map(__n); } - } #endif ~_Deque_base() _GLIBCXX_NOEXCEPT; - protected: typedef typename iterator::_Map_pointer _Map_pointer; - //This struct encapsulates the implementation of the std::deque - //standard container and at the same time makes use of the EBO - //for empty allocators. - struct _Deque_impl - : public _Tp_alloc_type + struct _Deque_impl_data { _Map_pointer _M_map; size_t _M_map_size; iterator _M_start; iterator _M_finish; - _Deque_impl() - : _Tp_alloc_type(), _M_map(), _M_map_size(0), - _M_start(), _M_finish() + _Deque_impl_data() _GLIBCXX_NOEXCEPT + : _M_map(), _M_map_size(), _M_start(), _M_finish() + { } + +#if __cplusplus >= 201103L + _Deque_impl_data(const _Deque_impl_data&) = default; + _Deque_impl_data& + operator=(const _Deque_impl_data&) = default; + + _Deque_impl_data(_Deque_impl_data&& __x) noexcept + : _Deque_impl_data(__x) + { __x = _Deque_impl_data(); } +#endif + + void + _M_swap_data(_Deque_impl_data& __x) _GLIBCXX_NOEXCEPT + { + // Do not use std::swap(_M_start, __x._M_start), etc as it loses + // information used by TBAA. + std::swap(*this, __x); + } + }; + + // This struct encapsulates the implementation of the std::deque + // standard container and at the same time makes use of the EBO + // for empty allocators. + struct _Deque_impl + : public _Tp_alloc_type, public _Deque_impl_data + { + _Deque_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Tp_alloc_type>::value) + : _Tp_alloc_type() { } _Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT - : _Tp_alloc_type(__a), _M_map(), _M_map_size(0), - _M_start(), _M_finish() + : _Tp_alloc_type(__a) { } #if __cplusplus >= 201103L _Deque_impl(_Deque_impl&&) = default; _Deque_impl(_Tp_alloc_type&& __a) noexcept - : _Tp_alloc_type(std::move(__a)), _M_map(), _M_map_size(0), - _M_start(), _M_finish() + : _Tp_alloc_type(std::move(__a)) { } -#endif - void _M_swap_data(_Deque_impl& __x) _GLIBCXX_NOEXCEPT - { - using std::swap; - swap(this->_M_start, __x._M_start); - swap(this->_M_finish, __x._M_finish); - swap(this->_M_map, __x._M_map); - swap(this->_M_map_size, __x._M_map_size); - } + _Deque_impl(_Deque_impl&& __d, _Tp_alloc_type&& __a) + : _Tp_alloc_type(std::move(__a)), _Deque_impl_data(std::move(__d)) + { } +#endif }; _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; } _Map_alloc_type _M_get_map_allocator() const _GLIBCXX_NOEXCEPT @@ -547,7 +563,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Map_alloc_traits::deallocate(__map_alloc, __p, __n); } - protected: void _M_initialize_map(size_t); void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish); void _M_destroy_nodes(_Map_pointer __nstart, @@ -561,9 +576,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _Deque_impl _M_move_impl() { - if (!_M_impl._M_map) - return std::move(_M_impl); - // Create a copy of the current allocator. _Tp_alloc_type __alloc{_M_get_Tp_allocator()}; // Put that copy in a moved-from state. @@ -791,7 +803,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef ptrdiff_t difference_type; typedef _Alloc allocator_type; - protected: + private: static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT { return __deque_buf_size(sizeof(_Tp)); } @@ -818,7 +830,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * @brief Creates a %deque with no elements. */ - deque() : _Base() { } +#if __cplusplus >= 201103L + deque() = default; +#else + deque() { } +#endif /** * @brief Creates a %deque with no elements. @@ -887,13 +903,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if __cplusplus >= 201103L /** * @brief %Deque move constructor. - * @param __x A %deque of identical element and allocator types. * - * The newly-created %deque contains the exact contents of @a __x. - * The contents of @a __x are a valid, but unspecified %deque. + * The newly-created %deque contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %deque. */ - deque(deque&& __x) - : _Base(std::move(__x)) { } + deque(deque&&) = default; /// Copy constructor with alternative allocator deque(const deque& __x, const allocator_type& __a) @@ -904,9 +920,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /// Move constructor with alternative allocator deque(deque&& __x, const allocator_type& __a) + : deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{}) + { } + + private: + deque(deque&& __x, const allocator_type& __a, true_type) + : _Base(std::move(__x), __a) + { } + + deque(deque&& __x, const allocator_type& __a, false_type) : _Base(std::move(__x), __a, __x.size()) { - if (__x.get_allocator() != __a) + if (__x.get_allocator() != __a && !__x.empty()) { std::__uninitialized_move_a(__x.begin(), __x.end(), this->_M_impl._M_start, @@ -915,6 +940,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } + public: /** * @brief Builds a %deque from an initializer list. * @param __l An initializer_list. @@ -956,7 +982,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER deque(_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 deque(_InputIterator __first, _InputIterator __last, @@ -1057,7 +1086,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typename = std::_RequireInputIter<_InputIterator>> void assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } #else template void @@ -1243,14 +1272,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void resize(size_type __new_size, const value_type& __x) - { - const size_type __len = size(); - if (__new_size > __len) - _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x); - else if (__new_size < __len) - _M_erase_at_end(this->_M_impl._M_start - + difference_type(__new_size)); - } #else /** * @brief Resizes the %deque to the specified number of elements. @@ -1265,6 +1286,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER */ void resize(size_type __new_size, value_type __x = value_type()) +#endif { const size_type __len = size(); if (__new_size > __len) @@ -1273,7 +1295,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_erase_at_end(this->_M_impl._M_start + difference_type(__new_size)); } -#endif #if __cplusplus >= 201103L /** A non-binding request to reduce memory use. */ @@ -1514,7 +1535,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_last - 1) { - _Alloc_traits::destroy(this->_M_impl, + _Alloc_traits::destroy(_M_get_Tp_allocator(), this->_M_impl._M_start._M_cur); ++this->_M_impl._M_start._M_cur; } @@ -1538,7 +1559,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER != this->_M_impl._M_finish._M_first) { --this->_M_impl._M_finish._M_cur; - _Alloc_traits::destroy(this->_M_impl, + _Alloc_traits::destroy(_M_get_Tp_allocator(), this->_M_impl._M_finish._M_cur); } else @@ -1602,6 +1623,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * @brief Inserts an initializer list into the %deque. * @param __p An iterator into the %deque. * @param __l An initializer_list. + * @return An iterator that points to the inserted data. * * This function will insert copies of the data in the * initializer_list @a __l into the %deque before the location @@ -1615,9 +1637,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER std::random_access_iterator_tag()); return begin() + __offset; } -#endif -#if __cplusplus >= 201103L /** * @brief Inserts a number of copies of given data into the %deque. * @param __position A const_iterator into the %deque. @@ -1669,8 +1689,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _InputIterator __last) { difference_type __offset = __position - cbegin(); - _M_insert_dispatch(__position._M_const_cast(), - __first, __last, __false_type()); + _M_range_insert_aux(__position._M_const_cast(), __first, __last, + std::__iterator_category(__first)); return begin() + __offset; } #else @@ -1776,6 +1796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER protected: // Internal constructor functions follow. +#if __cplusplus < 201103L || !_GLIBCXX_INLINE_VERSION // called by the range constructor to implement [23.1.1]/9 // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1789,6 +1810,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_fill_initialize(__x); } + // called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#endif + static size_t _S_check_init_len(size_t __n, const allocator_type& __a) { @@ -1806,16 +1838,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER return (std::min)(__diffmax, __allocmax); } - // called by the range constructor to implement [23.1.1]/9 - template - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { - _M_range_initialize(__first, __last, - std::__iterator_category(__first)); - } - // called by the second initialize_dispatch above //@{ /** @@ -1862,6 +1884,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Internal assign functions follow. The *_aux functions do the actual // assignment work for the range versions. +#if __cplusplus < 201103L || !_GLIBCXX_INLINE_VERSION // called by the range assign to implement [23.1.1]/9 // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1877,6 +1900,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_assign_dispatch(_InputIterator __first, _InputIterator __last, __false_type) { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#endif // called by the second assign_dispatch above template @@ -1942,6 +1966,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER // Internal insert functions follow. The *_aux functions do the actual // insertion work when all shortcuts fail. +#if __cplusplus < 201103L || !_GLIBCXX_INLINE_VERSION // called by the range insert to implement [23.1.1]/9 // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1962,6 +1987,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_range_insert_aux(__pos, __first, __last, std::__iterator_category(__first)); } +#endif // called by the second insert_dispatch above template diff --git a/libstdc++-v3/testsuite/23_containers/deque/allocator/default_init.cc b/libstdc++-v3/testsuite/23_containers/deque/allocator/default_init.cc new file mode 100644 index 00000000000..f6cc61e1fb8 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/deque/allocator/default_init.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2019 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::deque 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::deque 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; +}