Fix test failures introduced by PR #113697 (#116941)
[llvm-project.git] / llvm / unittests / ADT / FunctionExtrasTest.cpp
blob9809a92daac72468ed5bbd1762798523c2c3d628
1 //===- FunctionExtrasTest.cpp - Unit tests for function type erasure ------===//
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 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/FunctionExtras.h"
10 #include "CountCopyAndMove.h"
11 #include "gtest/gtest.h"
13 #include <memory>
14 #include <type_traits>
16 using namespace llvm;
18 namespace {
20 TEST(UniqueFunctionTest, Basic) {
21 unique_function<int(int, int)> Sum = [](int A, int B) { return A + B; };
22 EXPECT_EQ(Sum(1, 2), 3);
24 unique_function<int(int, int)> Sum2 = std::move(Sum);
25 EXPECT_EQ(Sum2(1, 2), 3);
27 unique_function<int(int, int)> Sum3 = [](int A, int B) { return A + B; };
28 Sum2 = std::move(Sum3);
29 EXPECT_EQ(Sum2(1, 2), 3);
31 Sum2 = unique_function<int(int, int)>([](int A, int B) { return A + B; });
32 EXPECT_EQ(Sum2(1, 2), 3);
34 // Explicit self-move test.
35 *&Sum2 = std::move(Sum2);
36 EXPECT_EQ(Sum2(1, 2), 3);
38 Sum2 = unique_function<int(int, int)>();
39 EXPECT_FALSE(Sum2);
41 // Make sure we can forward through l-value reference parameters.
42 unique_function<void(int &)> Inc = [](int &X) { ++X; };
43 int X = 42;
44 Inc(X);
45 EXPECT_EQ(X, 43);
47 // Make sure we can forward through r-value reference parameters with
48 // move-only types.
49 unique_function<int(std::unique_ptr<int> &&)> ReadAndDeallocByRef =
50 [](std::unique_ptr<int> &&Ptr) {
51 int V = *Ptr;
52 Ptr.reset();
53 return V;
55 std::unique_ptr<int> Ptr{new int(13)};
56 EXPECT_EQ(ReadAndDeallocByRef(std::move(Ptr)), 13);
57 EXPECT_FALSE((bool)Ptr);
59 // Make sure we can pass a move-only temporary as opposed to a local variable.
60 EXPECT_EQ(ReadAndDeallocByRef(std::unique_ptr<int>(new int(42))), 42);
62 // Make sure we can pass a move-only type by-value.
63 unique_function<int(std::unique_ptr<int>)> ReadAndDeallocByVal =
64 [](std::unique_ptr<int> Ptr) {
65 int V = *Ptr;
66 Ptr.reset();
67 return V;
69 Ptr.reset(new int(13));
70 EXPECT_EQ(ReadAndDeallocByVal(std::move(Ptr)), 13);
71 EXPECT_FALSE((bool)Ptr);
73 EXPECT_EQ(ReadAndDeallocByVal(std::unique_ptr<int>(new int(42))), 42);
76 TEST(UniqueFunctionTest, Captures) {
77 long A = 1, B = 2, C = 3, D = 4, E = 5;
79 unique_function<long()> Tmp;
81 unique_function<long()> C1 = [A]() { return A; };
82 EXPECT_EQ(C1(), 1);
83 Tmp = std::move(C1);
84 EXPECT_EQ(Tmp(), 1);
86 unique_function<long()> C2 = [A, B]() { return A + B; };
87 EXPECT_EQ(C2(), 3);
88 Tmp = std::move(C2);
89 EXPECT_EQ(Tmp(), 3);
91 unique_function<long()> C3 = [A, B, C]() { return A + B + C; };
92 EXPECT_EQ(C3(), 6);
93 Tmp = std::move(C3);
94 EXPECT_EQ(Tmp(), 6);
96 unique_function<long()> C4 = [A, B, C, D]() { return A + B + C + D; };
97 EXPECT_EQ(C4(), 10);
98 Tmp = std::move(C4);
99 EXPECT_EQ(Tmp(), 10);
101 unique_function<long()> C5 = [A, B, C, D, E]() { return A + B + C + D + E; };
102 EXPECT_EQ(C5(), 15);
103 Tmp = std::move(C5);
104 EXPECT_EQ(Tmp(), 15);
107 TEST(UniqueFunctionTest, MoveOnly) {
108 struct SmallCallable {
109 std::unique_ptr<int> A{new int(1)};
111 int operator()(int B) { return *A + B; }
113 unique_function<int(int)> Small = SmallCallable();
114 EXPECT_EQ(Small(2), 3);
115 unique_function<int(int)> Small2 = std::move(Small);
116 EXPECT_EQ(Small2(2), 3);
118 struct LargeCallable {
119 std::unique_ptr<int> A{new int(1)};
120 std::unique_ptr<int> B{new int(2)};
121 std::unique_ptr<int> C{new int(3)};
122 std::unique_ptr<int> D{new int(4)};
123 std::unique_ptr<int> E{new int(5)};
125 int operator()() { return *A + *B + *C + *D + *E; }
127 unique_function<int()> Large = LargeCallable();
128 EXPECT_EQ(Large(), 15);
129 unique_function<int()> Large2 = std::move(Large);
130 EXPECT_EQ(Large2(), 15);
133 TEST(UniqueFunctionTest, CountForwardingCopies) {
134 struct CopyCounter {
135 int &CopyCount;
137 CopyCounter(int &CopyCount) : CopyCount(CopyCount) {}
138 CopyCounter(const CopyCounter &Arg) : CopyCount(Arg.CopyCount) {
139 ++CopyCount;
143 unique_function<void(CopyCounter)> ByValF = [](CopyCounter) {};
144 int CopyCount = 0;
145 ByValF(CopyCounter(CopyCount));
146 EXPECT_EQ(1, CopyCount);
148 CopyCount = 0;
150 CopyCounter Counter{CopyCount};
151 ByValF(Counter);
153 EXPECT_EQ(2, CopyCount);
155 // Check that we don't generate a copy at all when we can bind a reference all
156 // the way down, even if that reference could *in theory* allow copies.
157 unique_function<void(const CopyCounter &)> ByRefF = [](const CopyCounter &) {
159 CopyCount = 0;
160 ByRefF(CopyCounter(CopyCount));
161 EXPECT_EQ(0, CopyCount);
163 CopyCount = 0;
165 CopyCounter Counter{CopyCount};
166 ByRefF(Counter);
168 EXPECT_EQ(0, CopyCount);
170 // If we use a reference, we can make a stronger guarantee that *no* copy
171 // occurs.
172 struct Uncopyable {
173 Uncopyable() = default;
174 Uncopyable(const Uncopyable &) = delete;
176 unique_function<void(const Uncopyable &)> UncopyableF =
177 [](const Uncopyable &) {};
178 UncopyableF(Uncopyable());
179 Uncopyable X;
180 UncopyableF(X);
183 TEST(UniqueFunctionTest, CountForwardingMoves) {
184 struct MoveCounter {
185 int &MoveCount;
187 MoveCounter(int &MoveCount) : MoveCount(MoveCount) {}
188 MoveCounter(MoveCounter &&Arg) : MoveCount(Arg.MoveCount) { ++MoveCount; }
191 unique_function<void(MoveCounter)> ByValF = [](MoveCounter) {};
192 int MoveCount = 0;
193 ByValF(MoveCounter(MoveCount));
194 EXPECT_EQ(1, MoveCount);
196 MoveCount = 0;
198 MoveCounter Counter{MoveCount};
199 ByValF(std::move(Counter));
201 EXPECT_EQ(2, MoveCount);
203 // Check that when we use an r-value reference we get no spurious copies.
204 unique_function<void(MoveCounter &&)> ByRefF = [](MoveCounter &&) {};
205 MoveCount = 0;
206 ByRefF(MoveCounter(MoveCount));
207 EXPECT_EQ(0, MoveCount);
209 MoveCount = 0;
211 MoveCounter Counter{MoveCount};
212 ByRefF(std::move(Counter));
214 EXPECT_EQ(0, MoveCount);
216 // If we use an r-value reference we can in fact make a stronger guarantee
217 // with an unmovable type.
218 struct Unmovable {
219 Unmovable() = default;
220 Unmovable(Unmovable &&) = delete;
222 unique_function<void(const Unmovable &)> UnmovableF = [](const Unmovable &) {
224 UnmovableF(Unmovable());
225 Unmovable X;
226 UnmovableF(X);
229 TEST(UniqueFunctionTest, Const) {
230 // Can assign from const lambda.
231 unique_function<int(int) const> Plus2 = [X(std::make_unique<int>(2))](int Y) {
232 return *X + Y;
234 EXPECT_EQ(5, Plus2(3));
236 // Can call through a const ref.
237 const auto &Plus2Ref = Plus2;
238 EXPECT_EQ(5, Plus2Ref(3));
240 // Can move-construct and assign.
241 unique_function<int(int) const> Plus2A = std::move(Plus2);
242 EXPECT_EQ(5, Plus2A(3));
243 unique_function<int(int) const> Plus2B;
244 Plus2B = std::move(Plus2A);
245 EXPECT_EQ(5, Plus2B(3));
247 // Can convert to non-const function type, but not back.
248 unique_function<int(int)> Plus2C = std::move(Plus2B);
249 EXPECT_EQ(5, Plus2C(3));
251 // Overloaded call operator correctly resolved.
252 struct ChooseCorrectOverload {
253 StringRef operator()() { return "non-const"; }
254 StringRef operator()() const { return "const"; }
256 unique_function<StringRef()> ChooseMutable = ChooseCorrectOverload();
257 ChooseCorrectOverload A;
258 EXPECT_EQ("non-const", ChooseMutable());
259 EXPECT_EQ("non-const", A());
260 unique_function<StringRef() const> ChooseConst = ChooseCorrectOverload();
261 const ChooseCorrectOverload &X = A;
262 EXPECT_EQ("const", ChooseConst());
263 EXPECT_EQ("const", X());
266 // Test that overloads on unique_functions are resolved as expected.
267 std::string returns(StringRef) { return "not a function"; }
268 std::string returns(unique_function<double()> F) { return "number"; }
269 std::string returns(unique_function<StringRef()> F) { return "string"; }
271 TEST(UniqueFunctionTest, SFINAE) {
272 EXPECT_EQ("not a function", returns("boo!"));
273 EXPECT_EQ("number", returns([] { return 42; }));
274 EXPECT_EQ("string", returns([] { return "hello"; }));
277 // A forward declared type, and a templated type.
278 class Incomplete;
279 template <typename T> class Templated { T A; };
281 // Check that we can define unique_function that have references to
282 // incomplete types, even if those types are templated over an
283 // incomplete type.
284 TEST(UniqueFunctionTest, IncompleteTypes) {
285 unique_function<void(Templated<Incomplete> &&)>
286 IncompleteArgumentRValueReference;
287 unique_function<void(Templated<Incomplete> &)>
288 IncompleteArgumentLValueReference;
289 unique_function<void(Templated<Incomplete> *)> IncompleteArgumentPointer;
290 unique_function<Templated<Incomplete> &()> IncompleteResultLValueReference;
291 unique_function<Templated<Incomplete> && ()> IncompleteResultRValueReference2;
292 unique_function<Templated<Incomplete> *()> IncompleteResultPointer;
295 // Incomplete function returning an incomplete type
296 Incomplete incompleteFunction();
297 const Incomplete incompleteFunctionConst();
299 // Check that we can assign a callable to a unique_function when the
300 // callable return value is incomplete.
301 TEST(UniqueFunctionTest, IncompleteCallableType) {
302 unique_function<Incomplete()> IncompleteReturnInCallable{incompleteFunction};
303 unique_function<const Incomplete()> IncompleteReturnInCallableConst{
304 incompleteFunctionConst};
305 unique_function<const Incomplete()> IncompleteReturnInCallableConstConversion{
306 incompleteFunction};
309 // Define the incomplete function
310 class Incomplete {};
311 Incomplete incompleteFunction() { return {}; }
312 const Incomplete incompleteFunctionConst() { return {}; }
314 // Check that we can store a pointer-sized payload inline in the unique_function.
315 TEST(UniqueFunctionTest, InlineStorageWorks) {
316 // We do assume a couple of implementation details of the unique_function here:
317 // - It can store certain small-enough payload inline
318 // - Inline storage size is at least >= sizeof(void*)
319 void *ptr = nullptr;
320 unique_function<void(void *)> UniqueFunctionWithInlineStorage{
321 [ptr](void *self) {
322 auto mid = reinterpret_cast<uintptr_t>(&ptr);
323 auto beg = reinterpret_cast<uintptr_t>(self);
324 auto end = reinterpret_cast<uintptr_t>(self) +
325 sizeof(unique_function<void(void *)>);
326 // Make sure the address of the captured pointer lies somewhere within
327 // the unique_function object.
328 EXPECT_TRUE(mid >= beg && mid < end);
330 UniqueFunctionWithInlineStorage(&UniqueFunctionWithInlineStorage);
333 // Check that the moved-from captured state is properly destroyed during
334 // move construction/assignment.
335 TEST(UniqueFunctionTest, MovedFromStateIsDestroyedCorrectly) {
336 CountCopyAndMove::ResetCounts();
338 unique_function<void()> CapturingFunction{
339 [Counter = CountCopyAndMove{}] {}};
340 unique_function<void()> CapturingFunctionMoved{
341 std::move(CapturingFunction)};
343 EXPECT_EQ(CountCopyAndMove::TotalConstructions(),
344 CountCopyAndMove::Destructions);
347 } // anonymous namespace