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 #ifndef INVOKE_HELPERS_H 11 #define INVOKE_HELPERS_H 12 13 #include <type_traits> 14 #include <cassert> 15 #include <functional> 16 17 #include "test_macros.h" 18 19 template <int I> 20 struct Int : public std::integral_constant<int, I> {}; 21 22 template <bool P> 23 struct Bool : public std::integral_constant<bool, P> {}; 24 25 struct Q_None { 26 template <class T> 27 struct apply { typedef T type; }; 28 }; 29 30 struct Q_Const { 31 template <class T> 32 struct apply { typedef T const type; }; 33 }; 34 35 struct Q_Volatile { 36 template <class T> 37 struct apply { typedef T volatile type; }; 38 }; 39 40 struct Q_CV { 41 template <class T> 42 struct apply { typedef T const volatile type; }; 43 }; 44 45 // Caster - A functor object that performs cv-qualifier and value category 46 // conversions. 47 // QualTag - A metafunction type that applies cv-qualifiers to its argument. 48 // RValue - True if the resulting object should be an RValue reference. 49 // False otherwise. 50 template <class QualTag, bool RValue = false> 51 struct Caster { 52 template <class T> 53 struct apply { 54 typedef typename std::remove_reference<T>::type RawType; 55 typedef typename QualTag::template apply<RawType>::type CVType; 56 #if TEST_STD_VER >= 11 57 typedef typename std::conditional<RValue, 58 CVType&&, CVType& 59 >::type type; 60 #else 61 typedef CVType& type; 62 #endif 63 }; 64 65 template <class T> 66 typename apply<T>::type 67 operator()(T& obj) const { 68 typedef typename apply<T>::type OutType; 69 return static_cast<OutType>(obj); 70 } 71 }; 72 73 typedef Caster<Q_None> LValueCaster; 74 typedef Caster<Q_Const> ConstCaster; 75 typedef Caster<Q_Volatile> VolatileCaster; 76 typedef Caster<Q_CV> CVCaster; 77 typedef Caster<Q_None, true> MoveCaster; 78 typedef Caster<Q_Const, true> MoveConstCaster; 79 typedef Caster<Q_Volatile, true> MoveVolatileCaster; 80 typedef Caster<Q_CV, true> MoveCVCaster; 81 82 83 template <class Tp> 84 Tp const& makeConst(Tp& ref) { return ref; } 85 86 template <class Tp> 87 Tp const* makeConst(Tp* ptr) { return ptr; } 88 89 template <class Tp> 90 std::reference_wrapper<const Tp> makeConst(std::reference_wrapper<Tp>& ref) { 91 return std::reference_wrapper<const Tp>(ref.get()); 92 } 93 94 template <class Tp> 95 Tp volatile& makeVolatile(Tp& ref) { return ref; } 96 97 template <class Tp> 98 Tp volatile* makeVolatile(Tp* ptr) { return ptr; } 99 100 template <class Tp> 101 std::reference_wrapper<volatile Tp> makeVolatile(std::reference_wrapper<Tp>& ref) { 102 return std::reference_wrapper<volatile Tp>(ref.get()); 103 } 104 105 template <class Tp> 106 Tp const volatile& makeCV(Tp& ref) { return ref; } 107 108 template <class Tp> 109 Tp const volatile* makeCV(Tp* ptr) { return ptr; } 110 111 template <class Tp> 112 std::reference_wrapper<const volatile Tp> makeCV(std::reference_wrapper<Tp>& ref) { 113 return std::reference_wrapper<const volatile Tp>(ref.get()); 114 } 115 116 // A shorter name for 'static_cast' 117 template <class QualType, class Tp> 118 QualType C_(Tp& v) { return static_cast<QualType>(v); }; 119 120 //============================================================================== 121 // ArgType - A non-copyable type intended to be used as a dummy argument type 122 // to test functions. 123 struct ArgType { 124 int value; 125 explicit ArgType(int val = 0) : value(val) {} 126 private: 127 ArgType(ArgType const&); 128 ArgType& operator=(ArgType const&); 129 }; 130 131 //============================================================================== 132 // DerivedFromBase - A type that derives from its template argument 'Base' 133 template <class Base> 134 struct DerivedFromType : public Base { 135 DerivedFromType() : Base() {} 136 template <class Tp> 137 explicit DerivedFromType(Tp const& t) : Base(t) {} 138 }; 139 140 //============================================================================== 141 // DerefToType - A type that dereferences to its template argument 'To'. 142 // The cv-ref qualifiers of the 'DerefToType' object do not propagate 143 // to the resulting 'To' object. 144 template <class To> 145 struct DerefToType { 146 To object; 147 148 DerefToType() {} 149 150 template <class Up> 151 explicit DerefToType(Up const& val) : object(val) {} 152 153 To& operator*() const volatile { return const_cast<To&>(object); } 154 }; 155 156 //============================================================================== 157 // DerefPropToType - A type that dereferences to its template argument 'To'. 158 // The cv-ref qualifiers of the 'DerefPropToType' object propagate 159 // to the resulting 'To' object. 160 template <class To> 161 struct DerefPropType { 162 To object; 163 164 DerefPropType() {} 165 166 template <class Up> 167 explicit DerefPropType(Up const& val) : object(val) {} 168 169 #if TEST_STD_VER < 11 170 To& operator*() { return object; } 171 To const& operator*() const { return object; } 172 To volatile& operator*() volatile { return object; } 173 To const volatile& operator*() const volatile { return object; } 174 #else 175 To& operator*() & { return object; } 176 To const& operator*() const & { return object; } 177 To volatile& operator*() volatile & { return object; } 178 To const volatile& operator*() const volatile & { return object; } 179 To&& operator*() && { return static_cast<To &&>(object); } 180 To const&& operator*() const && { return static_cast<To const&&>(object); } 181 To volatile&& operator*() volatile && { return static_cast<To volatile&&>(object); } 182 To const volatile&& operator*() const volatile && { return static_cast<To const volatile&&>(object); } 183 #endif 184 }; 185 186 //============================================================================== 187 // MethodID - A type that uniquely identifies a member function for a class. 188 // This type is used to communicate between the member functions being tested 189 // and the tests invoking them. 190 // - Test methods should call 'setUncheckedCall()' whenever they are invoked. 191 // - Tests consume the unchecked call using checkCall(<return-value>)` to assert 192 // that the method has been called and that the return value of `__invoke` 193 // matches what the method actually returned. 194 template <class T> 195 struct MethodID { 196 typedef void* IDType; 197 198 static int dummy; // A dummy memory location. 199 static void* id; // The "ID" is the value of this pointer. 200 static bool unchecked_call; // Has a call happened that has not been checked. 201 202 static void*& setUncheckedCall() { 203 assert(unchecked_call == false); 204 unchecked_call = true; 205 return id; 206 } 207 208 static bool checkCalled(void*& return_value) { 209 bool old = unchecked_call; 210 unchecked_call = false; 211 return old && id == return_value && &id == &return_value; 212 } 213 }; 214 215 template <class T> int MethodID<T>::dummy = 0; 216 template <class T> void* MethodID<T>::id = (void*)&MethodID<T>::dummy; 217 template <class T> bool MethodID<T>::unchecked_call = false; 218 219 220 //============================================================================== 221 // FunctionPtrID - Like MethodID but for free function pointers. 222 template <class T, T*> 223 struct FunctionPtrID { 224 static int dummy; // A dummy memory location. 225 static void* id; // The "ID" is the value of this pointer. 226 static bool unchecked_call; // Has a call happened that has not been checked. 227 228 static void*& setUncheckedCall() { 229 assert(unchecked_call == false); 230 unchecked_call = true; 231 return id; 232 } 233 234 static bool checkCalled(void*& return_value) { 235 bool old = unchecked_call; 236 unchecked_call = false; 237 return old && id == return_value && &id == &return_value; 238 } 239 }; 240 241 template <class T, T* Ptr> int FunctionPtrID<T, Ptr>::dummy = 0; 242 template <class T, T* Ptr> void* FunctionPtrID<T, Ptr>::id = (void*)&FunctionPtrID<T, Ptr>::dummy; 243 template <class T, T* Ptr> bool FunctionPtrID<T, Ptr>::unchecked_call = false; 244 245 //============================================================================== 246 // BasicTest - The basic test structure for everything except 247 // member object pointers. 248 // ID - The "Function Identifier" type used either MethodID or FunctionPtrID. 249 // Arity - The Arity of the call signature. 250 // ObjectCaster - The object transformation functor type. 251 // ArgCaster - The extra argument transformation functor type. 252 template <class ID, int Arity, class ObjectCaster = LValueCaster, 253 class ArgCaster = LValueCaster> 254 struct BasicTest { 255 template <class ObjectT> 256 void runTest(ObjectT& object) { 257 Int<Arity> A; 258 runTestImp(A, object); 259 } 260 261 template <class MethodPtr, class ObjectT> 262 void runTest(MethodPtr ptr, ObjectT& object) { 263 Int<Arity> A; 264 runTestImp(A, ptr, object); 265 } 266 267 private: 268 typedef void*& CallRet; 269 ObjectCaster object_cast; 270 ArgCaster arg_cast; 271 ArgType a0, a1, a2; 272 273 //========================================================================== 274 // BULLET 1, 2 AND 3 TEST METHODS 275 //========================================================================== 276 template <class MethodPtr, class ObjectT> 277 void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) { 278 { 279 static_assert((std::is_same< 280 decltype(std::__invoke(ptr, object_cast(object))) 281 , CallRet>::value), ""); 282 assert(ID::unchecked_call == false); 283 CallRet ret = std::__invoke(ptr, object_cast(object)); 284 assert(ID::checkCalled(ret)); 285 } 286 #if TEST_STD_VER >= 11 287 { 288 static_assert((std::is_same< 289 decltype(std::__invoke_constexpr(ptr, object_cast(object))) 290 , CallRet>::value), ""); 291 assert(ID::unchecked_call == false); 292 CallRet ret = std::__invoke_constexpr(ptr, object_cast(object)); 293 assert(ID::checkCalled(ret)); 294 } 295 #endif 296 } 297 298 template <class MethodPtr, class ObjectT> 299 void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) { 300 { 301 static_assert((std::is_same< 302 decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0))) 303 , CallRet>::value), ""); 304 assert(ID::unchecked_call == false); 305 CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0)); 306 assert(ID::checkCalled(ret)); 307 } 308 #if TEST_STD_VER >= 11 309 { 310 static_assert((std::is_same< 311 decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0))) 312 , CallRet>::value), ""); 313 assert(ID::unchecked_call == false); 314 CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0)); 315 assert(ID::checkCalled(ret)); 316 } 317 #endif 318 } 319 320 template <class MethodPtr, class ObjectT> 321 void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) { 322 { 323 static_assert((std::is_same< 324 decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1))) 325 , CallRet>::value), ""); 326 assert(ID::unchecked_call == false); 327 CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)); 328 assert(ID::checkCalled(ret)); 329 } 330 #if TEST_STD_VER >= 11 331 { 332 static_assert((std::is_same< 333 decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1))) 334 , CallRet>::value), ""); 335 assert(ID::unchecked_call == false); 336 CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)); 337 assert(ID::checkCalled(ret)); 338 } 339 #endif 340 } 341 342 template <class MethodPtr, class ObjectT> 343 void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) { 344 { 345 static_assert((std::is_same< 346 decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) 347 , CallRet>::value), ""); 348 assert(ID::unchecked_call == false); 349 CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); 350 assert(ID::checkCalled(ret)); 351 } 352 #if TEST_STD_VER >= 11 353 { 354 static_assert((std::is_same< 355 decltype(std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) 356 , CallRet>::value), ""); 357 assert(ID::unchecked_call == false); 358 CallRet ret = std::__invoke_constexpr(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); 359 assert(ID::checkCalled(ret)); 360 } 361 #endif 362 } 363 364 //========================================================================== 365 // BULLET 7 TEST METHODS 366 //========================================================================== 367 template <class ObjectT> 368 void runTestImp(Int<0>, ObjectT& object) { 369 { 370 static_assert((std::is_same< 371 decltype(std::__invoke(object_cast(object))) 372 , CallRet>::value), ""); 373 assert(ID::unchecked_call == false); 374 CallRet ret = std::__invoke(object_cast(object)); 375 assert(ID::checkCalled(ret)); 376 } 377 #if TEST_STD_VER >= 11 378 { 379 static_assert((std::is_same< 380 decltype(std::__invoke_constexpr(object_cast(object))) 381 , CallRet>::value), ""); 382 assert(ID::unchecked_call == false); 383 CallRet ret = std::__invoke_constexpr(object_cast(object)); 384 assert(ID::checkCalled(ret)); 385 } 386 #endif 387 } 388 389 template <class ObjectT> 390 void runTestImp(Int<1>, ObjectT& object) { 391 { 392 static_assert((std::is_same< 393 decltype(std::__invoke(object_cast(object), arg_cast(a0))) 394 , CallRet>::value), ""); 395 assert(ID::unchecked_call == false); 396 CallRet ret = std::__invoke(object_cast(object), arg_cast(a0)); 397 assert(ID::checkCalled(ret)); 398 } 399 #if TEST_STD_VER >= 11 400 { 401 static_assert((std::is_same< 402 decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0))) 403 , CallRet>::value), ""); 404 assert(ID::unchecked_call == false); 405 CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0)); 406 assert(ID::checkCalled(ret)); 407 } 408 #endif 409 } 410 411 template <class ObjectT> 412 void runTestImp(Int<2>, ObjectT& object) { 413 { 414 static_assert((std::is_same< 415 decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1))) 416 , CallRet>::value), ""); 417 assert(ID::unchecked_call == false); 418 CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)); 419 assert(ID::checkCalled(ret)); 420 } 421 #if TEST_STD_VER >= 11 422 { 423 static_assert((std::is_same< 424 decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1))) 425 , CallRet>::value), ""); 426 assert(ID::unchecked_call == false); 427 CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1)); 428 assert(ID::checkCalled(ret)); 429 } 430 #endif 431 } 432 433 template <class ObjectT> 434 void runTestImp(Int<3>, ObjectT& object) { 435 { 436 static_assert((std::is_same< 437 decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) 438 , CallRet>::value), ""); 439 assert(ID::unchecked_call == false); 440 CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); 441 assert(ID::checkCalled(ret)); 442 } 443 #if TEST_STD_VER >= 11 444 { 445 static_assert((std::is_same< 446 decltype(std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2))) 447 , CallRet>::value), ""); 448 assert(ID::unchecked_call == false); 449 CallRet ret = std::__invoke_constexpr(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)); 450 assert(ID::checkCalled(ret)); 451 } 452 #endif 453 } 454 }; 455 456 #endif // INVOKE_HELPERS_H 457