Eric Fiselier | 8e03071 | 2015-08-18 19:41:51 +0000 | [diff] [blame] | 1 | //===----------------------------------------------------------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is dual licensed under the MIT and the University of Illinois Open |
| 6 | // Source Licenses. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | // <functional> |
| 11 | |
| 12 | // class function<R(ArgTypes...)> |
| 13 | |
| 14 | // function(Fp); |
| 15 | |
| 16 | // Ensure that __not_null works for all function types. |
| 17 | // See https://llvm.org/bugs/show_bug.cgi?id=23589 |
| 18 | |
| 19 | //------------------------------------------------------------------------------ |
| 20 | // TESTING std::function<...>::__not_null(Callable) |
| 21 | // |
| 22 | // Concerns: |
| 23 | // 1) The call __not_null(Callable) is well formed and correct for each |
| 24 | // possible 'Callable' type category. These categories include: |
| 25 | // 1a) function pointers |
| 26 | // 1b) member function pointer |
| 27 | // 1c) member data pointer |
| 28 | // 1d) callable class type |
| 29 | // 1e) lambdas |
| 30 | // Categories 1a, 1b, and 1c are 'Nullable' types. Only objects of these |
| 31 | // types can be null. The other categories are not tested here. |
| 32 | // 3) '__not_null(Callable)' is well formed when the call signature includes |
| 33 | // varargs. |
| 34 | // 4) '__not_null(Callable)' works for Callable types with all aritys less |
| 35 | // than or equal to 3 in C++03. |
| 36 | // 5) '__not_null(Callable)' works when 'Callable' is a member function |
| 37 | // pointer to a cv or ref qualified function type. |
| 38 | // |
| 39 | // Plan: |
| 40 | // 1 For categories 1a, 1b and 1c define a set of |
| 41 | // 'Callable' objects for this category. This set should include examples |
| 42 | // of arity 0, 1, 2 and possible 3 including versions with varargs as the |
| 43 | // last parameter. |
| 44 | // |
| 45 | // 2 For each 'Callable' object in categories 1a, 1b and 1c do the following. |
| 46 | // |
| 47 | // 1 Define a type 'std::function<Sig>' as 'F' where 'Sig' is compatible with |
| 48 | // the signature of the 'Callable' object. |
| 49 | // |
| 50 | // 2 Create an object of type 'F' using a null pointer of type 'Callable'. |
| 51 | // Check that 'F.target<Callable>()' is null. |
| 52 | // |
| 53 | // 3 Create an object of type 'F' that is not null. Check that |
| 54 | // 'F.target<Callable>()' is not null and is equal to the original |
| 55 | // argument. |
| 56 | |
| 57 | #include <functional> |
| 58 | #include <type_traits> |
| 59 | #include <cassert> |
| 60 | |
| 61 | #include "test_macros.h" |
| 62 | |
| 63 | /////////////////////////////////////////////////////////////////////////////// |
| 64 | int foo() { return 42; } |
| 65 | int foo(int) { return 42; } |
| 66 | int foo(int, int) { return 42; } |
| 67 | int foo(int, int, int) { return 42; } |
| 68 | |
| 69 | int foo(...) { return 42; } |
| 70 | int foo(int, ...) { return 42; } |
| 71 | int foo(int, int, ...) { return 42; } |
| 72 | int foo(int, int, int, ...) { return 42; } |
| 73 | |
| 74 | /////////////////////////////////////////////////////////////////////////////// |
| 75 | struct MemFun03 { |
| 76 | int foo() { return 42; } |
| 77 | int foo() const { return 42; } |
| 78 | int foo() volatile { return 42; } |
| 79 | int foo() const volatile { return 42; } |
| 80 | |
| 81 | int foo(int) { return 42; } |
| 82 | int foo(int) const { return 42; } |
| 83 | int foo(int) volatile { return 42; } |
| 84 | int foo(int) const volatile { return 42; } |
| 85 | |
| 86 | int foo(int, int) { return 42; } |
| 87 | int foo(int, int) const { return 42; } |
| 88 | int foo(int, int) volatile { return 42; } |
| 89 | int foo(int, int) const volatile { return 42; } |
| 90 | |
| 91 | int foo(int, int, int) { return 42; } |
| 92 | int foo(int, int, int) const { return 42; } |
| 93 | int foo(int, int, int) volatile { return 42; } |
| 94 | int foo(int, int, int) const volatile { return 42; } |
| 95 | |
| 96 | int foo(...) { return 42; } |
| 97 | int foo(...) const { return 42; } |
| 98 | int foo(...) volatile { return 42; } |
| 99 | int foo(...) const volatile { return 42; } |
| 100 | |
| 101 | int foo(int, ...) { return 42; } |
| 102 | int foo(int, ...) const { return 42; } |
| 103 | int foo(int, ...) volatile { return 42; } |
| 104 | int foo(int, ...) const volatile { return 42; } |
| 105 | |
| 106 | int foo(int, int, ...) { return 42; } |
| 107 | int foo(int, int, ...) const { return 42; } |
| 108 | int foo(int, int, ...) volatile { return 42; } |
| 109 | int foo(int, int, ...) const volatile { return 42; } |
| 110 | |
| 111 | int foo(int, int, int, ...) { return 42; } |
| 112 | int foo(int, int, int, ...) const { return 42; } |
| 113 | int foo(int, int, int, ...) volatile { return 42; } |
| 114 | int foo(int, int, int, ...) const volatile { return 42; } |
| 115 | }; |
| 116 | |
| 117 | #if TEST_STD_VER >= 11 |
| 118 | struct MemFun11 { |
| 119 | int foo() & { return 42; } |
| 120 | int foo() const & { return 42; } |
| 121 | int foo() volatile & { return 42; } |
| 122 | int foo() const volatile & { return 42; } |
| 123 | |
| 124 | int foo(...) & { return 42; } |
| 125 | int foo(...) const & { return 42; } |
| 126 | int foo(...) volatile & { return 42; } |
| 127 | int foo(...) const volatile & { return 42; } |
| 128 | |
| 129 | int foo() && { return 42; } |
| 130 | int foo() const && { return 42; } |
| 131 | int foo() volatile && { return 42; } |
| 132 | int foo() const volatile && { return 42; } |
| 133 | |
| 134 | int foo(...) && { return 42; } |
| 135 | int foo(...) const && { return 42; } |
| 136 | int foo(...) volatile && { return 42; } |
| 137 | int foo(...) const volatile && { return 42; } |
| 138 | }; |
| 139 | #endif // TEST_STD_VER >= 11 |
| 140 | |
| 141 | struct MemData { |
| 142 | int foo; |
| 143 | }; |
| 144 | |
| 145 | // Create a non-null free function by taking the address of |
| 146 | // &static_cast<Tp&>(foo); |
| 147 | template <class Tp> |
| 148 | struct Creator { |
| 149 | static Tp create() { |
| 150 | return &foo; |
| 151 | } |
| 152 | }; |
| 153 | |
| 154 | // Create a non-null member pointer. |
| 155 | template <class Ret, class Class> |
| 156 | struct Creator<Ret Class::*> { |
| 157 | typedef Ret Class::*ReturnType; |
| 158 | static ReturnType create() { |
| 159 | return &Class::foo; |
| 160 | } |
| 161 | }; |
| 162 | |
| 163 | template <class TestFn, class Fn> |
| 164 | void test_imp() { |
| 165 | { // Check that the null value is detected |
| 166 | TestFn tf = nullptr; |
| 167 | std::function<Fn> f = tf; |
| 168 | assert(f.template target<TestFn>() == nullptr); |
| 169 | } |
| 170 | { // Check that the non-null value is detected. |
| 171 | TestFn tf = Creator<TestFn>::create(); |
| 172 | assert(tf != nullptr); |
| 173 | std::function<Fn> f = tf; |
| 174 | assert(f.template target<TestFn>() != nullptr); |
| 175 | assert(*f.template target<TestFn>() == tf); |
| 176 | } |
| 177 | } |
| 178 | |
| 179 | void test_func() { |
| 180 | test_imp<int(*)(), int()>(); |
| 181 | test_imp<int(*)(...), int()>(); |
| 182 | test_imp<int(*)(int), int(int)>(); |
| 183 | test_imp<int(*)(int, ...), int(int)>(); |
| 184 | test_imp<int(*)(int, int), int(int, int)>(); |
| 185 | test_imp<int(*)(int, int, ...), int(int, int)>(); |
| 186 | test_imp<int(*)(int, int, int), int(int, int, int)>(); |
| 187 | test_imp<int(*)(int, int, int, ...), int(int, int, int)>(); |
| 188 | } |
| 189 | |
| 190 | void test_mf() { |
| 191 | test_imp<int(MemFun03::*)(), int(MemFun03&)>(); |
| 192 | test_imp<int(MemFun03::*)(...), int(MemFun03&)>(); |
| 193 | test_imp<int(MemFun03::*)() const, int(MemFun03&)>(); |
| 194 | test_imp<int(MemFun03::*)(...) const, int(MemFun03&)>(); |
| 195 | test_imp<int(MemFun03::*)() volatile, int(MemFun03&)>(); |
| 196 | test_imp<int(MemFun03::*)(...) volatile, int(MemFun03&)>(); |
| 197 | test_imp<int(MemFun03::*)() const volatile, int(MemFun03&)>(); |
| 198 | test_imp<int(MemFun03::*)(...) const volatile, int(MemFun03&)>(); |
| 199 | |
| 200 | test_imp<int(MemFun03::*)(int), int(MemFun03&, int)>(); |
| 201 | test_imp<int(MemFun03::*)(int, ...), int(MemFun03&, int)>(); |
| 202 | test_imp<int(MemFun03::*)(int) const, int(MemFun03&, int)>(); |
| 203 | test_imp<int(MemFun03::*)(int, ...) const, int(MemFun03&, int)>(); |
| 204 | test_imp<int(MemFun03::*)(int) volatile, int(MemFun03&, int)>(); |
| 205 | test_imp<int(MemFun03::*)(int, ...) volatile, int(MemFun03&, int)>(); |
| 206 | test_imp<int(MemFun03::*)(int) const volatile, int(MemFun03&, int)>(); |
| 207 | test_imp<int(MemFun03::*)(int, ...) const volatile, int(MemFun03&, int)>(); |
| 208 | |
| 209 | test_imp<int(MemFun03::*)(int, int), int(MemFun03&, int, int)>(); |
| 210 | test_imp<int(MemFun03::*)(int, int, ...), int(MemFun03&, int, int)>(); |
| 211 | test_imp<int(MemFun03::*)(int, int) const, int(MemFun03&, int, int)>(); |
| 212 | test_imp<int(MemFun03::*)(int, int, ...) const, int(MemFun03&, int, int)>(); |
| 213 | test_imp<int(MemFun03::*)(int, int) volatile, int(MemFun03&, int, int)>(); |
| 214 | test_imp<int(MemFun03::*)(int, int, ...) volatile, int(MemFun03&, int, int)>(); |
| 215 | test_imp<int(MemFun03::*)(int, int) const volatile, int(MemFun03&, int, int)>(); |
| 216 | test_imp<int(MemFun03::*)(int, int, ...) const volatile, int(MemFun03&, int, int)>(); |
| 217 | |
| 218 | #if TEST_STD_VER >= 11 |
| 219 | test_imp<int(MemFun11::*)() &, int(MemFun11&)>(); |
| 220 | test_imp<int(MemFun11::*)(...) &, int(MemFun11&)>(); |
| 221 | test_imp<int(MemFun11::*)() const &, int(MemFun11&)>(); |
| 222 | test_imp<int(MemFun11::*)(...) const &, int(MemFun11&)>(); |
| 223 | test_imp<int(MemFun11::*)() volatile &, int(MemFun11&)>(); |
| 224 | test_imp<int(MemFun11::*)(...) volatile &, int(MemFun11&)>(); |
| 225 | test_imp<int(MemFun11::*)() const volatile &, int(MemFun11&)>(); |
| 226 | test_imp<int(MemFun11::*)(...) const volatile &, int(MemFun11&)>(); |
| 227 | |
| 228 | test_imp<int(MemFun11::*)() &&, int(MemFun11&&)>(); |
| 229 | test_imp<int(MemFun11::*)(...) &&, int(MemFun11&&)>(); |
| 230 | test_imp<int(MemFun11::*)() const &&, int(MemFun11&&)>(); |
| 231 | test_imp<int(MemFun11::*)(...) const &&, int(MemFun11&&)>(); |
| 232 | test_imp<int(MemFun11::*)() volatile &&, int(MemFun11&&)>(); |
| 233 | test_imp<int(MemFun11::*)(...) volatile &&, int(MemFun11&&)>(); |
| 234 | test_imp<int(MemFun11::*)() const volatile &&, int(MemFun11&&)>(); |
| 235 | test_imp<int(MemFun11::*)(...) const volatile &&, int(MemFun11&&)>(); |
| 236 | #endif |
| 237 | } |
| 238 | |
| 239 | void test_md() { |
| 240 | test_imp<int MemData::*, int(MemData&)>(); |
| 241 | } |
| 242 | |
| 243 | int main() { |
| 244 | test_func(); |
| 245 | test_mf(); |
| 246 | test_md(); |
| 247 | } |