//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // std::function support for the "blocks" extension // UNSUPPORTED: c++03 // This test requires the Blocks runtime, which is (only?) available // on Darwin out-of-the-box. // REQUIRES: has-fblocks && darwin // ADDITIONAL_COMPILE_FLAGS: -fblocks #include #include #include #include #include #include "test_macros.h" #include "count_new.h" struct A { static int count; int id_; explicit A(int id) { ++count; id_ = id; } A(const A &a) { id_ = a.id_; ++count; } ~A() { id_ = -1; --count; } int operator()() const { return -1; } int operator()(int i) const { return i; } int operator()(int, int) const { return -2; } int operator()(int, int, int) const { return -3; } int id() const { return id_; } }; int A::count = 0; int g(int) { return 0; } int main(int, char**) { // swap { std::function f1 = g; std::function f2 = ^(int x) { return x + 1; }; assert(globalMemCounter.checkOutstandingNewEq(0)); RTTI_ASSERT(*f1.target() == g); RTTI_ASSERT(*f2.target() != 0); swap(f1, f2); assert(globalMemCounter.checkOutstandingNewEq(0)); RTTI_ASSERT(*f1.target() != 0); RTTI_ASSERT(*f2.target() == g); } // operator bool { std::function f; assert(!f); f = ^(int x) { return x+1; }; assert(f); } // operator() { std::function r1(^{ return 4; }); assert(r1() == 4); } { __block bool called = false; std::function r1(^{ called = true; }); r1(); assert(called); } { __block int param = 0; std::function r1(^(int x){ param = x; }); r1(4); assert(param == 4); } { std::function r1(^(int x){ return x + 4; }); assert(r1(3) == 7); } { __block int param1 = 0; __block int param2 = 0; std::function r1(^(int x, int y){ param1 = x; param2 = y; }); r1(3, 4); assert(param1 == 3); assert(param2 == 4); } { std::function r1(^(int x, int y){ return x + y; }); assert(r1(3, 4) == 7); } // swap { std::function f1 = A(999); std::function f2 = ^(int x) { return x + 1; }; assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); RTTI_ASSERT(f1.target()->id() == 999); RTTI_ASSERT((*f2.target())(13) == 14); f1.swap(f2); assert(A::count == 1); assert(globalMemCounter.checkOutstandingNewEq(1)); RTTI_ASSERT((*f1.target())(13) == 14); RTTI_ASSERT(f2.target()->id() == 999); } assert(globalMemCounter.checkOutstandingNewEq(0)); assert(A::count == 0); // operator== and operator!= { std::function f; assert(f == nullptr); assert(nullptr == f); f = ^(int x) { return x + 1; }; assert(f != nullptr); assert(nullptr != f); } // target { int (^block)(int) = Block_copy(^(int x) { return x + 1; }); std::function f = block; RTTI_ASSERT(*f.target() == block); RTTI_ASSERT(f.target() == 0); Block_release(block); } // target_type { std::function f = ^(int x) { return x + 1; }; RTTI_ASSERT(f.target_type() == typeid(int(^)(int))); } return 0; }