* testsuite allocators patch @ 2014-06-20 20:37 François Dumont 2014-06-25 19:48 ` François Dumont 0 siblings, 1 reply; 17+ messages in thread From: François Dumont @ 2014-06-20 20:37 UTC (permalink / raw) To: libstdc++, gcc-patches Hi I would like to finally propose this patch before the one on _Rb_tree, as a separate one. I have adopted the same evolution on the tracker_allocator with even a perfect forwarding constructor to allow its usage on top of the uneq_allocator which take a personality parameter. Doing so I realized that move_assign_neg.cc tests were not accurate enough as they needed a non move propagating allocator and the uneq_allocator were not explicitly non propagating. 2014-06-21 François Dumont <fdumont@gcc.gnu.org> * testsuite/util/testsuite_allocator.h (tracker_allocator_counter::allocate): Remove new invocation, only collect information. (tracker_allocator_counter::deallocate): Remove delete invocation, only collect information. (check_inconsistent_alloc_value_type): New. (tracker_allocator): Transform as a facade for any allocator type. (uneq_allocator): Likewise. (propagating_allocator): Likewise. * testsuite/23_containers/forward_list/debug/move_assign_neg.cc: Use an explicitly non propagating allocator. * testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise. * testsuite/23_containers/multimap/debug/move_assign_neg.cc: likewise. * testsuite/23_containers/multiset/debug/move_assign_neg.cc: Likewise. * testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise. * testsuite/23_containers/unordered_map/debug/move_assign_neg.cc: Likewise. * testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc: Likewise. * testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc: Likewise. * testsuite/23_containers/unordered_set/debug/move_assign_neg.cc: Likewise. * testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise. Tested under Linux x86_64. Ok to commit ? François ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-20 20:37 testsuite allocators patch François Dumont @ 2014-06-25 19:48 ` François Dumont 2014-06-26 10:33 ` Jonathan Wakely 0 siblings, 1 reply; 17+ messages in thread From: François Dumont @ 2014-06-25 19:48 UTC (permalink / raw) To: libstdc++, gcc-patches [-- Attachment #1: Type: text/plain, Size: 1978 bytes --] Hi With the patch this time. > > I would like to finally propose this patch before the one on > _Rb_tree, as a separate one. > > I have adopted the same evolution on the tracker_allocator with > even a perfect forwarding constructor to allow its usage on top of the > uneq_allocator which take a personality parameter. Doing so I > realized that move_assign_neg.cc tests were not accurate enough as > they needed a non move propagating allocator and the uneq_allocator > were not explicitly non propagating. > > 2014-06-21 François Dumont <fdumont@gcc.gnu.org> > > * testsuite/util/testsuite_allocator.h > (tracker_allocator_counter::allocate): Remove new invocation, only > collect information. > (tracker_allocator_counter::deallocate): Remove delete invocation, > only > collect information. > (check_inconsistent_alloc_value_type): New. > (tracker_allocator): Transform as a facade for any allocator type. > (uneq_allocator): Likewise. > (propagating_allocator): Likewise. > * testsuite/23_containers/forward_list/debug/move_assign_neg.cc: > Use an > explicitly non propagating allocator. > * testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise. > * testsuite/23_containers/multimap/debug/move_assign_neg.cc: > likewise. > * testsuite/23_containers/multiset/debug/move_assign_neg.cc: > Likewise. > * testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise. > * testsuite/23_containers/unordered_map/debug/move_assign_neg.cc: > Likewise. > * > testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc: > Likewise. > * > testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc: > Likewise. > * testsuite/23_containers/unordered_set/debug/move_assign_neg.cc: > Likewise. > * testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise. > > Tested under Linux x86_64. > > Ok to commit ? > > François > [-- Attachment #2: testsuite_alloc.patch --] [-- Type: text/x-patch, Size: 21162 bytes --] Index: testsuite/util/testsuite_allocator.h =================================================================== --- testsuite/util/testsuite_allocator.h (revision 211713) +++ testsuite/util/testsuite_allocator.h (working copy) @@ -29,6 +29,7 @@ #include <tr1/unordered_map> #include <bits/move.h> #include <ext/pointer.h> +#include <ext/alloc_traits.h> #include <testsuite_hooks.h> namespace __gnu_test @@ -38,26 +39,19 @@ public: typedef std::size_t size_type; - static void* + static void allocate(size_type blocksize) - { - void* p = ::operator new(blocksize); - allocationCount_ += blocksize; - return p; - } + { allocationCount_ += blocksize; } static void - construct() { constructCount_++; } + construct() { ++constructCount_; } static void - destroy() { destructCount_++; } + destroy() { ++destructCount_; } static void - deallocate(void* p, size_type blocksize) - { - ::operator delete(p); - deallocationCount_ += blocksize; - } + deallocate(size_type blocksize) + { deallocationCount_ += blocksize; } static size_type get_allocation_count() { return allocationCount_; } @@ -87,103 +81,142 @@ static int destructCount_; }; - // A simple basic allocator that just forwards to the + // Helper to detect inconsistency between type used to instantiate an + // allocator and the underlying allocator value_type. + template<typename T, typename Alloc, + typename = typename Alloc::value_type> + struct check_consistent_alloc_value_type; + + template<typename T, typename Alloc> + struct check_consistent_alloc_value_type<T, Alloc, T> + { typedef T value_type; }; + + // An allocator facade that just intercepts some calls and forward them to the // tracker_allocator_counter to fulfill memory requests. This class // is templated on the target object type, but tracker isn't. - template<class T> - class tracker_allocator - { - private: - typedef tracker_allocator_counter counter_type; + template<typename T, typename Alloc = std::allocator<T> > + class tracker_allocator : public Alloc + { + private: + typedef tracker_allocator_counter counter_type; - public: - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; + typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; + + public: + typedef typename + check_consistent_alloc_value_type<T, Alloc>::value_type value_type; + typedef typename AllocTraits::pointer pointer; + typedef typename AllocTraits::size_type size_type; - template<class U> struct rebind { typedef tracker_allocator<U> other; }; + template<class U> + struct rebind + { + typedef tracker_allocator<U, + typename AllocTraits::template rebind<U>::other> other; + }; - pointer - address(reference value) const _GLIBCXX_NOEXCEPT - { return std::__addressof(value); } +#if __cplusplus >= 201103L + tracker_allocator() = default; + tracker_allocator(const tracker_allocator&) = default; + tracker_allocator(tracker_allocator&&) = default; - const_pointer - address(const_reference value) const _GLIBCXX_NOEXCEPT - { return std::__addressof(value); } + // Perfect forwarding constructor. + template<typename... _Args> + tracker_allocator(_Args&&... __args) + : Alloc(std::forward<_Args>(__args)...) + { } +#else + tracker_allocator() _GLIBCXX_USE_NOEXCEPT + { } - tracker_allocator() _GLIBCXX_USE_NOEXCEPT - { } + tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT + { } - tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT - { } - - template<class U> - tracker_allocator(const tracker_allocator<U>&) _GLIBCXX_USE_NOEXCEPT + ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT { } +#endif - ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT - { } + template<class U> + tracker_allocator(const tracker_allocator<U, + typename AllocTraits::template rebind<U>::other>& alloc) + _GLIBCXX_USE_NOEXCEPT + : Alloc(alloc) + { } - size_type - max_size() const _GLIBCXX_USE_NOEXCEPT - { return size_type(-1) / sizeof(T); } + pointer + allocate(size_type n, const void* = 0) + { + pointer p = AllocTraits::allocate(*this, n); + counter_type::allocate(n * sizeof(T)); + return p; + } - pointer - allocate(size_type n, const void* = 0) - { return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); } +#if __cplusplus >= 201103L + template<typename U, typename... Args> + void + construct(U* p, Args&&... args) + { + AllocTraits::construct(*this, p, std::forward<Args>(args)...); + counter_type::construct(); + } -#if __cplusplus >= 201103L - template<typename U, typename... Args> + template<typename U> + void + destroy(U* p) + { + AllocTraits::destroy(*this, p); + counter_type::destroy(); + } +#else void - construct(U* p, Args&&... args) + construct(pointer p, const T& value) { - ::new((void *)p) U(std::forward<Args>(args)...); + AllocTraits::construct(*this, p, value); counter_type::construct(); } - template<typename U> void - destroy(U* p) + destroy(pointer p) { - p->~U(); + AllocTraits::destroy(*this, p); counter_type::destroy(); } -#else - void - construct(pointer p, const T& value) - { - ::new ((void *)p) T(value); - counter_type::construct(); - } - - void - destroy(pointer p) - { - p->~T(); - counter_type::destroy(); - } #endif - void - deallocate(pointer p, size_type num) - { counter_type::deallocate(p, num * sizeof(T)); } - }; + void + deallocate(pointer p, size_type num) + { + counter_type::deallocate(num * sizeof(T)); + AllocTraits::deallocate(*this, p, num); + } - template<class T1, class T2> + // Implement swap for underlying allocators that might need it. + friend inline void + swap(tracker_allocator& a, tracker_allocator& b) + { + using std::swap; + + Alloc& aa = a; + Alloc& ab = b; + swap(aa, ab); + } + }; + + template<class T1, class Alloc1, class T2, class Alloc2> bool - operator==(const tracker_allocator<T1>&, - const tracker_allocator<T2>&) throw() - { return true; } + operator==(const tracker_allocator<T1, Alloc1>& lhs, + const tracker_allocator<T2, Alloc2>& rhs) throw() + { + const Alloc1& alloc1 = lhs; + const Alloc2& alloc2 = rhs; + return lhs == rhs; + } - template<class T1, class T2> + template<class T1, class Alloc1, class T2, class Alloc2> bool - operator!=(const tracker_allocator<T1>&, - const tracker_allocator<T2>&) throw() - { return false; } + operator!=(const tracker_allocator<T1, Alloc1>& lhs, + const tracker_allocator<T2, Alloc2>& rhs) throw() + { return !(lhs == rhs); } bool check_construct_destroy(const char* tag, int expected_c, int expected_d); @@ -219,7 +252,6 @@ throw; } - // A simple allocator which can be constructed endowed of a given // "personality" (an integer), queried in operator== to simulate the // behavior of realworld "unequal" allocators (i.e., not exploiting @@ -227,7 +259,7 @@ // filled at allocation time with (pointer, personality) pairs, is // then consulted to enforce the requirements in Table 32 about // deallocation vs allocator equality. Note that this allocator is - // swappable, not assignable, consistently with Option 3 of DR 431 + // swappable, not copy assignable, consistently with Option 3 of DR 431 // (see N1599). struct uneq_allocator_base { @@ -244,26 +276,33 @@ } }; - template<typename Tp> + template<typename Tp, typename Alloc = std::allocator<Tp> > class uneq_allocator - : private uneq_allocator_base + : private uneq_allocator_base, + public Alloc { + typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; + + Alloc& base() { return *this; } + const Alloc& base() const { return *this; } + void swap_base(Alloc& b) { swap(b, this->base()); } + public: - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef Tp* pointer; - typedef const Tp* const_pointer; - typedef Tp& reference; - typedef const Tp& const_reference; - typedef Tp value_type; + typedef typename check_consistent_alloc_value_type<Tp, Alloc>::value_type + value_type; + typedef typename AllocTraits::size_type size_type; + typedef typename AllocTraits::pointer pointer; #if __cplusplus >= 201103L - typedef std::true_type propagate_on_container_swap; + typedef std::true_type propagate_on_container_swap; #endif template<typename Tp1> - struct rebind - { typedef uneq_allocator<Tp1> other; }; + struct rebind + { + typedef uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other> other; + }; uneq_allocator() _GLIBCXX_USE_NOEXCEPT : personality(0) { } @@ -272,7 +311,9 @@ : personality(person) { } template<typename Tp1> - uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT + uneq_allocator(const uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other>& b) + _GLIBCXX_USE_NOEXCEPT : personality(b.get_personality()) { } ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT @@ -281,20 +322,9 @@ int get_personality() const { return personality; } pointer - address(reference x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(x); } - - const_pointer - address(const_reference x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(x); } - - pointer - allocate(size_type n, const void* = 0) + allocate(size_type n, const void* hint = 0) { - if (__builtin_expect(n > this->max_size(), false)) - std::__throw_bad_alloc(); - - pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp))); + pointer p = AllocTraits::allocate(*this, n); try { get_map().insert(map_type::value_type(reinterpret_cast<void*>(p), @@ -302,7 +332,7 @@ } catch(...) { - ::operator delete(p); + AllocTraits::deallocate(*this, p, n); __throw_exception_again; } return p; @@ -309,7 +339,7 @@ } void - deallocate(pointer p, size_type) + deallocate(pointer p, size_type n) { bool test __attribute__((unused)) = true; @@ -323,34 +353,18 @@ VERIFY( it->second == personality ); get_map().erase(it); - ::operator delete(p); + AllocTraits::deallocate(*this, p, n); } - size_type - max_size() const _GLIBCXX_USE_NOEXCEPT - { return size_type(-1) / sizeof(Tp); } - #if __cplusplus >= 201103L - template<typename U, typename... Args> - void - construct(U* p, Args&&... args) - { ::new((void *)p) U(std::forward<Args>(args)...); } - - template<typename U> - void - destroy(U* p) { p->~U(); } - // Not copy assignable... uneq_allocator& operator=(const uneq_allocator&) = delete; + + // ... but still moveable if base allocator is. + uneq_allocator& + operator=(uneq_allocator&&) = default; #else - void - construct(pointer p, const Tp& val) - { ::new((void *)p) Tp(val); } - - void - destroy(pointer p) { p->~Tp(); } - private: // Not assignable... uneq_allocator& @@ -358,21 +372,27 @@ #endif private: - // ... yet swappable! friend inline void swap(uneq_allocator& a, uneq_allocator& b) - { std::swap(a.personality, b.personality); } - + { + std::swap(a.personality, b.personality); + a.swap_base(b); + } + template<typename Tp1> - friend inline bool - operator==(const uneq_allocator& a, const uneq_allocator<Tp1>& b) - { return a.personality == b.personality; } + friend inline bool + operator==(const uneq_allocator& a, + const uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other>& b) + { return a.personality == b.personality; } template<typename Tp1> - friend inline bool - operator!=(const uneq_allocator& a, const uneq_allocator<Tp1>& b) - { return !(a == b); } + friend inline bool + operator!=(const uneq_allocator& a, + const uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other>& b) + { return !(a == b); } int personality; }; @@ -379,10 +399,12 @@ #if __cplusplus >= 201103L // An uneq_allocator which can be used to test allocator propagation. - template<typename Tp, bool Propagate> - class propagating_allocator : public uneq_allocator<Tp> + template<typename Tp, bool Propagate, typename Alloc = std::allocator<Tp>> + class propagating_allocator : public uneq_allocator<Tp, Alloc> { - typedef uneq_allocator<Tp> base_alloc; + typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; + + typedef uneq_allocator<Tp, Alloc> base_alloc; base_alloc& base() { return *this; } const base_alloc& base() const { return *this; } void swap_base(base_alloc& b) { swap(b, this->base()); } @@ -393,7 +415,11 @@ // default allocator_traits::rebind_alloc would select // uneq_allocator::rebind so we must define rebind here template<typename Up> - struct rebind { typedef propagating_allocator<Up, Propagate> other; }; + struct rebind + { + typedef propagating_allocator<Up, Propagate, + typename AllocTraits::template rebind<Up>::other> other; + }; propagating_allocator(int i) noexcept : base_alloc(i) @@ -400,8 +426,9 @@ { } template<typename Up> - propagating_allocator(const propagating_allocator<Up, Propagate>& a) - noexcept + propagating_allocator(const propagating_allocator<Up, Propagate, + typename AllocTraits::template rebind<Up>::other>& a) + noexcept : base_alloc(a) { } @@ -418,8 +445,8 @@ } template<bool P2> - propagating_allocator& - operator=(const propagating_allocator<Tp, P2>& a) noexcept + propagating_allocator& + operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept { static_assert(P2, "assigning propagating_allocator<T, true>"); propagating_allocator(a).swap_base(*this); Index: testsuite/23_containers/forward_list/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/forward_list/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::forward_list<int, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/map/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/map/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/map/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/multimap/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/multimap/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/multimap/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/multiset/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/multiset/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/multiset/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/set/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/set/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/set/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/unordered_map/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::unordered_map<int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::unordered_multiset<int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/unordered_set/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::unordered_set<int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/vector/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/vector/debug/move_assign_neg.cc (revision 211713) +++ testsuite/23_containers/vector/debug/move_assign_neg.cc (working copy) @@ -27,7 +27,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::vector<int, alloc_type> test_type; test_type v1(alloc_type(1)); ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-25 19:48 ` François Dumont @ 2014-06-26 10:33 ` Jonathan Wakely 2014-06-26 20:45 ` François Dumont 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Wakely @ 2014-06-26 10:33 UTC (permalink / raw) To: François Dumont; +Cc: libstdc++, gcc-patches On 25/06/14 21:47 +0200, François Dumont wrote: >> I would like to finally propose this patch before the one on >>_Rb_tree, as a separate one. >> >> I have adopted the same evolution on the tracker_allocator with >>even a perfect forwarding constructor to allow its usage on top of >>the uneq_allocator which take a personality parameter. Doing so I >>realized that move_assign_neg.cc tests were not accurate enough as >>they needed a non move propagating allocator and the uneq_allocator >>were not explicitly non propagating. Ah, that's good to improve them then. >Index: testsuite/util/testsuite_allocator.h >=================================================================== >--- testsuite/util/testsuite_allocator.h (revision 211713) >+++ testsuite/util/testsuite_allocator.h (working copy) >@@ -87,103 +81,142 @@ > static int destructCount_; > }; > >- // A simple basic allocator that just forwards to the >+ // Helper to detect inconsistency between type used to instantiate an >+ // allocator and the underlying allocator value_type. >+ template<typename T, typename Alloc, >+ typename = typename Alloc::value_type> >+ struct check_consistent_alloc_value_type; >+ >+ template<typename T, typename Alloc> >+ struct check_consistent_alloc_value_type<T, Alloc, T> >+ { typedef T value_type; }; >+ >+ // An allocator facade that just intercepts some calls and forward them to the > // tracker_allocator_counter to fulfill memory requests. This class This comment is no longer true, tracker_allocator_counter does not fulfil the memory requests. > // is templated on the target object type, but tracker isn't. >- template<class T> >- class tracker_allocator >- { >- private: >- typedef tracker_allocator_counter counter_type; >+ template<typename T, typename Alloc = std::allocator<T> > >+ class tracker_allocator : public Alloc >+ { >+ private: >+ typedef tracker_allocator_counter counter_type; > >- public: >- typedef T value_type; >- typedef T* pointer; >- typedef const T* const_pointer; >- typedef T& reference; >- typedef const T& const_reference; >- typedef std::size_t size_type; >- typedef std::ptrdiff_t difference_type; >+ typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; >+ >+ public: >+ typedef typename >+ check_consistent_alloc_value_type<T, Alloc>::value_type value_type; >+ typedef typename AllocTraits::pointer pointer; >+ typedef typename AllocTraits::size_type size_type; Thanks for doing this - I think it makes the facade more useful if it uses allocator_traits and so can be combined with SimpleAllocator and CustomPointerAlloc. >- template<class U> struct rebind { typedef tracker_allocator<U> other; }; >+ template<class U> >+ struct rebind >+ { >+ typedef tracker_allocator<U, >+ typename AllocTraits::template rebind<U>::other> other; >+ }; > >- pointer >- address(reference value) const _GLIBCXX_NOEXCEPT >- { return std::__addressof(value); } >+#if __cplusplus >= 201103L >+ tracker_allocator() = default; >+ tracker_allocator(const tracker_allocator&) = default; >+ tracker_allocator(tracker_allocator&&) = default; > >- const_pointer >- address(const_reference value) const _GLIBCXX_NOEXCEPT >- { return std::__addressof(value); } >+ // Perfect forwarding constructor. >+ template<typename... _Args> >+ tracker_allocator(_Args&&... __args) >+ : Alloc(std::forward<_Args>(__args)...) >+ { } >+#else >+ tracker_allocator() _GLIBCXX_USE_NOEXCEPT The _GLIBCXX_USE_NOEXCEPT macro expands to nothing in C++03 mode, so you might as well omit it in the #else branch. OK for trunk if you make the tracker_allocator comment correct. Thanks! ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-26 10:33 ` Jonathan Wakely @ 2014-06-26 20:45 ` François Dumont 2014-06-26 21:24 ` Paolo Carlini 0 siblings, 1 reply; 17+ messages in thread From: François Dumont @ 2014-06-26 20:45 UTC (permalink / raw) To: Jonathan Wakely; +Cc: libstdc++, gcc-patches On 26/06/2014 12:33, Jonathan Wakely wrote: > > The _GLIBCXX_USE_NOEXCEPT macro expands to nothing in C++03 mode, so > you might as well omit it in the #else branch. > > OK for trunk if you make the tracker_allocator comment correct. > > Thanks! > > Committed with: // An allocator facade that intercepts allocate/deallocate/construct/destroy // calls and track them through the tracker_allocator_counter class. This // class is templated on the target object type, but tracker isn't. template<typename T, typename Alloc = std::allocator<T> > class tracker_allocator : public Alloc Thanks for feedback. François ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-26 20:45 ` François Dumont @ 2014-06-26 21:24 ` Paolo Carlini 2014-06-26 22:39 ` Jonathan Wakely 0 siblings, 1 reply; 17+ messages in thread From: Paolo Carlini @ 2014-06-26 21:24 UTC (permalink / raw) To: François Dumont, Jonathan Wakely; +Cc: libstdc++, gcc-patches Hi, I'm afraid something went badly wrong with this commit, I'm seeing tens of fails. See eg: https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html Paolo. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-26 21:24 ` Paolo Carlini @ 2014-06-26 22:39 ` Jonathan Wakely 2014-06-27 7:30 ` Paolo Carlini 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Wakely @ 2014-06-26 22:39 UTC (permalink / raw) To: Paolo Carlini; +Cc: François Dumont, libstdc++, gcc-patches On 26/06/14 23:21 +0200, Paolo Carlini wrote: >Hi, > >I'm afraid something went badly wrong with this commit, I'm seeing >tens of fails. See eg: > > https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html It seems that uneq_allocator is no longer copy constructible. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-26 22:39 ` Jonathan Wakely @ 2014-06-27 7:30 ` Paolo Carlini 2014-06-27 17:33 ` Jonathan Wakely 0 siblings, 1 reply; 17+ messages in thread From: Paolo Carlini @ 2014-06-27 7:30 UTC (permalink / raw) To: Jonathan Wakely; +Cc: François Dumont, libstdc++, gcc-patches Hi, On 06/27/2014 12:38 AM, Jonathan Wakely wrote: > On 26/06/14 23:21 +0200, Paolo Carlini wrote: >> Hi, >> >> I'm afraid something went badly wrong with this commit, I'm seeing >> tens of fails. See eg: >> >> https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html > > It seems that uneq_allocator is no longer copy constructible. Can you spot a quick fix, like a thinko, or do you think Francois has to look into it? I'm inclined to revert it for now, the noise is quite annoying... Thanks, Paolo. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-27 7:30 ` Paolo Carlini @ 2014-06-27 17:33 ` Jonathan Wakely 2014-06-27 19:51 ` Paolo Carlini 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Wakely @ 2014-06-27 17:33 UTC (permalink / raw) To: Paolo Carlini Cc: Jonathan Wakely, François Dumont, libstdc++, gcc-patches I didn't see an obvious fix (I'm not sure if the templated constructor can deduce its argument since the change) but have been out all day and not had a chance to look into it. On 27 June 2014 08:27, Paolo Carlini <paolo.carlini@oracle.com> wrote: > Hi, > > > On 06/27/2014 12:38 AM, Jonathan Wakely wrote: >> >> On 26/06/14 23:21 +0200, Paolo Carlini wrote: >>> >>> Hi, >>> >>> I'm afraid something went badly wrong with this commit, I'm seeing tens >>> of fails. See eg: >>> >>> https://gcc.gnu.org/ml/gcc-testresults/2014-06/msg02439.html >> >> >> It seems that uneq_allocator is no longer copy constructible. > > Can you spot a quick fix, like a thinko, or do you think Francois has to > look into it? I'm inclined to revert it for now, the noise is quite > annoying... > > Thanks, > Paolo. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-27 17:33 ` Jonathan Wakely @ 2014-06-27 19:51 ` Paolo Carlini 2014-06-27 21:29 ` François Dumont 2014-07-23 20:46 ` François Dumont 0 siblings, 2 replies; 17+ messages in thread From: Paolo Carlini @ 2014-06-27 19:51 UTC (permalink / raw) To: Jonathan Wakely Cc: Jonathan Wakely, François Dumont, libstdc++, gcc-patches Hi, On 06/27/2014 07:33 PM, Jonathan Wakely wrote: > I didn't see an obvious fix (I'm not sure if the templated constructor > can deduce its argument since the change) but have been out all day > and not had a chance to look into it. Ok, thanks. I'm reverting the last two libstdc++-v3 commits. Paolo. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-27 19:51 ` Paolo Carlini @ 2014-06-27 21:29 ` François Dumont 2014-07-23 20:46 ` François Dumont 1 sibling, 0 replies; 17+ messages in thread From: François Dumont @ 2014-06-27 21:29 UTC (permalink / raw) To: Paolo Carlini, Jonathan Wakely; +Cc: Jonathan Wakely, libstdc++, gcc-patches On 27/06/2014 21:48, Paolo Carlini wrote: > Hi, > > On 06/27/2014 07:33 PM, Jonathan Wakely wrote: >> I didn't see an obvious fix (I'm not sure if the templated constructor >> can deduce its argument since the change) but have been out all day >> and not had a chance to look into it. > Ok, thanks. I'm reverting the last two libstdc++-v3 commits. > > Paolo. > It run fine on my side but maybe because of other modifications I have. I will revert those and reapply the patch to see what is wrong. Sorry François ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-06-27 19:51 ` Paolo Carlini 2014-06-27 21:29 ` François Dumont @ 2014-07-23 20:46 ` François Dumont 2014-07-24 8:58 ` Jonathan Wakely 2014-07-29 19:42 ` Jonathan Wakely 1 sibling, 2 replies; 17+ messages in thread From: François Dumont @ 2014-07-23 20:46 UTC (permalink / raw) To: Paolo Carlini, Jonathan Wakely; +Cc: Jonathan Wakely, libstdc++, gcc-patches [-- Attachment #1: Type: text/plain, Size: 935 bytes --] On 27/06/2014 21:48, Paolo Carlini wrote: > Hi, > > On 06/27/2014 07:33 PM, Jonathan Wakely wrote: >> I didn't see an obvious fix (I'm not sure if the templated constructor >> can deduce its argument since the change) but have been out all day >> and not had a chance to look into it. > Ok, thanks. I'm reverting the last two libstdc++-v3 commits. > > Paolo. > Hi Back from vacation, ready to have this patch committed eventually. Here is the new version with the missing default and copy constructor. I have a small question regarding some code next to the one I am modifying in this patch. I can see lines like: propagating_allocator() noexcept = default; When using a default implementation shouldn't we let the compiler decide if it should be noexcept or not depending on the member fields or base class default constructors ? Tested under Linux x86_64. Ok to commit ? François [-- Attachment #2: testsuite_alloc.patch --] [-- Type: text/x-patch, Size: 21616 bytes --] Index: testsuite/util/testsuite_allocator.h =================================================================== --- testsuite/util/testsuite_allocator.h (revision 212959) +++ testsuite/util/testsuite_allocator.h (working copy) @@ -29,6 +29,7 @@ #include <tr1/unordered_map> #include <bits/move.h> #include <ext/pointer.h> +#include <ext/alloc_traits.h> #include <testsuite_hooks.h> namespace __gnu_test @@ -38,26 +39,19 @@ public: typedef std::size_t size_type; - static void* + static void allocate(size_type blocksize) - { - void* p = ::operator new(blocksize); - allocationCount_ += blocksize; - return p; - } + { allocationCount_ += blocksize; } static void - construct() { constructCount_++; } + construct() { ++constructCount_; } static void - destroy() { destructCount_++; } + destroy() { ++destructCount_; } static void - deallocate(void* p, size_type blocksize) - { - ::operator delete(p); - deallocationCount_ += blocksize; - } + deallocate(size_type blocksize) + { deallocationCount_ += blocksize; } static size_type get_allocation_count() { return allocationCount_; } @@ -87,103 +81,142 @@ static int destructCount_; }; - // A simple basic allocator that just forwards to the - // tracker_allocator_counter to fulfill memory requests. This class - // is templated on the target object type, but tracker isn't. - template<class T> - class tracker_allocator - { - private: - typedef tracker_allocator_counter counter_type; + // Helper to detect inconsistency between type used to instantiate an + // allocator and the underlying allocator value_type. + template<typename T, typename Alloc, + typename = typename Alloc::value_type> + struct check_consistent_alloc_value_type; - public: - typedef T value_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - - template<class U> struct rebind { typedef tracker_allocator<U> other; }; - - pointer - address(reference value) const _GLIBCXX_NOEXCEPT - { return std::__addressof(value); } + template<typename T, typename Alloc> + struct check_consistent_alloc_value_type<T, Alloc, T> + { typedef T value_type; }; - const_pointer - address(const_reference value) const _GLIBCXX_NOEXCEPT - { return std::__addressof(value); } + // An allocator facade that intercepts allocate/deallocate/construct/destroy + // calls and track them through the tracker_allocator_counter class. This + // class is templated on the target object type, but tracker isn't. + template<typename T, typename Alloc = std::allocator<T> > + class tracker_allocator : public Alloc + { + private: + typedef tracker_allocator_counter counter_type; - tracker_allocator() _GLIBCXX_USE_NOEXCEPT - { } + typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; - tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT - { } + public: + typedef typename + check_consistent_alloc_value_type<T, Alloc>::value_type value_type; + typedef typename AllocTraits::pointer pointer; + typedef typename AllocTraits::size_type size_type; - template<class U> - tracker_allocator(const tracker_allocator<U>&) _GLIBCXX_USE_NOEXCEPT + template<class U> + struct rebind + { + typedef tracker_allocator<U, + typename AllocTraits::template rebind<U>::other> other; + }; + +#if __cplusplus >= 201103L + tracker_allocator() = default; + tracker_allocator(const tracker_allocator&) = default; + tracker_allocator(tracker_allocator&&) = default; + + // Perfect forwarding constructor. + template<typename... _Args> + tracker_allocator(_Args&&... __args) + : Alloc(std::forward<_Args>(__args)...) + { } +#else + tracker_allocator() { } - ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT - { } + tracker_allocator(const tracker_allocator&) + { } - size_type - max_size() const _GLIBCXX_USE_NOEXCEPT - { return size_type(-1) / sizeof(T); } + ~tracker_allocator() + { } +#endif - pointer - allocate(size_type n, const void* = 0) - { return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); } + template<class U> + tracker_allocator(const tracker_allocator<U, + typename AllocTraits::template rebind<U>::other>& alloc) + _GLIBCXX_USE_NOEXCEPT + : Alloc(alloc) + { } + pointer + allocate(size_type n, const void* = 0) + { + pointer p = AllocTraits::allocate(*this, n); + counter_type::allocate(n * sizeof(T)); + return p; + } + #if __cplusplus >= 201103L - template<typename U, typename... Args> + template<typename U, typename... Args> + void + construct(U* p, Args&&... args) + { + AllocTraits::construct(*this, p, std::forward<Args>(args)...); + counter_type::construct(); + } + + template<typename U> + void + destroy(U* p) + { + AllocTraits::destroy(*this, p); + counter_type::destroy(); + } +#else void - construct(U* p, Args&&... args) + construct(pointer p, const T& value) { - ::new((void *)p) U(std::forward<Args>(args)...); + AllocTraits::construct(*this, p, value); counter_type::construct(); } - template<typename U> void - destroy(U* p) + destroy(pointer p) { - p->~U(); + AllocTraits::destroy(*this, p); counter_type::destroy(); } -#else - void - construct(pointer p, const T& value) - { - ::new ((void *)p) T(value); - counter_type::construct(); - } - - void - destroy(pointer p) - { - p->~T(); - counter_type::destroy(); - } #endif - void - deallocate(pointer p, size_type num) - { counter_type::deallocate(p, num * sizeof(T)); } - }; + void + deallocate(pointer p, size_type num) + { + counter_type::deallocate(num * sizeof(T)); + AllocTraits::deallocate(*this, p, num); + } - template<class T1, class T2> + // Implement swap for underlying allocators that might need it. + friend inline void + swap(tracker_allocator& a, tracker_allocator& b) + { + using std::swap; + + Alloc& aa = a; + Alloc& ab = b; + swap(aa, ab); + } + }; + + template<class T1, class Alloc1, class T2, class Alloc2> bool - operator==(const tracker_allocator<T1>&, - const tracker_allocator<T2>&) throw() - { return true; } + operator==(const tracker_allocator<T1, Alloc1>& lhs, + const tracker_allocator<T2, Alloc2>& rhs) throw() + { + const Alloc1& alloc1 = lhs; + const Alloc2& alloc2 = rhs; + return lhs == rhs; + } - template<class T1, class T2> + template<class T1, class Alloc1, class T2, class Alloc2> bool - operator!=(const tracker_allocator<T1>&, - const tracker_allocator<T2>&) throw() - { return false; } + operator!=(const tracker_allocator<T1, Alloc1>& lhs, + const tracker_allocator<T2, Alloc2>& rhs) throw() + { return !(lhs == rhs); } bool check_construct_destroy(const char* tag, int expected_c, int expected_d); @@ -193,7 +226,7 @@ check_deallocate_null() { // Let's not core here... - Alloc a; + Alloc a; a.deallocate(0, 1); a.deallocate(0, 10); return true; @@ -219,7 +252,6 @@ throw; } - // A simple allocator which can be constructed endowed of a given // "personality" (an integer), queried in operator== to simulate the // behavior of realworld "unequal" allocators (i.e., not exploiting @@ -227,7 +259,7 @@ // filled at allocation time with (pointer, personality) pairs, is // then consulted to enforce the requirements in Table 32 about // deallocation vs allocator equality. Note that this allocator is - // swappable, not assignable, consistently with Option 3 of DR 431 + // swappable, not copy assignable, consistently with Option 3 of DR 431 // (see N1599). struct uneq_allocator_base { @@ -244,26 +276,33 @@ } }; - template<typename Tp> + template<typename Tp, typename Alloc = std::allocator<Tp> > class uneq_allocator - : private uneq_allocator_base + : private uneq_allocator_base, + public Alloc { + typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; + + Alloc& base() { return *this; } + const Alloc& base() const { return *this; } + void swap_base(Alloc& b) { swap(b, this->base()); } + public: - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef Tp* pointer; - typedef const Tp* const_pointer; - typedef Tp& reference; - typedef const Tp& const_reference; - typedef Tp value_type; + typedef typename check_consistent_alloc_value_type<Tp, Alloc>::value_type + value_type; + typedef typename AllocTraits::size_type size_type; + typedef typename AllocTraits::pointer pointer; #if __cplusplus >= 201103L - typedef std::true_type propagate_on_container_swap; + typedef std::true_type propagate_on_container_swap; #endif template<typename Tp1> - struct rebind - { typedef uneq_allocator<Tp1> other; }; + struct rebind + { + typedef uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other> other; + }; uneq_allocator() _GLIBCXX_USE_NOEXCEPT : personality(0) { } @@ -270,9 +309,16 @@ uneq_allocator(int person) _GLIBCXX_USE_NOEXCEPT : personality(person) { } + +#if __cplusplus >= 201103L + uneq_allocator(const uneq_allocator&) = default; + uneq_allocator(uneq_allocator&&) = default; +#endif template<typename Tp1> - uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT + uneq_allocator(const uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other>& b) + _GLIBCXX_USE_NOEXCEPT : personality(b.get_personality()) { } ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT @@ -281,20 +327,10 @@ int get_personality() const { return personality; } pointer - address(reference x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(x); } - - const_pointer - address(const_reference x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(x); } + allocate(size_type n, const void* hint = 0) + { + pointer p = AllocTraits::allocate(*this, n); - pointer - allocate(size_type n, const void* = 0) - { - if (__builtin_expect(n > this->max_size(), false)) - std::__throw_bad_alloc(); - - pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp))); try { get_map().insert(map_type::value_type(reinterpret_cast<void*>(p), @@ -302,14 +338,15 @@ } catch(...) { - ::operator delete(p); + AllocTraits::deallocate(*this, p, n); __throw_exception_again; } + return p; } void - deallocate(pointer p, size_type) + deallocate(pointer p, size_type n) { bool test __attribute__((unused)) = true; @@ -323,34 +360,18 @@ VERIFY( it->second == personality ); get_map().erase(it); - ::operator delete(p); + AllocTraits::deallocate(*this, p, n); } - size_type - max_size() const _GLIBCXX_USE_NOEXCEPT - { return size_type(-1) / sizeof(Tp); } - #if __cplusplus >= 201103L - template<typename U, typename... Args> - void - construct(U* p, Args&&... args) - { ::new((void *)p) U(std::forward<Args>(args)...); } - - template<typename U> - void - destroy(U* p) { p->~U(); } - // Not copy assignable... uneq_allocator& operator=(const uneq_allocator&) = delete; + + // ... but still moveable if base allocator is. + uneq_allocator& + operator=(uneq_allocator&&) = default; #else - void - construct(pointer p, const Tp& val) - { ::new((void *)p) Tp(val); } - - void - destroy(pointer p) { p->~Tp(); } - private: // Not assignable... uneq_allocator& @@ -358,21 +379,27 @@ #endif private: - // ... yet swappable! friend inline void swap(uneq_allocator& a, uneq_allocator& b) - { std::swap(a.personality, b.personality); } - + { + std::swap(a.personality, b.personality); + a.swap_base(b); + } + template<typename Tp1> - friend inline bool - operator==(const uneq_allocator& a, const uneq_allocator<Tp1>& b) - { return a.personality == b.personality; } + friend inline bool + operator==(const uneq_allocator& a, + const uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other>& b) + { return a.personality == b.personality; } template<typename Tp1> - friend inline bool - operator!=(const uneq_allocator& a, const uneq_allocator<Tp1>& b) - { return !(a == b); } + friend inline bool + operator!=(const uneq_allocator& a, + const uneq_allocator<Tp1, + typename AllocTraits::template rebind<Tp1>::other>& b) + { return !(a == b); } int personality; }; @@ -379,10 +406,12 @@ #if __cplusplus >= 201103L // An uneq_allocator which can be used to test allocator propagation. - template<typename Tp, bool Propagate> - class propagating_allocator : public uneq_allocator<Tp> + template<typename Tp, bool Propagate, typename Alloc = std::allocator<Tp>> + class propagating_allocator : public uneq_allocator<Tp, Alloc> { - typedef uneq_allocator<Tp> base_alloc; + typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits; + + typedef uneq_allocator<Tp, Alloc> base_alloc; base_alloc& base() { return *this; } const base_alloc& base() const { return *this; } void swap_base(base_alloc& b) { swap(b, this->base()); } @@ -393,7 +422,11 @@ // default allocator_traits::rebind_alloc would select // uneq_allocator::rebind so we must define rebind here template<typename Up> - struct rebind { typedef propagating_allocator<Up, Propagate> other; }; + struct rebind + { + typedef propagating_allocator<Up, Propagate, + typename AllocTraits::template rebind<Up>::other> other; + }; propagating_allocator(int i) noexcept : base_alloc(i) @@ -400,8 +433,9 @@ { } template<typename Up> - propagating_allocator(const propagating_allocator<Up, Propagate>& a) - noexcept + propagating_allocator(const propagating_allocator<Up, Propagate, + typename AllocTraits::template rebind<Up>::other>& a) + noexcept : base_alloc(a) { } @@ -418,8 +452,8 @@ } template<bool P2> - propagating_allocator& - operator=(const propagating_allocator<Tp, P2>& a) noexcept + propagating_allocator& + operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept { static_assert(P2, "assigning propagating_allocator<T, true>"); propagating_allocator(a).swap_base(*this); Index: testsuite/23_containers/forward_list/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/forward_list/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/forward_list/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::forward_list<int, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/map/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/map/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/map/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/multimap/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/multimap/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/multimap/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/multiset/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/multiset/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/multiset/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/set/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/set/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/set/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type; test_type v1(alloc_type(1)); Index: testsuite/23_containers/unordered_map/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/unordered_map/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::unordered_map<int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,8 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type; + typedef __gnu_test::propagating_allocator<std::pair<const int, int>, + false> alloc_type; typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::unordered_multiset<int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/unordered_set/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/unordered_set/debug/move_assign_neg.cc (working copy) @@ -25,7 +25,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::unordered_set<int, std::hash<int>, std::equal_to<int>, alloc_type> test_type; Index: testsuite/23_containers/vector/debug/move_assign_neg.cc =================================================================== --- testsuite/23_containers/vector/debug/move_assign_neg.cc (revision 212959) +++ testsuite/23_containers/vector/debug/move_assign_neg.cc (working copy) @@ -27,7 +27,7 @@ { bool test __attribute__((unused)) = true; - typedef __gnu_test::uneq_allocator<int> alloc_type; + typedef __gnu_test::propagating_allocator<int, false> alloc_type; typedef __gnu_debug::vector<int, alloc_type> test_type; test_type v1(alloc_type(1)); ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-07-23 20:46 ` François Dumont @ 2014-07-24 8:58 ` Jonathan Wakely 2014-07-24 20:30 ` François Dumont 2014-07-29 19:42 ` Jonathan Wakely 1 sibling, 1 reply; 17+ messages in thread From: Jonathan Wakely @ 2014-07-24 8:58 UTC (permalink / raw) To: François Dumont Cc: Paolo Carlini, Jonathan Wakely, libstdc++, gcc-patches On 23/07/14 22:33 +0200, François Dumont wrote: > I have a small question regarding some code next to the one I am >modifying in this patch. I can see lines like: > > propagating_allocator() noexcept = default; > > When using a default implementation shouldn't we let the compiler >decide if it should be noexcept or not depending on the member fields >or base class default constructors ? Stating it explicitly means you get an error if the default implementation is not noexcept. That can be useful, to ensure you don't silently start getting a throwing constructor by mistake because of a change to a base class. I'm not sure if I added the noexcept above, but if I did that might have been what I was intending it to do. I don't remember. I'll review the rest of the patch ASAP. Did you test it with no other changes in your tree, and run the entire testsuite? ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-07-24 8:58 ` Jonathan Wakely @ 2014-07-24 20:30 ` François Dumont 2014-07-24 23:36 ` Jonathan Wakely 0 siblings, 1 reply; 17+ messages in thread From: François Dumont @ 2014-07-24 20:30 UTC (permalink / raw) To: Jonathan Wakely; +Cc: Paolo Carlini, Jonathan Wakely, libstdc++, gcc-patches On 24/07/2014 10:55, Jonathan Wakely wrote: > On 23/07/14 22:33 +0200, François Dumont wrote: >> I have a small question regarding some code next to the one I am >> modifying in this patch. I can see lines like: >> >> propagating_allocator() noexcept = default; >> >> When using a default implementation shouldn't we let the compiler >> decide if it should be noexcept or not depending on the member fields >> or base class default constructors ? > > Stating it explicitly means you get an error if the default > implementation is not noexcept. That can be useful, to ensure you > don't silently start getting a throwing constructor by mistake because > of a change to a base class. > > I'm not sure if I added the noexcept above, but if I did that might > have been what I was intending it to do. I don't remember. > > I'll review the rest of the patch ASAP. Did you test it with no other > changes in your tree, and run the entire testsuite? > Ok, thanks for the explanation, it is clear now. Yes I have tested with no other changes in my tree and got only those pretty printers errors which are unrelated I think: Python Exception <class 'TypeError'> iter() returned non-iterator of type '_contained': $2 = std::experimental::optional<int> [no contained value] skipping: Python Exception <class 'TypeError'> iter() returned non-iterator of type '_contained': got: $2 = std::experimental::optional<int> [no contained value] PASS: libstdc++-prettyprinters/libfundts.cc print o Python Exception <class 'TypeError'> iter() returned non-iterator of type '_contained': $3 = std::experimental::optional<bool> skipping: Python Exception <class 'TypeError'> iter() returned non-iterator of type '_contained': got: $3 = std::experimental::optional<bool> FAIL: libstdc++-prettyprinters/libfundts.cc print ob Python Exception <class 'TypeError'> iter() returned non-iterator of type '_contained': $4 = std::experimental::optional<int> skipping: Python Exception <class 'TypeError'> iter() returned non-iterator of type '_contained': got: $4 = std::experimental::optional<int> FAIL: libstdc++-prettyprinters/libfundts.cc print oi François ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-07-24 20:30 ` François Dumont @ 2014-07-24 23:36 ` Jonathan Wakely 2014-07-29 21:34 ` Jonathan Wakely 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Wakely @ 2014-07-24 23:36 UTC (permalink / raw) To: François Dumont Cc: Jonathan Wakely, Paolo Carlini, libstdc++, gcc-patches On 24 July 2014 21:11, François Dumont wrote: > > Yes I have tested with no other changes in my tree and got only those pretty > printers errors which are unrelated I think: > > Python Exception <class 'TypeError'> iter() returned non-iterator of type > '_contained': > $2 = std::experimental::optional<int> [no contained value] I haven't seen these, I'll fix them on Monday, thanks. ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-07-24 23:36 ` Jonathan Wakely @ 2014-07-29 21:34 ` Jonathan Wakely 2014-07-29 21:44 ` Jonathan Wakely 0 siblings, 1 reply; 17+ messages in thread From: Jonathan Wakely @ 2014-07-29 21:34 UTC (permalink / raw) To: libstdc++, gcc-patches; +Cc: François Dumont, Paolo Carlini [-- Attachment #1: Type: text/plain, Size: 572 bytes --] On 25/07/14 00:19 +0100, Jonathan Wakely wrote: >On 24 July 2014 21:11, François Dumont wrote: >> >> Yes I have tested with no other changes in my tree and got only those pretty >> printers errors which are unrelated I think: >> >> Python Exception <class 'TypeError'> iter() returned non-iterator of type >> '_contained': >> $2 = std::experimental::optional<int> [no contained value] > >I haven't seen these, I'll fix them on Monday, thanks. Fixed by the attached patch. Tested x86_64-linux (thanks to Samual Bronson for testing with Python3) and committed to trunk. [-- Attachment #2: patch.txt --] [-- Type: text/x-patch, Size: 1031 bytes --] commit 7de83299c42041611360a1426f5164270ac6c6b6 Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Jul 29 20:08:31 2014 +0100 * python/libstdcxx/v6/printers.py (SingleObjContainerPrinter._contained): Use compatibility mixin. diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index 15d7a88..2e5cd6c 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -851,14 +851,14 @@ class SingleObjContainerPrinter(object): return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(), type) or str(type) - class _contained: + class _contained(Iterator): def __init__ (self, val): self.val = val def __iter__ (self): return self - def next (self): + def __next__(self): if self.val is None: raise StopIteration retval = self.val ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-07-29 21:34 ` Jonathan Wakely @ 2014-07-29 21:44 ` Jonathan Wakely 0 siblings, 0 replies; 17+ messages in thread From: Jonathan Wakely @ 2014-07-29 21:44 UTC (permalink / raw) To: libstdc++, gcc-patches; +Cc: François Dumont, Paolo Carlini On 29/07/14 22:33 +0100, Jonathan Wakely wrote: >Tested x86_64-linux (thanks to Samual Bronson for testing with >Python3) and committed to trunk. Oops, Samuel not Samual ... no idea why my fingers typed that wrong! ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: testsuite allocators patch 2014-07-23 20:46 ` François Dumont 2014-07-24 8:58 ` Jonathan Wakely @ 2014-07-29 19:42 ` Jonathan Wakely 1 sibling, 0 replies; 17+ messages in thread From: Jonathan Wakely @ 2014-07-29 19:42 UTC (permalink / raw) To: François Dumont Cc: Paolo Carlini, Jonathan Wakely, libstdc++, gcc-patches On 23/07/14 22:33 +0200, François Dumont wrote: >On 27/06/2014 21:48, Paolo Carlini wrote: >>Hi, >> >>On 06/27/2014 07:33 PM, Jonathan Wakely wrote: >>>I didn't see an obvious fix (I'm not sure if the templated constructor >>>can deduce its argument since the change) but have been out all day >>>and not had a chance to look into it. >>Ok, thanks. I'm reverting the last two libstdc++-v3 commits. >> >>Paolo. >> > >Hi > > Back from vacation, ready to have this patch committed eventually. > > Here is the new version with the missing default and copy constructor. > > I have a small question regarding some code next to the one I am >modifying in this patch. I can see lines like: > > propagating_allocator() noexcept = default; > > When using a default implementation shouldn't we let the compiler >decide if it should be noexcept or not depending on the member fields >or base class default constructors ? > > Tested under Linux x86_64. > > Ok to commit ? OK, thanks. ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2014-07-29 21:39 UTC | newest] Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2014-06-20 20:37 testsuite allocators patch François Dumont 2014-06-25 19:48 ` François Dumont 2014-06-26 10:33 ` Jonathan Wakely 2014-06-26 20:45 ` François Dumont 2014-06-26 21:24 ` Paolo Carlini 2014-06-26 22:39 ` Jonathan Wakely 2014-06-27 7:30 ` Paolo Carlini 2014-06-27 17:33 ` Jonathan Wakely 2014-06-27 19:51 ` Paolo Carlini 2014-06-27 21:29 ` François Dumont 2014-07-23 20:46 ` François Dumont 2014-07-24 8:58 ` Jonathan Wakely 2014-07-24 20:30 ` François Dumont 2014-07-24 23:36 ` Jonathan Wakely 2014-07-29 21:34 ` Jonathan Wakely 2014-07-29 21:44 ` Jonathan Wakely 2014-07-29 19:42 ` Jonathan Wakely
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).