diff options
5 files changed, 232 insertions, 137 deletions
diff --git a/libcxx/include/__functional_03 b/libcxx/include/__functional_03 index f048ea32437..99354834234 100644 --- a/libcxx/include/__functional_03 +++ b/libcxx/include/__functional_03 @@ -333,7 +333,8 @@ template<class _Fp, class _Alloc, class _Rp> __base<_Rp()>* __func<_Fp, _Alloc, _Rp()>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -359,7 +360,8 @@ template<class _Fp, class _Alloc, class _Rp> void __func<_Fp, _Alloc, _Rp()>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -417,7 +419,8 @@ template<class _Fp, class _Alloc, class _Rp, class _A0> __base<_Rp(_A0)>* __func<_Fp, _Alloc, _Rp(_A0)>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -443,7 +446,8 @@ template<class _Fp, class _Alloc, class _Rp, class _A0> void __func<_Fp, _Alloc, _Rp(_A0)>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -501,7 +505,8 @@ template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> __base<_Rp(_A0, _A1)>* __func<_Fp, _Alloc, _Rp(_A0, _A1)>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -527,7 +532,8 @@ template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1> void __func<_Fp, _Alloc, _Rp(_A0, _A1)>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -585,7 +591,8 @@ template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> __base<_Rp(_A0, _A1, _A2)>* __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::__clone() const { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); typedef __allocator_destructor<_Ap> _Dp; unique_ptr<__func, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); @@ -611,7 +618,8 @@ template<class _Fp, class _Alloc, class _Rp, class _A0, class _A1, class _A2> void __func<_Fp, _Alloc, _Rp(_A0, _A1, _A2)>::destroy_deallocate() { - typedef typename _Alloc::template rebind<__func>::other _Ap; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __rebind_alloc_helper<__alloc_traits, __func>::type _Ap; _Ap __a(__f_.second()); __f_.~__compressed_pair<_Fp, _Alloc>(); __a.deallocate(this, 1); @@ -794,7 +802,7 @@ function<_Rp()>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { @@ -1091,7 +1099,7 @@ function<_Rp(_A0)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { @@ -1388,7 +1396,7 @@ function<_Rp(_A0, _A1)>::function(allocator_arg_t, const _Alloc& __a0, _Fp __f, if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { @@ -1685,7 +1693,7 @@ function<_Rp(_A0, _A1, _A2)>::function(allocator_arg_t, const _Alloc& __a0, _Fp if (sizeof(_FF) <= sizeof(__buf_)) { __f_ = (__base*)&__buf_; - ::new (__f_) _FF(__f); + ::new (__f_) _FF(__f, __a0); } else { diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp index 741a3b9a955..352ecfc602b 100644 --- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_F.pass.cpp @@ -17,84 +17,90 @@ #include <cassert> #include "min_allocator.h" +#include "test_allocator.h" +#include "count_new.hpp" +#include "../function_types.h" -class A -{ - int data_[10]; -public: - static int count; +class DummyClass {}; - A() +template <class FuncType, class AllocType> +void test_FunctionObject(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = i; + FunctionObject target; + assert(FunctionObject::count == 1); + assert(globalMemCounter.checkOutstandingNewEq(0)); + std::function<FuncType> f2(std::allocator_arg, alloc, target); + assert(FunctionObject::count == 2); + assert(globalMemCounter.checkOutstandingNewEq(1)); + assert(f2.template target<FunctionObject>()); + assert(f2.template target<FuncType>() == 0); + assert(f2.template target<FuncType*>() == 0); } + assert(FunctionObject::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); +} - A(const A&) {++count;} - - ~A() {--count;} - int operator()(int i) const +template <class FuncType, class AllocType> +void test_FreeFunction(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; + FuncType* target = &FreeFunction; + assert(globalMemCounter.checkOutstandingNewEq(0)); + std::function<FuncType> f2(std::allocator_arg, alloc, target); + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f2.template target<FuncType*>()); + assert(*f2.template target<FuncType*>() == target); + assert(f2.template target<FuncType>() == 0); + assert(f2.template target<DummyClass>() == 0); } + assert(globalMemCounter.checkOutstandingNewEq(0)); +} - int foo(int) const {return 1;} -}; +template <class TargetType, class FuncType, class AllocType> +void test_MemFunClass(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); + { + TargetType target = &MemFunClass::foo; + assert(globalMemCounter.checkOutstandingNewEq(0)); + std::function<FuncType> f2(std::allocator_arg, alloc, target); + assert(globalMemCounter.checkOutstandingNewEq(0)); + assert(f2.template target<TargetType>()); + assert(*f2.template target<TargetType>() == target); + assert(f2.template target<FuncType*>() == 0); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); +} -int A::count = 0; +template <class Alloc> +void test_for_alloc(Alloc& alloc) { + test_FunctionObject<int()>(alloc); + test_FunctionObject<int(int)>(alloc); + test_FunctionObject<int(int, int)>(alloc); + test_FunctionObject<int(int, int, int)>(alloc); -int g(int) {return 0;} + test_FreeFunction<int()>(alloc); + test_FreeFunction<int(int)>(alloc); + test_FreeFunction<int(int, int)>(alloc); + test_FreeFunction<int(int, int, int)>(alloc); -class Foo { -public: - void bar(int k) { } -}; + test_MemFunClass<int(MemFunClass::*)() const, int(MemFunClass&)>(alloc); + test_MemFunClass<int(MemFunClass::*)(int) const, int(MemFunClass&, int)>(alloc); + test_MemFunClass<int(MemFunClass::*)(int, int) const, int(MemFunClass&, int, int)>(alloc); +} int main() { { - std::function<int(int)> f(std::allocator_arg, bare_allocator<A>(), A()); - assert(A::count == 1); - assert(f.target<A>()); - assert(f.target<int(*)(int)>() == 0); - } - assert(A::count == 0); - { - std::function<int(int)> f(std::allocator_arg, bare_allocator<int(*)(int)>(), g); - assert(f.target<int(*)(int)>()); - assert(f.target<A>() == 0); - } - { - std::function<int(int)> f(std::allocator_arg, bare_allocator<int(*)(int)>(), - (int (*)(int))0); - assert(!f); - assert(f.target<int(*)(int)>() == 0); - assert(f.target<A>() == 0); - } - { - std::function<int(const A*, int)> f(std::allocator_arg, - bare_allocator<int(A::*)(int)const>(), - &A::foo); - assert(f); - assert(f.target<int (A::*)(int) const>() != 0); - } -#if __cplusplus >= 201103L - { - Foo f; - std::function<void(int)> fun = std::bind(&Foo::bar, &f, std::placeholders::_1); - fun(10); + bare_allocator<DummyClass> bare_alloc; + test_for_alloc(bare_alloc); } -#endif { - std::function<void(int)> fun(std::allocator_arg, - bare_allocator<int(*)(int)>(), - &g); - assert(fun); - assert(fun.target<int(*)(int)>() != 0); - fun(10); + non_default_test_allocator<DummyClass> non_default_alloc(42); + test_for_alloc(non_default_alloc); } } diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp index e89636a69d6..371eb98de1a 100644 --- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp +++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/alloc_function.pass.cpp @@ -20,81 +20,105 @@ #include "min_allocator.h" #include "test_allocator.h" #include "count_new.hpp" +#include "../function_types.h" -class A -{ - int data_[10]; -public: - static int count; - - A() - { - ++count; - for (int i = 0; i < 10; ++i) - data_[i] = i; - } - - A(const A&) {++count;} - - ~A() {--count;} - - int operator()(int i) const - { - for (int j = 0; j < 10; ++j) - i += data_[j]; - return i; - } -}; - -int A::count = 0; +class DummyClass {}; -int g(int) {return 0;} - -int main() +template <class FuncType, class AllocType> +void test_FunctionObject(AllocType& alloc) { assert(globalMemCounter.checkOutstandingNewEq(0)); { - std::function<int(int)> f = A(); - assert(A::count == 1); + // Construct function from FunctionObject. + std::function<FuncType> f = FunctionObject(); + assert(FunctionObject::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); - assert(f.target<A>()); - assert(f.target<int(*)(int)>() == 0); - std::function<int(int)> f2(std::allocator_arg, bare_allocator<A>(), f); - assert(A::count == 2); + assert(f.template target<FunctionObject>()); + assert(f.template target<FuncType>() == 0); + assert(f.template target<FuncType*>() == 0); + // Copy function with allocator + std::function<FuncType> f2(std::allocator_arg, alloc, f); + assert(FunctionObject::count == 2); assert(globalMemCounter.checkOutstandingNewEq(2)); - assert(f2.target<A>()); - assert(f2.target<int(*)(int)>() == 0); + assert(f2.template target<FunctionObject>()); + assert(f2.template target<FuncType>() == 0); + assert(f2.template target<FuncType*>() == 0); } - assert(A::count == 0); + assert(FunctionObject::count == 0); assert(globalMemCounter.checkOutstandingNewEq(0)); - { - std::function<int(int)> f = g; - assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target<int(*)(int)>()); - assert(f.target<A>() == 0); - std::function<int(int)> f2(std::allocator_arg, bare_allocator<int(*)(int)>(), f); - assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target<int(*)(int)>()); - assert(f2.target<A>() == 0); - } +} + +template <class FuncType, class AllocType> +void test_FreeFunction(AllocType& alloc) +{ assert(globalMemCounter.checkOutstandingNewEq(0)); { + // Construct function from function pointer. + FuncType* target = &FreeFunction; + std::function<FuncType> f = target; assert(globalMemCounter.checkOutstandingNewEq(0)); - non_default_test_allocator<std::function<int(int)> > al(1); - std::function<int(int)> f2(std::allocator_arg, al, g); + assert(f.template target<FuncType*>()); + assert(*f.template target<FuncType*>() == target); + assert(f.template target<FuncType>() == 0); + // Copy function with allocator + std::function<FuncType> f2(std::allocator_arg, alloc, f); assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target<int(*)(int)>()); - assert(f2.target<A>() == 0); + assert(f2.template target<FuncType*>()); + assert(*f2.template target<FuncType*>() == target); + assert(f2.template target<FuncType>() == 0); } assert(globalMemCounter.checkOutstandingNewEq(0)); +} + +template <class TargetType, class FuncType, class AllocType> +void test_MemFunClass(AllocType& alloc) +{ + assert(globalMemCounter.checkOutstandingNewEq(0)); { - std::function<int(int)> f; + // Construct function from function pointer. + TargetType target = &MemFunClass::foo; + std::function<FuncType> f = target; assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f.target<int(*)(int)>() == 0); - assert(f.target<A>() == 0); - std::function<int(int)> f2(std::allocator_arg, bare_allocator<int>(), f); + assert(f.template target<TargetType>()); + assert(*f.template target<TargetType>() == target); + assert(f.template target<FuncType*>() == 0); + // Copy function with allocator + std::function<FuncType> f2(std::allocator_arg, alloc, f); assert(globalMemCounter.checkOutstandingNewEq(0)); - assert(f2.target<int(*)(int)>() == 0); - assert(f2.target<A>() == 0); + assert(f2.template target<TargetType>()); + assert(*f2.template target<TargetType>() == target); + assert(f2.template target<FuncType*>() == 0); } + assert(globalMemCounter.checkOutstandingNewEq(0)); +} + +template <class Alloc> +void test_for_alloc(Alloc& alloc) +{ + // Large FunctionObject -- Allocation should occur + test_FunctionObject<int()>(alloc); + test_FunctionObject<int(int)>(alloc); + test_FunctionObject<int(int, int)>(alloc); + test_FunctionObject<int(int, int, int)>(alloc); + // Free function -- No allocation should occur + test_FreeFunction<int()>(alloc); + test_FreeFunction<int(int)>(alloc); + test_FreeFunction<int(int, int)>(alloc); + test_FreeFunction<int(int, int, int)>(alloc); + // Member function -- No allocation should occur. + test_MemFunClass<int(MemFunClass::*)() const, int(MemFunClass&)>(alloc); + test_MemFunClass<int(MemFunClass::*)(int) const, int(MemFunClass&, int)>(alloc); + test_MemFunClass<int(MemFunClass::*)(int, int) const, int(MemFunClass&, int, int)>(alloc); +} + +int main() +{ + { + bare_allocator<DummyClass> alloc; + test_for_alloc(alloc); + } + { + non_default_test_allocator<DummyClass> alloc(42); + test_for_alloc(alloc); + } } diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h new file mode 100644 index 00000000000..55eb80f43ff --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/function_types.h @@ -0,0 +1,57 @@ +#ifndef FUNCTION_TYPES_H +#define FUNCTION_TYPES_H + + +class FunctionObject +{ + int data_[10]; // dummy variable to prevent small object optimization in + // std::function +public: + static int count; + + FunctionObject() { + ++count; + for (int i = 0; i < 10; ++i) data_[i] = i; + } + + FunctionObject(const FunctionObject&) {++count;} + ~FunctionObject() {--count; ((void)data_); } + + int operator()() const { return 42; } + int operator()(int i) const { return i; } + int operator()(int i, int) const { return i; } + int operator()(int i, int, int) const { return i; } +}; + +int FunctionObject::count = 0; + +class MemFunClass +{ + int data_[10]; // dummy variable to prevent small object optimization in + // std::function +public: + static int count; + + MemFunClass() { + ++count; + for (int i = 0; i < 10; ++i) data_[i] = 0; + } + + MemFunClass(const MemFunClass&) {++count; ((void)data_); } + + ~MemFunClass() {--count;} + + int foo() const { return 42; } + int foo(int i) const { return i; } + int foo(int i, int) const { return i; } + int foo(int i, int, int) const { return i; } +}; + +int MemFunClass::count = 0; + +int FreeFunction() { return 42; } +int FreeFunction(int i) {return i;} +int FreeFunction(int i, int) { return i; } +int FreeFunction(int i, int, int) { return i; } + +#endif // FUNCTION_TYPES_H diff --git a/libcxx/test/support/test_allocator.h b/libcxx/test/support/test_allocator.h index 03bd3905606..47ef1d55678 100644 --- a/libcxx/test/support/test_allocator.h +++ b/libcxx/test/support/test_allocator.h @@ -74,10 +74,10 @@ public: } ++time_to_throw; ++alloc_count; - return (pointer)std::malloc(n * sizeof(T)); + return (pointer)::operator new(n * sizeof(T)); } void deallocate(pointer p, size_type n) - {assert(data_ >= 0); --alloc_count; std::free(p);} + {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p);} size_type max_size() const throw() {return UINT_MAX / sizeof(T);} void construct(pointer p, const T& val) @@ -134,10 +134,10 @@ public: } ++time_to_throw; ++alloc_count; - return (pointer)std::malloc(n * sizeof(T)); + return (pointer)::operator new (n * sizeof(T)); } void deallocate(pointer p, size_type n) - {assert(data_ >= 0); --alloc_count; std::free(p);} + {assert(data_ >= 0); --alloc_count; ::operator delete((void*)p); } size_type max_size() const throw() {return UINT_MAX / sizeof(T);} void construct(pointer p, const T& val) @@ -200,9 +200,9 @@ public: template <class U> other_allocator(const other_allocator<U>& a) : data_(a.data_) {} T* allocate(std::size_t n) - {return (T*)std::malloc(n * sizeof(T));} + {return (T*)::operator new(n * sizeof(T));} void deallocate(T* p, std::size_t n) - {std::free(p);} + {::operator delete((void*)p);} other_allocator select_on_container_copy_construction() const {return other_allocator(-2);} |