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