15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier 
95a83710eSEric Fiselier // <functional>
1031cbe0f2SLouis Dionne // REQUIRES: c++03 || c++11 || c++14
115a83710eSEric Fiselier 
125a83710eSEric Fiselier // class function<R(ArgTypes...)>
135a83710eSEric Fiselier 
145a83710eSEric Fiselier // template<class A> function(allocator_arg_t, const A&, const function&);
155a83710eSEric Fiselier 
16b4fb705eSLouis Dionne // This test runs in C++03, but we have deprecated using std::function in C++03.
17*c475e31aSNikolas Klauser // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS -D_LIBCPP_ENABLE_CXX03_FUNCTION
185a83710eSEric Fiselier 
195a83710eSEric Fiselier #include <functional>
205a83710eSEric Fiselier #include <cassert>
215a83710eSEric Fiselier 
227fc6a556SMarshall Clow #include "test_macros.h"
236d370568SEric Fiselier #include "min_allocator.h"
245a83710eSEric Fiselier #include "test_allocator.h"
25cc89063bSNico Weber #include "count_new.h"
26b11df184SEric Fiselier #include "../function_types.h"
275a83710eSEric Fiselier 
28b11df184SEric Fiselier class DummyClass {};
295a83710eSEric Fiselier 
30b11df184SEric Fiselier template <class FuncType, class AllocType>
test_FunctionObject(AllocType & alloc)31b11df184SEric Fiselier void test_FunctionObject(AllocType& alloc)
325a83710eSEric Fiselier {
33b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
34b11df184SEric Fiselier     {
35b11df184SEric Fiselier     // Construct function from FunctionObject.
36b11df184SEric Fiselier     std::function<FuncType> f = FunctionObject();
37b11df184SEric Fiselier     assert(FunctionObject::count == 1);
38b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(1));
39bb09ef95SLouis Dionne     RTTI_ASSERT(f.template target<FunctionObject>());
40bb09ef95SLouis Dionne     RTTI_ASSERT(f.template target<FuncType>() == 0);
41bb09ef95SLouis Dionne     RTTI_ASSERT(f.template target<FuncType*>() == 0);
42b11df184SEric Fiselier     // Copy function with allocator
43b11df184SEric Fiselier     std::function<FuncType> f2(std::allocator_arg, alloc, f);
44b11df184SEric Fiselier     assert(FunctionObject::count == 2);
45b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(2));
46bb09ef95SLouis Dionne     RTTI_ASSERT(f2.template target<FunctionObject>());
47bb09ef95SLouis Dionne     RTTI_ASSERT(f2.template target<FuncType>() == 0);
48bb09ef95SLouis Dionne     RTTI_ASSERT(f2.template target<FuncType*>() == 0);
49b11df184SEric Fiselier     }
50b11df184SEric Fiselier     assert(FunctionObject::count == 0);
51b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
525a83710eSEric Fiselier }
535a83710eSEric Fiselier 
54b11df184SEric Fiselier template <class FuncType, class AllocType>
test_FreeFunction(AllocType & alloc)55b11df184SEric Fiselier void test_FreeFunction(AllocType& alloc)
565a83710eSEric Fiselier {
57b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
58b11df184SEric Fiselier     {
59b11df184SEric Fiselier     // Construct function from function pointer.
60b11df184SEric Fiselier     FuncType* target = &FreeFunction;
61b11df184SEric Fiselier     std::function<FuncType> f = target;
62b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
63bb09ef95SLouis Dionne     RTTI_ASSERT(f.template target<FuncType*>());
64bb09ef95SLouis Dionne     RTTI_ASSERT(*f.template target<FuncType*>() == target);
65bb09ef95SLouis Dionne     RTTI_ASSERT(f.template target<FuncType>() == 0);
66b11df184SEric Fiselier     // Copy function with allocator
67b11df184SEric Fiselier     std::function<FuncType> f2(std::allocator_arg, alloc, f);
68b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
69bb09ef95SLouis Dionne     RTTI_ASSERT(f2.template target<FuncType*>());
70bb09ef95SLouis Dionne     RTTI_ASSERT(*f2.template target<FuncType*>() == target);
71bb09ef95SLouis Dionne     RTTI_ASSERT(f2.template target<FuncType>() == 0);
725a83710eSEric Fiselier     }
73b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
74b11df184SEric Fiselier }
755a83710eSEric Fiselier 
76b11df184SEric Fiselier template <class TargetType, class FuncType, class AllocType>
test_MemFunClass(AllocType & alloc)77b11df184SEric Fiselier void test_MemFunClass(AllocType& alloc)
78b11df184SEric Fiselier {
79b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
80b11df184SEric Fiselier     {
81b11df184SEric Fiselier     // Construct function from function pointer.
82b11df184SEric Fiselier     TargetType target = &MemFunClass::foo;
83b11df184SEric Fiselier     std::function<FuncType> f = target;
84b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
85bb09ef95SLouis Dionne     RTTI_ASSERT(f.template target<TargetType>());
86bb09ef95SLouis Dionne     RTTI_ASSERT(*f.template target<TargetType>() == target);
87bb09ef95SLouis Dionne     RTTI_ASSERT(f.template target<FuncType*>() == 0);
88b11df184SEric Fiselier     // Copy function with allocator
89b11df184SEric Fiselier     std::function<FuncType> f2(std::allocator_arg, alloc, f);
90b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
91bb09ef95SLouis Dionne     RTTI_ASSERT(f2.template target<TargetType>());
92bb09ef95SLouis Dionne     RTTI_ASSERT(*f2.template target<TargetType>() == target);
93bb09ef95SLouis Dionne     RTTI_ASSERT(f2.template target<FuncType*>() == 0);
94b11df184SEric Fiselier     }
95b11df184SEric Fiselier     assert(globalMemCounter.checkOutstandingNewEq(0));
96b11df184SEric Fiselier }
975a83710eSEric Fiselier 
98b11df184SEric Fiselier template <class Alloc>
test_for_alloc(Alloc & alloc)99b11df184SEric Fiselier void test_for_alloc(Alloc& alloc)
100b11df184SEric Fiselier {
101b11df184SEric Fiselier     // Large FunctionObject -- Allocation should occur
102b11df184SEric Fiselier     test_FunctionObject<int()>(alloc);
103b11df184SEric Fiselier     test_FunctionObject<int(int)>(alloc);
104b11df184SEric Fiselier     test_FunctionObject<int(int, int)>(alloc);
105b11df184SEric Fiselier     test_FunctionObject<int(int, int, int)>(alloc);
106b11df184SEric Fiselier     // Free function -- No allocation should occur
107b11df184SEric Fiselier     test_FreeFunction<int()>(alloc);
108b11df184SEric Fiselier     test_FreeFunction<int(int)>(alloc);
109b11df184SEric Fiselier     test_FreeFunction<int(int, int)>(alloc);
110b11df184SEric Fiselier     test_FreeFunction<int(int, int, int)>(alloc);
111b11df184SEric Fiselier     // Member function -- No allocation should occur.
112b11df184SEric Fiselier     test_MemFunClass<int(MemFunClass::*)() const, int(MemFunClass&)>(alloc);
113b11df184SEric Fiselier     test_MemFunClass<int(MemFunClass::*)(int) const, int(MemFunClass&, int)>(alloc);
114b11df184SEric Fiselier     test_MemFunClass<int(MemFunClass::*)(int, int) const, int(MemFunClass&, int, int)>(alloc);
115b11df184SEric Fiselier }
1165a83710eSEric Fiselier 
main(int,char **)1172df59c50SJF Bastien int main(int, char**)
1185a83710eSEric Fiselier {
1190b43db52SDan Albert   globalMemCounter.reset();
1205a83710eSEric Fiselier   {
121b11df184SEric Fiselier     bare_allocator<DummyClass> alloc;
122b11df184SEric Fiselier     test_for_alloc(alloc);
1235a83710eSEric Fiselier   }
1245a83710eSEric Fiselier   {
125b11df184SEric Fiselier     non_default_test_allocator<DummyClass> alloc(42);
126b11df184SEric Fiselier     test_for_alloc(alloc);
1275a83710eSEric Fiselier   }
1282df59c50SJF Bastien 
1292df59c50SJF Bastien   return 0;
1305a83710eSEric Fiselier }
131