PR libstdc++/87544 limit max_size() to PTRDIFF_MAX / sizeof(T)
The C++17 standard requires the default implementation for allocator_traits::max_size to return SIZE_MAX / sizeof(value_type). That causes GCC to warn because the value could be larger than can sensibly be passed to malloc. This patch changes the new_allocator and malloc_allocator max_size() members to use PTRDIFF_MAX instead of SIZE_MAX (and because they define it, the allocator_traits default isn't used). This also changes vector::max_size to impose a sensible limit using PTRDIFF_MAX for cases where the value from the allocator or allocator_traits is not sensible. PR libstdc++/87544 * include/bits/stl_vector.h (vector::_S_max_size): Limit size to PTRDIFF_MAX / sizeof(value_type). * include/ext/malloc_allocator.h (malloc_allocator::max_size): Likewise. * include/ext/new_allocator.h (new_allocator::max_size): Likewise. * testsuite/23_containers/vector/allocator/minimal.cc: Adjust expected value for max_size(). * testsuite/23_containers/vector/capacity/87544.cc: New test. From-SVN: r265021
This commit is contained in:
parent
d3a46ecb38
commit
422a9f7789
@ -1,3 +1,15 @@
|
||||
2018-10-10 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/87544
|
||||
* include/bits/stl_vector.h (vector::_S_max_size): Limit size to
|
||||
PTRDIFF_MAX / sizeof(value_type).
|
||||
* include/ext/malloc_allocator.h (malloc_allocator::max_size):
|
||||
Likewise.
|
||||
* include/ext/new_allocator.h (new_allocator::max_size): Likewise.
|
||||
* testsuite/23_containers/vector/allocator/minimal.cc: Adjust
|
||||
expected value for max_size().
|
||||
* testsuite/23_containers/vector/capacity/87544.cc: New test.
|
||||
|
||||
2018-10-09 François Dumont <fdumont@gcc.gnu.org>
|
||||
|
||||
* include/bits/stl_list.h
|
||||
|
@ -1726,7 +1726,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
|
||||
static size_type
|
||||
_S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT
|
||||
{
|
||||
const size_t __diffmax = __gnu_cxx::__numeric_traits<ptrdiff_t>::__max;
|
||||
// std::distance(begin(), end()) cannot be greater than PTRDIFF_MAX,
|
||||
// and realistically we can't store more than PTRDIFF_MAX/sizeof(T)
|
||||
// (even if std::allocator_traits::max_size says we can).
|
||||
const size_t __diffmax
|
||||
= __gnu_cxx::__numeric_traits<ptrdiff_t>::__max / sizeof(_Tp);
|
||||
const size_t __allocmax = _Alloc_traits::max_size(__a);
|
||||
return (std::min)(__diffmax, __allocmax);
|
||||
}
|
||||
|
@ -139,7 +139,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
size_type
|
||||
max_size() const _GLIBCXX_USE_NOEXCEPT
|
||||
{ return size_t(-1) / sizeof(_Tp); }
|
||||
{
|
||||
#if __PTRDIFF_MAX__ < __SIZE_MAX__
|
||||
return size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
|
||||
#else
|
||||
return size_t(-1) / sizeof(_Tp);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Up, typename... _Args>
|
||||
|
@ -130,7 +130,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
size_type
|
||||
max_size() const _GLIBCXX_USE_NOEXCEPT
|
||||
{ return size_t(-1) / sizeof(_Tp); }
|
||||
{
|
||||
#if __PTRDIFF_MAX__ < __SIZE_MAX__
|
||||
return size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
|
||||
#else
|
||||
return size_t(-1) / sizeof(_Tp);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Up, typename... _Args>
|
||||
|
@ -35,7 +35,7 @@ void test01()
|
||||
typedef std::vector<T, alloc_type> test_type;
|
||||
test_type v(alloc_type{});
|
||||
v.push_back(T());
|
||||
VERIFY( v.max_size() == traits_type::max_size(v.get_allocator()) );
|
||||
VERIFY( v.max_size() <= traits_type::max_size(v.get_allocator()) );
|
||||
}
|
||||
|
||||
int main()
|
||||
|
@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2018 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-options "-O2" }
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
template<class T>
|
||||
struct Alloc : public std::allocator<T>
|
||||
{
|
||||
template<class U>
|
||||
struct rebind { typedef Alloc<U> other; };
|
||||
|
||||
Alloc() : std::allocator<T>() {}
|
||||
|
||||
template<class U>
|
||||
Alloc(const Alloc<U>& other) : std::allocator<T>(other) {}
|
||||
|
||||
T* allocate(std::size_t num, const void* = 0)
|
||||
{
|
||||
std::size_t size = num * sizeof(T);
|
||||
void *result = std::malloc(size);
|
||||
if(size>16 && (std::size_t(result) & 15)!=0) {
|
||||
std::free(result);
|
||||
return 0;
|
||||
}
|
||||
return static_cast<T*>( result );
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t) { std::free(p); }
|
||||
};
|
||||
|
||||
unsigned f(std::vector<int, Alloc<int> >& v)
|
||||
{
|
||||
v.push_back(1);
|
||||
return v.size();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
struct Alloc2 : public Alloc<T>
|
||||
{
|
||||
template<class U>
|
||||
struct rebind { typedef Alloc2<U> other; };
|
||||
|
||||
Alloc2() : Alloc<T>() {}
|
||||
|
||||
template<class U>
|
||||
Alloc2(const Alloc2<U>& other) : Alloc<T>(other) {}
|
||||
|
||||
std::size_t max_size() const { return std::size_t(-1) / sizeof(T); }
|
||||
};
|
||||
|
||||
unsigned g(std::vector<int, Alloc2<int> >& v)
|
||||
{
|
||||
v.push_back(1);
|
||||
return v.size();
|
||||
}
|
Loading…
Reference in New Issue
Block a user