Commit 20067423 by Jonathan Wakely Committed by Jonathan Wakely

alloc_traits.h (allocator_traits::_S_allocate): Do not use varargs when argument could be non-POD.

	* 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.

From-SVN: r207240
parent 77574c35
2014-01-28 Jonathan Wakely <jwakely@redhat.com> 2014-01-28 Jonathan Wakely <jwakely@redhat.com>
* 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.
2014-01-28 Jonathan Wakely <jwakely@redhat.com>
Kyle Lippincott <spectral@google.com> Kyle Lippincott <spectral@google.com>
PR libstdc++/59656 PR libstdc++/59656
......
...@@ -73,24 +73,19 @@ _GLIBCXX_HAS_NESTED_TYPE(difference_type) ...@@ -73,24 +73,19 @@ _GLIBCXX_HAS_NESTED_TYPE(difference_type)
class __ptrtr_rebind_helper class __ptrtr_rebind_helper
{ {
template<typename _Ptr2, typename _Up2> template<typename _Ptr2, typename _Up2>
static constexpr bool static constexpr true_type
_S_chk(typename _Ptr2::template rebind<_Up2>*) _S_chk(typename _Ptr2::template rebind<_Up2>*);
{ return true; }
template<typename, typename> template<typename, typename>
static constexpr bool static constexpr false_type
_S_chk(...) _S_chk(...);
{ return false; }
public: public:
static const bool __value = _S_chk<_Ptr, _Up>(nullptr); using __type = decltype(_S_chk<_Ptr, _Up>(nullptr));
}; };
template<typename _Ptr, typename _Up>
const bool __ptrtr_rebind_helper<_Ptr, _Up>::__value;
template<typename _Tp, typename _Up, template<typename _Tp, typename _Up,
bool = __ptrtr_rebind_helper<_Tp, _Up>::__value> bool = __ptrtr_rebind_helper<_Tp, _Up>::__type::value>
struct __ptrtr_rebind; struct __ptrtr_rebind;
template<typename _Tp, typename _Up> template<typename _Tp, typename _Up>
......
...@@ -1080,9 +1080,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -1080,9 +1080,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
clear(); clear();
if (__x._M_root() != 0) if (__x._M_root() != 0)
_M_move_data(__x, std::true_type()); _M_move_data(__x, std::true_type());
if (_Alloc_traits::_S_propagate_on_move_assign()) std::__alloc_on_move(_M_get_Node_allocator(),
std::__alloc_on_move(_M_get_Node_allocator(), __x._M_get_Node_allocator());
__x._M_get_Node_allocator());
return true; return true;
} }
return false; return false;
......
...@@ -165,13 +165,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -165,13 +165,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
pointer pointer
_M_allocate(size_t __n) _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 void
_M_deallocate(pointer __p, size_t __n) _M_deallocate(pointer __p, size_t __n)
{ {
typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr;
if (__p) if (__p)
_M_impl.deallocate(__p, __n); _Tr::deallocate(_M_impl, __p, __n);
} }
private: private:
...@@ -1446,9 +1450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ...@@ -1446,9 +1450,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
vector __tmp(get_allocator()); vector __tmp(get_allocator());
this->_M_impl._M_swap_data(__tmp._M_impl); this->_M_impl._M_swap_data(__tmp._M_impl);
this->_M_impl._M_swap_data(__x._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 // Do move assignment when it might not be possible to move source
......
...@@ -44,73 +44,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -44,73 +44,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
template<typename _Alloc> template<typename _Alloc>
struct __allocator_always_compares_equal struct __allocator_always_compares_equal : std::false_type { };
{ static const bool value = false; };
template<typename _Alloc>
const bool __allocator_always_compares_equal<_Alloc>::value;
template<typename _Tp> template<typename _Tp>
struct __allocator_always_compares_equal<std::allocator<_Tp>> struct __allocator_always_compares_equal<std::allocator<_Tp>>
{ static const bool value = true; }; : std::true_type { };
template<typename _Tp>
const bool __allocator_always_compares_equal<std::allocator<_Tp>>::value;
template<typename, typename> struct array_allocator; template<typename, typename> struct array_allocator;
template<typename _Tp, typename _Array> template<typename _Tp, typename _Array>
struct __allocator_always_compares_equal<array_allocator<_Tp, _Array>> struct __allocator_always_compares_equal<array_allocator<_Tp, _Array>>
{ static const bool value = true; }; : std::true_type { };
template<typename _Tp, typename _Array>
const bool
__allocator_always_compares_equal<array_allocator<_Tp, _Array>>::value;
template<typename> struct bitmap_allocator; template<typename> struct bitmap_allocator;
template<typename _Tp> template<typename _Tp>
struct __allocator_always_compares_equal<bitmap_allocator<_Tp>> struct __allocator_always_compares_equal<bitmap_allocator<_Tp>>
{ static const bool value = true; }; : std::true_type { };
template<typename _Tp>
const bool __allocator_always_compares_equal<bitmap_allocator<_Tp>>::value;
template<typename> struct malloc_allocator; template<typename> struct malloc_allocator;
template<typename _Tp> template<typename _Tp>
struct __allocator_always_compares_equal<malloc_allocator<_Tp>> struct __allocator_always_compares_equal<malloc_allocator<_Tp>>
{ static const bool value = true; }; : std::true_type { };
template<typename _Tp>
const bool __allocator_always_compares_equal<malloc_allocator<_Tp>>::value;
template<typename> struct mt_allocator; template<typename> struct mt_allocator;
template<typename _Tp> template<typename _Tp>
struct __allocator_always_compares_equal<mt_allocator<_Tp>> struct __allocator_always_compares_equal<mt_allocator<_Tp>>
{ static const bool value = true; }; : std::true_type { };
template<typename _Tp>
const bool __allocator_always_compares_equal<mt_allocator<_Tp>>::value;
template<typename> struct new_allocator; template<typename> struct new_allocator;
template<typename _Tp> template<typename _Tp>
struct __allocator_always_compares_equal<new_allocator<_Tp>> struct __allocator_always_compares_equal<new_allocator<_Tp>>
{ static const bool value = true; }; : std::true_type { };
template<typename _Tp>
const bool __allocator_always_compares_equal<new_allocator<_Tp>>::value;
template<typename> struct pool_allocator; template<typename> struct pool_allocator;
template<typename _Tp> template<typename _Tp>
struct __allocator_always_compares_equal<pool_allocator<_Tp>> struct __allocator_always_compares_equal<pool_allocator<_Tp>>
{ static const bool value = true; }; : std::true_type { };
template<typename _Tp>
const bool __allocator_always_compares_equal<pool_allocator<_Tp>>::value;
#endif #endif
/** /**
...@@ -131,7 +105,7 @@ template<typename _Alloc> ...@@ -131,7 +105,7 @@ template<typename _Alloc>
typedef typename _Base_type::const_pointer const_pointer; typedef typename _Base_type::const_pointer const_pointer;
typedef typename _Base_type::size_type size_type; typedef typename _Base_type::size_type size_type;
typedef typename _Base_type::difference_type difference_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 value_type& reference;
typedef const value_type& const_reference; typedef const value_type& const_reference;
using _Base_type::allocate; using _Base_type::allocate;
...@@ -142,10 +116,9 @@ template<typename _Alloc> ...@@ -142,10 +116,9 @@ template<typename _Alloc>
private: private:
template<typename _Ptr> template<typename _Ptr>
struct __is_custom_pointer using __is_custom_pointer
: std::integral_constant<bool, std::is_same<pointer, _Ptr>::value = std::__and_<std::is_same<pointer, _Ptr>,
&& !std::is_pointer<_Ptr>::value> std::__not_<std::is_pointer<_Ptr>>>;
{ };
public: public:
// overload construct for non-standard pointer types // overload construct for non-standard pointer types
......
// { 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
// <http://www.gnu.org/licenses/>.
#include <memory>
#include <testsuite_allocator.h>
// User-defined pointer type with non-trivial destructor.
template<typename T>
struct Pointer : __gnu_test::PointerBase<Pointer<T>, T>
{
using __gnu_test::PointerBase<Pointer<T>, T>::PointerBase;
~Pointer() { /* non-trivial */ }
};
// Minimal allocator with user-defined pointer type.
template<typename T>
struct Alloc
{
typedef T value_type;
typedef Pointer<T> pointer;
Alloc() = default;
template<typename U>
Alloc(const Alloc<U>&) { }
pointer allocate(std::size_t n) // does not take a hint
{ return pointer(std::allocator<T>().allocate(n)); }
void deallocate(pointer p, std::size_t n)
{ std::allocator<T>().deallocate(p.value, n); }
};
template<typename T>
bool operator==(Alloc<T> l, Alloc<T> r) { return true; }
template<typename T>
bool operator!=(Alloc<T> l, Alloc<T> r) { return false; }
void test01()
{
typedef std::allocator_traits<Alloc<int>> 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();
}
// { 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
// <http://www.gnu.org/licenses/>.
#include <memory>
#include <testsuite_allocator.h>
// { dg-do compile }
template<typename T>
struct ptr
{
ptr() = default;
template<typename U>
ptr(ptr<U> const& p) { }
};
// This doesn't meet the allocator requirements, it's only to check
// that allocator_traits finds the right nested types.
template<typename T>
struct alloc
{
typedef T value_type;
typedef ptr<T> pointer;
typedef ptr<const T> const_pointer;
typedef ptr<void> void_pointer;
typedef ptr<const void> 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<int> alloc_type;
typedef std::allocator_traits<alloc_type> traits;
using std::is_same;
static_assert( is_same<traits::pointer, alloc_type::pointer>::value,
"pointer" );
static_assert( is_same<traits::const_pointer,
alloc_type::const_pointer>::value,
"const_pointer" );
static_assert( is_same<traits::void_pointer, alloc_type::void_pointer>::value,
"void_pointer" );
static_assert( is_same<traits::const_void_pointer,
alloc_type::const_void_pointer>::value,
"const_void_pointer");
static_assert( is_same<traits::difference_type,
alloc_type::difference_type>::value,
"difference_type" );
static_assert( is_same<traits::size_type, alloc_type::size_type>::value,
"size_type" );
static_assert( is_same<traits::size_type, alloc_type::size_type>::value,
"size_type" );
static_assert( is_same<traits::propagate_on_container_copy_assignment,
alloc_type::propagate_on_container_copy_assignment
>::value,
"propagate_on_container_copy_assignment" );
static_assert( is_same<traits::propagate_on_container_move_assignment,
alloc_type::propagate_on_container_move_assignment
>::value,
"propagate_on_container_move_assignment" );
static_assert( is_same<traits::propagate_on_container_swap,
alloc_type::propagate_on_container_swap>::value,
"propagate_on_container_swap" );
...@@ -517,6 +517,106 @@ namespace __gnu_test ...@@ -517,6 +517,106 @@ namespace __gnu_test
void deallocate(pointer p, std::size_t n) void deallocate(pointer p, std::size_t n)
{ std::allocator<Tp>::deallocate(std::addressof(*p), n); } { std::allocator<Tp>::deallocate(std::addressof(*p), n); }
}; };
// Utility for use as CRTP base class of custom pointer types
template<typename Derived, typename T>
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<typename D, typename U,
typename = decltype(static_cast<T*>(std::declval<U*>()))>
PointerBase(const PointerBase<D, U>& 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<Derived&>(*this); }
};
template<typename D, typename T>
std::ptrdiff_t operator-(PointerBase<D, T> l, PointerBase<D, T> r)
{ return l.value - r.value; }
template<typename D, typename T>
bool operator==(PointerBase<D, T> l, PointerBase<D, T> r)
{ return l.value == r.value; }
template<typename D, typename T>
bool operator!=(PointerBase<D, T> l, PointerBase<D, T> r)
{ return l.value != r.value; }
// implementation for void specializations
template<typename T>
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<typename D, typename U,
typename = decltype(static_cast<T*>(std::declval<U*>()))>
PointerBase_void(const PointerBase<D, U>& p) : value(p.value) { }
explicit operator bool() const { return value != nullptr; }
};
template<typename Derived>
struct PointerBase<Derived, void> : PointerBase_void<void>
{
using PointerBase_void::PointerBase_void;
typedef Derived pointer;
};
template<typename Derived>
struct PointerBase<Derived, const void> : PointerBase_void<const void>
{
using PointerBase_void::PointerBase_void;
typedef Derived pointer;
};
#endif #endif
} // namespace __gnu_test } // namespace __gnu_test
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment