forked from OSchip/llvm-project
[libcxx] Throw correct exception from std::vector::reserve
According to the standard [vector.capacity]/5, std::vector<T>::reserve shall throw an exception of type std::length_error when the requested capacity exceeds max_size(). This behavior is not implemented correctly: the function 'reserve' simply propagates the exception from allocator<T>::allocate. Before D110846 that exception used to be of type std::length_error (which is correct for vector<T>::reserve, but incorrect for allocator<T>::allocate). This patch fixes the issue and adds regression tests. Reviewed By: Quuxplusone, ldionne, #libc Differential Revision: https://reviews.llvm.org/D112068
This commit is contained in:
parent
49be23a1eb
commit
05a2d17668
|
@ -1590,6 +1590,8 @@ vector<_Tp, _Allocator>::reserve(size_type __n)
|
|||
{
|
||||
if (__n > capacity())
|
||||
{
|
||||
if (__n > max_size())
|
||||
this->__throw_length_error();
|
||||
allocator_type& __a = this->__alloc();
|
||||
__split_buffer<value_type, allocator_type&> __v(__n, size(), __a);
|
||||
__swap_out_circular_buffer(__v);
|
||||
|
@ -3018,6 +3020,8 @@ vector<bool, _Allocator>::reserve(size_type __n)
|
|||
{
|
||||
if (__n > capacity())
|
||||
{
|
||||
if (__n > max_size())
|
||||
this->__throw_length_error();
|
||||
vector __v(this->get_allocator());
|
||||
__v.__vallocate(__n);
|
||||
__v.__construct_at_end(this->begin(), this->end());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "test_macros.h"
|
||||
#include "min_allocator.h"
|
||||
#include "test_allocator.h"
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
|
@ -56,6 +57,23 @@ int main(int, char**)
|
|||
assert(v.capacity() >= 150);
|
||||
}
|
||||
#endif
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
std::vector<bool, limited_allocator<bool, 10> > v;
|
||||
v.reserve(5);
|
||||
try {
|
||||
// A typical implementation would allocate chunks of bits.
|
||||
// In libc++ the chunk has the same size as the machine word. It is
|
||||
// reasonable to assume that in practice no implementation would use
|
||||
// 64 kB or larger chunks.
|
||||
v.reserve(10 * 65536);
|
||||
assert(false);
|
||||
} catch (const std::length_error&) {
|
||||
// no-op
|
||||
}
|
||||
assert(v.capacity() >= 5);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -67,6 +67,22 @@ int main(int, char**)
|
|||
assert(is_contiguous_container_asan_correct(v));
|
||||
}
|
||||
#endif
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
{
|
||||
std::vector<int, limited_allocator<int, 100> > v;
|
||||
v.reserve(50);
|
||||
assert(v.capacity() == 50);
|
||||
assert(is_contiguous_container_asan_correct(v));
|
||||
try {
|
||||
v.reserve(101);
|
||||
assert(false);
|
||||
} catch (const std::length_error&) {
|
||||
// no-op
|
||||
}
|
||||
assert(v.capacity() == 50);
|
||||
assert(is_contiguous_container_asan_correct(v));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue