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 // std::function support for the "blocks" extension
10
11 // UNSUPPORTED: c++03
12
13 // This test requires the Blocks runtime, which is (only?) available
14 // on Darwin out-of-the-box.
15 // REQUIRES: has-fblocks && darwin
16
17 // RUN: %{build} -fblocks
18 // RUN: %{run}
19
20 #include <functional>
21 #include <cstdlib>
22 #include <cassert>
23
24 #include <Block.h>
25
26 #include "test_macros.h"
27 #include "count_new.h"
28
29
30 struct A {
31 static int count;
32 int id_;
AA33 explicit A(int id) { ++count; id_ = id; }
AA34 A(const A &a) { id_ = a.id_; ++count; }
~AA35 ~A() { id_ = -1; --count; }
operator ()A36 int operator()() const { return -1; }
operator ()A37 int operator()(int i) const { return i; }
operator ()A38 int operator()(int, int) const { return -2; }
operator ()A39 int operator()(int, int, int) const { return -3; }
idA40 int id() const { return id_; }
41 };
42
43 int A::count = 0;
44
g(int)45 int g(int) { return 0; }
46
main(int,char **)47 int main(int, char**)
48 {
49 // swap
50 {
51 std::function<int(int)> f1 = g;
52 std::function<int(int)> f2 = ^(int x) { return x + 1; };
53 assert(globalMemCounter.checkOutstandingNewEq(0));
54 RTTI_ASSERT(*f1.target<int(*)(int)>() == g);
55 RTTI_ASSERT(*f2.target<int(^)(int)>() != 0);
56 swap(f1, f2);
57 assert(globalMemCounter.checkOutstandingNewEq(0));
58 RTTI_ASSERT(*f1.target<int(^)(int)>() != 0);
59 RTTI_ASSERT(*f2.target<int(*)(int)>() == g);
60 }
61
62 // operator bool
63 {
64 std::function<int(int)> f;
65 assert(!f);
66 f = ^(int x) { return x+1; };
67 assert(f);
68 }
69
70 // operator()
71 {
72 std::function<int ()> r1(^{ return 4; });
73 assert(r1() == 4);
74 }
75 {
76 __block bool called = false;
77 std::function<void ()> r1(^{ called = true; });
78 r1();
79 assert(called);
80 }
81 {
82 __block int param = 0;
83 std::function<void (int)> r1(^(int x){ param = x; });
84 r1(4);
85 assert(param == 4);
86 }
87 {
88 std::function<int (int)> r1(^(int x){ return x + 4; });
89 assert(r1(3) == 7);
90 }
91 {
92 __block int param1 = 0;
93 __block int param2 = 0;
94 std::function<void (int, int)> r1(^(int x, int y){ param1 = x; param2 = y; });
95 r1(3, 4);
96 assert(param1 == 3);
97 assert(param2 == 4);
98 }
99 {
100 std::function<int (int, int)> r1(^(int x, int y){ return x + y; });
101 assert(r1(3, 4) == 7);
102 }
103
104 // swap
105 {
106 std::function<int(int)> f1 = A(999);
107 std::function<int(int)> f2 = ^(int x) { return x + 1; };
108 assert(A::count == 1);
109 assert(globalMemCounter.checkOutstandingNewEq(1));
110 RTTI_ASSERT(f1.target<A>()->id() == 999);
111 RTTI_ASSERT((*f2.target<int(^)(int)>())(13) == 14);
112 f1.swap(f2);
113 assert(A::count == 1);
114 assert(globalMemCounter.checkOutstandingNewEq(1));
115 RTTI_ASSERT((*f1.target<int(^)(int)>())(13) == 14);
116 RTTI_ASSERT(f2.target<A>()->id() == 999);
117 }
118 assert(globalMemCounter.checkOutstandingNewEq(0));
119 assert(A::count == 0);
120
121 // operator== and operator!=
122 {
123 std::function<int(int)> f;
124 assert(f == nullptr);
125 assert(nullptr == f);
126 f = ^(int x) { return x + 1; };
127 assert(f != nullptr);
128 assert(nullptr != f);
129 }
130
131 // target
132 {
133 int (^block)(int) = Block_copy(^(int x) { return x + 1; });
134 std::function<int(int)> f = block;
135 RTTI_ASSERT(*f.target<int(^)(int)>() == block);
136 RTTI_ASSERT(f.target<int(*)(int)>() == 0);
137 Block_release(block);
138 }
139
140 // target_type
141 {
142 std::function<int(int)> f = ^(int x) { return x + 1; };
143 RTTI_ASSERT(f.target_type() == typeid(int(^)(int)));
144 }
145
146 return 0;
147 }
148