mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-12 12:48:59 +00:00
Bug #19473. If you pass an allocator to std::function, we should use that allocator, not construct one from scratch. Add a test to make sure
llvm-svn: 206623
This commit is contained in:
parent
f8361d127a
commit
5f7c2db2ce
@ -1617,21 +1617,22 @@ function<_Rp(_ArgTypes...)>::function(allocator_arg_t, const _Alloc& __a0, _Fp _
|
||||
if (__not_null(__f))
|
||||
{
|
||||
typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _FF;
|
||||
if (sizeof(_FF) <= sizeof(__buf_) && is_nothrow_copy_constructible<_Fp>::value)
|
||||
typedef typename __alloc_traits::template
|
||||
#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
||||
rebind_alloc<_FF>
|
||||
#else
|
||||
rebind_alloc<_FF>::other
|
||||
#endif
|
||||
_Ap;
|
||||
_Ap __a(__a0);
|
||||
if (sizeof(_FF) <= sizeof(__buf_) &&
|
||||
is_nothrow_copy_constructible<_Fp>::value && is_nothrow_copy_constructible<_Ap>::value)
|
||||
{
|
||||
__f_ = (__base*)&__buf_;
|
||||
::new (__f_) _FF(_VSTD::move(__f));
|
||||
::new (__f_) _FF(_VSTD::move(__f), _Alloc(__a));
|
||||
}
|
||||
else
|
||||
{
|
||||
typedef typename __alloc_traits::template
|
||||
#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
|
||||
rebind_alloc<_FF>
|
||||
#else
|
||||
rebind_alloc<_FF>::other
|
||||
#endif
|
||||
_Ap;
|
||||
_Ap __a(__a0);
|
||||
typedef __allocator_destructor<_Ap> _Dp;
|
||||
unique_ptr<__base, _Dp> __hold(__a.allocate(1), _Dp(__a, 1));
|
||||
::new (__hold.get()) _FF(_VSTD::move(__f), _Alloc(__a));
|
||||
|
@ -92,6 +92,66 @@ public:
|
||||
{return !(x == y);}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class non_default_test_allocator
|
||||
: public test_alloc_base
|
||||
{
|
||||
int data_;
|
||||
|
||||
template <class U> friend class non_default_test_allocator;
|
||||
public:
|
||||
|
||||
typedef unsigned size_type;
|
||||
typedef int difference_type;
|
||||
typedef T value_type;
|
||||
typedef value_type* pointer;
|
||||
typedef const value_type* const_pointer;
|
||||
typedef typename std::add_lvalue_reference<value_type>::type reference;
|
||||
typedef typename std::add_lvalue_reference<const value_type>::type const_reference;
|
||||
|
||||
template <class U> struct rebind {typedef non_default_test_allocator<U> other;};
|
||||
|
||||
// non_default_test_allocator() throw() : data_(0) {++count;}
|
||||
explicit non_default_test_allocator(int i) throw() : data_(i) {++count;}
|
||||
non_default_test_allocator(const non_default_test_allocator& a) throw()
|
||||
: data_(a.data_) {++count;}
|
||||
template <class U> non_default_test_allocator(const non_default_test_allocator<U>& a) throw()
|
||||
: data_(a.data_) {++count;}
|
||||
~non_default_test_allocator() throw() {assert(data_ >= 0); --count; data_ = -1;}
|
||||
pointer address(reference x) const {return &x;}
|
||||
const_pointer address(const_reference x) const {return &x;}
|
||||
pointer allocate(size_type n, const void* = 0)
|
||||
{
|
||||
assert(data_ >= 0);
|
||||
if (time_to_throw >= throw_after) {
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
throw std::bad_alloc();
|
||||
#else
|
||||
std::terminate();
|
||||
#endif
|
||||
}
|
||||
++time_to_throw;
|
||||
++alloc_count;
|
||||
return (pointer)std::malloc(n * sizeof(T));
|
||||
}
|
||||
void deallocate(pointer p, size_type n)
|
||||
{assert(data_ >= 0); --alloc_count; std::free(p);}
|
||||
size_type max_size() const throw()
|
||||
{return UINT_MAX / sizeof(T);}
|
||||
void construct(pointer p, const T& val)
|
||||
{::new(p) T(val);}
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
void construct(pointer p, T&& val)
|
||||
{::new(p) T(std::move(val));}
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
void destroy(pointer p) {p->~T();}
|
||||
|
||||
friend bool operator==(const non_default_test_allocator& x, const non_default_test_allocator& y)
|
||||
{return x.data_ == y.data_;}
|
||||
friend bool operator!=(const non_default_test_allocator& x, const non_default_test_allocator& y)
|
||||
{return !(x == y);}
|
||||
};
|
||||
|
||||
template <>
|
||||
class test_allocator<void>
|
||||
: public test_alloc_base
|
||||
|
@ -92,6 +92,15 @@ int main()
|
||||
}
|
||||
assert(new_called == 0);
|
||||
{
|
||||
assert(new_called == 0);
|
||||
non_default_test_allocator<std::function<int(int)>> al(1);
|
||||
std::function<int(int)> f2(std::allocator_arg, al, g);
|
||||
assert(new_called == 0);
|
||||
assert(f2.target<int(*)(int)>());
|
||||
assert(f2.target<A>() == 0);
|
||||
}
|
||||
assert(new_called == 0);
|
||||
{
|
||||
std::function<int(int)> f;
|
||||
assert(new_called == 0);
|
||||
assert(f.target<int(*)(int)>() == 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user