1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // XFAIL: LIBCXX-WINDOWS-FIXME
10 
11 // <functional>
12 
13 // class function<R(ArgTypes...)>
14 
15 // function(const function&  f);
16 // function(function&& f); // noexcept in C++20
17 
18 // This test runs in C++03, but we have deprecated using std::function in C++03.
19 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
20 
21 #include <functional>
22 #include <memory>
23 #include <cstdlib>
24 #include <cassert>
25 
26 #include "test_macros.h"
27 #include "count_new.h"
28 
29 class A
30 {
31     int data_[10];
32 public:
33     static int count;
34 
35     A()
36     {
37         ++count;
38         for (int i = 0; i < 10; ++i)
39             data_[i] = i;
40     }
41 
42     A(const A&) {++count;}
43 
44     ~A() {--count;}
45 
46     int operator()(int i) const
47     {
48         for (int j = 0; j < 10; ++j)
49             i += data_[j];
50         return i;
51     }
52 };
53 
54 int A::count = 0;
55 
56 int g(int) {return 0;}
57 
58 int main(int, char**)
59 {
60     globalMemCounter.reset();
61     assert(globalMemCounter.checkOutstandingNewEq(0));
62     {
63     std::function<int(int)> f = A();
64     assert(A::count == 1);
65     assert(globalMemCounter.checkOutstandingNewEq(1));
66     RTTI_ASSERT(f.target<A>());
67     RTTI_ASSERT(f.target<int(*)(int)>() == 0);
68     std::function<int(int)> f2 = f;
69     assert(A::count == 2);
70     assert(globalMemCounter.checkOutstandingNewEq(2));
71     RTTI_ASSERT(f2.target<A>());
72     RTTI_ASSERT(f2.target<int(*)(int)>() == 0);
73     }
74     assert(A::count == 0);
75     assert(globalMemCounter.checkOutstandingNewEq(0));
76     {
77     std::function<int(int)> f = g;
78     assert(globalMemCounter.checkOutstandingNewEq(0));
79     RTTI_ASSERT(f.target<int(*)(int)>());
80     RTTI_ASSERT(f.target<A>() == 0);
81     std::function<int(int)> f2 = f;
82     assert(globalMemCounter.checkOutstandingNewEq(0));
83     RTTI_ASSERT(f2.target<int(*)(int)>());
84     RTTI_ASSERT(f2.target<A>() == 0);
85     }
86     assert(globalMemCounter.checkOutstandingNewEq(0));
87     {
88     std::function<int(int)> f;
89     assert(globalMemCounter.checkOutstandingNewEq(0));
90     RTTI_ASSERT(f.target<int(*)(int)>() == 0);
91     RTTI_ASSERT(f.target<A>() == 0);
92     std::function<int(int)> f2 = f;
93     assert(globalMemCounter.checkOutstandingNewEq(0));
94     RTTI_ASSERT(f2.target<int(*)(int)>() == 0);
95     RTTI_ASSERT(f2.target<A>() == 0);
96     }
97     {
98     std::function<int(int)> f;
99     assert(globalMemCounter.checkOutstandingNewEq(0));
100     RTTI_ASSERT(f.target<int(*)(int)>() == 0);
101     RTTI_ASSERT(f.target<A>() == 0);
102     assert(!f);
103     std::function<long(int)> g = f;
104     assert(globalMemCounter.checkOutstandingNewEq(0));
105     RTTI_ASSERT(g.target<long(*)(int)>() == 0);
106     RTTI_ASSERT(g.target<A>() == 0);
107     assert(!g);
108     }
109 #if TEST_STD_VER >= 11
110     assert(globalMemCounter.checkOutstandingNewEq(0));
111     { // Test rvalue references
112         std::function<int(int)> f = A();
113         assert(A::count == 1);
114         assert(globalMemCounter.checkOutstandingNewEq(1));
115         RTTI_ASSERT(f.target<A>());
116         RTTI_ASSERT(f.target<int(*)(int)>() == 0);
117 		LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
118 #if TEST_STD_VER > 17
119 		ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
120 #endif
121         std::function<int(int)> f2 = std::move(f);
122         assert(A::count == 1);
123         assert(globalMemCounter.checkOutstandingNewEq(1));
124         RTTI_ASSERT(f2.target<A>());
125         RTTI_ASSERT(f2.target<int(*)(int)>() == 0);
126         RTTI_ASSERT(f.target<A>() == 0);
127         RTTI_ASSERT(f.target<int(*)(int)>() == 0);
128     }
129     assert(globalMemCounter.checkOutstandingNewEq(0));
130     {
131         // Test that moving a function constructed from a reference wrapper
132         // is done without allocating.
133         DisableAllocationGuard g;
134         using Ref = std::reference_wrapper<A>;
135         A a;
136         Ref aref(a);
137         std::function<int(int)> f(aref);
138         assert(A::count == 1);
139         RTTI_ASSERT(f.target<A>() == nullptr);
140         RTTI_ASSERT(f.target<Ref>());
141 		LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
142 #if TEST_STD_VER > 17
143 		ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
144 #endif
145         std::function<int(int)> f2(std::move(f));
146         assert(A::count == 1);
147         RTTI_ASSERT(f2.target<A>() == nullptr);
148         RTTI_ASSERT(f2.target<Ref>());
149 #if defined(_LIBCPP_VERSION)
150         RTTI_ASSERT(f.target<Ref>()); // f is unchanged because the target is small
151 #endif
152     }
153     {
154         // Test that moving a function constructed from a function pointer
155         // is done without allocating
156         DisableAllocationGuard guard;
157         using Ptr = int(*)(int);
158         Ptr p = g;
159         std::function<int(int)> f(p);
160         RTTI_ASSERT(f.target<A>() == nullptr);
161         RTTI_ASSERT(f.target<Ptr>());
162 		LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
163 #if TEST_STD_VER > 17
164 		ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
165 #endif
166         std::function<int(int)> f2(std::move(f));
167         RTTI_ASSERT(f2.target<A>() == nullptr);
168         RTTI_ASSERT(f2.target<Ptr>());
169 #if defined(_LIBCPP_VERSION)
170         RTTI_ASSERT(f.target<Ptr>()); // f is unchanged because the target is small
171 #endif
172     }
173 #endif  // TEST_STD_VER >= 11
174 
175   return 0;
176 }
177