From patchwork Fri Oct 31 20:49: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: 405578 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 C69EB1400A0 for ; Sat, 1 Nov 2014 07:50:03 +1100 (AEDT) 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=fTeddI4o9seuFBtBeplUMRBRCh4tk0XrAZy1CNcSb9MVltclRJBMl hGPj38/4ejadHThcMV4w5toJLc9xckahpElZ0GOQ1BTYzgqKt17FYWYNiMomLb8I CsALlzA0hgS3gYbMpCr3JXrdW9OFmi7cmHXCdO+cQQbVqmM8B6sTLk= 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=JMs31ddQ4aOme6WMeoAMJpdnhXM=; b=W9d+IvvxtphSvoT7oNcL kC1xZ7Y5DDJricAhxsIxd+XMQKl/S+kV+W8lWo6HtrqKFb+PD3pe90cDEdO8Nbfw ouUCS3z8txN6eVw0f9gfN14insw6maeL7Ov08+3ZUwQYv4Xxpph/j6Mk+5tXOBKF vyZDBBxxtN94nyyuMhVG67E= Received: (qmail 13403 invoked by alias); 31 Oct 2014 20:49:54 -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 13376 invoked by uid 89); 31 Oct 2014 20:49: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; Fri, 31 Oct 2014 20:49:48 +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 s9VKnl0q014173 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 31 Oct 2014 16:49:47 -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 s9VKnjSC032680; Fri, 31 Oct 2014 16:49:46 -0400 Date: Fri, 31 Oct 2014 20:49:45 +0000 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [patch] Make std::vector meet C++11 allocator requirements. Message-ID: <20141031204945.GO3033@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) There's no better time to fix evil vector than Halloween. All allocator operations must go through allocator_traits and _Bit_type* must be replaced with the allocator's pointer type. Rather than rewriting all the iterators and base classes to use _Bit_pointer everywhere I only changed _M_end_of_storage and added _M_end_addr() to convert it from _Bit_pointer to _Bit_type*, which optimizes to nothing for the usual case where they're the same type. Tested x86_64-linux, committed to trunk. commit fa404848f2a2753f2b1a52188b5ec30a6dd9949f Author: Jonathan Wakely Date: Fri Oct 31 20:02:13 2014 +0000 Make std::vector meet C++11 allocator requirements. * include/bits/stl_bvector.h (_Bvector_base): Use allocator_traits. (_Bvector_base::_Bvector_impl): Use allocator's pointer type. (_Bvector_base::_M_end_addr()): Convert to raw pointer. (vector): Use allocator_traits and _M_end_addr. Add allocator extended constructors. * include/bits/vector.tcc (vector): Use allocator_traits and _M_end_addr. * testsuite/23_containers/vector/bool/allocator/copy.cc: New. * testsuite/23_containers/vector/bool/allocator/minimal.cc: New. * testsuite/23_containers/vector/bool/allocator/noexcept.cc: New. * testsuite/23_containers/vector/bool/allocator/copy_assign.cc: New. * testsuite/23_containers/vector/bool/allocator/move.cc: New. * testsuite/23_containers/vector/bool/allocator/swap.cc: New. * testsuite/23_containers/vector/bool/allocator/ext_ptr.cc: New. * testsuite/23_containers/vector/bool/allocator/move_assign.cc: New. diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 996eb1a..c93b96c 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -410,30 +410,41 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER template struct _Bvector_base { - typedef typename _Alloc::template rebind<_Bit_type>::other - _Bit_alloc_type; - + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Bit_type>::other _Bit_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Bit_alloc_type> + _Bit_alloc_traits; + typedef typename _Bit_alloc_traits::pointer _Bit_pointer; + struct _Bvector_impl : public _Bit_alloc_type { _Bit_iterator _M_start; _Bit_iterator _M_finish; - _Bit_type* _M_end_of_storage; + _Bit_pointer _M_end_of_storage; _Bvector_impl() - : _Bit_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage(0) + : _Bit_alloc_type(), _M_start(), _M_finish(), _M_end_of_storage() { } _Bvector_impl(const _Bit_alloc_type& __a) - : _Bit_alloc_type(__a), _M_start(), _M_finish(), _M_end_of_storage(0) + : _Bit_alloc_type(__a), _M_start(), _M_finish(), _M_end_of_storage() { } #if __cplusplus >= 201103L _Bvector_impl(_Bit_alloc_type&& __a) : _Bit_alloc_type(std::move(__a)), _M_start(), _M_finish(), - _M_end_of_storage(0) + _M_end_of_storage() { } #endif + + _Bit_type* + _M_end_addr() const _GLIBCXX_NOEXCEPT + { + if (_M_end_of_storage) + return std::__addressof(_M_end_of_storage[-1]) + 1; + return 0; + } }; public: @@ -466,7 +477,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER this->_M_impl._M_end_of_storage = __x._M_impl._M_end_of_storage; __x._M_impl._M_start = _Bit_iterator(); __x._M_impl._M_finish = _Bit_iterator(); - __x._M_impl._M_end_of_storage = 0; + __x._M_impl._M_end_of_storage = nullptr; } #endif @@ -476,16 +487,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER protected: _Bvector_impl _M_impl; - _Bit_type* + _Bit_pointer _M_allocate(size_t __n) - { return _M_impl.allocate(_S_nword(__n)); } + { return _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n)); } void _M_deallocate() { if (_M_impl._M_start._M_p) - _M_impl.deallocate(_M_impl._M_start._M_p, - _M_impl._M_end_of_storage - _M_impl._M_start._M_p); + { + const size_t __n = _M_impl._M_end_addr() - _M_impl._M_start._M_p; + _Bit_alloc_traits::deallocate(_M_impl, + _M_impl._M_end_of_storage - __n, + __n); + } } static size_t @@ -526,6 +541,8 @@ template class vector : protected _Bvector_base<_Alloc> { typedef _Bvector_base<_Alloc> _Base; + typedef typename _Base::_Bit_pointer _Bit_pointer; + typedef typename _Base::_Bit_alloc_traits _Bit_alloc_traits; #if __cplusplus >= 201103L template friend struct hash; @@ -573,7 +590,7 @@ template : _Base(__a) { _M_initialize(__n); - std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_of_storage, + std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_addr(), __value ? ~0 : 0); } #else @@ -583,13 +600,13 @@ template : _Base(__a) { _M_initialize(__n); - std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_of_storage, + std::fill(this->_M_impl._M_start._M_p, this->_M_impl._M_end_addr(), __value ? ~0 : 0); } #endif vector(const vector& __x) - : _Base(__x._M_get_Bit_allocator()) + : _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator())) { _M_initialize(__x.size()); _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); @@ -599,6 +616,34 @@ template vector(vector&& __x) noexcept : _Base(std::move(__x)) { } + vector(vector&& __x, const allocator_type& __a) + noexcept(_Bit_alloc_traits::_S_always_equal()) + : _Base(__a) + { + if (__x.get_allocator() == __a) + { + this->_M_impl._M_start = __x._M_impl._M_start; + this->_M_impl._M_finish = __x._M_impl._M_finish; + this->_M_impl._M_end_of_storage = __x._M_impl._M_end_of_storage; + __x._M_impl._M_start = _Bit_iterator(); + __x._M_impl._M_finish = _Bit_iterator(); + __x._M_impl._M_end_of_storage = nullptr; + } + else + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), begin()); + __x.clear(); + } + } + + vector(const vector& __x, const allocator_type& __a) + : _Base(__a) + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); + } + vector(initializer_list __l, const allocator_type& __a = allocator_type()) : _Base(__a) @@ -633,6 +678,21 @@ template { if (&__x == this) return *this; +#if __cplusplus >= 201103L + if (_Bit_alloc_traits::_S_propagate_on_copy_assign()) + { + if (this->_M_get_Bit_allocator() != __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + _M_initialize(__x.size()); + } + else + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } +#endif if (__x.size() > capacity()) { this->_M_deallocate(); @@ -645,12 +705,32 @@ template #if __cplusplus >= 201103L vector& - operator=(vector&& __x) + operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move()) { - // NB: DR 1204. - // NB: DR 675. - this->clear(); - this->swap(__x); + if (_Bit_alloc_traits::_S_propagate_on_move_assign() + || this->_M_get_Bit_allocator() == __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + this->_M_impl._M_start = __x._M_impl._M_start; + this->_M_impl._M_finish = __x._M_impl._M_finish; + this->_M_impl._M_end_of_storage = __x._M_impl._M_end_of_storage; + __x._M_impl._M_start = _Bit_iterator(); + __x._M_impl._M_finish = _Bit_iterator(); + __x._M_impl._M_end_of_storage = nullptr; + std::__alloc_on_move(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } + else + { + if (__x.size() > capacity()) + { + this->_M_deallocate(); + _M_initialize(__x.size()); + } + this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), + begin()); + __x.clear(); + } return *this; } @@ -752,14 +832,15 @@ template const size_type __isize = __gnu_cxx::__numeric_traits::__max - int(_S_word_bit) + 1; - const size_type __asize = _M_get_Bit_allocator().max_size(); + const size_type __asize + = _Bit_alloc_traits::max_size(_M_get_Bit_allocator()); return (__asize <= __isize / int(_S_word_bit) ? __asize * int(_S_word_bit) : __isize); } size_type capacity() const _GLIBCXX_NOEXCEPT - { return size_type(const_iterator(this->_M_impl._M_end_of_storage, 0) + { return size_type(const_iterator(this->_M_impl._M_end_addr(), 0) - begin()); } bool @@ -836,7 +917,7 @@ template void push_back(bool __x) { - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage) + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) *this->_M_impl._M_finish++ = __x; else _M_insert_aux(end(), __x); @@ -844,16 +925,16 @@ template void swap(vector& __x) +#if __cplusplus >= 201103L + noexcept(_Bit_alloc_traits::_S_nothrow_swap()) +#endif { std::swap(this->_M_impl._M_start, __x._M_impl._M_start); std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish); std::swap(this->_M_impl._M_end_of_storage, __x._M_impl._M_end_of_storage); - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 431. Swapping containers with unequal allocators. - std::__alloc_swap:: - _S_do_it(_M_get_Bit_allocator(), __x._M_get_Bit_allocator()); + _Bit_alloc_traits::_S_on_swap(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); } // [23.2.5]/1, third-to-last entry in synopsis listing @@ -873,7 +954,7 @@ template #endif { const difference_type __n = __position - begin(); - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr() && __position == end()) *this->_M_impl._M_finish++ = __x; else @@ -962,8 +1043,8 @@ template void flip() _GLIBCXX_NOEXCEPT { - for (_Bit_type * __p = this->_M_impl._M_start._M_p; - __p != this->_M_impl._M_end_of_storage; ++__p) + _Bit_type * const __end = this->_M_impl._M_end_addr(); + for (_Bit_type * __p = this->_M_impl._M_start._M_p; __p != __end; ++__p) *__p = ~*__p; } @@ -997,9 +1078,9 @@ template void _M_initialize(size_type __n) { - _Bit_type* __q = this->_M_allocate(__n); + _Bit_pointer __q = this->_M_allocate(__n); this->_M_impl._M_end_of_storage = __q + _S_nword(__n); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = iterator(std::__addressof(*__q), 0); this->_M_impl._M_finish = this->_M_impl._M_start + difference_type(__n); } @@ -1021,7 +1102,7 @@ template { _M_initialize(static_cast(__n)); std::fill(this->_M_impl._M_start._M_p, - this->_M_impl._M_end_of_storage, __x ? ~0 : 0); + this->_M_impl._M_end_addr(), __x ? ~0 : 0); } template @@ -1069,14 +1150,14 @@ template if (__n > size()) { std::fill(this->_M_impl._M_start._M_p, - this->_M_impl._M_end_of_storage, __x ? ~0 : 0); + this->_M_impl._M_end_addr(), __x ? ~0 : 0); insert(end(), __n - size(), __x); } else { _M_erase_at_end(begin() + __n); std::fill(this->_M_impl._M_start._M_p, - this->_M_impl._M_end_of_storage, __x ? ~0 : 0); + this->_M_impl._M_end_addr(), __x ? ~0 : 0); } } diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index 19784c0..229fa6d 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -699,11 +699,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector:: _M_reallocate(size_type __n) { - _Bit_type* __q = this->_M_allocate(__n); - this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__n); + iterator __start(std::__addressof(*__q), 0); + this->_M_impl._M_finish = _M_copy_aligned(begin(), end(), __start); this->_M_deallocate(); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; this->_M_impl._M_end_of_storage = __q + _S_nword(__n); } @@ -725,15 +725,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(__n, "vector::_M_fill_insert"); - _Bit_type * __q = this->_M_allocate(__len); - iterator __i = _M_copy_aligned(begin(), __position, - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); std::fill(__i, __i + difference_type(__n), __x); this->_M_impl._M_finish = std::copy(__position, end(), __i + difference_type(__n)); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; } } @@ -759,14 +759,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(__n, "vector::_M_insert_range"); - _Bit_type * __q = this->_M_allocate(__len); - iterator __i = _M_copy_aligned(begin(), __position, - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); __i = std::copy(__first, __last, __i); this->_M_impl._M_finish = std::copy(__position, end(), __i); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; } } } @@ -776,7 +776,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector:: _M_insert_aux(iterator __position, bool __x) { - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_of_storage) + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) { std::copy_backward(__position, this->_M_impl._M_finish, this->_M_impl._M_finish + 1); @@ -787,14 +787,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(size_type(1), "vector::_M_insert_aux"); - _Bit_type * __q = this->_M_allocate(__len); - iterator __i = _M_copy_aligned(begin(), __position, - iterator(__q, 0)); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); *__i++ = __x; this->_M_impl._M_finish = std::copy(__position, end(), __i); this->_M_deallocate(); this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = iterator(__q, 0); + this->_M_impl._M_start = __start; } } diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy.cc new file mode 100644 index 0000000..7bd0b98 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy.cc @@ -0,0 +1,70 @@ +// 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 +// . + +// { dg-options "-std=gnu++11" } + +#include +#include +#include + +using T = bool; + +using __gnu_test::propagating_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(v1); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(0 == v2.get_allocator().get_personality()); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(v1); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +void test03() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(v1, alloc_type(2)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy_assign.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy_assign.cc new file mode 100644 index 0000000..eac6b43 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/copy_assign.cc @@ -0,0 +1,61 @@ +// 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 +// . + +// { dg-options "-std=gnu++11" } + +#include +#include +#include + +using T = bool; + +using __gnu_test::propagating_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = v1; + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = v1; + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/ext_ptr.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/ext_ptr.cc new file mode 100644 index 0000000..94087be --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/ext_ptr.cc @@ -0,0 +1,44 @@ +// 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 +// . + +// { dg-options "-std=gnu++11" } + +#include +#include +#include +#include + +using T = bool; + +using __gnu_test::CustomPointerAlloc; + +template class std::vector>; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef CustomPointerAlloc alloc_type; + typedef std::vector test_type; + test_type v; + v.push_back(T()); + VERIFY( ++v.begin() == v.end() ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/minimal.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/minimal.cc new file mode 100644 index 0000000..56d88b0 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/minimal.cc @@ -0,0 +1,38 @@ +// 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 +// . + +// { dg-options "-std=gnu++11" } +// { dg-do compile } + +#include +#include +#include + +using T = bool; + +using __gnu_test::SimpleAllocator; + +template class std::vector>; + +void test01() +{ + typedef SimpleAllocator alloc_type; + typedef std::allocator_traits traits_type; + typedef std::vector test_type; + test_type v(alloc_type{}); + v.push_back(T()); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move.cc new file mode 100644 index 0000000..c6afcd3 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move.cc @@ -0,0 +1,59 @@ +// 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 +// . + +// { dg-options "-std=gnu++11" } + +#include +#include +#include + +using T = bool; + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef uneq_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1 = { T() }; + auto it = v1.begin(); + test_type v2(std::move(v1)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef uneq_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1 = { T() }; + test_type v2(std::move(v1), alloc_type(2)); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move_assign.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move_assign.cc new file mode 100644 index 0000000..da95498 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/move_assign.cc @@ -0,0 +1,80 @@ +// 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 +// . + +// { dg-options "-std=gnu++11" } + +#include +#include +#include + +using T = bool; + +using __gnu_test::propagating_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = std::move(v1); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + auto it = v1.begin(); + test_type v2(alloc_type(2)); + v2.push_back(T()); + v2 = std::move(v1); + VERIFY( it == v2.begin() ); + VERIFY(0 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +void test03() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + auto it = v1.begin(); + test_type v2(alloc_type(1)); + v2.push_back(T()); + v2 = std::move(v1); + VERIFY( it == v2.begin() ); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + test03(); + return 0; +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/noexcept.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/noexcept.cc new file mode 100644 index 0000000..e86e6b2 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/noexcept.cc @@ -0,0 +1,66 @@ +// 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 +// . + +// { dg-do compile } +// { dg-options "-std=gnu++11" } + +#include +#include + +using T = bool; + +namespace __gnu_test +{ + template + inline void + swap(propagating_allocator& l, propagating_allocator& r) + noexcept(false) + { } +} + +using __gnu_test::propagating_allocator; + +void test01() +{ + typedef std::allocator alloc_type; + typedef std::vector test_type; + test_type v1; + test_type v2; + // this is a GNU extension for std::allocator + static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" ); + static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" ); +} + +void test02() +{ + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + test_type v2(alloc_type(2)); + static_assert( !noexcept( v1 = std::move(v2) ), "Move assign can throw" ); + static_assert( noexcept( v1.swap(v2) ), "Swap cannot throw" ); +} + +void test03() +{ + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + test_type v2(alloc_type(2)); + static_assert( noexcept( v1 = std::move(v2) ), "Move assign cannot throw" ); + static_assert( !noexcept( v1.swap(v2) ), "Swap can throw" ); +} diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc new file mode 100644 index 0000000..cedb24f --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/allocator/swap.cc @@ -0,0 +1,80 @@ +// 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 +// . + +// { dg-options "-std=gnu++11" } + +#include +#include +#include + +using T = bool; + +using __gnu_test::propagating_allocator; + +// It is undefined behaviour to swap() containers wth unequal allocators +// if the allocator doesn't propagate, so ensure the allocators compare +// equal, while still being able to test propagation via get_personality(). +bool +operator==(const propagating_allocator&, + const propagating_allocator&) +{ + return true; +} + +bool +operator!=(const propagating_allocator&, + const propagating_allocator&) +{ + return false; +} + +void test01() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + std::swap(v1, v2); + VERIFY(1 == v1.get_allocator().get_personality()); + VERIFY(2 == v2.get_allocator().get_personality()); + // swap back so assertions in uneq_allocator::deallocate don't fail + std::swap(v1, v2); +} + +void test02() +{ + bool test __attribute__((unused)) = true; + typedef propagating_allocator alloc_type; + typedef std::vector test_type; + test_type v1(alloc_type(1)); + v1.push_back(T()); + test_type v2(alloc_type(2)); + v2.push_back(T()); + std::swap(v1, v2); + VERIFY(2 == v1.get_allocator().get_personality()); + VERIFY(1 == v2.get_allocator().get_personality()); +} + +int main() +{ + test01(); + test02(); + return 0; +}