From patchwork Mon Apr 28 21:07:47 2014 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: 343599 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 B2FDE1400BE for ; Tue, 29 Apr 2014 07:08:41 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; q=dns; s=default; b=dxyb2yNgNUTmI7uBe EFtmxkxIOrTdhdaQJ6oEf9Svu+a8qkMJbwB7q2mbljncsvVEfhWfCm9VJ1T58T68 by7/RkR8OmZGuci9bWWX/FksPXxnrkRdZdeMxIg75vacQjjXzu7ayjFOICFLMkev L8+cR9qwZs1EWkkZ/hJj9mzizk= 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 :message-id:date:from:mime-version:to:cc:subject:references :in-reply-to:content-type; s=default; bh=4rC9kB/QsiJbNh6WRzXh1k7 SZ34=; b=vycnkfJkZy/30LaHMLigA0RpuzXWKMijz42vZEhWQ9g6nxDhKLewlFC GGGSPqsjQa5LUVh02Dl6dNwAexb4SYpa0oQsstFSgway+IuaJzqRlxqEyWuyeQ8G mOElZZAmCh6l813szzkOXPA9m+c74v9RTHqHvEy1M5oamRjUk91U= Received: (qmail 31825 invoked by alias); 28 Apr 2014 21:08:10 -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 31799 invoked by uid 89); 28 Apr 2014 21:08:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.1 required=5.0 tests=AWL, BAYES_50, FILL_THIS_FORM_LOAN, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail-we0-f179.google.com Received: from mail-we0-f179.google.com (HELO mail-we0-f179.google.com) (74.125.82.179) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 28 Apr 2014 21:07:56 +0000 Received: by mail-we0-f179.google.com with SMTP id x48so6796840wes.24 for ; Mon, 28 Apr 2014 14:07:52 -0700 (PDT) X-Received: by 10.194.92.81 with SMTP id ck17mr21199821wjb.14.1398719272367; Mon, 28 Apr 2014 14:07:52 -0700 (PDT) Received: from [192.168.0.22] (arf62-1-82-237-250-248.fbx.proxad.net. [82.237.250.248]) by mx.google.com with ESMTPSA id fx6sm476843wib.4.2014.04.28.14.07.48 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 28 Apr 2014 14:07:50 -0700 (PDT) Message-ID: <535EC323.2050108@gmail.com> Date: Mon, 28 Apr 2014 23:07:47 +0200 From: =?ISO-8859-1?Q?Fran=E7ois_Dumont?= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0 MIME-Version: 1.0 To: Jonathan Wakely CC: "libstdc++@gcc.gnu.org" , gcc-patches Subject: Re: debug container patch References: <53503D01.5000007@gmail.com> <20140427133918.GV928@redhat.com> In-Reply-To: <20140427133918.GV928@redhat.com> On 27/04/2014 15:39, Jonathan Wakely wrote: > On 17/04/14 22:43 +0200, François Dumont wrote: >> Hi >> >> Here is a patch to globally enhance debug containers implementation. > > François, sorry for the delay, this is a large patch and I wanted to > give it the time it deserves to review properly. No problem, I see that there are a lot of proposals lately. > > I understand why this is needed, but it changes the layout of the > classes in very significant ways, meaning the debug containers will > not be compatible across GCC releases. I'm OK with that now, but from > the next major GCC release I'd like to avoid that in future. I remember Paolo saying that there is no abi guaranty for debug mode this is why I didn't hesitate in making this proposal. Will there be one in the future ? I plan also breaking changes for profile mode to fix its very bad performance. > >> I noticed also that in std/c++11/debug.cc we have some methods >> qualified with noexcept while in a C++03 user code those methods will >> have a throw() qualification. Is that fine ? > > As I said in my last mail, yes, those specifications are compatible. > But I don't think your changes are doing what you think they are doing > in all cases. Using _GLIBCXX_NOEXCEPT does not expand to throw() in > C++03 mode, it expands to nothing. Yes, I discover this difference in one of your recent mail. > >> * include/debug/safe_unordered_container.tcc > > N.B. This file has no changes listed in the changelog entry. I reviewed the ChangeLog and limit modifications like in this file. Note however that patch have been generated with '-x -b' option to hide white space modifications. I clean usage of white chars in impacted files, replaced some white spaces with tabs and remove useless white spaces. > >> @@ -69,8 +75,26 @@ >> >> // 23.2.1.1 construct/copy/destroy: >> >> - deque() : _Base() { } >> +#if __cplusplus < 201103L >> + deque() >> + : _Base() { } >> >> + deque(const deque& __x) >> + : _Base(__x) { } >> + >> + ~deque() _GLIBCXX_NOEXCEPT { } > > In C++03 mode the _GLIBCXX_NOEXCEPT macro expands to an empty string, > so it is useless in this chunk of code, which is only compiled for > C++03 mode. It should probably just be removed here (and in all the > other debug containers which use it in C++03-only code). Ok, I cleaned those. Did you mean removing the whole explicit destructor ? Is it a coding Standard to always explicitly implement the destructor or just a way to have Doxygen generate ? > + * before-begin ownership.*/ >> + template >> + void >> + _Safe_forward_list<_SafeSequence>:: >> + _M_swap(_Safe_sequence_base& __other) noexcept >> + { >> + __gnu_cxx::__scoped_lock sentry(_M_this()._M_get_mutex()); > > Shouldn't we be locking both containers' mutexes here? > As we do in src/c++11/debug.cc Good point, not a regression but nice to fix in this patch. > >> + forward_list(forward_list&& __list, const allocator_type& __al) >> + : _Safe(std::move(__list), __al), >> + _Base(std::move(__list), __al) >> + { } > > This makes me feel uneasy, seeing a moved-from object being used > again, but I don't think changing it to use static_casts to the two > base classes would look better, so let's leave it like that. That indeed looks scary, we replaced with: forward_list(forward_list&& __list, const allocator_type& __al) : _Safe(std::move(__list._M_safe()), __al), _Base(std::move(__list._M_base()), __al) { } it makes clearer the fact that we move each part. > >> Index: include/debug/safe_base.h >> =================================================================== >> --- include/debug/safe_base.h (revision 209446) >> +++ include/debug/safe_base.h (working copy) >> @@ -188,22 +188,18 @@ >> >> protected: >> // Initialize with a version number of 1 and no iterators >> - _Safe_sequence_base() >> + _Safe_sequence_base() _GLIBCXX_NOEXCEPT > > This use of _GLIBCXX_NOEXCEPT are correct, if the intention is to be > noexcept in C++11 and have no exception specification in C++98/C++03. Yes, I preferred to use default implementation for special function in C++11 so I qualified as many things as possible noexcept so that resulting noexcept qualification depends only on the normal mode noexcept qualification. > >> : _M_iterators(0), _M_const_iterators(0), _M_version(1) >> { } >> >> #if __cplusplus >= 201103L >> _Safe_sequence_base(const _Safe_sequence_base&) noexcept >> : _Safe_sequence_base() { } >> - >> - _Safe_sequence_base(_Safe_sequence_base&& __x) noexcept >> - : _Safe_sequence_base() >> - { _M_swap(__x); } >> #endif >> >> /** Notify all iterators that reference this sequence that the >> sequence is being destroyed. */ >> - ~_Safe_sequence_base() >> + ~_Safe_sequence_base() _GLIBCXX_NOEXCEPT > > This is redundant. In C++03 the macro expands to nothing, and in C++11 > destructors are noexcept by default anyway, so the macro adds nothing. Ok, I didn't knew, I cleaned those then. > >> { this->_M_detach_all(); } >> >> /** Detach all iterators, leaving them singular. */ >> @@ -231,7 +227,7 @@ >> * one container now reference the other container. >> */ >> void >> - _M_swap(_Safe_sequence_base& __x); >> + _M_swap(_Safe_sequence_base& __x) _GLIBCXX_NOEXCEPT; > > This is OK, if the intention is to only have an exc eption spec in > C++11. This is used in noexcept constructors so I prefer to make it noexcept too. I replaced this one with _GLIBCXX_USE_NOEXCEPT cause in src/c++11/debug.cc we always build it as noexcept, just in case it impacts the mangled name. I saw _GLIBCXX_NOTHROW in c++config but doesn't seem to be used. > > >> +#if __cplusplus >= 201103L >> + _Safe_container& >> + operator=(_Safe_container&& __x) noexcept >> + { >> + __glibcxx_check_self_move_assign(__x); > > N.B. I'm writing a paper for the next committee meeting to make it > clear that self-move-assignment is not undefined behaviour, so this > check will have to be removed in the future. At least your change > means there are fewer places to remove it from :-) > See http://gcc.gnu.org/PR59603 for some background. > > I only looked over the testsuite changes quickly, but they look good. > > The changes above are only minor, overall I like the proposal very > much. Thanks for working on this, one day our debug mode containers > will be perfect! :-) > Not yet, I will start submitting patches for the debug algos soon :-) Here is the patch again with all your remarks. Ok to commit with the following ChangeLog ? 2014-04-29 François Dumont * include/debug/macros.h [__glibcxx_check_equal_allocs]: Add parameter to pass the 2 instances to check allocator equality. * include/debug/safe_container.h: New, define _Safe_container<>. * include/Makefile.am: Add previous. * include/debug/deque (std::__debug::deque<>): Inherit _Safe_container<>. Use default implementation for all special functions. * include/debug/forward_list (std::__debug::forward_list<>): Likewise. * include/debug/list (std::__debug::list<>): Likewise. * include/debug/map.h (std::__debug::map<>): Likewise. * include/debug/multimap.h (std::__debug::multimap<>): Likewise. * include/debug/set.h (std::__debug::set<>): Likewise. * include/debug/multiset.h (std::__debug::multiset<>): Likewise. * include/debug/string (std::__debug::basic_string<>): Likewise. * include/debug/unordered_map (std::__debug::unordered_map<>): Likewise. (std::__debug::unordered_multimap<>): Likewise. * include/debug/unordered_set (std::__debug::unordered_set<>): Likewise. (std::__debug::unordered_multiset<>): Likewise. * include/debug/vector (std::__debug::vector<>): Likewise. * include/debug/safe_base.h (_Safe_sequence_base()): Add noexcept. (_Safe_sequence_base(_Safe_sequence_base&&): Remove. (~_Safe_sequence_base()): Add noexcept. * include/debug/safe_sequence.h (std::__debug::_Safe_node_sequence<>): New. * include/debug/safe_unordered_base.h (_Safe_unordered_container_base()): Add noexcept. (~_Safe_unordered_container_base()): Likewise. (_M_swap(_Safe_unordered_container_base&)): Likewise. * include/debug/safe_unordered_container.h: (_Safe_unordered_container<>::_M_invalidate_locals()): New. (_Safe_unordered_container<>::_M_invalidate_all()): New. * src/c++11/debug.cc: Limit includes, adapt methods noexcept qualifications. * testsuite/util/debug/checks.h (check_construct1): Just implement an invalid constructor invocation and no other operations potentially not supported by some types of container. (check_construct2): Likewise. (check_construct3): Likewise. * testsuite/23_containers/forward_list/allocator/move.cc: Add check on iterators to make sure they are correctly moved in debug mode. * testsuite/23_containers/forward_list/allocator/move_assign.cc: Likewise. * testsuite/23_containers/map/allocator/move.cc: Likewise. * testsuite/23_containers/map/allocator/move_assign.cc: Likewise. * testsuite/23_containers/multimap/allocator/move.cc: Likewise. * testsuite/23_containers/multimap/allocator/move_assign.cc: Likewise. * testsuite/23_containers/multiset/allocator/move.cc: Likewise. * testsuite/23_containers/multiset/allocator/move_assign.cc: Likewise. * testsuite/23_containers/set/allocator/move.cc: Likewise. * testsuite/23_containers/set/allocator/move_assign.cc: Likewise. * testsuite/23_containers/unordered_map/allocator/move.cc: Likewise. * testsuite/23_containers/unordered_map/allocator/move_assign.cc: Likewise. * testsuite/23_containers/unordered_multimap/allocator/move.cc: Likewise. * testsuite/23_containers/unordered_multimap/allocator/move_assign.cc: Likewise. * testsuite/23_containers/unordered_multiset/allocator/move.cc: Likewise. * testsuite/23_containers/unordered_multiset/allocator/move_assign.cc: Likewise. * testsuite/23_containers/unordered_set/allocator/move.cc: Likewise. * testsuite/23_containers/unordered_set/allocator/move_assign.cc: Likewise. * testsuite/23_containers/forward_list/debug/construct1_neg.cc: New. * testsuite/23_containers/forward_list/debug/construct2_neg.cc: New. * testsuite/23_containers/forward_list/debug/construct3_neg.cc: New. * testsuite/23_containers/forward_list/debug/construct4_neg.cc: New. * testsuite/23_containers/forward_list/debug/move_assign_neg.cc: New. * testsuite/23_containers/forward_list/debug/move_neg.cc: New. * testsuite/23_containers/map/debug/construct5_neg.cc: New. * testsuite/23_containers/map/debug/move_assign_neg.cc: New. * testsuite/23_containers/map/debug/move_neg.cc: New. * testsuite/23_containers/multimap/debug/construct5_neg.cc: New. * testsuite/23_containers/multimap/debug/move_assign_neg.cc: New. * testsuite/23_containers/multimap/debug/move_neg.cc: New. * testsuite/23_containers/multiset/debug/construct5_neg.cc: New. * testsuite/23_containers/multiset/debug/move_assign_neg.cc: New. * testsuite/23_containers/multiset/debug/move_neg.cc: New. * testsuite/23_containers/set/debug/construct5_neg.cc: New. * testsuite/23_containers/set/debug/move_assign_neg.cc: New. * testsuite/23_containers/set/debug/move_neg.cc: New. * testsuite/23_containers/unordered_map/debug/construct5_neg.cc: New. * testsuite/23_containers/unordered_map/debug/move_assign_neg.cc: New. * testsuite/23_containers/unordered_map/debug/move_neg.cc: New. * testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc: New. * testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc: New. * testsuite/23_containers/unordered_multimap/debug/move_neg.cc: New. * testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc: New. * testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc: New. * testsuite/23_containers/unordered_multiset/debug/move_neg.cc: New. * testsuite/23_containers/unordered_set/debug/construct5_neg.cc: New. * testsuite/23_containers/unordered_set/debug/move_assign_neg.cc: New. * testsuite/23_containers/unordered_set/debug/move_neg.cc: New. * testsuite/23_containers/vector/debug/move_neg.cc: New. François Index: include/Makefile.am =================================================================== --- include/Makefile.am (revision 209879) +++ include/Makefile.am (working copy) @@ -733,6 +733,7 @@ ${debug_srcdir}/multimap.h \ ${debug_srcdir}/multiset.h \ ${debug_srcdir}/safe_base.h \ + ${debug_srcdir}/safe_container.h \ ${debug_srcdir}/safe_iterator.h \ ${debug_srcdir}/safe_iterator.tcc \ ${debug_srcdir}/safe_local_iterator.h \ Index: include/debug/deque =================================================================== --- include/debug/deque (revision 209879) +++ include/debug/deque (working copy) @@ -31,6 +31,7 @@ #include #include +#include #include namespace std _GLIBCXX_VISIBILITY(default) @@ -40,21 +41,26 @@ /// Class std::deque with safety/checking/debug instrumentation. template > class deque - : public _GLIBCXX_STD_C::deque<_Tp, _Allocator>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + deque<_Tp, _Allocator>, _Allocator, + __gnu_debug::_Safe_sequence, false>, + public _GLIBCXX_STD_C::deque<_Tp, _Allocator> { typedef _GLIBCXX_STD_C::deque<_Tp, _Allocator> _Base; + typedef __gnu_debug::_Safe_container< + deque, _Allocator, __gnu_debug::_Safe_sequence, false> _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; + public: typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator,deque> + typedef __gnu_debug::_Safe_iterator<_Base_iterator, deque> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,deque> + typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, deque> const_iterator; typedef typename _Base::size_type size_type; @@ -69,8 +75,26 @@ // 23.2.1.1 construct/copy/destroy: - deque() : _Base() { } +#if __cplusplus < 201103L + deque() + : _Base() { } + deque(const deque& __x) + : _Base(__x) { } + + ~deque() { } +#else + deque() = default; + deque(const deque&) = default; + deque(deque&&) = default; + + deque(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__l, __a) { } + + ~deque() = default; +#endif + explicit deque(const _Allocator& __a) : _Base(__a) { } @@ -103,48 +127,28 @@ __gnu_debug::__base(__last), __a) { } - deque(const deque& __x) - : _Base(__x) { } - deque(const _Base& __x) : _Base(__x) { } -#if __cplusplus >= 201103L - deque(deque&& __x) - : _Base(std::move(__x)) - { this->_M_swap(__x); } - - deque(initializer_list __l, - const allocator_type& __a = allocator_type()) - : _Base(__l, __a) { } -#endif - - ~deque() _GLIBCXX_NOEXCEPT { } - +#if __cplusplus < 201103L deque& operator=(const deque& __x) { - *static_cast<_Base*>(this) = __x; - this->_M_invalidate_all(); + this->_M_safe() = __x; + _M_base() = __x; return *this; } +#else + deque& + operator=(const deque&) = default; -#if __cplusplus >= 201103L deque& - operator=(deque&& __x) noexcept - { - // NB: DR 1204. - // NB: DR 675. - __glibcxx_check_self_move_assign(__x); - clear(); - swap(__x); - return *this; - } + operator=(deque&&) = default; deque& operator=(initializer_list __l) { - *static_cast<_Base*>(this) = __l; + _M_base() = __l; this->_M_invalidate_all(); return *this; } @@ -241,7 +245,7 @@ typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth; this->_M_invalidate_if(_After_nth(__n, _Base::begin())); } - + public: // 23.2.1.2 capacity: using _Base::size; @@ -559,10 +563,13 @@ } void - swap(deque& __x) _GLIBCXX_NOEXCEPT + swap(deque& __x) +#if __cplusplus >= 201103L + noexcept( noexcept(declval<_Base>().swap(__x)) ) +#endif { + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); } void Index: include/debug/forward_list =================================================================== --- include/debug/forward_list (revision 209879) +++ include/debug/forward_list (working copy) @@ -33,8 +33,138 @@ #include #include +#include #include +namespace __gnu_debug +{ + /// Special iterators swap and invalidation for forward_list because of the + /// before_begin iterator. + template + class _Safe_forward_list + : public _Safe_sequence<_SafeSequence> + { + _SafeSequence& + _M_this() noexcept + { return *static_cast<_SafeSequence*>(this); } + + static void + _M_swap_aux(_Safe_sequence_base& __lhs, + _Safe_iterator_base*& __lhs_iterators, + _Safe_sequence_base& __rhs, + _Safe_iterator_base*& __rhs_iterators); + + void _M_swap_single(_Safe_sequence_base&) noexcept; + + protected: + void + _M_invalidate_all() + { + using _Base_const_iterator = __decltype(_M_this()._M_base().cend()); + this->_M_invalidate_if([this](_Base_const_iterator __it) + { + return __it != _M_this()._M_base().cbefore_begin() + && __it != _M_this()._M_base().cend(); }); + } + + void _M_swap(_Safe_sequence_base&) noexcept; + }; + + template + void + _Safe_forward_list<_SafeSequence>:: + _M_swap_aux(_Safe_sequence_base& __lhs, + _Safe_iterator_base*& __lhs_iterators, + _Safe_sequence_base& __rhs, + _Safe_iterator_base*& __rhs_iterators) + { + using const_iterator = typename _SafeSequence::const_iterator; + _Safe_iterator_base* __bbegin_its = 0; + _Safe_iterator_base* __last_bbegin = 0; + _SafeSequence& __rseq = static_cast<_SafeSequence&>(__rhs); + + for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;) + { + // Even iterator is cast to const_iterator, not a problem. + const_iterator* __victim = static_cast(__iter); + __iter = __iter->_M_next; + if (__victim->base() == __rseq._M_base().cbefore_begin()) + { + __victim->_M_unlink(); + if (__lhs_iterators == __victim) + __lhs_iterators = __victim->_M_next; + if (__bbegin_its) + { + __victim->_M_next = __bbegin_its; + __bbegin_its->_M_prior = __victim; + } + else + __last_bbegin = __victim; + __bbegin_its = __victim; + } + else + __victim->_M_sequence = &__lhs; + } + + if (__bbegin_its) + { + if (__rhs_iterators) + { + __rhs_iterators->_M_prior = __last_bbegin; + __last_bbegin->_M_next = __rhs_iterators; + } + __rhs_iterators = __bbegin_its; + } + } + + template + void + _Safe_forward_list<_SafeSequence>:: + _M_swap_single(_Safe_sequence_base& __other) noexcept + { + std::swap(_M_this()._M_iterators, __other._M_iterators); + std::swap(_M_this()._M_const_iterators, __other._M_const_iterators); + // Useless, always 1 on forward_list + //std::swap(_M_this()_M_version, __other._M_version); + _Safe_iterator_base* __this_its = _M_this()._M_iterators; + _M_swap_aux(__other, __other._M_iterators, + _M_this(), _M_this()._M_iterators); + _Safe_iterator_base* __this_const_its = _M_this()._M_const_iterators; + _M_swap_aux(__other, __other._M_const_iterators, + _M_this(), _M_this()._M_const_iterators); + _M_swap_aux(_M_this(), __this_its, + __other, __other._M_iterators); + _M_swap_aux(_M_this(), __this_const_its, + __other, __other._M_const_iterators); + } + + /* Special forward_list _M_swap version that does not swap the + * before-begin ownership.*/ + template + void + _Safe_forward_list<_SafeSequence>:: + _M_swap(_Safe_sequence_base& __other) noexcept + { + // We need to lock both sequences to swap + using namespace __gnu_cxx; + __mutex *__this_mutex = &_M_this()._M_get_mutex(); + __mutex *__other_mutex = &__other._M_get_mutex(); + if (__this_mutex == __other_mutex) + { + __scoped_lock __lock(*__this_mutex); + _M_swap_single(__other); + } + else + { + __scoped_lock __l1(__this_mutex < __other_mutex + ? *__this_mutex : *__other_mutex); + __scoped_lock __l2(__this_mutex < __other_mutex + ? *__other_mutex : *__this_mutex); + _M_swap_single(__other); + } + } +} + namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug @@ -42,119 +172,88 @@ /// Class std::forward_list with safety/checking/debug instrumentation. template > class forward_list - : public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + forward_list<_Tp, _Alloc>, _Alloc, __gnu_debug::_Safe_forward_list>, + public _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> { typedef _GLIBCXX_STD_C::forward_list<_Tp, _Alloc> _Base; + typedef __gnu_debug::_Safe_container< + forward_list, _Alloc, __gnu_debug::_Safe_forward_list> _Safe; typedef typename _Base::iterator _Base_iterator; typedef typename _Base::const_iterator _Base_const_iterator; - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_GLIBCXX_STD_C::_Fwd_list_node<_Tp>>::other _Node_alloc_type; - - typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; - public: typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, - forward_list> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, - forward_list> const_iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_iterator, forward_list> iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_const_iterator, forward_list> const_iterator; typedef typename _Base::size_type size_type; typedef typename _Base::difference_type difference_type; typedef _Tp value_type; - typedef _Alloc allocator_type; + typedef typename _Base::allocator_type allocator_type; typedef typename _Base::pointer pointer; typedef typename _Base::const_pointer const_pointer; // 23.2.3.1 construct/copy/destroy: explicit - forward_list(const _Alloc& __al = _Alloc()) + forward_list(const allocator_type& __al = allocator_type()) : _Base(__al) { } - forward_list(const forward_list& __list, const _Alloc& __al) + forward_list(const forward_list& __list, const allocator_type& __al) : _Base(__list, __al) { } - forward_list(forward_list&& __list, const _Alloc& __al) - : _Base(std::move(__list._M_base()), __al) - { - if (__list.get_allocator() == __al) - this->_M_swap(__list); - else - __list._M_invalidate_all(); - } + forward_list(forward_list&& __list, const allocator_type& __al) + : _Safe(std::move(__list._M_safe()), __al), + _Base(std::move(__list._M_base()), __al) + { } explicit - forward_list(size_type __n, const _Alloc& __al = _Alloc()) + forward_list(size_type __n, const allocator_type& __al = allocator_type()) : _Base(__n, __al) { } forward_list(size_type __n, const _Tp& __value, - const _Alloc& __al = _Alloc()) + const allocator_type& __al = allocator_type()) : _Base(__n, __value, __al) { } template> forward_list(_InputIterator __first, _InputIterator __last, - const _Alloc& __al = _Alloc()) + const allocator_type& __al = allocator_type()) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), __gnu_debug::__base(__last), __al) { } - forward_list(const forward_list& __list) - : _Base(__list) - { } + forward_list(const forward_list&) = default; - forward_list(forward_list&& __list) noexcept - : _Base(std::move(__list._M_base())) - { - this->_M_swap(__list); - } + forward_list(forward_list&&) = default; forward_list(std::initializer_list<_Tp> __il, - const _Alloc& __al = _Alloc()) + const allocator_type& __al = allocator_type()) : _Base(__il, __al) { } - ~forward_list() noexcept - { } + ~forward_list() = default; forward_list& - operator=(const forward_list& __list) - { - static_cast<_Base&>(*this) = __list; - this->_M_invalidate_all(); - return *this; - } + operator=(const forward_list&) = default; forward_list& - operator=(forward_list&& __list) - noexcept(_Node_alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__list); - bool __xfer_memory = _Node_alloc_traits::_S_propagate_on_move_assign() - || __list.get_allocator() == this->get_allocator(); - static_cast<_Base&>(*this) = std::move(__list); - if (__xfer_memory) - this->_M_swap(__list); - else - this->_M_invalidate_all(); - __list._M_invalidate_all(); - return *this; - } + operator=(forward_list&&) = default; forward_list& operator=(std::initializer_list<_Tp> __il) { - static_cast<_Base&>(*this) = __il; + _M_base() = __il; this->_M_invalidate_all(); return *this; } @@ -347,12 +446,10 @@ void swap(forward_list& __list) - noexcept(_Node_alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__list)) ) { - if (!_Node_alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__list); + _Safe::_M_swap(__list); _Base::swap(__list); - this->_M_swap(__list); } void @@ -644,93 +741,9 @@ const _Base& _M_base() const noexcept { return *this; } - - private: - void - _M_invalidate_all() - { - this->_M_invalidate_if([this](_Base_const_iterator __it) - { - return __it != this->_M_base().cbefore_begin() - && __it != this->_M_base().cend(); - }); - } - typedef __gnu_debug::_Safe_iterator_base _Safe_iterator_base; - static void - _M_swap_aux(forward_list& __lhs, - _Safe_iterator_base*& __lhs_iterators, - forward_list& __rhs, - _Safe_iterator_base*& __rhs_iterators); - void _M_swap(forward_list& __list); }; template - void - forward_list<_Tp, _Alloc>:: - _M_swap_aux(forward_list<_Tp, _Alloc>& __lhs, - __gnu_debug::_Safe_iterator_base*& __lhs_iterators, - forward_list<_Tp, _Alloc>& __rhs, - __gnu_debug::_Safe_iterator_base*& __rhs_iterators) - { - using __gnu_debug::_Safe_iterator_base; - _Safe_iterator_base* __bbegin_its = 0; - _Safe_iterator_base* __last_bbegin = 0; - for (_Safe_iterator_base* __iter = __lhs_iterators; __iter;) - { - // Even iterator are casted to const_iterator, not a problem. - const_iterator* __victim = static_cast(__iter); - __iter = __iter->_M_next; - if (__victim->base() == __rhs._M_base().cbefore_begin()) - { - __victim->_M_unlink(); - if (__lhs_iterators == __victim) - __lhs_iterators = __victim->_M_next; - if (__bbegin_its) - { - __victim->_M_next = __bbegin_its; - __bbegin_its->_M_prior = __victim; - } - else - __last_bbegin = __victim; - __bbegin_its = __victim; - } - else - __victim->_M_sequence = &__lhs; - } - - if (__bbegin_its) - { - if (__rhs_iterators) - { - __rhs_iterators->_M_prior = __last_bbegin; - __last_bbegin->_M_next = __rhs_iterators; - } - __rhs_iterators = __bbegin_its; - } - } - - /* Special forward_list _M_swap version that do not swap the - * before-begin ownership.*/ - template - void - forward_list<_Tp, _Alloc>:: - _M_swap(forward_list<_Tp, _Alloc>& __list) - { - __gnu_cxx::__scoped_lock sentry(this->_M_get_mutex()); - std::swap(this->_M_iterators, __list._M_iterators); - std::swap(this->_M_const_iterators, __list._M_const_iterators); - // Useless, always 1 on forward_list - //std::swap(this->_M_version, __list._M_version); - _Safe_iterator_base* __this_its = this->_M_iterators; - _M_swap_aux(__list, __list._M_iterators, *this, this->_M_iterators); - _Safe_iterator_base* __this_const_its = this->_M_const_iterators; - _M_swap_aux(__list, __list._M_const_iterators, *this, - this->_M_const_iterators); - _M_swap_aux(*this, __this_its, __list, __list._M_iterators); - _M_swap_aux(*this, __this_const_its, __list, __list._M_const_iterators); - } - - template bool operator==(const forward_list<_Tp, _Alloc>& __lx, const forward_list<_Tp, _Alloc>& __ly) Index: include/debug/list =================================================================== --- include/debug/list (revision 209879) +++ include/debug/list (working copy) @@ -31,6 +31,7 @@ #include #include +#include #include namespace std _GLIBCXX_VISIBILITY(default) @@ -40,15 +41,20 @@ /// Class std::list with safety/checking/debug instrumentation. template > class list - : public _GLIBCXX_STD_C::list<_Tp, _Allocator>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + list<_Tp, _Allocator>, _Allocator, + __gnu_debug::_Safe_node_sequence, false>, + public _GLIBCXX_STD_C::list<_Tp, _Allocator> { typedef _GLIBCXX_STD_C::list<_Tp, _Allocator> _Base; + typedef __gnu_debug::_Safe_container< + list, _Allocator, __gnu_debug::_Safe_node_sequence, false> _Safe; typedef typename _Base::iterator _Base_iterator; typedef typename _Base::const_iterator _Base_const_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + public: typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; @@ -70,9 +76,26 @@ // 23.2.2.1 construct/copy/destroy: - list() _GLIBCXX_NOEXCEPT +#if __cplusplus < 201103L + list() : _Base() { } + list(const list& __x) + : _Base(__x) { } + + ~list() { } +#else + list() = default; + list(const list&) = default; + list(list&&) = default; + + list(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__l, __a) { } + + ~list() = default; +#endif + explicit list(const _Allocator& __a) _GLIBCXX_NOEXCEPT : _Base(__a) { } @@ -105,49 +128,29 @@ __gnu_debug::__base(__last), __a) { } - list(const list& __x) - : _Base(__x) { } - list(const _Base& __x) : _Base(__x) { } -#if __cplusplus >= 201103L - list(list&& __x) noexcept - : _Base(std::move(__x)) - { this->_M_swap(__x); } - - list(initializer_list __l, - const allocator_type& __a = allocator_type()) - : _Base(__l, __a) { } -#endif - - ~list() _GLIBCXX_NOEXCEPT { } - +#if __cplusplus < 201103L list& operator=(const list& __x) { - static_cast<_Base&>(*this) = __x; - this->_M_invalidate_all(); + this->_M_safe() = __x; + _M_base() = __x; return *this; } +#else + list& + operator=(const list&) = default; -#if __cplusplus >= 201103L list& - operator=(list&& __x) - { - // NB: DR 1204. - // NB: DR 675. - __glibcxx_check_self_move_assign(__x); - clear(); - swap(__x); - return *this; - } + operator=(list&&) = default; list& operator=(initializer_list __l) { - static_cast<_Base&>(*this) = __l; this->_M_invalidate_all(); + _M_base() = __l; return *this; } @@ -245,16 +248,14 @@ { this->_M_detach_singular(); - // if __sz < size(), invalidate all iterators in [begin+__sz, end()) + // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); _Base_iterator __end = _Base::end(); for (size_type __i = __sz; __victim != __end && __i > 0; --__i) ++__victim; for (; __victim != __end; ++__victim) - { this->_M_invalidate_if(_Equal(__victim)); - } __try { @@ -272,16 +273,14 @@ { this->_M_detach_singular(); - // if __sz < size(), invalidate all iterators in [begin+__sz, end()) + // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); _Base_iterator __end = _Base::end(); for (size_type __i = __sz; __victim != __end && __i > 0; --__i) ++__victim; for (; __victim != __end; ++__victim) - { this->_M_invalidate_if(_Equal(__victim)); - } __try { @@ -299,16 +298,14 @@ { this->_M_detach_singular(); - // if __sz < size(), invalidate all iterators in [begin+__sz, end()) + // if __sz < size(), invalidate all iterators in [begin + __sz, end()) _Base_iterator __victim = _Base::begin(); _Base_iterator __end = _Base::end(); for (size_type __i = __sz; __victim != __end && __i > 0; --__i) ++__victim; for (; __victim != __end; ++__victim) - { this->_M_invalidate_if(_Equal(__victim)); - } __try { @@ -504,9 +501,12 @@ void swap(list& __x) +#if __cplusplus >= 201103L + noexcept( noexcept(declval<_Base>().swap(__x)) ) +#endif { + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); } void @@ -742,13 +742,6 @@ const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } - - private: - void - _M_invalidate_all() - { - this->_M_invalidate_if(_Not_equal(_Base::end())); - } }; template Index: include/debug/macros.h =================================================================== --- include/debug/macros.h (revision 209879) +++ include/debug/macros.h (working copy) @@ -347,10 +347,10 @@ _M_message(__gnu_debug::__msg_valid_load_factor) \ ._M_sequence(*this, "this")) -#define __glibcxx_check_equal_allocs(_Other) \ -_GLIBCXX_DEBUG_VERIFY(this->get_allocator() == _Other.get_allocator(), \ +#define __glibcxx_check_equal_allocs(_This, _Other) \ +_GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \ _M_message(__gnu_debug::__msg_equal_allocs) \ - ._M_sequence(*this, "this")) + ._M_sequence(_This, "this")) #ifdef _GLIBCXX_DEBUG_PEDANTIC # define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_ASSERT(_String != 0) Index: include/debug/map.h =================================================================== --- include/debug/map.h (revision 209879) +++ include/debug/map.h (working copy) @@ -30,6 +30,7 @@ #define _GLIBCXX_DEBUG_MAP_H 1 #include +#include #include #include @@ -41,19 +42,20 @@ template, typename _Allocator = std::allocator > > class map - : public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + map<_Key, _Tp, _Compare, _Allocator>, _Allocator, + __gnu_debug::_Safe_node_sequence>, + public _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator> { - typedef _GLIBCXX_STD_C::map<_Key, _Tp, _Compare, _Allocator> _Base; + typedef _GLIBCXX_STD_C::map< + _Key, _Tp, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_container< + map, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; -#if __cplusplus >= 201103L - typedef __gnu_cxx::__alloc_traits _Alloc_traits; -#endif public: // types: typedef _Key key_type; @@ -78,33 +80,18 @@ // 23.3.1.1 construct/copy/destroy: +#if __cplusplus < 201103L map() : _Base() { } - explicit map(const _Compare& __comp, - const _Allocator& __a = _Allocator()) - : _Base(__comp, __a) { } - - template - map(_InputIterator __first, _InputIterator __last, - const _Compare& __comp = _Compare(), - const _Allocator& __a = _Allocator()) - : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, - __last)), - __gnu_debug::__base(__last), - __comp, __a) { } - map(const map& __x) : _Base(__x) { } - map(const _Base& __x) - : _Base(__x) { } + ~map() { } +#else + map() = default; + map(const map&) = default; + map(map&&) = default; -#if __cplusplus >= 201103L - map(map&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _Base(std::move(__x)) - { this->_M_swap(__x); } - map(initializer_list __l, const _Compare& __c = _Compare(), const allocator_type& __a = allocator_type()) @@ -118,7 +105,8 @@ : _Base(__m, __a) { } map(map&& __m, const allocator_type& __a) - : _Base(std::move(__m._M_base()), __a) { } + : _Safe(std::move(__m._M_safe()), __a), + _Base(std::move(__m._M_base()), __a) { } map(initializer_list __l, const allocator_type& __a) : _Base(__l, __a) { } @@ -130,34 +118,40 @@ __last)), __gnu_debug::__base(__last), __a) { } + + ~map() = default; #endif - ~map() _GLIBCXX_NOEXCEPT { } + map(const _Base& __x) + : _Base(__x) { } + explicit map(const _Compare& __comp, + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + + template + map(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a) { } + +#if __cplusplus < 201103L map& operator=(const map& __x) { + this->_M_safe() = __x; _M_base() = __x; - this->_M_invalidate_all(); return *this; } +#else + map& + operator=(const map&) = default; -#if __cplusplus >= 201103L map& - operator=(map&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(map&&) = default; map& operator=(initializer_list __l) @@ -173,7 +167,7 @@ using _Base::get_allocator; // iterators: - iterator + iterator begin() _GLIBCXX_NOEXCEPT { return iterator(_Base::begin(), this); } @@ -395,15 +389,11 @@ void swap(map& __x) #if __cplusplus >= 201103L - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) #endif { -#if __cplusplus >= 201103L - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); -#endif + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); } void @@ -467,14 +457,6 @@ const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } - - private: - void - _M_invalidate_all() - { - typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; - this->_M_invalidate_if(_Not_equal(_M_base().end())); - } }; template +#include #include #include @@ -41,20 +42,20 @@ template, typename _Allocator = std::allocator > > class multimap - : public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + multimap<_Key, _Tp, _Compare, _Allocator>, _Allocator, + __gnu_debug::_Safe_node_sequence>, + public _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator> { - typedef _GLIBCXX_STD_C::multimap<_Key, _Tp, _Compare, _Allocator> _Base; + typedef _GLIBCXX_STD_C::multimap< + _Key, _Tp, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_container< + multimap, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; -#if __cplusplus >= 201103L - typedef __gnu_cxx::__alloc_traits _Alloc_traits; -#endif public: // types: typedef _Key key_type; @@ -79,33 +80,18 @@ // 23.3.1.1 construct/copy/destroy: +#if __cplusplus < 201103L multimap() : _Base() { } - explicit multimap(const _Compare& __comp, - const _Allocator& __a = _Allocator()) - : _Base(__comp, __a) { } - - template - multimap(_InputIterator __first, _InputIterator __last, - const _Compare& __comp = _Compare(), - const _Allocator& __a = _Allocator()) - : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, - __last)), - __gnu_debug::__base(__last), - __comp, __a) { } - multimap(const multimap& __x) : _Base(__x) { } - multimap(const _Base& __x) - : _Base(__x) { } + ~multimap() { } +#else + multimap() = default; + multimap(const multimap&) = default; + multimap(multimap&&) = default; -#if __cplusplus >= 201103L - multimap(multimap&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _Base(std::move(__x)) - { this->_M_swap(__x); } - multimap(initializer_list __l, const _Compare& __c = _Compare(), const allocator_type& __a = allocator_type()) @@ -119,47 +105,52 @@ : _Base(__m, __a) { } multimap(multimap&& __m, const allocator_type& __a) - : _Base(std::move(__m._M_base()), __a) { } + : _Safe(std::move(__m._M_safe()), __a), + _Base(std::move(__m._M_base()), __a) { } multimap(initializer_list __l, const allocator_type& __a) - : _Base(__l, __a) - { } + : _Base(__l, __a) { } template multimap(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), - __gnu_debug::__base(__last), __a) - { } + __gnu_debug::__base(__last), __a) { } + + ~multimap() = default; #endif - ~multimap() _GLIBCXX_NOEXCEPT { } + explicit multimap(const _Compare& __comp, + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + template + multimap(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a) { } + + multimap(const _Base& __x) + : _Base(__x) { } + +#if __cplusplus < 201103L multimap& operator=(const multimap& __x) { + this->_M_safe() = __x; _M_base() = __x; - this->_M_invalidate_all(); return *this; } +#else + multimap& + operator=(const multimap&) = default; -#if __cplusplus >= 201103L multimap& - operator=(multimap&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(multimap&&) = default; multimap& operator=(initializer_list __l) @@ -247,7 +238,7 @@ this); } #endif - + iterator insert(const value_type& __x) { return iterator(_Base::insert(__x), this); } @@ -379,15 +370,11 @@ void swap(multimap& __x) #if __cplusplus >= 201103L - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) #endif { -#if __cplusplus >= 201103L - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); -#endif + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); } void @@ -451,14 +438,6 @@ const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } - - private: - void - _M_invalidate_all() - { - typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; - this->_M_invalidate_if(_Not_equal(_Base::end())); - } }; template +#include #include #include @@ -41,19 +42,19 @@ template, typename _Allocator = std::allocator<_Key> > class multiset - : public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + multiset<_Key, _Compare, _Allocator>, _Allocator, + __gnu_debug::_Safe_node_sequence>, + public _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator> { typedef _GLIBCXX_STD_C::multiset<_Key, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_container< + multiset, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; -#if __cplusplus >= 201103L - typedef __gnu_cxx::__alloc_traits _Alloc_traits; -#endif public: // types: typedef _Key key_type; @@ -78,33 +79,18 @@ // 23.3.3.1 construct/copy/destroy: +#if __cplusplus < 201103L multiset() : _Base() { } - explicit multiset(const _Compare& __comp, - const _Allocator& __a = _Allocator()) - : _Base(__comp, __a) { } - - template - multiset(_InputIterator __first, _InputIterator __last, - const _Compare& __comp = _Compare(), - const _Allocator& __a = _Allocator()) - : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, - __last)), - __gnu_debug::__base(__last), - __comp, __a) { } - multiset(const multiset& __x) : _Base(__x) { } - multiset(const _Base& __x) - : _Base(__x) { } + ~multiset() { } +#else + multiset() = default; + multiset(const multiset&) = default; + multiset(multiset&&) = default; -#if __cplusplus >= 201103L - multiset(multiset&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _Base(std::move(__x)) - { this->_M_swap(__x); } - multiset(initializer_list __l, const _Compare& __comp = _Compare(), const allocator_type& __a = allocator_type()) @@ -118,7 +104,8 @@ : _Base(__m, __a) { } multiset(multiset&& __m, const allocator_type& __a) - : _Base(std::move(__m._M_base()), __a) { } + : _Safe(std::move(__m._M_safe()), __a), + _Base(std::move(__m._M_base()), __a) { } multiset(initializer_list __l, const allocator_type& __a) : _Base(__l, __a) @@ -129,36 +116,41 @@ const allocator_type& __a) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), - __gnu_debug::__base(__last), __a) - { } + __gnu_debug::__base(__last), __a) { } + + ~multiset() = default; #endif - ~multiset() _GLIBCXX_NOEXCEPT { } + explicit multiset(const _Compare& __comp, + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + template + multiset(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a) { } + + multiset(const _Base& __x) + : _Base(__x) { } + +#if __cplusplus < 201103L multiset& operator=(const multiset& __x) { + this->_M_safe() = __x; _M_base() = __x; - this->_M_invalidate_all(); return *this; } +#else + multiset& + operator=(const multiset&) = default; -#if __cplusplus >= 201103L multiset& - operator=(multiset&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(multiset&&) = default; multiset& operator=(initializer_list __l) @@ -233,7 +225,8 @@ iterator emplace(_Args&&... __args) { - return iterator(_Base::emplace(std::forward<_Args>(__args)...), this); + return iterator(_Base::emplace(std::forward<_Args>(__args)...), + this); } template @@ -364,15 +357,11 @@ void swap(multiset& __x) #if __cplusplus >= 201103L - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) #endif { -#if __cplusplus >= 201103L - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); -#endif + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); } void @@ -444,14 +433,6 @@ const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } - - private: - void - _M_invalidate_all() - { - typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; - this->_M_invalidate_if(_Not_equal(_Base::end())); - } }; template Index: include/debug/safe_base.h =================================================================== --- include/debug/safe_base.h (revision 209879) +++ include/debug/safe_base.h (working copy) @@ -104,7 +104,8 @@ ~_Safe_iterator_base() { this->_M_detach(); } /** For use in _Safe_iterator. */ - __gnu_cxx::__mutex& _M_get_mutex() throw (); + __gnu_cxx::__mutex& + _M_get_mutex() throw (); public: /** Attaches this iterator to the given sequence, detaching it @@ -112,30 +113,37 @@ * new sequence is the NULL pointer, the iterator is left * unattached. */ - void _M_attach(_Safe_sequence_base* __seq, bool __constant); + void + _M_attach(_Safe_sequence_base* __seq, bool __constant); /** Likewise, but not thread-safe. */ - void _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw (); + void + _M_attach_single(_Safe_sequence_base* __seq, bool __constant) throw (); /** Detach the iterator for whatever sequence it is attached to, * if any. */ - void _M_detach(); + void + _M_detach(); /** Likewise, but not thread-safe. */ - void _M_detach_single() throw (); + void + _M_detach_single() throw (); /** Determines if we are attached to the given sequence. */ - bool _M_attached_to(const _Safe_sequence_base* __seq) const + bool + _M_attached_to(const _Safe_sequence_base* __seq) const { return _M_sequence == __seq; } /** Is this iterator singular? */ - _GLIBCXX_PURE bool _M_singular() const throw (); + _GLIBCXX_PURE bool + _M_singular() const throw (); /** Can we compare this iterator to the given iterator @p __x? Returns true if both iterators are nonsingular and reference the same sequence. */ - _GLIBCXX_PURE bool _M_can_compare(const _Safe_iterator_base& __x) const throw (); + _GLIBCXX_PURE bool + _M_can_compare(const _Safe_iterator_base& __x) const throw (); /** Invalidate the iterator, making it singular. */ void @@ -188,17 +196,13 @@ protected: // Initialize with a version number of 1 and no iterators - _Safe_sequence_base() + _Safe_sequence_base() _GLIBCXX_NOEXCEPT : _M_iterators(0), _M_const_iterators(0), _M_version(1) { } #if __cplusplus >= 201103L _Safe_sequence_base(const _Safe_sequence_base&) noexcept : _Safe_sequence_base() { } - - _Safe_sequence_base(_Safe_sequence_base&& __x) noexcept - : _Safe_sequence_base() - { _M_swap(__x); } #endif /** Notify all iterators that reference this sequence that the @@ -231,10 +235,11 @@ * one container now reference the other container. */ void - _M_swap(_Safe_sequence_base& __x); + _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT; /** For use in _Safe_sequence. */ - __gnu_cxx::__mutex& _M_get_mutex() throw (); + __gnu_cxx::__mutex& + _M_get_mutex() throw (); public: /** Invalidates all iterators. */ Index: include/debug/safe_container.h =================================================================== --- include/debug/safe_container.h (revision 0) +++ include/debug/safe_container.h (working copy) @@ -0,0 +1,125 @@ +// Safe container implementation -*- C++ -*- + +// 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. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/safe_container.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_SAFE_CONTAINER_H +#define _GLIBCXX_DEBUG_SAFE_CONTAINER_H 1 + +#include + +namespace __gnu_debug +{ + /// Safe class dealing with some allocator dependent operations. + template class _SafeBase, + bool _IsCxx11AllocatorAware = true> + class _Safe_container + : public _SafeBase<_SafeContainer> + { + typedef _SafeBase<_SafeContainer> _Base; + + _SafeContainer& + _M_cont() _GLIBCXX_NOEXCEPT + { return *static_cast<_SafeContainer*>(this); } + + protected: + _Safe_container& + _M_safe() _GLIBCXX_NOEXCEPT + { return *this; } + +#if __cplusplus >= 201103L + _Safe_container() = default; + _Safe_container(const _Safe_container&) = default; + _Safe_container(_Safe_container&& __x) noexcept + : _Safe_container() + { _Base::_M_swap(__x); } + + _Safe_container(_Safe_container&& __x, + const _Alloc& __a) + : _Safe_container() + { + if (__x._M_cont().get_allocator() == __a) + _Base::_M_swap(__x); + else + __x._M_invalidate_all(); + } +#endif + + public: + // Copy assignment invalidate all iterators. + _Safe_container& + operator=(const _Safe_container&) _GLIBCXX_NOEXCEPT + { + this->_M_invalidate_all(); + return *this; + } + +#if __cplusplus >= 201103L + _Safe_container& + operator=(_Safe_container&& __x) noexcept + { + __glibcxx_check_self_move_assign(__x); + + if (_IsCxx11AllocatorAware) + { + typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits; + + bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() + || _M_cont().get_allocator() == __x._M_cont().get_allocator(); + if (__xfer_memory) + _Base::_M_swap(__x); + else + this->_M_invalidate_all(); + } + else + _Base::_M_swap(__x); + + __x._M_invalidate_all(); + return *this; + } + + void + _M_swap(_Safe_container& __x) noexcept + { + if (_IsCxx11AllocatorAware) + { + typedef __gnu_cxx::__alloc_traits<_Alloc> _Alloc_traits; + + if (!_Alloc_traits::_S_propagate_on_swap()) + __glibcxx_check_equal_allocs(this->_M_cont()._M_base(), + __x._M_cont()._M_base()); + } + + _Base::_M_swap(__x); + } +#endif + }; + +} // namespace __gnu_debug + +#endif Index: include/debug/safe_iterator.h =================================================================== --- include/debug/safe_iterator.h (revision 209879) +++ include/debug/safe_iterator.h (working copy) @@ -58,7 +58,7 @@ /** Iterators that derive from _Safe_iterator_base can be determined singular * or non-singular. **/ - inline bool + inline bool __check_singular_aux(const _Safe_iterator_base* __x) { return __x->_M_singular(); } Index: include/debug/safe_sequence.h =================================================================== --- include/debug/safe_sequence.h (revision 209879) +++ include/debug/safe_sequence.h (working copy) @@ -127,6 +127,25 @@ void _M_transfer_from_if(_Safe_sequence& __from, _Predicate __pred); }; + + /// Like _Safe_sequence but with a special _M_invalidate_all implementation + /// not invalidating past-the-end iterators. Used by node based sequence. + template + class _Safe_node_sequence + : public _Safe_sequence<_Sequence> + { + protected: + void + _M_invalidate_all() + { + typedef typename _Sequence::const_iterator _Const_iterator; + typedef typename _Const_iterator::iterator_type _Base_const_iterator; + typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; + const _Sequence& __seq = *static_cast<_Sequence*>(this); + this->_M_invalidate_if(_Not_equal(__seq._M_base().end())); + } + }; + } // namespace __gnu_debug #include Index: include/debug/safe_unordered_base.h =================================================================== --- include/debug/safe_unordered_base.h (revision 209879) +++ include/debug/safe_unordered_base.h (working copy) @@ -80,7 +80,7 @@ ~_Safe_local_iterator_base() { this->_M_detach(); } _Safe_unordered_container_base* - _M_get_container() const _GLIBCXX_NOEXCEPT; + _M_get_container() const noexcept; public: /** Attaches this iterator to the given container, detaching it @@ -132,15 +132,16 @@ protected: // Initialize with a version number of 1 and no iterators - _Safe_unordered_container_base() + _Safe_unordered_container_base() noexcept : _M_local_iterators(nullptr), _M_const_local_iterators(nullptr) { } - // Initialize with a version number of 1 and no iterators + // Copy constructor does not copy iterators. _Safe_unordered_container_base(const _Safe_unordered_container_base&) noexcept : _Safe_unordered_container_base() { } + // When moved unordered containers iterators are swapped. _Safe_unordered_container_base(_Safe_unordered_container_base&& __x) noexcept : _Safe_unordered_container_base() @@ -148,7 +149,7 @@ /** Notify all iterators that reference this container that the container is being destroyed. */ - ~_Safe_unordered_container_base() + ~_Safe_unordered_container_base() noexcept { this->_M_detach_all(); } /** Detach all iterators, leaving them singular. */ @@ -161,7 +162,7 @@ * one container now reference the other container. */ void - _M_swap(_Safe_unordered_container_base& __x); + _M_swap(_Safe_unordered_container_base& __x) noexcept; public: /** Attach an iterator to this container. */ Index: include/debug/safe_unordered_container.h =================================================================== --- include/debug/safe_unordered_container.h (revision 209879) +++ include/debug/safe_unordered_container.h (working copy) @@ -57,7 +57,31 @@ template class _Safe_unordered_container : public _Safe_unordered_container_base { - public: + private: + _Container& + _M_cont() noexcept + { return *static_cast<_Container*>(this); } + + protected: + void + _M_invalidate_locals() + { + auto __local_end = _M_cont()._M_base().end(0); + this->_M_invalidate_local_if( + [__local_end](__decltype(_M_cont()._M_base().cend(0)) __it) + { return __it != __local_end; }); + } + + void + _M_invalidate_all() + { + auto __end = _M_cont()._M_base().end(); + this->_M_invalidate_if( + [__end](__decltype(_M_cont()._M_base().cend()) __it) + { return __it != __end; }); + _M_invalidate_locals(); + } + /** Invalidates all iterators @c x that reference this container, are not singular, and for which @c __pred(x) returns @c true. @c __pred will be invoked with the normal iterators nested Index: include/debug/set.h =================================================================== --- include/debug/set.h (revision 209879) +++ include/debug/set.h (working copy) @@ -30,10 +30,11 @@ #define _GLIBCXX_DEBUG_SET_H 1 #include +#include #include #include -namespace std _GLIBCXX_VISIBILITY(default) +namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug { @@ -41,18 +42,19 @@ template, typename _Allocator = std::allocator<_Key> > class set - : public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + set<_Key, _Compare, _Allocator>, _Allocator, + __gnu_debug::_Safe_node_sequence>, + public _GLIBCXX_STD_C::set<_Key,_Compare,_Allocator> { typedef _GLIBCXX_STD_C::set<_Key, _Compare, _Allocator> _Base; + typedef __gnu_debug::_Safe_container< + set, _Allocator, __gnu_debug::_Safe_node_sequence> _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; -#if __cplusplus >= 201103L - typedef __gnu_cxx::__alloc_traits _Alloc_traits; -#endif + public: // types: typedef _Key key_type; @@ -77,33 +79,18 @@ // 23.3.3.1 construct/copy/destroy: +#if __cplusplus < 201103L set() : _Base() { } - explicit set(const _Compare& __comp, - const _Allocator& __a = _Allocator()) - : _Base(__comp, __a) { } - - template - set(_InputIterator __first, _InputIterator __last, - const _Compare& __comp = _Compare(), - const _Allocator& __a = _Allocator()) - : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, - __last)), - __gnu_debug::__base(__last), - __comp, __a) { } - set(const set& __x) : _Base(__x) { } - set(const _Base& __x) - : _Base(__x) { } + ~set() { } +#else + set() = default; + set(const set&) = default; + set(set&&) = default; -#if __cplusplus >= 201103L - set(set&& __x) - noexcept(is_nothrow_copy_constructible<_Compare>::value) - : _Base(std::move(__x)) - { this->_M_swap(__x); } - set(initializer_list __l, const _Compare& __comp = _Compare(), const allocator_type& __a = allocator_type()) @@ -117,47 +104,52 @@ : _Base(__x, __a) { } set(set&& __x, const allocator_type& __a) - : _Base(std::move(__x._M_base()), __a) { } + : _Safe(std::move(__x._M_safe()), __a), + _Base(std::move(__x._M_base()), __a) { } set(initializer_list __l, const allocator_type& __a) - : _Base(__l, __a) - { } + : _Base(__l, __a) { } template set(_InputIterator __first, _InputIterator __last, const allocator_type& __a) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), - __gnu_debug::__base(__last), __a) - { } + __gnu_debug::__base(__last), __a) { } + + ~set() = default; #endif - ~set() _GLIBCXX_NOEXCEPT { } + explicit set(const _Compare& __comp, + const _Allocator& __a = _Allocator()) + : _Base(__comp, __a) { } + template + set(_InputIterator __first, _InputIterator __last, + const _Compare& __comp = _Compare(), + const _Allocator& __a = _Allocator()) + : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, + __last)), + __gnu_debug::__base(__last), + __comp, __a) { } + + set(const _Base& __x) + : _Base(__x) { } + +#if __cplusplus < 201103L set& operator=(const set& __x) { + this->_M_safe() = __x; _M_base() = __x; - this->_M_invalidate_all(); return *this; } +#else + set& + operator=(const set&) = default; -#if __cplusplus >= 201103L set& - operator=(set&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(set&&) = default; set& operator=(initializer_list __l) @@ -372,15 +364,11 @@ void swap(set& __x) #if __cplusplus >= 201103L - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) #endif { -#if __cplusplus >= 201103L - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); -#endif + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); } void @@ -452,14 +440,6 @@ const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } - - private: - void - _M_invalidate_all() - { - typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; - this->_M_invalidate_if(_Not_equal(_M_base().end())); - } }; template Index: include/debug/string =================================================================== --- include/debug/string (revision 209879) +++ include/debug/string (working copy) @@ -31,6 +31,7 @@ #include #include +#include #include namespace __gnu_debug @@ -39,12 +40,14 @@ template, typename _Allocator = std::allocator<_CharT> > class basic_string + : public __gnu_debug::_Safe_container< + basic_string<_CharT, _Traits, _Allocator>, _Allocator, + _Safe_sequence, false> : public std::basic_string<_CharT, _Traits, _Allocator>, - public __gnu_debug::_Safe_sequence > { typedef std::basic_string<_CharT, _Traits, _Allocator> _Base; - typedef __gnu_debug::_Safe_sequence _Safe_base; + typedef __gnu_debug::_Safe_container< + basic_string, _Allocator, _Safe_sequence, false> _Safe; public: // types: @@ -58,10 +61,10 @@ typedef typename _Base::pointer pointer; typedef typename _Base::const_pointer const_pointer; - typedef __gnu_debug::_Safe_iterator - iterator; - typedef __gnu_debug::_Safe_iterator const_iterator; + typedef __gnu_debug::_Safe_iterator< + typename _Base::iterator, basic_string> iterator; + typedef __gnu_debug::_Safe_iterator< + typename _Base::const_iterator, basic_string> const_iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; @@ -71,18 +74,29 @@ // 21.3.1 construct/copy/destroy: explicit basic_string(const _Allocator& __a = _Allocator()) // _GLIBCXX_NOEXCEPT - : _Base(__a) - { } + : _Base(__a) { } - // Provides conversion from a release-mode string to a debug-mode string - basic_string(const _Base& __base) : _Base(__base) { } +#if __cplusplus < 201103L + basic_string(const basic_string& __str) + : _Base(__str) { } - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 42. string ctors specify wrong default allocator - basic_string(const basic_string& __str) - : _Base(__str, 0, _Base::npos, __str.get_allocator()) + ~basic_string() { } +#else + basic_string(const basic_string&) = default; + basic_string(basic_string&&) = default; + + basic_string(std::initializer_list<_CharT> __l, + const _Allocator& __a = _Allocator()) + : _Base(__l, __a) { } + ~basic_string() = default; +#endif // C++11 + + // Provides conversion from a normal-mode string to a debug-mode string + basic_string(const _Base& __base) + : _Base(__base) { } + // _GLIBCXX_RESOLVE_LIB_DEFECTS // 42. string ctors specify wrong default allocator basic_string(const basic_string& __str, size_type __pos, @@ -113,32 +127,27 @@ __gnu_debug::__base(__end), __a) { } -#if __cplusplus >= 201103L - basic_string(basic_string&& __str) // noexcept - : _Base(std::move(__str)) - { } - - basic_string(std::initializer_list<_CharT> __l, - const _Allocator& __a = _Allocator()) - : _Base(__l, __a) - { } -#endif // C++11 - - ~basic_string() _GLIBCXX_NOEXCEPT { } - +#if __cplusplus < 201103L basic_string& operator=(const basic_string& __str) { - *static_cast<_Base*>(this) = __str; - this->_M_invalidate_all(); + this->_M_safe() = __str; + _M_base() = __str; return *this; } +#else + basic_string& + operator=(const basic_string&) = default; basic_string& + operator=(basic_string&&) = default; +#endif + + basic_string& operator=(const _CharT* __s) { __glibcxx_check_string(__s); - *static_cast<_Base*>(this) = __s; + _M_base() = __s; this->_M_invalidate_all(); return *this; } @@ -146,25 +155,16 @@ basic_string& operator=(_CharT __c) { - *static_cast<_Base*>(this) = __c; + _M_base() = __c; this->_M_invalidate_all(); return *this; } #if __cplusplus >= 201103L basic_string& - operator=(basic_string&& __str) - { - __glibcxx_check_self_move_assign(__str); - *static_cast<_Base*>(this) = std::move(__str); - this->_M_invalidate_all(); - return *this; - } - - basic_string& operator=(std::initializer_list<_CharT> __l) { - *static_cast<_Base*>(this) = __l; + _M_base() = __l; this->_M_invalidate_all(); return *this; } @@ -704,12 +704,13 @@ } void - swap(basic_string<_CharT,_Traits,_Allocator>& __x) + swap(basic_string& __x) +#if __cplusplus >= 201103L + noexcept( noexcept(declval<_Base>().swap(__x)) ) +#endif { + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); - this->_M_invalidate_all(); - __x._M_invalidate_all(); } // 21.3.6 string operations: @@ -801,7 +802,7 @@ { return _Base::find_first_of(__c, __pos); } size_type - find_last_of(const basic_string& __str, + find_last_of(const basic_string& __str, size_type __pos = _Base::npos) const _GLIBCXX_NOEXCEPT { return _Base::find_last_of(__str, __pos); } @@ -922,7 +923,7 @@ const _Base& _M_base() const _GLIBCXX_NOEXCEPT { return *this; } - using _Safe_base::_M_invalidate_all; + using _Safe::_M_invalidate_all; }; template Index: include/debug/unordered_map =================================================================== --- include/debug/unordered_map (revision 209879) +++ include/debug/unordered_map (working copy) @@ -35,6 +35,7 @@ # include #include +#include #include #include @@ -48,21 +49,21 @@ typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator > > class unordered_map - : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, - public __gnu_debug::_Safe_unordered_container > + : public __gnu_debug::_Safe_container< + unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc, + __gnu_debug::_Safe_unordered_container>, + public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> { typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> _Base; - typedef __gnu_debug::_Safe_unordered_container _Safe_base; + typedef __gnu_debug::_Safe_container _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; - typedef typename _Base::const_local_iterator _Base_const_local_iterator; + typedef typename _Base::const_local_iterator + _Base_const_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator; - typedef __gnu_cxx::__alloc_traits _Alloc_traits; - public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -72,14 +73,14 @@ typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, - unordered_map> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, - unordered_map> const_iterator; - typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator, - unordered_map> local_iterator; - typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator, - unordered_map> const_local_iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_iterator, unordered_map> iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_const_iterator, unordered_map> const_iterator; + typedef __gnu_debug::_Safe_local_iterator< + _Base_local_iterator, unordered_map> local_iterator; + typedef __gnu_debug::_Safe_local_iterator< + _Base_const_local_iterator, unordered_map> const_local_iterator; explicit unordered_map(size_type __n = 10, @@ -89,10 +90,10 @@ : _Base(__n, __hf, __eql, __a) { } template - unordered_map(_InputIterator __first, _InputIterator __last, + unordered_map(_InputIterator __first, _InputIterator __last, size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), @@ -108,18 +109,16 @@ explicit unordered_map(const allocator_type& __a) - : _Base(__a) - { } + : _Base(__a) { } unordered_map(const unordered_map& __umap, const allocator_type& __a) - : _Base(__umap._M_base(), __a) - { } + : _Base(__umap, __a) { } unordered_map(unordered_map&& __umap, const allocator_type& __a) - : _Base(std::move(__umap._M_base()), __a) - { } + : _Safe(std::move(__umap._M_safe()), __a), + _Base(std::move(__umap._M_base()), __a) { } unordered_map(initializer_list __l, size_type __n = 0, @@ -128,31 +127,13 @@ const allocator_type& __a = allocator_type()) : _Base(__l, __n, __hf, __eql, __a) { } - ~unordered_map() noexcept { } + ~unordered_map() = default; unordered_map& - operator=(const unordered_map& __x) - { - _M_base() = __x._M_base(); - this->_M_invalidate_all(); - return *this; - } + operator=(const unordered_map&) = default; unordered_map& - operator=(unordered_map&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(unordered_map&&) = default; unordered_map& operator=(initializer_list __l) @@ -164,12 +145,10 @@ void swap(unordered_map& __x) - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) { - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); + _Safe::_M_swap(__x); _Base::swap(__x); - _Safe_base::_M_swap(__x); } void @@ -179,7 +158,7 @@ this->_M_invalidate_all(); } - iterator + iterator begin() noexcept { return iterator(_Base::begin(), this); } @@ -301,7 +280,7 @@ { __glibcxx_check_insert(__hint); size_type __bucket_count = this->bucket_count(); - _Base_iterator __it = _Base::insert(__hint.base(), __obj); + _Base_iterator __it = _Base::insert(__hint.base(), __obj); _M_check_rehashed(__bucket_count); return iterator(__it, this); } @@ -409,7 +388,7 @@ [__victim](_Base_const_local_iterator __it) { return __it._M_curr() == __victim._M_cur; }); size_type __bucket_count = this->bucket_count(); - _Base_iterator __next = _Base::erase(__it.base()); + _Base_iterator __next = _Base::erase(__it.base()); _M_check_rehashed(__bucket_count); return iterator(__next, this); } @@ -449,28 +428,10 @@ private: void - _M_invalidate_locals() - { - _Base_local_iterator __local_end = _Base::end(0); - this->_M_invalidate_local_if( - [__local_end](_Base_const_local_iterator __it) - { return __it != __local_end; }); - } - - void - _M_invalidate_all() - { - _Base_iterator __end = _Base::end(); - this->_M_invalidate_if([__end](_Base_const_iterator __it) - { return __it != __end; }); - _M_invalidate_locals(); - } - - void _M_check_rehashed(size_type __prev_count) { if (__prev_count != this->bucket_count()) - _M_invalidate_locals(); + this->_M_invalidate_locals(); } }; @@ -502,23 +463,20 @@ typename _Pred = std::equal_to<_Key>, typename _Alloc = std::allocator > > class unordered_multimap - : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, - _Pred, _Alloc>, - public __gnu_debug::_Safe_unordered_container > + : public __gnu_debug::_Safe_container< + unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc, + __gnu_debug::_Safe_unordered_container>, + public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> { typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> _Base; - typedef __gnu_debug::_Safe_unordered_container - _Safe_base; + typedef __gnu_debug::_Safe_container _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; typedef typename _Base::const_local_iterator _Base_const_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator; - typedef __gnu_cxx::__alloc_traits _Alloc_traits; - public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -528,10 +486,10 @@ typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, - unordered_multimap> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, - unordered_multimap> const_iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_iterator, unordered_multimap> iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_const_iterator, unordered_multimap> const_iterator; typedef __gnu_debug::_Safe_local_iterator< _Base_local_iterator, unordered_multimap> local_iterator; typedef __gnu_debug::_Safe_local_iterator< @@ -545,10 +503,10 @@ : _Base(__n, __hf, __eql, __a) { } template - unordered_multimap(_InputIterator __first, _InputIterator __last, + unordered_multimap(_InputIterator __first, _InputIterator __last, size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), @@ -557,25 +515,23 @@ unordered_multimap(const unordered_multimap&) = default; - unordered_multimap(const _Base& __x) + unordered_multimap(const _Base& __x) : _Base(__x) { } unordered_multimap(unordered_multimap&&) = default; explicit unordered_multimap(const allocator_type& __a) - : _Base(__a) - { } + : _Base(__a) { } unordered_multimap(const unordered_multimap& __umap, const allocator_type& __a) - : _Base(__umap._M_base(), __a) - { } + : _Base(__umap, __a) { } unordered_multimap(unordered_multimap&& __umap, const allocator_type& __a) - : _Base(std::move(__umap._M_base()), __a) - { } + : _Safe(std::move(__umap._M_safe()), __a), + _Base(std::move(__umap._M_base()), __a) { } unordered_multimap(initializer_list __l, size_type __n = 0, @@ -584,48 +540,28 @@ const allocator_type& __a = allocator_type()) : _Base(__l, __n, __hf, __eql, __a) { } - ~unordered_multimap() noexcept { } + ~unordered_multimap() = default; unordered_multimap& - operator=(const unordered_multimap& __x) - { - _M_base() = __x._M_base(); - this->_M_invalidate_all(); - return *this; - } + operator=(const unordered_multimap&) = default; unordered_multimap& - operator=(unordered_multimap&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(unordered_multimap&&) = default; unordered_multimap& operator=(initializer_list __l) { - _M_base() = __l; + this->_M_base() = __l; this->_M_invalidate_all(); return *this; } void swap(unordered_multimap& __x) - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) { - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); + _Safe::_M_swap(__x); _Base::swap(__x); - _Safe_base::_M_swap(__x); } void @@ -635,7 +571,7 @@ this->_M_invalidate_all(); } - iterator + iterator begin() noexcept { return iterator(_Base::begin(), this); } @@ -901,28 +837,10 @@ private: void - _M_invalidate_locals() - { - _Base_local_iterator __local_end = _Base::end(0); - this->_M_invalidate_local_if( - [__local_end](_Base_const_local_iterator __it) - { return __it != __local_end; }); - } - - void - _M_invalidate_all() - { - _Base_iterator __end = _Base::end(); - this->_M_invalidate_if([__end](_Base_const_iterator __it) - { return __it != __end; }); - _M_invalidate_locals(); - } - - void _M_check_rehashed(size_type __prev_count) { if (__prev_count != this->bucket_count()) - _M_invalidate_locals(); + this->_M_invalidate_locals(); } }; Index: include/debug/unordered_set =================================================================== --- include/debug/unordered_set (revision 209879) +++ include/debug/unordered_set (working copy) @@ -35,6 +35,7 @@ # include #include +#include #include #include @@ -48,20 +49,21 @@ typename _Pred = std::equal_to<_Value>, typename _Alloc = std::allocator<_Value> > class unordered_set - : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>, - public __gnu_debug::_Safe_unordered_container > + : public __gnu_debug::_Safe_container< + unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc, + __gnu_debug::_Safe_unordered_container>, + public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc> { - typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash, - _Pred, _Alloc> _Base; - typedef __gnu_debug::_Safe_unordered_container _Safe_base; + typedef _GLIBCXX_STD_C::unordered_set< + _Value, _Hash, _Pred, _Alloc> _Base; + typedef __gnu_debug::_Safe_container< + unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container> _Safe; + typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; typedef typename _Base::const_local_iterator _Base_const_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator; - typedef __gnu_cxx::__alloc_traits _Alloc_traits; public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -71,14 +73,14 @@ typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, - unordered_set> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, - unordered_set> const_iterator; - typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator, - unordered_set> local_iterator; - typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator, - unordered_set> const_local_iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_iterator, unordered_set> iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_const_iterator, unordered_set> const_iterator; + typedef __gnu_debug::_Safe_local_iterator< + _Base_local_iterator, unordered_set> local_iterator; + typedef __gnu_debug::_Safe_local_iterator< + _Base_const_local_iterator, unordered_set> const_local_iterator; explicit unordered_set(size_type __n = 10, @@ -88,10 +90,10 @@ : _Base(__n, __hf, __eql, __a) { } template - unordered_set(_InputIterator __first, _InputIterator __last, + unordered_set(_InputIterator __first, _InputIterator __last, size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), @@ -107,18 +109,16 @@ explicit unordered_set(const allocator_type& __a) - : _Base(__a) - { } + : _Base(__a) { } unordered_set(const unordered_set& __uset, const allocator_type& __a) - : _Base(__uset._M_base(), __a) - { } + : _Base(__uset, __a) { } unordered_set(unordered_set&& __uset, const allocator_type& __a) - : _Base(std::move(__uset._M_base()), __a) - { } + : _Safe(std::move(__uset._M_safe()), __a), + _Base(std::move(__uset._M_base()), __a) { } unordered_set(initializer_list __l, size_type __n = 0, @@ -127,31 +127,13 @@ const allocator_type& __a = allocator_type()) : _Base(__l, __n, __hf, __eql, __a) { } - ~unordered_set() noexcept { } + ~unordered_set() = default; unordered_set& - operator=(const unordered_set& __x) - { - _M_base() = __x._M_base(); - this->_M_invalidate_all(); - return *this; - } + operator=(const unordered_set&) = default; unordered_set& - operator=(unordered_set&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(unordered_set&&) = default; unordered_set& operator=(initializer_list __l) @@ -163,12 +145,10 @@ void swap(unordered_set& __x) - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) { - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); + _Safe::_M_swap(__x); _Base::swap(__x); - _Safe_base::_M_swap(__x); } void @@ -178,7 +158,7 @@ this->_M_invalidate_all(); } - iterator + iterator begin() noexcept { return iterator(_Base::begin(), this); } @@ -290,8 +270,8 @@ insert(const value_type& __obj) { size_type __bucket_count = this->bucket_count(); - typedef std::pair<_Base_iterator, bool> __pair_type; - __pair_type __res = _Base::insert(__obj); + std::pair<_Base_iterator, bool> __res + = _Base::insert(__obj); _M_check_rehashed(__bucket_count); return std::make_pair(iterator(__res.first, this), __res.second); } @@ -310,8 +290,8 @@ insert(value_type&& __obj) { size_type __bucket_count = this->bucket_count(); - typedef std::pair __pair_type; - __pair_type __res = _Base::insert(std::move(__obj)); + std::pair<_Base_iterator, bool> __res + = _Base::insert(std::move(__obj)); _M_check_rehashed(__bucket_count); return std::make_pair(iterator(__res.first, this), __res.second); } @@ -356,8 +336,8 @@ std::pair equal_range(const key_type& __key) { - typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; - __pair_type __res = _Base::equal_range(__key); + std::pair<_Base_iterator, _Base_iterator> __res + = _Base::equal_range(__key); return std::make_pair(iterator(__res.first, this), iterator(__res.second, this)); } @@ -446,29 +426,10 @@ private: void - _M_invalidate_locals() - { - _Base_local_iterator __local_end = _Base::end(0); - this->_M_invalidate_local_if( - [__local_end](_Base_const_local_iterator __it) - { return __it != __local_end; }); - } - - void - _M_invalidate_all() - { - _Base_iterator __end = _Base::end(); - this->_M_invalidate_if( - [__end](_Base_const_iterator __it) - { return __it != __end; }); - _M_invalidate_locals(); - } - - void _M_check_rehashed(size_type __prev_count) { if (__prev_count != this->bucket_count()) - _M_invalidate_locals(); + this->_M_invalidate_locals(); } }; @@ -497,22 +458,21 @@ typename _Pred = std::equal_to<_Value>, typename _Alloc = std::allocator<_Value> > class unordered_multiset - : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>, - public __gnu_debug::_Safe_unordered_container< - unordered_multiset<_Value, _Hash, _Pred, _Alloc> > + : public __gnu_debug::_Safe_container< + unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc, + __gnu_debug::_Safe_unordered_container>, + public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc> { - typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, - _Pred, _Alloc> _Base; - typedef __gnu_debug::_Safe_unordered_container - _Safe_base; + typedef _GLIBCXX_STD_C::unordered_multiset< + _Value, _Hash, _Pred, _Alloc> _Base; + typedef __gnu_debug::_Safe_container _Safe; typedef typename _Base::const_iterator _Base_const_iterator; typedef typename _Base::iterator _Base_iterator; - typedef typename _Base::const_local_iterator _Base_const_local_iterator; + typedef typename _Base::const_local_iterator + _Base_const_local_iterator; typedef typename _Base::local_iterator _Base_local_iterator; - typedef __gnu_cxx::__alloc_traits _Alloc_traits; - public: typedef typename _Base::size_type size_type; typedef typename _Base::hasher hasher; @@ -522,10 +482,10 @@ typedef typename _Base::key_type key_type; typedef typename _Base::value_type value_type; - typedef __gnu_debug::_Safe_iterator<_Base_iterator, - unordered_multiset> iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, - unordered_multiset> const_iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_iterator, unordered_multiset> iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_const_iterator, unordered_multiset> const_iterator; typedef __gnu_debug::_Safe_local_iterator< _Base_local_iterator, unordered_multiset> local_iterator; typedef __gnu_debug::_Safe_local_iterator< @@ -539,10 +499,10 @@ : _Base(__n, __hf, __eql, __a) { } template - unordered_multiset(_InputIterator __first, _InputIterator __last, + unordered_multiset(_InputIterator __first, _InputIterator __last, size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), const allocator_type& __a = allocator_type()) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), @@ -551,25 +511,23 @@ unordered_multiset(const unordered_multiset&) = default; - unordered_multiset(const _Base& __x) + unordered_multiset(const _Base& __x) : _Base(__x) { } unordered_multiset(unordered_multiset&&) = default; explicit unordered_multiset(const allocator_type& __a) - : _Base(__a) - { } + : _Base(__a) { } unordered_multiset(const unordered_multiset& __uset, const allocator_type& __a) - : _Base(__uset._M_base(), __a) - { } - + : _Base(__uset, __a) { } + unordered_multiset(unordered_multiset&& __uset, const allocator_type& __a) - : _Base(std::move(__uset._M_base()), __a) - { } + : _Safe(std::move(__uset._M_safe()), __a), + _Base(std::move(__uset._M_base()), __a) { } unordered_multiset(initializer_list __l, size_type __n = 0, @@ -578,48 +536,28 @@ const allocator_type& __a = allocator_type()) : _Base(__l, __n, __hf, __eql, __a) { } - ~unordered_multiset() noexcept { } + ~unordered_multiset() = default; unordered_multiset& - operator=(const unordered_multiset& __x) - { - _M_base() = __x._M_base(); - this->_M_invalidate_all(); - return *this; - } + operator=(const unordered_multiset&) = default; unordered_multiset& - operator=(unordered_multiset&& __x) - noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - __x._M_invalidate_all(); - return *this; - } + operator=(unordered_multiset&&) = default; unordered_multiset& operator=(initializer_list __l) { - _M_base() = __l; + this->_M_base() = __l; this->_M_invalidate_all(); return *this; } void swap(unordered_multiset& __x) - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) { - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); + _Safe::_M_swap(__x); _Base::swap(__x); - _Safe_base::_M_swap(__x); } void @@ -751,7 +689,7 @@ { __glibcxx_check_insert(__hint); size_type __bucket_count = this->bucket_count(); - _Base_iterator __it = _Base::insert(__hint.base(), __obj); + _Base_iterator __it = _Base::insert(__hint.base(), __obj); _M_check_rehashed(__bucket_count); return iterator(__it, this); } @@ -760,7 +698,7 @@ insert(value_type&& __obj) { size_type __bucket_count = this->bucket_count(); - _Base_iterator __it = _Base::insert(std::move(__obj)); + _Base_iterator __it = _Base::insert(std::move(__obj)); _M_check_rehashed(__bucket_count); return iterator(__it, this); } @@ -770,7 +708,7 @@ { __glibcxx_check_insert(__hint); size_type __bucket_count = this->bucket_count(); - _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj)); + _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj)); _M_check_rehashed(__bucket_count); return iterator(__it, this); } @@ -805,8 +743,8 @@ std::pair equal_range(const key_type& __key) { - typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; - __pair_type __res = _Base::equal_range(__key); + std::pair<_Base_iterator, _Base_iterator> __res + = _Base::equal_range(__key); return std::make_pair(iterator(__res.first, this), iterator(__res.second, this)); } @@ -885,28 +823,10 @@ private: void - _M_invalidate_locals() - { - _Base_local_iterator __local_end = _Base::end(0); - this->_M_invalidate_local_if( - [__local_end](_Base_const_local_iterator __it) - { return __it != __local_end; }); - } - - void - _M_invalidate_all() - { - _Base_iterator __end = _Base::end(); - this->_M_invalidate_if([__end](_Base_const_iterator __it) - { return __it != __end; }); - _M_invalidate_locals(); - } - - void _M_check_rehashed(size_type __prev_count) { if (__prev_count != this->bucket_count()) - _M_invalidate_locals(); + this->_M_invalidate_locals(); } }; Index: include/debug/vector =================================================================== --- include/debug/vector (revision 209879) +++ include/debug/vector (working copy) @@ -32,8 +32,68 @@ #include #include #include +#include #include +namespace __gnu_debug +{ + /// Special vector safe base class to add a guaranteed capacity information + /// useful to detect code relying on the libstdc++ reallocation management + /// implementation detail. + template + class _Safe_vector + { + typedef typename _BaseSequence::size_type size_type; + + const _SafeSequence& + _M_seq() const { return *static_cast(this); } + + protected: + _Safe_vector() _GLIBCXX_NOEXCEPT + : _M_guaranteed_capacity(0) + { _M_update_guaranteed_capacity(); } + + _Safe_vector(const _Safe_vector&) _GLIBCXX_NOEXCEPT + : _M_guaranteed_capacity(0) + { _M_update_guaranteed_capacity(); } + + _Safe_vector(size_type __n) _GLIBCXX_NOEXCEPT + : _M_guaranteed_capacity(__n) + { } + +#if __cplusplus >= 201103L + _Safe_vector(_Safe_vector&& __x) noexcept + : _Safe_vector() + { __x._M_guaranteed_capacity = 0; } + + _Safe_vector& + operator=(const _Safe_vector&) noexcept + { _M_update_guaranteed_capacity(); } + + _Safe_vector& + operator=(_Safe_vector&& __x) noexcept + { + _M_update_guaranteed_capacity(); + __x._M_guaranteed_capacity = 0; + } +#endif + + size_type _M_guaranteed_capacity; + + bool + _M_requires_reallocation(size_type __elements) const _GLIBCXX_NOEXCEPT + { return __elements > _M_seq().capacity(); } + + void + _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT + { + if (_M_seq().size() > _M_guaranteed_capacity) + _M_guaranteed_capacity = _M_seq().size(); + } + }; +} + namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug @@ -42,28 +102,30 @@ template > class vector - : public _GLIBCXX_STD_C::vector<_Tp, _Allocator>, - public __gnu_debug::_Safe_sequence > + : public __gnu_debug::_Safe_container< + vector<_Tp, _Allocator>, _Allocator, __gnu_debug::_Safe_sequence>, + public _GLIBCXX_STD_C::vector<_Tp, _Allocator>, + public __gnu_debug::_Safe_vector< + vector<_Tp, _Allocator>, + _GLIBCXX_STD_C::vector<_Tp, _Allocator> > { typedef _GLIBCXX_STD_C::vector<_Tp, _Allocator> _Base; + typedef __gnu_debug::_Safe_container< + vector, _Allocator, __gnu_debug::_Safe_sequence> _Safe; + typedef __gnu_debug::_Safe_vector _Safe_vector; typedef typename _Base::iterator _Base_iterator; typedef typename _Base::const_iterator _Base_const_iterator; typedef __gnu_debug::_Equal_to<_Base_const_iterator> _Equal; -#if __cplusplus >= 201103L - typedef __gnu_debug::_Safe_sequence > _Safe_base; - typedef __gnu_cxx::__alloc_traits<_Allocator> _Alloc_traits; -#endif - public: typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef __gnu_debug::_Safe_iterator<_Base_iterator,vector> - iterator; - typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,vector> - const_iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_iterator, vector> iterator; + typedef __gnu_debug::_Safe_iterator< + _Base_const_iterator, vector> const_iterator; typedef typename _Base::size_type size_type; typedef typename _Base::difference_type difference_type; @@ -77,26 +139,30 @@ // 23.2.4.1 construct/copy/destroy: +#if __cplusplus < 201103L vector() _GLIBCXX_NOEXCEPT - : _Base(), _M_guaranteed_capacity(0) { } + : _Base() { } +#else + vector() = default; +#endif explicit vector(const _Allocator& __a) _GLIBCXX_NOEXCEPT - : _Base(__a), _M_guaranteed_capacity(0) { } + : _Base(__a) { } #if __cplusplus >= 201103L explicit vector(size_type __n, const _Allocator& __a = _Allocator()) - : _Base(__n, __a), _M_guaranteed_capacity(__n) { } + : _Base(__n, __a), _Safe_vector(__n) { } vector(size_type __n, const _Tp& __value, const _Allocator& __a = _Allocator()) - : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { } + : _Base(__n, __value, __a) { } #else explicit vector(size_type __n, const _Tp& __value = _Tp(), const _Allocator& __a = _Allocator()) - : _Base(__n, __value, __a), _M_guaranteed_capacity(__n) { } + : _Base(__n, __value, __a) { } #endif #if __cplusplus >= 201103L @@ -109,79 +175,58 @@ const _Allocator& __a = _Allocator()) : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, __last)), - __gnu_debug::__base(__last), __a), - _M_guaranteed_capacity(0) - { _M_update_guaranteed_capacity(); } + __gnu_debug::__base(__last), __a) { } +#if __cplusplus < 201103L vector(const vector& __x) - : _Base(__x), _M_guaranteed_capacity(__x.size()) { } + : _Base(__x) { } - /// Construction from a normal-mode vector - vector(const _Base& __x) - : _Base(__x), _M_guaranteed_capacity(__x.size()) { } + ~vector() _GLIBCXX_NOEXCEPT { } +#else + vector(const vector&) = default; + vector(vector&&) = default; -#if __cplusplus >= 201103L - vector(vector&& __x) noexcept - : _Base(std::move(__x)), - _Safe_base(std::move(__x)), - _M_guaranteed_capacity(this->size()) - { __x._M_guaranteed_capacity = 0; } - vector(const vector& __x, const allocator_type& __a) - : _Base(__x, __a), _M_guaranteed_capacity(__x.size()) { } + : _Base(__x, __a) { } vector(vector&& __x, const allocator_type& __a) - : _Base(std::move(__x), __a), - _M_guaranteed_capacity(this->size()) - { - if (__x.get_allocator() == __a) - this->_M_swap(__x); - else - __x._M_invalidate_all(); - __x._M_guaranteed_capacity = 0; - } + : _Safe(std::move(__x._M_safe()), __a), + _Base(std::move(__x._M_base()), __a), + _Safe_vector(std::move(__x)) { } vector(initializer_list __l, const allocator_type& __a = allocator_type()) - : _Base(__l, __a), - _M_guaranteed_capacity(__l.size()) { } + : _Base(__l, __a) { } + + ~vector() = default; #endif - ~vector() _GLIBCXX_NOEXCEPT { } + /// Construction from a normal-mode vector + vector(const _Base& __x) + : _Base(__x) { } +#if __cplusplus < 201103L vector& operator=(const vector& __x) { + this->_M_safe() = __x; _M_base() = __x; - this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); return *this; } +#else + vector& + operator=(const vector&) = default; -#if __cplusplus >= 201103L vector& - operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move()) - { - __glibcxx_check_self_move_assign(__x); - bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() - || __x.get_allocator() == this->get_allocator(); - _M_base() = std::move(__x._M_base()); - if (__xfer_memory) - this->_M_swap(__x); - else - this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); - __x._M_invalidate_all(); - __x._M_guaranteed_capacity = 0; - return *this; - } + operator=(vector&&) = default; vector& operator=(initializer_list __l) { _M_base() = __l; this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); return *this; } #endif @@ -199,7 +244,7 @@ _Base::assign(__gnu_debug::__base(__first), __gnu_debug::__base(__last)); this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } void @@ -207,7 +252,7 @@ { _Base::assign(__n, __u); this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #if __cplusplus >= 201103L @@ -216,7 +261,7 @@ { _Base::assign(__l); this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #endif @@ -281,37 +326,37 @@ void resize(size_type __sz) { - bool __realloc = _M_requires_reallocation(__sz); + bool __realloc = this->_M_requires_reallocation(__sz); if (__sz < this->size()) this->_M_invalidate_after_nth(__sz); _Base::resize(__sz); if (__realloc) this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } void resize(size_type __sz, const _Tp& __c) { - bool __realloc = _M_requires_reallocation(__sz); + bool __realloc = this->_M_requires_reallocation(__sz); if (__sz < this->size()) this->_M_invalidate_after_nth(__sz); _Base::resize(__sz, __c); if (__realloc) this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #else void resize(size_type __sz, _Tp __c = _Tp()) { - bool __realloc = _M_requires_reallocation(__sz); + bool __realloc = this->_M_requires_reallocation(__sz); if (__sz < this->size()) this->_M_invalidate_after_nth(__sz); _Base::resize(__sz, __c); if (__realloc) this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #endif @@ -321,7 +366,7 @@ { if (_Base::_M_shrink_to_fit()) { - _M_guaranteed_capacity = _Base::capacity(); + this->_M_guaranteed_capacity = _Base::capacity(); this->_M_invalidate_all(); } } @@ -331,7 +376,7 @@ capacity() const _GLIBCXX_NOEXCEPT { #ifdef _GLIBCXX_DEBUG_PEDANTIC - return _M_guaranteed_capacity; + return this->_M_guaranteed_capacity; #else return _Base::capacity(); #endif @@ -342,10 +387,10 @@ void reserve(size_type __n) { - bool __realloc = _M_requires_reallocation(__n); + bool __realloc = this->_M_requires_reallocation(__n); _Base::reserve(__n); - if (__n > _M_guaranteed_capacity) - _M_guaranteed_capacity = __n; + if (__n > this->_M_guaranteed_capacity) + this->_M_guaranteed_capacity = __n; if (__realloc) this->_M_invalidate_all(); } @@ -403,11 +448,11 @@ void push_back(const _Tp& __x) { - bool __realloc = _M_requires_reallocation(this->size() + 1); + bool __realloc = this->_M_requires_reallocation(this->size() + 1); _Base::push_back(__x); if (__realloc) this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #if __cplusplus >= 201103L @@ -421,11 +466,11 @@ void emplace_back(_Args&&... __args) { - bool __realloc = _M_requires_reallocation(this->size() + 1); + bool __realloc = this->_M_requires_reallocation(this->size() + 1); _Base::emplace_back(std::forward<_Args>(__args)...); if (__realloc) this->_M_invalidate_all(); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #endif @@ -443,7 +488,7 @@ emplace(const_iterator __position, _Args&&... __args) { __glibcxx_check_insert(__position); - bool __realloc = _M_requires_reallocation(this->size() + 1); + bool __realloc = this->_M_requires_reallocation(this->size() + 1); difference_type __offset = __position.base() - _Base::begin(); _Base_iterator __res = _Base::emplace(__position.base(), std::forward<_Args>(__args)...); @@ -451,7 +496,7 @@ this->_M_invalidate_all(); else this->_M_invalidate_after_nth(__offset); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); return iterator(__res, this); } #endif @@ -464,14 +509,14 @@ #endif { __glibcxx_check_insert(__position); - bool __realloc = _M_requires_reallocation(this->size() + 1); + bool __realloc = this->_M_requires_reallocation(this->size() + 1); difference_type __offset = __position.base() - _Base::begin(); _Base_iterator __res = _Base::insert(__position.base(), __x); if (__realloc) this->_M_invalidate_all(); else this->_M_invalidate_after_nth(__offset); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); return iterator(__res, this); } @@ -492,14 +537,14 @@ insert(const_iterator __position, size_type __n, const _Tp& __x) { __glibcxx_check_insert(__position); - bool __realloc = _M_requires_reallocation(this->size() + __n); + bool __realloc = this->_M_requires_reallocation(this->size() + __n); difference_type __offset = __position.base() - _Base::cbegin(); _Base_iterator __res = _Base::insert(__position.base(), __n, __x); if (__realloc) this->_M_invalidate_all(); else this->_M_invalidate_after_nth(__offset); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); return iterator(__res, this); } #else @@ -507,14 +552,14 @@ insert(iterator __position, size_type __n, const _Tp& __x) { __glibcxx_check_insert(__position); - bool __realloc = _M_requires_reallocation(this->size() + __n); + bool __realloc = this->_M_requires_reallocation(this->size() + __n); difference_type __offset = __position.base() - _Base::begin(); _Base::insert(__position.base(), __n, __x); if (__realloc) this->_M_invalidate_all(); else this->_M_invalidate_after_nth(__offset); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #endif @@ -540,7 +585,7 @@ this->_M_invalidate_all(); else this->_M_invalidate_after_nth(__offset); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); return iterator(__res, this); } #else @@ -563,7 +608,7 @@ this->_M_invalidate_all(); else this->_M_invalidate_after_nth(__offset); - _M_update_guaranteed_capacity(); + this->_M_update_guaranteed_capacity(); } #endif @@ -611,16 +656,12 @@ void swap(vector& __x) #if __cplusplus >= 201103L - noexcept(_Alloc_traits::_S_nothrow_swap()) + noexcept( noexcept(declval<_Base>().swap(__x)) ) #endif { -#if __cplusplus >= 201103L - if (!_Alloc_traits::_S_propagate_on_swap()) - __glibcxx_check_equal_allocs(__x); -#endif + _Safe::_M_swap(__x); _Base::swap(__x); - this->_M_swap(__x); - std::swap(_M_guaranteed_capacity, __x._M_guaranteed_capacity); + std::swap(this->_M_guaranteed_capacity, __x._M_guaranteed_capacity); } void @@ -628,7 +669,7 @@ { _Base::clear(); this->_M_invalidate_all(); - _M_guaranteed_capacity = 0; + this->_M_guaranteed_capacity = 0; } _Base& @@ -638,20 +679,7 @@ _M_base() const _GLIBCXX_NOEXCEPT { return *this; } private: - size_type _M_guaranteed_capacity; - - bool - _M_requires_reallocation(size_type __elements) _GLIBCXX_NOEXCEPT - { return __elements > this->capacity(); } - void - _M_update_guaranteed_capacity() _GLIBCXX_NOEXCEPT - { - if (this->size() > _M_guaranteed_capacity) - _M_guaranteed_capacity = this->size(); - } - - void _M_invalidate_after_nth(difference_type __n) _GLIBCXX_NOEXCEPT { typedef __gnu_debug::_After_nth_from<_Base_const_iterator> _After_nth; Index: src/c++11/debug.cc =================================================================== --- src/c++11/debug.cc (revision 209879) +++ src/c++11/debug.cc (working copy) @@ -23,8 +23,8 @@ // . #include -#include -#include +#include +#include #include #include #include @@ -235,7 +235,7 @@ void _Safe_sequence_base:: - _M_swap(_Safe_sequence_base& __x) + _M_swap(_Safe_sequence_base& __x) noexcept { // We need to lock both sequences to swap using namespace __gnu_cxx; @@ -382,7 +382,7 @@ _Safe_unordered_container_base* _Safe_local_iterator_base:: - _M_get_container() const _GLIBCXX_NOEXCEPT + _M_get_container() const noexcept { return static_cast<_Safe_unordered_container_base*>(_M_sequence); } void @@ -455,7 +455,7 @@ void _Safe_unordered_container_base:: - _M_swap(_Safe_unordered_container_base& __x) + _M_swap(_Safe_unordered_container_base& __x) noexcept { // We need to lock both containers to swap using namespace __gnu_cxx; Index: testsuite/23_containers/forward_list/allocator/move.cc =================================================================== --- testsuite/23_containers/forward_list/allocator/move.cc (revision 209879) +++ testsuite/23_containers/forward_list/allocator/move.cc (working copy) @@ -32,9 +32,11 @@ typedef std::forward_list 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() Index: testsuite/23_containers/forward_list/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/forward_list/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/forward_list/allocator/move_assign.cc (working copy) @@ -46,11 +46,13 @@ typedef std::forward_list test_type; test_type v1(alloc_type(1)); v1.push_front(T()); + auto it = v1.begin(); test_type v2(alloc_type(2)); v2.push_front(T()); v2 = std::move(v1); VERIFY(0 == v1.get_allocator().get_personality()); VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/forward_list/debug/construct1_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/construct1_neg.cc (revision 0) +++ testsuite/23_containers/forward_list/debug/construct1_neg.cc (working copy) @@ -0,0 +1,34 @@ +// 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-require-debug-mode "" } +// { dg-options "-std=gnu++11" } +// { dg-do run { xfail *-*-* } } + +#include +#include + +void test01() +{ + __gnu_test::check_construct1 >(); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/forward_list/debug/construct2_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/construct2_neg.cc (revision 0) +++ testsuite/23_containers/forward_list/debug/construct2_neg.cc (working copy) @@ -0,0 +1,34 @@ +// 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-require-debug-mode "" } +// { dg-options "-std=gnu++11" } +// { dg-do run { xfail *-*-* } } + +#include +#include + +void test01() +{ + __gnu_test::check_construct2 >(); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/forward_list/debug/construct3_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/construct3_neg.cc (revision 0) +++ testsuite/23_containers/forward_list/debug/construct3_neg.cc (working copy) @@ -0,0 +1,34 @@ +// Copyright (C) 2010-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-require-debug-mode "" } +// { dg-options "-std=gnu++11" } +// { dg-do run { xfail *-*-* } } + +#include +#include + +void test01() +{ + __gnu_test::check_construct3 >(); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/forward_list/debug/construct4_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/construct4_neg.cc (revision 0) +++ testsuite/23_containers/forward_list/debug/construct4_neg.cc (working copy) @@ -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" } +// { dg-do run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::forward_list test_type; + test_type v1(alloc_type(1)); + v1.push_front(0); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it == v2.begin() ); // Error, it is singular +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/forward_list/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/forward_list/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::forward_list test_type; + + test_type v1(alloc_type(1)); + v1.push_front(0); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + v2.push_front(1); + + v2 = std::move(v1); + + VERIFY( *it == 0 ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/forward_list/debug/move_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/forward_list/debug/move_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator alloc_type; + typedef __gnu_debug::forward_list test_type; + + test_type v1(alloc_type(1)); + v1 = { 0 }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/map/allocator/move.cc =================================================================== --- testsuite/23_containers/map/allocator/move.cc (revision 209879) +++ testsuite/23_containers/map/allocator/move.cc (working copy) @@ -38,9 +38,13 @@ typedef std::map test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + 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() Index: testsuite/23_containers/map/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/map/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/map/allocator/move_assign.cc (working copy) @@ -38,9 +38,11 @@ typedef std::map test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + test_type v2(alloc_type(2)); v2 = { test_type::value_type{} }; v2 = std::move(v1); + VERIFY(1 == v1.get_allocator().get_personality()); VERIFY(2 == v2.get_allocator().get_personality()); } @@ -52,11 +54,15 @@ typedef std::map test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + auto it = v1.begin(); + test_type v2(alloc_type(2)); v2 = { test_type::value_type{} }; v2 = std::move(v1); + VERIFY(0 == v1.get_allocator().get_personality()); VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/map/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/map/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/map/debug/construct5_neg.cc (working copy) @@ -0,0 +1,45 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator > alloc_type; + typedef __gnu_debug::map, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it->first == 0 ); // Error, it is singular +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/map/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/map/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/map/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator > alloc_type; + typedef __gnu_debug::map, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + v2.insert(std::make_pair(1, 1)); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/map/debug/move_neg.cc =================================================================== --- testsuite/23_containers/map/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/map/debug/move_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator > alloc_type; + typedef __gnu_debug::map, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { { 0, 0 } }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it->first == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/multimap/allocator/move.cc =================================================================== --- testsuite/23_containers/multimap/allocator/move.cc (revision 209879) +++ testsuite/23_containers/multimap/allocator/move.cc (working copy) @@ -38,9 +38,13 @@ typedef std::multimap test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + 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() Index: testsuite/23_containers/multimap/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/multimap/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/multimap/allocator/move_assign.cc (working copy) @@ -52,11 +52,13 @@ typedef std::multimap test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + auto it = v1.begin(); test_type v2(alloc_type(2)); v2 = { test_type::value_type{} }; v2 = std::move(v1); VERIFY(0 == v1.get_allocator().get_personality()); VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/multimap/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/multimap/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/multimap/debug/construct5_neg.cc (working copy) @@ -0,0 +1,45 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator > alloc_type; + typedef __gnu_debug::multimap, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it->first == 0 ); // Error, it is singular +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/multimap/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/multimap/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/multimap/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator > alloc_type; + typedef __gnu_debug::multimap, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + v2.insert(std::make_pair(1, 1)); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/multimap/debug/move_neg.cc =================================================================== --- testsuite/23_containers/multimap/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/multimap/debug/move_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator > alloc_type; + typedef __gnu_debug::multimap, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { { 0, 0 } }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it->first == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/multiset/allocator/move.cc =================================================================== --- testsuite/23_containers/multiset/allocator/move.cc (revision 209879) +++ testsuite/23_containers/multiset/allocator/move.cc (working copy) @@ -36,9 +36,13 @@ typedef std::multiset test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + 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() Index: testsuite/23_containers/multiset/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/multiset/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/multiset/allocator/move_assign.cc (working copy) @@ -50,11 +50,13 @@ typedef std::multiset test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + auto it = v1.begin(); test_type v2(alloc_type(2)); v2 = { test_type::value_type{} }; v2 = std::move(v1); VERIFY(0 == v1.get_allocator().get_personality()); VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/multiset/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/multiset/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/multiset/debug/construct5_neg.cc (working copy) @@ -0,0 +1,45 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::multiset, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(0); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); // Error, it is singular +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/multiset/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/multiset/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/multiset/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::multiset, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(0); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + v2.insert(1); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/multiset/debug/move_neg.cc =================================================================== --- testsuite/23_containers/multiset/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/multiset/debug/move_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator alloc_type; + typedef __gnu_debug::multiset, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { 0 }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/set/allocator/move.cc =================================================================== --- testsuite/23_containers/set/allocator/move.cc (revision 209879) +++ testsuite/23_containers/set/allocator/move.cc (working copy) @@ -38,9 +38,13 @@ typedef std::set test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + 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() Index: testsuite/23_containers/set/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/set/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/set/allocator/move_assign.cc (working copy) @@ -50,11 +50,13 @@ typedef std::set test_type; test_type v1(alloc_type(1)); v1 = { test_type::value_type{} }; + auto it = v1.begin(); test_type v2(alloc_type(2)); v2 = { test_type::value_type{} }; v2 = std::move(v1); VERIFY(0 == v1.get_allocator().get_personality()); VERIFY(1 == v2.get_allocator().get_personality()); + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/set/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/set/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/set/debug/construct5_neg.cc (working copy) @@ -0,0 +1,45 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::set, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(0); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); // Error, it is singular +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/set/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/set/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/set/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::set, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(0); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + v2.insert(1); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/set/debug/move_neg.cc =================================================================== --- testsuite/23_containers/set/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/set/debug/move_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator alloc_type; + typedef __gnu_debug::set, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { 0 }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_map/allocator/move.cc =================================================================== --- testsuite/23_containers/unordered_map/allocator/move.cc (revision 209879) +++ testsuite/23_containers/unordered_map/allocator/move.cc (working copy) @@ -45,9 +45,11 @@ test_type v1(alloc_type(1)); v1.emplace(std::piecewise_construct, std::make_tuple(T()), std::make_tuple(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() Index: testsuite/23_containers/unordered_map/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/unordered_map/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/unordered_map/allocator/move_assign.cc (working copy) @@ -66,6 +66,8 @@ v1.emplace(std::piecewise_construct, std::make_tuple(1), std::make_tuple(1)); + auto it = v1.begin(); + test_type v2(alloc_type(2)); v2.emplace(std::piecewise_construct, std::make_tuple(2), std::make_tuple(2)); @@ -79,6 +81,8 @@ VERIFY( counter_type::move_assign_count == 0 ); VERIFY( counter_type::destructor_count == 2 ); + + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/unordered_map/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/unordered_map/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/unordered_map/debug/construct5_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator> alloc_type; + typedef __gnu_debug::unordered_map, + std::equal_to, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_map/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator > alloc_type; + typedef __gnu_debug::unordered_map, std::equal_to, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_map/debug/move_neg.cc =================================================================== --- testsuite/23_containers/unordered_map/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/unordered_map/debug/move_neg.cc (working copy) @@ -0,0 +1,49 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator > alloc_type; + typedef __gnu_debug::unordered_map< + int, int, std::hash, std::equal_to, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { { 0, 0 } }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it->first == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_multimap/allocator/move.cc =================================================================== --- testsuite/23_containers/unordered_multimap/allocator/move.cc (revision 209879) +++ testsuite/23_containers/unordered_multimap/allocator/move.cc (working copy) @@ -45,9 +45,11 @@ test_type v1(alloc_type(1)); v1.emplace(std::piecewise_construct, std::make_tuple(T()), std::make_tuple(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() Index: testsuite/23_containers/unordered_multimap/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/unordered_multimap/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/unordered_multimap/allocator/move_assign.cc (working copy) @@ -66,6 +66,8 @@ v1.emplace(std::piecewise_construct, std::make_tuple(1), std::make_tuple(1)); + auto it = v1.begin(); + test_type v2(alloc_type(2)); v2.emplace(std::piecewise_construct, std::make_tuple(2), std::make_tuple(2)); @@ -79,6 +81,8 @@ VERIFY( counter_type::move_assign_count == 0 ); VERIFY( counter_type::destructor_count == 2 ); + + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/unordered_multimap/debug/construct5_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator> alloc_type; + typedef __gnu_debug::unordered_multimap, std::equal_to, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator> alloc_type; + typedef __gnu_debug::unordered_multimap, + std::equal_to, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(std::make_pair(0, 0)); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_multimap/debug/move_neg.cc =================================================================== --- testsuite/23_containers/unordered_multimap/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/unordered_multimap/debug/move_neg.cc (working copy) @@ -0,0 +1,49 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator > alloc_type; + typedef __gnu_debug::unordered_multimap< + int, int, std::hash, std::equal_to, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { { 0, 0 } }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it->first == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_multiset/allocator/move.cc =================================================================== --- testsuite/23_containers/unordered_multiset/allocator/move.cc (revision 209879) +++ testsuite/23_containers/unordered_multiset/allocator/move.cc (working copy) @@ -44,9 +44,11 @@ typedef std::unordered_multiset test_type; test_type v1(alloc_type(1)); v1.insert(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() Index: testsuite/23_containers/unordered_multiset/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/unordered_multiset/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/unordered_multiset/allocator/move_assign.cc (working copy) @@ -63,6 +63,8 @@ test_type v1(alloc_type(1)); v1.emplace(0); + auto it = v1.begin(); + test_type v2(alloc_type(2)); v2.emplace(0); @@ -76,6 +78,8 @@ VERIFY( counter_type::move_count == 0 ); VERIFY( counter_type::copy_count == 0 ); VERIFY( counter_type::destructor_count == 1 ); + + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/unordered_multiset/debug/construct5_neg.cc (working copy) @@ -0,0 +1,47 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::unordered_multiset, + std::equal_to, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.insert(0); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it == v2.begin() ); // Error, it is singular +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,49 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::unordered_multiset, + std::equal_to, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.emplace(0); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + v2.emplace(1); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_multiset/debug/move_neg.cc =================================================================== --- testsuite/23_containers/unordered_multiset/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/unordered_multiset/debug/move_neg.cc (working copy) @@ -0,0 +1,49 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator alloc_type; + typedef __gnu_debug::unordered_multiset< + int, std::hash, std::equal_to, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { 0 }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_set/allocator/move.cc =================================================================== --- testsuite/23_containers/unordered_set/allocator/move.cc (revision 209879) +++ testsuite/23_containers/unordered_set/allocator/move.cc (working copy) @@ -44,9 +44,11 @@ typedef std::unordered_set test_type; test_type v1(alloc_type(1)); v1.insert(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() Index: testsuite/23_containers/unordered_set/allocator/move_assign.cc =================================================================== --- testsuite/23_containers/unordered_set/allocator/move_assign.cc (revision 209879) +++ testsuite/23_containers/unordered_set/allocator/move_assign.cc (working copy) @@ -63,6 +63,8 @@ test_type v1(alloc_type(1)); v1.emplace(0); + auto it = v1.begin(); + test_type v2(alloc_type(2)); v2.emplace(0); @@ -76,6 +78,8 @@ VERIFY( counter_type::move_count == 0 ); VERIFY( counter_type::copy_count == 0 ); VERIFY( counter_type::destructor_count == 1 ); + + VERIFY( it == v2.begin() ); } int main() Index: testsuite/23_containers/unordered_set/debug/construct5_neg.cc =================================================================== --- testsuite/23_containers/unordered_set/debug/construct5_neg.cc (revision 0) +++ testsuite/23_containers/unordered_set/debug/construct5_neg.cc (working copy) @@ -0,0 +1,45 @@ +// 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 run { xfail *-*-* } } + +#include + +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::unordered_set, + std::equal_to, alloc_type> test_type; + test_type v1(alloc_type(1)); + v1.insert(0); + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( it == v2.begin() ); // Error, it is singular +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_set/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (revision 0) +++ testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (working copy) @@ -0,0 +1,49 @@ +// 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 run { xfail *-*-* } } + +#include +#include + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef __gnu_test::uneq_allocator alloc_type; + typedef __gnu_debug::unordered_set, + std::equal_to, + alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1.emplace(0); + auto it = v1.begin(); + + test_type v2(alloc_type(2)); + v2.emplace(1); + + v2 = std::move(v1); + + VERIFY( it == v2.begin() ); // Error, it is singular. +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/unordered_set/debug/move_neg.cc =================================================================== --- testsuite/23_containers/unordered_set/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/unordered_set/debug/move_neg.cc (working copy) @@ -0,0 +1,49 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator alloc_type; + typedef __gnu_debug::unordered_set< + int, std::hash, std::equal_to, alloc_type> test_type; + + test_type v1(alloc_type(1)); + v1 = { 0 }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/23_containers/vector/debug/move_neg.cc =================================================================== --- testsuite/23_containers/vector/debug/move_neg.cc (revision 0) +++ testsuite/23_containers/vector/debug/move_neg.cc (working copy) @@ -0,0 +1,48 @@ +// 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 run { xfail *-*-* } } + +#include + +#include +#include + +using __gnu_test::uneq_allocator; + +void test01() +{ + bool test __attribute__((unused)) = true; + + typedef uneq_allocator alloc_type; + typedef __gnu_debug::vector test_type; + + test_type v1(alloc_type(1)); + v1 = { 0 }; + auto it = v1.begin(); + + test_type v2(std::move(v1), alloc_type(2)); + + VERIFY( *it == 0 ); +} + +int main() +{ + test01(); + return 0; +} Index: testsuite/util/debug/checks.h =================================================================== --- testsuite/util/debug/checks.h (revision 209879) +++ testsuite/util/debug/checks.h (working copy) @@ -179,10 +179,8 @@ val_type *first = &v.front() + 1; val_type *last = first + 2; - cont_type c1(first, last); - VERIFY(c1.size() == 2); - cont_type c2(last, first); // Expected failure + cont_type c(last, first); // Expected failure } // Check that invalid range of debug random iterators is detected @@ -206,10 +204,8 @@ typename vector_type::iterator first = v.begin() + 1; typename vector_type::iterator last = first + 2; - cont_type c1(first, last); - VERIFY(c1.size() == 2); - cont_type c2(last, first); // Expected failure + cont_type c(last, first); // Expected failure } // Check that invalid range of debug not random iterators is detected @@ -233,10 +229,8 @@ typename list_type::iterator first = l.begin(); ++first; typename list_type::iterator last = first; ++last; ++last; - cont_type c1(first, last); - VERIFY(c1.size() == 2); - cont_type c2(last, first); // Expected failure + cont_type c(last, first); // Expected failure } template