diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2017-01-20 12:03:36 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2017-01-20 12:03:36 +0000 |
commit | 4dfdda108f5263c91312da23d8f3be3b685c9607 (patch) | |
tree | 20248b5dcaa4ce11e0ca39f8c3077e983ba2d368 | |
parent | 2ebd93e1d7f611a9aa06c67c7b9bd82495d6adc2 (diff) | |
download | gcc-4dfdda108f5263c91312da23d8f3be3b685c9607.zip gcc-4dfdda108f5263c91312da23d8f3be3b685c9607.tar.gz gcc-4dfdda108f5263c91312da23d8f3be3b685c9607.tar.bz2 |
PR72792 detect allocator pointer types without invalid rebinding
PR libstdc++/72792
* include/bits/alloc_traits.h (__allocator_traits_base::__diff_type)
(__allocator_traits_base::__size_type): Remove.
(allocator_traits::_Ptr): New class template to detect const and void
pointer types without instantiating pointer_traits::rebind
unnecessarily.
(allocator_traits::_Diff): Likewise for detecting difference_type.
(allocator_traits::_Size): New class template to detect size_type
without instantiating make_unsigned unnecessarily.
* include/bits/ptr_traits.h (pointer_traits::element_type): Use
__detected_or_t instead of __detected_or_t_.
* include/std/type_traits (__detected_or_t_): Remove.
* testsuite/20_util/allocator_traits/members/pointers.cc: New test.
From-SVN: r244706
-rw-r--r-- | libstdc++-v3/ChangeLog | 14 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/alloc_traits.h | 55 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/ptr_traits.h | 2 | ||||
-rw-r--r-- | libstdc++-v3/include/std/type_traits | 6 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/allocator_traits/members/pointers.cc | 52 |
5 files changed, 104 insertions, 25 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index c8cdaaa..5725179 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,6 +1,20 @@ 2017-01-20 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/72792 + * include/bits/alloc_traits.h (__allocator_traits_base::__diff_type) + (__allocator_traits_base::__size_type): Remove. + (allocator_traits::_Ptr): New class template to detect const and void + pointer types without instantiating pointer_traits::rebind + unnecessarily. + (allocator_traits::_Diff): Likewise for detecting difference_type. + (allocator_traits::_Size): New class template to detect size_type + without instantiating make_unsigned unnecessarily. + * include/bits/ptr_traits.h (pointer_traits::element_type): Use + __detected_or_t instead of __detected_or_t_. + * include/std/type_traits (__detected_or_t_): Remove. + * testsuite/20_util/allocator_traits/members/pointers.cc: New test. + + PR libstdc++/72792 PR libstdc++/72793 * include/bits/alloc_traits.h (__allocator_traits_base::__rebind): Replace with class template using void_t. diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index a836711..4d1e489 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -62,10 +62,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using __cv_pointer = typename _Tp::const_void_pointer; template<typename _Tp> - using __diff_type = typename _Tp::difference_type; - template<typename _Tp> - using __size_type = typename _Tp::size_type; - template<typename _Tp> using __pocca = typename _Tp::propagate_on_container_copy_assignment; template<typename _Tp> using __pocma = typename _Tp::propagate_on_container_move_assignment; @@ -98,15 +94,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ using pointer = __detected_or_t<value_type*, __pointer, _Alloc>; + private: + // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp> + template<template<typename> class _Func, typename _Tp, typename = void> + struct _Ptr + { + using type = typename pointer_traits<pointer>::template rebind<_Tp>; + }; + + template<template<typename> class _Func, typename _Tp> + struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> + { + using type = _Func<_Alloc>; + }; + + // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type + template<typename _A2, typename _PtrT, typename = void> + struct _Diff + { using type = typename pointer_traits<_PtrT>::difference_type; }; + + template<typename _A2, typename _PtrT> + struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>> + { using type = typename _A2::difference_type; }; + + // Select _A2::size_type or make_unsigned<_DiffT>::type + template<typename _A2, typename _DiffT, typename = void> + struct _Size : make_unsigned<_DiffT> { }; + + template<typename _A2, typename _DiffT> + struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>> + { using type = typename _A2::size_type; }; + + public: /** * @brief The allocator's const pointer type. * * @c Alloc::const_pointer if that type exists, otherwise * <tt> pointer_traits<pointer>::rebind<const value_type> </tt> */ - using const_pointer - = __detected_or_t<__ptr_rebind<pointer, const value_type>, - __c_pointer, _Alloc>; + using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; /** * @brief The allocator's void pointer type. @@ -114,8 +140,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::void_pointer if that type exists, otherwise * <tt> pointer_traits<pointer>::rebind<void> </tt> */ - using void_pointer - = __detected_or_t<__ptr_rebind<pointer, void>, __v_pointer, _Alloc>; + using void_pointer = typename _Ptr<__v_pointer, void>::type; /** * @brief The allocator's const void pointer type. @@ -123,9 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::const_void_pointer if that type exists, otherwise * <tt> pointer_traits<pointer>::rebind<const void> </tt> */ - using const_void_pointer - = __detected_or_t<__ptr_rebind<pointer, const void>, __cv_pointer, - _Alloc>; + using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; /** * @brief The allocator's difference type @@ -133,9 +156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::difference_type if that type exists, otherwise * <tt> pointer_traits<pointer>::difference_type </tt> */ - using difference_type - = __detected_or_t<typename pointer_traits<pointer>::difference_type, - __diff_type, _Alloc>; + using difference_type = typename _Diff<_Alloc, pointer>::type; /** * @brief The allocator's size type @@ -143,9 +164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @c Alloc::size_type if that type exists, otherwise * <tt> make_unsigned<difference_type>::type </tt> */ - using size_type - = __detected_or_t<typename make_unsigned<difference_type>::type, - __size_type, _Alloc>; + using size_type = typename _Size<_Alloc, difference_type>::type; /** * @brief How the allocator is propagated on copy assignment diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index d390d04..797e7fc 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -97,7 +97,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// The type pointed to. using element_type - = __detected_or_t_<__get_first_arg_t, __element_type, _Ptr>; + = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>; /// The type used to represent the difference between two pointers. using difference_type diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index a50f06c..3e2014e 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2565,12 +2565,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __detected_or_t = typename __detected_or<_Default, _Op, _Args...>::type; - // _Op<_Args...> if that is a valid type, otherwise _Default<_Args...>. - template<template<typename...> class _Default, - template<typename...> class _Op, typename... _Args> - using __detected_or_t_ = - __detected_or_t<_Default<_Args...>, _Op, _Args...>; - /// @} group metaprogramming /** diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/members/pointers.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/members/pointers.cc new file mode 100644 index 0000000..f25c54f --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator_traits/members/pointers.cc @@ -0,0 +1,52 @@ +// Copyright (C) 2017 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/>. + +// { dg-do compile { target c++11 } } + +#include <memory> + +// Non-type template param means pointer_traits::rebind can't be instantiated. +template<typename T, int = 0> + struct Pointer + { + using element_type = T; + Pointer(T* p = nullptr) : ptr(p) { } + T* ptr; + }; + +template<typename T> + struct Alloc + { + using value_type = T; + using pointer = Pointer<T>; + using const_pointer = Pointer<const T>; + using void_pointer = Pointer<void>; + using const_void_pointer = Pointer<const void>; + + pointer allocate(std::size_t n) + { return std::allocator<T>().allocate(n); } + + void allocate(pointer p, std::size_t n) + { return std::allocator<T>().deallocate(p, n); } + }; + +// The nested pointer types in Alloc should be found without attempting to +// instantiate pointer_traits::rebind (which would fail): +std::allocator_traits<Alloc<int>>::pointer p; +std::allocator_traits<Alloc<int>>::const_pointer cp; +std::allocator_traits<Alloc<int>>::void_pointer vp; +std::allocator_traits<Alloc<int>>::const_void_pointer cvp; |