From patchwork Wed Jan 29 14:59:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 315078 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 E850F2C009C for ; Thu, 30 Jan 2014 01:59:15 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=pyhKwZbjiYxfMxrPWYaCmfGblPoW7N9sJ1+C49Ec7pu0nGnmb1j/2 DhzHmzHPt4HqCrfRJswcKNnn9xvBbpZRS5rh7BSBWxze4TPY5pck8K8c76V8/P3E upuGNb2rARbq+Z1eRiaqw8jA1JrH+EMnpwfQdkjNvpjJJceVJUJijk= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=Yy/4XwCTT6aGZoM5dWoNHQ8qYzA=; b=rz4Q+A0JQa0i6alFVNoI D7UTKtUcJKG+8FvWIngb01PUzqgc4dXBXS/M7gRm2lj/DhYulqUayiSfaFm5eQUQ 4rGMpls/eN3uNNDzBHx+NHvxOB03Gu1jfopGbNEyvkNOkBjc7Ml72+bqp16EpfMs Ctv/h6Z02VceHjpsFM+PZfo= Received: (qmail 2412 invoked by alias); 29 Jan 2014 14:59:08 -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 2395 invoked by uid 89); 29 Jan 2014 14:59:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS, T_FILL_THIS_FORM_SHORT autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 29 Jan 2014 14:59:04 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s0TEx3QU012823 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jan 2014 09:59:03 -0500 Received: from localhost (vpn1-7-88.ams2.redhat.com [10.36.7.88]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id s0TEx18f007564; Wed, 29 Jan 2014 09:59:02 -0500 Date: Wed, 29 Jan 2014 14:59:01 +0000 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [patch] fix a couple of std::allocator_traits bugs Message-ID: <20140129145901.GA21297@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) std::allocator_traits::allocate(a, n, hint) could fail to compile if the const_void_pointer passed as the hint was a non-trivial type, because it was passed to a varargs function. std::vector was not using std::allocator_traits for calls to A::allocate and A::deallocate. Also remove some redundant conditions in std::vector and _Rb_tree and in allocator_traits simplify SFINAE uses and use true_type / false_type to avoid needing definitions for static const bool members. I added PointerBase to testsuite_allocator.h to help create custom pointer types for testing because it's non-trivial to define the whole thing every time you need one. There's also a new test to verify the allocator_traits typedefs are correct. Tested x86_64-linux, committed to trunk. (I didn't fix up some dg-error line numbers relating to stl_vector.h because I'm also committing another patch that changes them again, so I only did it once.) * include/bits/alloc_traits.h (allocator_traits::_S_allocate): Do not use varargs when argument could be non-POD. (__alloctr_rebind_helper): Eliminate static const bool member by using true_type and false_type. (allocator_traits::__allocate_helper): Likewise. (allocator_traits::__construct_helper): Likewise. (allocator_traits::__destroy_helper): Likewise. (allocator_traits::__maxsize_helper): Likewise. (allocator_traits::__select_helper): Likewise. * include/bits/ptr_traits.h (__ptrtr_rebind_helper): Likewise. * include/bits/stl_tree.h (_Rb_tree::operator=(const _Rb_tree&)): Remove redundant condition. * include/bits/stl_vector.h (vector::operator=(const vector&)): Likewise. (_Vector_impl::_M_allocate, _Vector_impl::_M_deallocate): Use indirection through __alloc_traits. * include/ext/alloc_traits.h (__allocator_always_compares_equal): Eliminate static const bool members by using true_type and false_type. (__gnu_cxx::__alloc_traits::__is_custom_pointer): Optimize. * testsuite/util/testsuite_allocator.h (PointerBase): Define. * testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc: New. * testsuite/20_util/allocator_traits/requirements/typedefs2.cc: New. commit fa11899fe418aaee495c5fd3ed4215a9df319e33 Author: Jonathan Wakely Date: Tue Apr 16 22:19:59 2013 +0100 * include/bits/alloc_traits.h (allocator_traits::_S_allocate): Do not use varargs when argument could be non-POD. (__alloctr_rebind_helper): Eliminate static const bool member by using true_type and false_type. (allocator_traits::__allocate_helper): Likewise. (allocator_traits::__construct_helper): Likewise. (allocator_traits::__destroy_helper): Likewise. (allocator_traits::__maxsize_helper): Likewise. (allocator_traits::__select_helper): Likewise. * include/bits/ptr_traits.h (__ptrtr_rebind_helper): Likewise. * include/bits/stl_tree.h (_Rb_tree::operator=(const _Rb_tree&)): Remove redundant condition. * include/bits/stl_vector.h (vector::operator=(const vector&)): Likewise. (_Vector_impl::_M_allocate, _Vector_impl::_M_deallocate): Use indirection through __alloc_traits. * include/ext/alloc_traits.h (__allocator_always_compares_equal): Eliminate static const bool members by using true_type and false_type. (__gnu_cxx::__alloc_traits::__is_custom_pointer): Optimize. * testsuite/util/testsuite_allocator.h (PointerBase): Define. * testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc: New. * testsuite/20_util/allocator_traits/requirements/typedefs2.cc: New. diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index 86ed222..23fe8de 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -44,24 +44,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class __alloctr_rebind_helper { template - static constexpr bool - _S_chk(typename _Alloc2::template rebind<_Tp2>::other*) - { return true; } + static constexpr true_type + _S_chk(typename _Alloc2::template rebind<_Tp2>::other*); template - static constexpr bool - _S_chk(...) - { return false; } + static constexpr false_type + _S_chk(...); public: - static const bool __value = _S_chk<_Alloc, _Tp>(nullptr); + using __type = decltype(_S_chk<_Alloc, _Tp>(nullptr)); }; - template - const bool __alloctr_rebind_helper<_Alloc, _Tp>::__value; - template::__value> + bool = __alloctr_rebind_helper<_Alloc, _Tp>::__type::value> struct __alloctr_rebind; template @@ -71,7 +66,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template class _Alloc, typename _Tp, - typename _Up, typename... _Args> + typename _Up, typename... _Args> struct __alloctr_rebind<_Alloc<_Up, _Args...>, _Tp, false> { typedef _Alloc<_Tp, _Args...> __type; @@ -140,7 +135,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(const_void_pointer, typedef __const_void_pointer const_void_pointer; _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type, - typename pointer_traits::difference_type) + typename pointer_traits::difference_type) /** * @brief The allocator's difference type @@ -151,7 +146,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(difference_type, typedef __difference_type difference_type; _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type, - typename make_unsigned::type) + typename make_unsigned::type) /** * @brief The allocator's size type @@ -162,7 +157,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(size_type, typedef __size_type size_type; _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment, - false_type) + false_type) /** * @brief How the allocator is propagated on copy assignment @@ -171,10 +166,10 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_copy_assignment, * otherwise @c false_type */ typedef __propagate_on_container_copy_assignment - propagate_on_container_copy_assignment; + propagate_on_container_copy_assignment; _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment, - false_type) + false_type) /** * @brief How the allocator is propagated on move assignment @@ -183,10 +178,10 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_move_assignment, * otherwise @c false_type */ typedef __propagate_on_container_move_assignment - propagate_on_container_move_assignment; + propagate_on_container_move_assignment; _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, - false_type) + false_type) /** * @brief How the allocator is propagated on swap @@ -199,9 +194,9 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, #undef _GLIBCXX_ALLOC_TR_NESTED_TYPE template - using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type; + using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type; template - using rebind_traits = allocator_traits>; + using rebind_traits = allocator_traits>; private: template @@ -216,20 +211,22 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, template static false_type __test(...); - typedef decltype(__test<_Alloc>(0)) type; - static const bool value = type::value; + using type = decltype(__test<_Alloc>(0)); }; template - static typename - enable_if<__allocate_helper<_Alloc2>::value, pointer>::type - _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint) + using __has_allocate = typename __allocate_helper<_Alloc2>::type; + + template>> + static pointer + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint) { return __a.allocate(__n, __hint); } - template - static typename - enable_if::value, pointer>::type - _S_allocate(_Alloc2& __a, size_type __n, ...) + template>>> + static pointer + _S_allocate(_Alloc2& __a, size_type __n, _UnusedHint) { return __a.allocate(__n); } template @@ -243,21 +240,23 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, template static false_type __test(...); - typedef decltype(__test<_Alloc>(0)) type; - static const bool value = type::value; + using type = decltype(__test<_Alloc>(0)); }; template - static typename - enable_if<__construct_helper<_Tp, _Args...>::value, void>::type - _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) + using __has_construct + = typename __construct_helper<_Tp, _Args...>::type; + + template + static _Require<__has_construct<_Tp, _Args...>> + _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) { __a.construct(__p, std::forward<_Args>(__args)...); } template - static typename - enable_if<__and_<__not_<__construct_helper<_Tp, _Args...>>, - is_constructible<_Tp, _Args...>>::value, void>::type - _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) + static + _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, + is_constructible<_Tp, _Args...>>> + _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) { ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); } template @@ -271,18 +270,20 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, template static false_type __test(...); - typedef decltype(__test<_Alloc>(0)) type; - static const bool value = type::value; + using type = decltype(__test<_Alloc>(0)); }; template - static typename enable_if<__destroy_helper<_Tp>::value, void>::type - _S_destroy(_Alloc& __a, _Tp* __p) + using __has_destroy = typename __destroy_helper<_Tp>::type; + + template + static _Require<__has_destroy<_Tp>> + _S_destroy(_Alloc& __a, _Tp* __p) { __a.destroy(__p); } template - static typename enable_if::value, void>::type - _S_destroy(_Alloc&, _Tp* __p) + static _Require<__not_<__has_destroy<_Tp>>> + _S_destroy(_Alloc&, _Tp* __p) { __p->~_Tp(); } template @@ -295,20 +296,22 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, template static false_type __test(...); - typedef decltype(__test<_Alloc2>(0)) type; - static const bool value = type::value; + using type = decltype(__test<_Alloc2>(0)); }; template - static typename - enable_if<__maxsize_helper<_Alloc2>::value, size_type>::type - _S_max_size(_Alloc2& __a) + using __has_max_size = typename __maxsize_helper<_Alloc2>::type; + + template>> + static size_type + _S_max_size(_Alloc2& __a, int) { return __a.max_size(); } - template - static typename - enable_if::value, size_type>::type - _S_max_size(_Alloc2&) + template>>> + static size_type + _S_max_size(_Alloc2&, ...) { return __gnu_cxx::__numeric_traits::__max; } template @@ -322,19 +325,22 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, template static false_type __test(...); - typedef decltype(__test<_Alloc2>(0)) type; - static const bool value = type::value; + using type = decltype(__test<_Alloc2>(0)); }; + template - static typename - enable_if<__select_helper<_Alloc2>::value, _Alloc2>::type - _S_select(_Alloc2& __a) + using __has_soccc = typename __select_helper<_Alloc2>::type; + + template>> + static _Alloc2 + _S_select(_Alloc2& __a, int) { return __a.select_on_container_copy_construction(); } - template - static typename - enable_if::value, _Alloc2>::type - _S_select(_Alloc2& __a) + template>>> + static _Alloc2 + _S_select(_Alloc2& __a, ...) { return __a; } public: @@ -413,7 +419,7 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, * otherwise returns @c numeric_limits::max() */ static size_type max_size(const _Alloc& __a) noexcept - { return _S_max_size(__a); } + { return _S_max_size(__a, 0); } /** * @brief Obtain an allocator to use when copying a container. @@ -425,31 +431,10 @@ _GLIBCXX_ALLOC_TR_NESTED_TYPE(propagate_on_container_swap, */ static _Alloc select_on_container_copy_construction(const _Alloc& __rhs) - { return _S_select(__rhs); } + { return _S_select(__rhs, 0); } }; template - template - const bool allocator_traits<_Alloc>::__allocate_helper<_Alloc2>::value; - - template - template - const bool - allocator_traits<_Alloc>::__construct_helper<_Tp, _Args...>::value; - - template - template - const bool allocator_traits<_Alloc>::__destroy_helper<_Tp>::value; - - template - template - const bool allocator_traits<_Alloc>::__maxsize_helper<_Alloc2>::value; - - template - template - const bool allocator_traits<_Alloc>::__select_helper<_Alloc2>::value; - - template inline void __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) { __one = __two; } diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 714db79..94995c8 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -73,24 +73,19 @@ _GLIBCXX_HAS_NESTED_TYPE(difference_type) class __ptrtr_rebind_helper { template - static constexpr bool - _S_chk(typename _Ptr2::template rebind<_Up2>*) - { return true; } + static constexpr true_type + _S_chk(typename _Ptr2::template rebind<_Up2>*); template - static constexpr bool - _S_chk(...) - { return false; } + static constexpr false_type + _S_chk(...); public: - static const bool __value = _S_chk<_Ptr, _Up>(nullptr); + using __type = decltype(_S_chk<_Ptr, _Up>(nullptr)); }; - template - const bool __ptrtr_rebind_helper<_Ptr, _Up>::__value; - template::__value> + bool = __ptrtr_rebind_helper<_Tp, _Up>::__type::value> struct __ptrtr_rebind; template diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index d24b1f7..4bc3c60 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -1080,9 +1080,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION clear(); if (__x._M_root() != 0) _M_move_data(__x, std::true_type()); - if (_Alloc_traits::_S_propagate_on_move_assign()) - std::__alloc_on_move(_M_get_Node_allocator(), - __x._M_get_Node_allocator()); + std::__alloc_on_move(_M_get_Node_allocator(), + __x._M_get_Node_allocator()); return true; } return false; diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index f482957..98ac708 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -165,13 +165,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER pointer _M_allocate(size_t __n) - { return __n != 0 ? _M_impl.allocate(__n) : 0; } + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; + return __n != 0 ? _Tr::allocate(_M_impl, __n) : 0; + } void _M_deallocate(pointer __p, size_t __n) { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; if (__p) - _M_impl.deallocate(__p, __n); + _Tr::deallocate(_M_impl, __p, __n); } private: @@ -1446,9 +1450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER vector __tmp(get_allocator()); this->_M_impl._M_swap_data(__tmp._M_impl); this->_M_impl._M_swap_data(__x._M_impl); - if (_Alloc_traits::_S_propagate_on_move_assign()) - std::__alloc_on_move(_M_get_Tp_allocator(), - __x._M_get_Tp_allocator()); + std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); } // Do move assignment when it might not be possible to move source diff --git a/libstdc++-v3/include/ext/alloc_traits.h b/libstdc++-v3/include/ext/alloc_traits.h index 26e457f..14fbc43 100644 --- a/libstdc++-v3/include/ext/alloc_traits.h +++ b/libstdc++-v3/include/ext/alloc_traits.h @@ -44,73 +44,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L template - struct __allocator_always_compares_equal - { static const bool value = false; }; - - template - const bool __allocator_always_compares_equal<_Alloc>::value; + struct __allocator_always_compares_equal : std::false_type { }; template struct __allocator_always_compares_equal> - { static const bool value = true; }; - - template - const bool __allocator_always_compares_equal>::value; + : std::true_type { }; template struct array_allocator; template struct __allocator_always_compares_equal> - { static const bool value = true; }; - - template - const bool - __allocator_always_compares_equal>::value; + : std::true_type { }; template struct bitmap_allocator; template struct __allocator_always_compares_equal> - { static const bool value = true; }; - - template - const bool __allocator_always_compares_equal>::value; + : std::true_type { }; template struct malloc_allocator; template struct __allocator_always_compares_equal> - { static const bool value = true; }; - - template - const bool __allocator_always_compares_equal>::value; + : std::true_type { }; template struct mt_allocator; template struct __allocator_always_compares_equal> - { static const bool value = true; }; - - template - const bool __allocator_always_compares_equal>::value; + : std::true_type { }; template struct new_allocator; template struct __allocator_always_compares_equal> - { static const bool value = true; }; - - template - const bool __allocator_always_compares_equal>::value; + : std::true_type { }; template struct pool_allocator; template struct __allocator_always_compares_equal> - { static const bool value = true; }; - - template - const bool __allocator_always_compares_equal>::value; + : std::true_type { }; #endif /** @@ -131,7 +105,7 @@ template typedef typename _Base_type::const_pointer const_pointer; typedef typename _Base_type::size_type size_type; typedef typename _Base_type::difference_type difference_type; - // C++0x allocators do not define reference or const_reference + // C++11 allocators do not define reference or const_reference typedef value_type& reference; typedef const value_type& const_reference; using _Base_type::allocate; @@ -142,10 +116,9 @@ template private: template - struct __is_custom_pointer - : std::integral_constant::value - && !std::is_pointer<_Ptr>::value> - { }; + using __is_custom_pointer + = std::__and_, + std::__not_>>; public: // overload construct for non-standard pointer types diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc new file mode 100644 index 0000000..b5883dc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator_traits/members/allocate_hint_nonpod.cc @@ -0,0 +1,69 @@ +// { dg-options "-std=gnu++11" } + +// 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 +// . + +#include +#include + +// User-defined pointer type with non-trivial destructor. +template +struct Pointer : __gnu_test::PointerBase, T> +{ + using __gnu_test::PointerBase, T>::PointerBase; + + ~Pointer() { /* non-trivial */ } +}; + +// Minimal allocator with user-defined pointer type. +template +struct Alloc +{ + typedef T value_type; + typedef Pointer pointer; + + Alloc() = default; + + template + Alloc(const Alloc&) { } + + pointer allocate(std::size_t n) // does not take a hint + { return pointer(std::allocator().allocate(n)); } + + void deallocate(pointer p, std::size_t n) + { std::allocator().deallocate(p.value, n); } +}; + +template +bool operator==(Alloc l, Alloc r) { return true; } + +template +bool operator!=(Alloc l, Alloc r) { return false; } + +void test01() +{ + typedef std::allocator_traits> traits_type; + traits_type::allocator_type a; + traits_type::const_void_pointer v; + traits_type::pointer p = traits_type::allocate(a, 1, v); + traits_type::deallocate(a, p, 1); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/typedefs2.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/typedefs2.cc new file mode 100644 index 0000000..04521a2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator_traits/requirements/typedefs2.cc @@ -0,0 +1,93 @@ +// { dg-options "-std=gnu++11" } +// +// Copyright (C) 2013 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 +// . + +#include +#include + +// { dg-do compile } + +template +struct ptr +{ + ptr() = default; + template + ptr(ptr const& p) { } +}; + +// This doesn't meet the allocator requirements, it's only to check +// that allocator_traits finds the right nested types. +template +struct alloc +{ + typedef T value_type; + + typedef ptr pointer; + typedef ptr const_pointer; + typedef ptr void_pointer; + typedef ptr const_void_pointer; + typedef int difference_type; + typedef int size_type; + + typedef std::false_type propagate_on_container_copy_assignment; + typedef std::false_type propagate_on_container_move_assignment; + typedef std::false_type propagate_on_container_swap; +}; + +typedef alloc alloc_type; +typedef std::allocator_traits traits; + +using std::is_same; + +static_assert( is_same::value, + "pointer" ); + +static_assert( is_same::value, + "const_pointer" ); + +static_assert( is_same::value, + "void_pointer" ); + +static_assert( is_same::value, + "const_void_pointer"); + +static_assert( is_same::value, + "difference_type" ); + +static_assert( is_same::value, + "size_type" ); + +static_assert( is_same::value, + "size_type" ); + +static_assert( is_same::value, + "propagate_on_container_copy_assignment" ); + +static_assert( is_same::value, + "propagate_on_container_move_assignment" ); + +static_assert( is_same::value, + "propagate_on_container_swap" ); diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index 748557c..822a025 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -517,6 +517,106 @@ namespace __gnu_test void deallocate(pointer p, std::size_t n) { std::allocator::deallocate(std::addressof(*p), n); } }; + + // Utility for use as CRTP base class of custom pointer types + template + struct PointerBase + { + typedef T element_type; + + // typedefs for iterator_traits + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + typedef Derived pointer; + typedef T& reference; + + T* value; + + explicit PointerBase(T* p = nullptr) : value(p) { } + + template(std::declval()))> + PointerBase(const PointerBase& p) : value(p.value) { } + + T& operator*() const { return *value; } + T* operator->() const { return value; } + + Derived& operator++() { ++value; return derived(); } + Derived operator++(int) { Derived tmp(derived()); ++value; return tmp; } + Derived& operator--() { --value; return derived(); } + Derived operator--(int) { Derived tmp(derived()); --value; return tmp; } + + Derived& operator+=(difference_type n) { value += n; return derived(); } + Derived& operator-=(difference_type n) { value -= n; return derived(); } + + explicit operator bool() const { return value != nullptr; } + + Derived + operator+(difference_type n) const + { + Derived p(derived()); + return p += n; + } + + Derived + operator-(difference_type n) const + { + Derived p(derived()); + return p -= n; + } + + private: + Derived& derived() { return static_cast(*this); } + }; + + template + std::ptrdiff_t operator-(PointerBase l, PointerBase r) + { return l.value - r.value; } + + template + bool operator==(PointerBase l, PointerBase r) + { return l.value == r.value; } + + template + bool operator!=(PointerBase l, PointerBase r) + { return l.value != r.value; } + + // implementation for void specializations + template + struct PointerBase_void + { + typedef T element_type; + + // typedefs for iterator_traits + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef std::random_access_iterator_tag iterator_category; + + T* value; + + explicit PointerBase_void(T* p = nullptr) : value(p) { } + + template(std::declval()))> + PointerBase_void(const PointerBase& p) : value(p.value) { } + + explicit operator bool() const { return value != nullptr; } + }; + + template + struct PointerBase : PointerBase_void + { + using PointerBase_void::PointerBase_void; + typedef Derived pointer; + }; + + template + struct PointerBase : PointerBase_void + { + using PointerBase_void::PointerBase_void; + typedef Derived pointer; + }; #endif } // namespace __gnu_test