Checking more __invoke tests.
authorEric Fiselier <eric@efcs.ca>
Tue, 28 Jul 2015 01:25:36 +0000 (01:25 +0000)
committerEric Fiselier <eric@efcs.ca>
Tue, 28 Jul 2015 01:25:36 +0000 (01:25 +0000)
Before I start trying to fix __invoke in C++03 it needs better test coverage.
This patch adds a large amount of tests for __invoke.

llvm-svn: 243366

libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h [new file with mode: 0644]

diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_1_and_2.pass.cpp
new file mode 100644 (file)
index 0000000..e579f20
--- /dev/null
@@ -0,0 +1,318 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <functional>
+
+// INVOKE (f, t1, t2, ..., tN)
+
+//------------------------------------------------------------------------------
+// TESTING INVOKE(f, t1, t2, ..., tN)
+//   - Bullet 1 -- (t1.*f)(t2, ..., tN)
+//   - Bullet 2 -- ((*t1).*f)(t2, ..., tN)
+//
+// Overview:
+//    Bullets 1 and 2 handle the case where 'f' is a pointer to member function.
+//    Bullet 1 only handles the cases where t1 is an object of type T or a
+//    type derived from 'T'. Bullet 2 handles all other cases.
+//
+// Concerns:
+//   1) cv-qualified member function signatures are accepted.
+//   2) reference qualified member function signatures are accepted.
+//   3) member functions with varargs at the end are accepted.
+//   4) The arguments are perfect forwarded to the member function call.
+//   5) Classes that are publicly derived from 'T' are accepted as the call object
+//   6) All types that dereference to T or a type derived from T can be used
+//      as the call object.
+//   7) Pointers to T or a type derived from T can be used as the call object.
+//   8) Reference return types are properly deduced.
+//
+//
+// Plan:
+//   1) Create a class that contains a set, 'S', of non-static functions.
+//     'S' should include functions that cover every single combination
+//      of qualifiers and varargs for arities of 0, 1 and 2 (C-1,2,3).
+//      The argument types used in the functions should be non-copyable (C-4).
+//      The functions should return 'MethodID::setUncheckedCall()'.
+//
+//   2) Create a set of supported call object, 'Objs', of different types
+//      and behaviors. (C-5,6,7)
+//
+//   3) Attempt to call each function, 'f', in 'S' with each call object, 'c',
+//      in 'Objs'. After every attempted call to 'f' check that 'f' was
+//      actually called using 'MethodID::checkCalled(<return-value>)'
+//
+//       3b) If 'f' is reference qualified call 'f' with the properly qualified
+//       call object. Otherwise call 'f' with lvalue call objects.
+//
+//       3a) If 'f' is const, volatile, or cv qualified then call it with call
+//       objects that are equally or less cv-qualified.
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "invoke_helpers.h"
+
+//==============================================================================
+// MemFun03 - C++03 compatible set of test member functions.
+struct MemFun03 {
+    typedef void*& R;
+#define F(...) \
+    R f(__VA_ARGS__) { return MethodID<R(MemFun03::*)(__VA_ARGS__)>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) const { return MethodID<R(MemFun03::*)(__VA_ARGS__) const>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) volatile { return MethodID<R(MemFun03::*)(__VA_ARGS__) volatile>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) const volatile { return MethodID<R(MemFun03::*)(__VA_ARGS__) const volatile>::setUncheckedCall(); }
+#
+    F()
+    F(...)
+    F(ArgType&)
+    F(ArgType&, ...)
+    F(ArgType&, ArgType&)
+    F(ArgType&, ArgType&, ...)
+    F(ArgType&, ArgType&, ArgType&)
+    F(ArgType&, ArgType&, ArgType&, ...)
+#undef F
+public:
+    MemFun03() {}
+private:
+    MemFun03(MemFun03 const&);
+    MemFun03& operator=(MemFun03 const&);
+};
+
+
+#if TEST_STD_VER >= 11
+
+//==============================================================================
+// MemFun11 - C++11 reference qualified test member functions.
+struct MemFun11 {
+    typedef void*& R;
+    typedef MemFun11 C;
+#define F(...) \
+    R f(__VA_ARGS__) & { return MethodID<R(C::*)(__VA_ARGS__) &>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) const & { return MethodID<R(C::*)(__VA_ARGS__) const &>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) volatile & { return MethodID<R(C::*)(__VA_ARGS__) volatile &>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) const volatile & { return MethodID<R(C::*)(__VA_ARGS__) const volatile &>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) && { return MethodID<R(C::*)(__VA_ARGS__) &&>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) const && { return MethodID<R(C::*)(__VA_ARGS__) const &&>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) volatile && { return MethodID<R(C::*)(__VA_ARGS__) volatile &&>::setUncheckedCall(); } \
+    R f(__VA_ARGS__) const volatile && { return MethodID<R(C::*)(__VA_ARGS__) const volatile &&>::setUncheckedCall(); }
+#
+    F()
+    F(...)
+    F(ArgType&&)
+    F(ArgType&&, ...)
+    F(ArgType&&, ArgType&&)
+    F(ArgType&&, ArgType&&, ...)
+    F(ArgType&&, ArgType&&, ArgType&&)
+    F(ArgType&&, ArgType&&, ArgType&&, ...)
+#undef F
+public:
+    MemFun11() {}
+private:
+    MemFun11(MemFun11 const&);
+    MemFun11& operator=(MemFun11 const&);
+};
+
+#endif // TEST_STD_VER >= 11
+
+
+//==============================================================================
+// TestCase - A test case for a single member function.
+//   ClassType - The type of the class being tested.
+//   CallSig   - The function signature of the method being tested.
+//   Arity     - the arity of 'CallSig'
+//   CV        - the cv qualifiers of 'CallSig' represented as a type tag.
+//   RValue    - The method is RValue qualified.
+//   ArgRValue - Call the method with RValue arguments.
+template <class ClassType, class CallSig, int Arity, class CV,
+          bool RValue = false, bool ArgRValue = false>
+struct TestCaseImp {
+public:
+
+    static void run() { TestCaseImp().doTest(); }
+
+private:
+    //==========================================================================
+    // TEST DISPATCH
+    void doTest() {
+         // (Plan-2) Create test call objects.
+        typedef ClassType T;
+        typedef DerivedFromType<T> D;
+        T obj;
+        T* obj_ptr = &obj;
+        D der;
+        D* der_ptr = &der;
+        DerefToType<T>   dref;
+        DerefPropType<T> dref2;
+
+         // (Plan-3) Dispatch based on the CV tags.
+        CV tag;
+        Bool<!RValue> NotRValue;
+        runTestDispatch(tag,  obj);
+        runTestDispatch(tag,  der);
+        runTestDispatch(tag, dref2);
+        runTestDispatchIf(NotRValue, tag,  dref);
+        runTestDispatchIf(NotRValue, tag,  obj_ptr);
+        runTestDispatchIf(NotRValue, tag, der_ptr);
+    }
+
+    template <class QT, class Tp>
+    void runTestDispatchIf(Bool<true>, QT q, Tp& v) {
+        runTestDispatch(q, v);
+    }
+
+    template <class QT, class Tp>
+    void runTestDispatchIf(Bool<false>, QT, Tp&) {
+    }
+
+    template <class Tp>
+    void runTestDispatch(Q_None, Tp& v) {
+        runTest(v);
+    }
+
+    template <class Tp>
+    void runTestDispatch(Q_Const, Tp& v) {
+        Tp const& cv = v;
+        runTest(v);
+        runTest(cv);
+    }
+
+    template <class Tp>
+    void runTestDispatch(Q_Volatile, Tp& v) {
+        Tp volatile& vv = v;
+        runTest(v);
+        runTest(vv);
+    }
+
+    template <class Tp>
+    void runTestDispatch(Q_CV, Tp& v) {
+        Tp const& cv = v;
+        Tp volatile& vv = v;
+        Tp const volatile& cvv = v;
+        runTest(v);
+        runTest(cv);
+        runTest(vv);
+        runTest(cvv);
+    }
+
+    template <class Obj>
+    void runTest(Obj& obj) {
+        typedef Caster<Q_None, RValue> SCast;
+        typedef Caster<Q_None, ArgRValue> ACast;
+        typedef CallSig (ClassType::*MemPtr);
+        // Delegate test to logic in invoke_helpers.h
+        BasicTest<MethodID<MemPtr>, Arity, SCast, ACast> b;
+        b.runTest( (MemPtr)&ClassType::f, obj);
+    }
+};
+
+template <class Sig, int Arity, class CV>
+struct TestCase : public TestCaseImp<MemFun03, Sig, Arity, CV> {};
+
+#if TEST_STD_VER >= 11
+template <class Sig, int Arity, class CV, bool RValue = false>
+struct TestCase11 : public TestCaseImp<MemFun11, Sig, Arity, CV, RValue, true> {};
+#endif
+
+int main() {
+    typedef void*& R;
+    typedef ArgType A;
+    TestCase<R(),                                   0, Q_None>::run();
+    TestCase<R() const,                             0, Q_Const>::run();
+    TestCase<R() volatile,                          0, Q_Volatile>::run();
+    TestCase<R() const volatile,                    0, Q_CV>::run();
+    TestCase<R(...),                                0, Q_None>::run();
+    TestCase<R(...) const,                          0, Q_Const>::run();
+    TestCase<R(...) volatile,                       0, Q_Volatile>::run();
+    TestCase<R(...) const volatile,                 0, Q_CV>::run();
+    TestCase<R(A&),                                 1, Q_None>::run();
+    TestCase<R(A&) const,                           1, Q_Const>::run();
+    TestCase<R(A&) volatile,                        1, Q_Volatile>::run();
+    TestCase<R(A&) const volatile,                  1, Q_CV>::run();
+    TestCase<R(A&, ...),                            1, Q_None>::run();
+    TestCase<R(A&, ...) const,                      1, Q_Const>::run();
+    TestCase<R(A&, ...) volatile,                   1, Q_Volatile>::run();
+    TestCase<R(A&, ...) const volatile,             1, Q_CV>::run();
+    TestCase<R(A&, A&),                             2, Q_None>::run();
+    TestCase<R(A&, A&) const,                       2, Q_Const>::run();
+    TestCase<R(A&, A&) volatile,                    2, Q_Volatile>::run();
+    TestCase<R(A&, A&) const volatile,              2, Q_CV>::run();
+    TestCase<R(A&, A&, ...),                        2, Q_None>::run();
+    TestCase<R(A&, A&, ...) const,                  2, Q_Const>::run();
+    TestCase<R(A&, A&, ...) volatile,               2, Q_Volatile>::run();
+    TestCase<R(A&, A&, ...) const volatile,         2, Q_CV>::run();
+    TestCase<R(A&, A&, A&),                         3, Q_None>::run();
+    TestCase<R(A&, A&, A&) const,                   3, Q_Const>::run();
+    TestCase<R(A&, A&, A&) volatile,                3, Q_Volatile>::run();
+    TestCase<R(A&, A&, A&) const volatile,          3, Q_CV>::run();
+    TestCase<R(A&, A&, A&, ...),                    3, Q_None>::run();
+    TestCase<R(A&, A&, A&, ...) const,              3, Q_Const>::run();
+    TestCase<R(A&, A&, A&, ...) volatile,           3, Q_Volatile>::run();
+    TestCase<R(A&, A&, A&, ...) const volatile,     3, Q_CV>::run();
+
+#if TEST_STD_VER >= 11
+    TestCase11<R() &,                               0, Q_None>::run();
+    TestCase11<R() const &,                         0, Q_Const>::run();
+    TestCase11<R() volatile &,                      0, Q_Volatile>::run();
+    TestCase11<R() const volatile &,                0, Q_CV>::run();
+    TestCase11<R(...) &,                            0, Q_None>::run();
+    TestCase11<R(...) const &,                      0, Q_Const>::run();
+    TestCase11<R(...) volatile &,                   0, Q_Volatile>::run();
+    TestCase11<R(...) const volatile &,             0, Q_CV>::run();
+    TestCase11<R(A&&) &,                            1, Q_None>::run();
+    TestCase11<R(A&&) const &,                      1, Q_Const>::run();
+    TestCase11<R(A&&) volatile &,                   1, Q_Volatile>::run();
+    TestCase11<R(A&&) const volatile &,             1, Q_CV>::run();
+    TestCase11<R(A&&, ...) &,                       1, Q_None>::run();
+    TestCase11<R(A&&, ...) const &,                 1, Q_Const>::run();
+    TestCase11<R(A&&, ...) volatile &,              1, Q_Volatile>::run();
+    TestCase11<R(A&&, ...) const volatile &,        1, Q_CV>::run();
+    TestCase11<R(A&&, A&&) &,                       2, Q_None>::run();
+    TestCase11<R(A&&, A&&) const &,                 2, Q_Const>::run();
+    TestCase11<R(A&&, A&&) volatile &,              2, Q_Volatile>::run();
+    TestCase11<R(A&&, A&&) const volatile &,        2, Q_CV>::run();
+    TestCase11<R(A&&, A&&, ...) &,                  2, Q_None>::run();
+    TestCase11<R(A&&, A&&, ...) const &,            2, Q_Const>::run();
+    TestCase11<R(A&&, A&&, ...) volatile &,         2, Q_Volatile>::run();
+    TestCase11<R(A&&, A&&, ...) const volatile &,   2, Q_CV>::run();
+    TestCase11<R() &&,                              0, Q_None, /* RValue */ true>::run();
+    TestCase11<R() const &&,                        0, Q_Const, /* RValue */ true>::run();
+    TestCase11<R() volatile &&,                     0, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R() const volatile &&,               0, Q_CV, /* RValue */ true>::run();
+    TestCase11<R(...) &&,                           0, Q_None, /* RValue */ true>::run();
+    TestCase11<R(...) const &&,                     0, Q_Const, /* RValue */ true>::run();
+    TestCase11<R(...) volatile &&,                  0, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R(...) const volatile &&,            0, Q_CV, /* RValue */ true>::run();
+    TestCase11<R(A&&) &&,                           1, Q_None, /* RValue */ true>::run();
+    TestCase11<R(A&&) const &&,                     1, Q_Const, /* RValue */ true>::run();
+    TestCase11<R(A&&) volatile &&,                  1, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R(A&&) const volatile &&,            1, Q_CV, /* RValue */ true>::run();
+    TestCase11<R(A&&, ...) &&,                      1, Q_None, /* RValue */ true>::run();
+    TestCase11<R(A&&, ...) const &&,                1, Q_Const, /* RValue */ true>::run();
+    TestCase11<R(A&&, ...) volatile &&,             1, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R(A&&, ...) const volatile &&,       1, Q_CV, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&) &&,                      2, Q_None, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&) const &&,                2, Q_Const, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&) volatile &&,             2, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&) const volatile &&,       2, Q_CV, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, ...) &&,                 2, Q_None, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, ...) const &&,           2, Q_Const, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, ...) volatile &&,        2, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, ...) const volatile &&,  2, Q_CV, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&) &&,                 3, Q_None, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&) const &&,           3, Q_Const, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&) volatile &&,        3, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&) const volatile &&,  3, Q_CV, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&, ...)  &&,                 3, Q_None, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&, ...)  const &&,           3, Q_Const, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&, ...)  volatile &&,        3, Q_Volatile, /* RValue */ true>::run();
+    TestCase11<R(A&&, A&&, A&&, ...)  const volatile &&,  3, Q_CV, /* RValue */ true>::run();
+#endif
+}
\ No newline at end of file
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_3_and_4.pass.cpp
new file mode 100644 (file)
index 0000000..b6fe190
--- /dev/null
@@ -0,0 +1,164 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <functional>
+
+// INVOKE (f, t1, t2, ..., tN)
+
+//------------------------------------------------------------------------------
+// TESTING INVOKE(f, t1, t2, ..., tN)
+//   - Bullet 3 -- t1.*f
+//   - Bullet 4 -- (*t1).*f
+//
+// Overview:
+//    Bullets 3 and 4 handle the case where 'f' is a pointer to member object.
+//    Bullet 3 only handles the cases where t1 is an object of type T or a
+//    type derived from 'T'. Bullet 4 handles all other cases.
+//
+// Concerns:
+//   1) The return type is always an lvalue reference.
+//   2) The return type is not less cv-qualified that the object that contains it.
+//   3) The return type is not less cv-qualified than object type.
+//   4) The call object is perfectly forwarded.
+//   5) Classes that are publicly derived from 'T' are accepted as the call object
+//   6) All types that dereference to T or a type derived from T can be used
+//      as the call object.
+//   7) Pointers to T or a type derived from T can be used as the call object.
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "invoke_helpers.h"
+
+template <class Tp>
+struct TestMemberObject {
+    TestMemberObject() : object() {}
+    Tp object;
+private:
+    TestMemberObject(TestMemberObject const&);
+    TestMemberObject& operator=(TestMemberObject const&);
+};
+
+template <class ObjectType>
+struct TestCase {
+    public:
+
+    static void run() { TestCase().doTest(); }
+
+private:
+    typedef TestMemberObject<ObjectType> TestType;
+
+    //==========================================================================
+    // TEST DISPATCH
+    void doTest() {
+        typedef DerivedFromType<TestType> Derived;
+        TestType obj;
+        TestType* obj_ptr = &obj;
+        Derived der;
+        Derived* der_ptr = &der;
+        DerefToType<TestType>   dref;
+        DerefPropType<TestType> dref2;
+
+        {
+            typedef ObjectType (TestType::*MemPtr);
+            typedef ObjectType E;
+            MemPtr M = &TestType::object;
+            runTestDispatch<E>(M, obj, &obj.object);
+            runTestDispatch<E>(M, der, &der.object);
+            runTestDispatch<E>(M, dref2, &dref2.object.object);
+            runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
+            runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
+            runTestPointerDispatch<E>(M, dref, &dref.object.object);
+        }
+        {
+            typedef ObjectType const (TestType::*CMemPtr);
+            typedef ObjectType const E;
+            CMemPtr M = &TestType::object;
+            runTestDispatch<E>(M, obj, &obj.object);
+            runTestDispatch<E>(M, der, &der.object);
+            runTestDispatch<E>(M, dref2, &dref2.object.object);
+            runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
+            runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
+            runTestPointerDispatch<E>(M, dref, &dref.object.object);
+        }
+        {
+            typedef ObjectType volatile (TestType::*VMemPtr);
+            typedef ObjectType volatile E;
+            VMemPtr M = &TestType::object;
+            runTestDispatch<E>(M, obj,  &obj.object);
+            runTestDispatch<E>(M, der,  &der.object);
+            runTestDispatch<E>(M, dref2, &dref2.object.object);
+            runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
+            runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
+            runTestPointerDispatch<E>(M, dref,    &dref.object.object);
+        }
+        {
+            typedef ObjectType const volatile (TestType::*CVMemPtr);
+            typedef ObjectType const volatile E;
+            CVMemPtr M = &TestType::object;
+            runTestDispatch<E>(M, obj,   &obj.object);
+            runTestDispatch<E>(M, der,   &der.object);
+            runTestDispatch<E>(M, dref2, &dref2.object.object);
+            runTestPointerDispatch<E>(M, obj_ptr, &obj_ptr->object);
+            runTestPointerDispatch<E>(M, der_ptr, &der_ptr->object);
+            runTestPointerDispatch<E>(M, dref,    &dref.object.object);
+        }
+    }
+
+    template <class Expect, class Fn, class T>
+    void runTestDispatch(Fn M, T& obj, ObjectType* expect) {
+        runTest<Expect &>              (M, C_<T&>(obj),                expect);
+        runTest<Expect const&>         (M, C_<T const&>(obj),          expect);
+        runTest<Expect volatile&>      (M, C_<T volatile&>(obj),       expect);
+        runTest<Expect const volatile&>(M, C_<T const volatile&>(obj), expect);
+#if TEST_STD_VER >= 11
+        runTest<Expect&&>               (M, C_<T&&>(obj),                expect);
+        runTest<Expect const&&>         (M, C_<T const&&>(obj),          expect);
+        runTest<Expect volatile&&>      (M, C_<T volatile&&>(obj),       expect);
+        runTest<Expect const volatile&&>(M, C_<T const volatile&&>(obj), expect);
+#endif
+    }
+
+    template <class Expect, class Fn, class T>
+    void runTestPointerDispatch(Fn M, T& obj, ObjectType* expect) {
+        runTest<Expect&>(M, C_<T &>(obj),               expect);
+        runTest<Expect&>(M, C_<T const&>(obj),          expect);
+        runTest<Expect&>(M, C_<T volatile&>(obj),       expect);
+        runTest<Expect&>(M, C_<T const volatile&>(obj), expect);
+#if TEST_STD_VER >= 11
+        runTest<Expect&>(M, C_<T&&>(obj),                expect);
+        runTest<Expect&>(M, C_<T const&&>(obj),          expect);
+        runTest<Expect&>(M, C_<T volatile&&>(obj),       expect);
+        runTest<Expect&>(M, C_<T const volatile&&>(obj), expect);
+#endif
+    }
+
+    template <class Expect, class Fn, class T>
+#if TEST_STD_VER >= 11
+    void runTest(Fn M, T&& obj, ObjectType* expect) {
+#else
+    void runTest(Fn M, T& obj, ObjectType* expect ) {
+#endif
+        static_assert((std::is_same<
+            decltype(std::__invoke(M, std::forward<T>(obj))), Expect
+          >::value), "");
+        Expect e = std::__invoke(M, std::forward<T>(obj));
+        assert(&e == expect);
+    }
+};
+
+int main() {
+    TestCase<ArgType>::run();
+    TestCase<ArgType const>::run();
+    TestCase<ArgType volatile>::run();
+    TestCase<ArgType const volatile>::run();
+    TestCase<ArgType*>::run();
+}
\ No newline at end of file
diff --git a/libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp b/libcxx/test/std/utilities/function.objects/func.require/bullet_5.pass.cpp
new file mode 100644 (file)
index 0000000..3f3c96a
--- /dev/null
@@ -0,0 +1,327 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <functional>
+
+// INVOKE (f, t1, t2, ..., tN)
+
+//------------------------------------------------------------------------------
+// TESTING INVOKE(f, t1, t2, ..., tN)
+//   - Bullet 5 -- f(t2, ..., tN)
+//
+// Overview:
+//    Bullet 5 handles the cases where the first argument is not a member
+//   function.
+//
+// Concerns:
+//   1) Different types of callable objects are supported. Including
+//      1a) Free Function pointers and references.
+//      1b) Classes which provide a call operator
+//      1c) lambdas
+//   2) The callable objects are perfect forwarded.
+//   3) The arguments are perfect forwarded.
+//   4) Signatures which include varargs are supported.
+//   5) In C++03 3 extra arguments should be allowed.
+//
+// Plan:
+//  1) Define a set of free functions, 'SF', and class types with call
+//     operators, 'SC', that address concerns 4 and 5. The free functions should
+//     return 'FunctionID::setUncheckedCall()' and the call operators should
+//     return 'MethodID::setUncheckedCall()'.
+//
+//  2) For each function 'f' in 'SF' and 'SC' attempt to call 'f'
+//     using the correct number of arguments and cv-ref qualifiers. Check that
+//     'f' has been called using 'FunctionID::checkCall()' if 'f' is a free
+//     function and 'MethodID::checkCall()' otherwise.
+
+
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "invoke_helpers.h"
+
+
+//==============================================================================
+// freeFunction03 - A C++03 free function.
+void*& freeFunction03() {
+    return FunctionPtrID<void*&(), freeFunction03>::setUncheckedCall();
+}
+
+void*& freeFunction03(...) {
+    return FunctionPtrID<void*&(...), freeFunction03>::setUncheckedCall();
+}
+
+template <class A0>
+void*& freeFunction03(A0&) {
+    return FunctionPtrID<void*&(A0&), freeFunction03>::setUncheckedCall();
+}
+
+
+template <class A0>
+void*& freeFunction03(A0&, ...) {
+    return FunctionPtrID<void*&(A0&, ...), freeFunction03>::setUncheckedCall();
+}
+
+template <class A0, class A1>
+void*& freeFunction03(A0&, A1&) {
+    return FunctionPtrID<void*&(A0&, A1&), freeFunction03>::setUncheckedCall();
+}
+
+
+template <class A0, class A1>
+void*& freeFunction03(A0&, A1&, ...) {
+    return FunctionPtrID<void*&(A0&, A1&, ...), freeFunction03>::setUncheckedCall();
+}
+
+template <class A0, class A1, class A2>
+void*& freeFunction03(A0&, A1&, A2&) {
+    return FunctionPtrID<void*&(A0&, A1&, A2&), freeFunction03>::setUncheckedCall();
+}
+
+template <class A0, class A1, class A2>
+void*& freeFunction03(A0&, A1&, A2&, ...) {
+    return FunctionPtrID<void*&(A0&, A1&, A2&, ...), freeFunction03>::setUncheckedCall();
+}
+
+//==============================================================================
+// Functor03 - C++03 compatible functor object
+struct Functor03 {
+    typedef void*& R;
+    typedef Functor03 C;
+#define F(Args, ...) \
+    __VA_ARGS__ R operator() Args { return MethodID<R(C::*) Args>::setUncheckedCall(); } \
+    __VA_ARGS__ R operator() Args const { return MethodID<R(C::*) Args const>::setUncheckedCall(); } \
+    __VA_ARGS__ R operator() Args volatile { return MethodID<R(C::*) Args volatile>::setUncheckedCall(); } \
+    __VA_ARGS__ R operator() Args const volatile { return MethodID<R(C::*) Args const volatile>::setUncheckedCall(); }
+#
+    F(())
+    F((A0&), template <class A0>)
+    F((A0&, A1&), template <class A0, class A1>)
+    F((A0&, A1&, A2&), template <class A0, class A1, class A2>)
+#undef F
+public:
+    Functor03() {}
+private:
+    Functor03(Functor03 const&);
+    Functor03& operator=(Functor03 const&);
+};
+
+
+#if TEST_STD_VER >= 11
+
+//==============================================================================
+// freeFunction11 - A C++11 free function.
+template <class ...Args>
+void*& freeFunction11(Args&&...) {
+    return FunctionPtrID<void*&(Args&&...), freeFunction11>::setUncheckedCall();
+}
+
+template <class ...Args>
+void*& freeFunction11(Args&&...,...) {
+    return FunctionPtrID<void*&(Args&&...,...), freeFunction11>::setUncheckedCall();
+}
+
+//==============================================================================
+// Functor11 - C++11 reference qualified test member functions.
+struct Functor11 {
+    typedef void*& R;
+    typedef Functor11 C;
+
+#define F(CV) \
+    template <class ...Args> \
+    R operator()(Args&&...) CV { return MethodID<R(C::*)(Args&&...) CV>::setUncheckedCall(); }
+#
+    F(&)
+    F(const &)
+    F(volatile &)
+    F(const volatile &)
+    F(&&)
+    F(const &&)
+    F(volatile &&)
+    F(const volatile &&)
+#undef F
+public:
+    Functor11() {}
+private:
+    Functor11(Functor11 const&);
+    Functor11& operator=(Functor11 const&);
+};
+
+#endif // TEST_STD_VER >= 11
+
+
+//==============================================================================
+// TestCaseFunctorImp - A test case for an operator() class method.
+//   ClassType - The type of the call object.
+//   CallSig   - The function signature of the call operator being tested.
+//   Arity     - the arity of 'CallSig'
+//   ObjCaster - Transformation function applied to call object.
+//   ArgCaster - Transformation function applied to the extra arguments.
+template <class ClassType, class CallSig, int Arity,
+          class ObjCaster, class ArgCaster = LValueCaster>
+struct TestCaseFunctorImp {
+public:
+    static void run() {
+        typedef MethodID<CallSig ClassType::*> MID;
+        BasicTest<MID, Arity, ObjCaster, ArgCaster> t;
+        typedef ClassType T;
+        typedef DerivedFromType<T> D;
+        T obj;
+        D der;
+        t.runTest(obj);
+        t.runTest(der);
+    }
+};
+
+//==============================================================================
+// TestCaseFreeFunction - A test case for a free function.
+//   CallSig   - The function signature of the free function being tested.
+//   FnPtr     - The function being tested.
+//   Arity     - the arity of 'CallSig'
+//   ArgCaster - Transformation function to be applied to the extra arguments.
+template <class CallSig, CallSig* FnPtr, int Arity, class ArgCaster>
+struct TestCaseFreeFunction {
+public:
+    static void run() {
+        typedef FunctionPtrID<CallSig, FnPtr> FID;
+        BasicTest<FID, Arity, LValueCaster, ArgCaster> t;
+
+        DerefToType<CallSig*> deref_to(FnPtr);
+        DerefToType<CallSig&> deref_to_ref(*FnPtr);
+
+        t.runTest(FnPtr);
+        t.runTest(*FnPtr);
+        t.runTest(deref_to);
+        t.runTest(deref_to_ref);
+    }
+};
+
+//==============================================================================
+//                          runTest Helpers
+//==============================================================================
+#if TEST_STD_VER >= 11
+template <class Sig, int Arity, class ArgCaster>
+void runFunctionTestCase11() {
+    TestCaseFreeFunction<Sig, freeFunction11, Arity, ArgCaster>();
+}
+#endif
+
+template <class Sig, int Arity, class ArgCaster>
+void runFunctionTestCase() {
+    TestCaseFreeFunction<Sig, freeFunction03, Arity, ArgCaster>();
+#if TEST_STD_VER >= 11
+    runFunctionTestCase11<Sig, Arity, ArgCaster>();
+#endif
+}
+
+template <class Sig, int Arity, class ObjCaster, class ArgCaster>
+void runFunctorTestCase() {
+    TestCaseFunctorImp<Functor03, Sig, Arity, ObjCaster, ArgCaster>::run();
+}
+
+template <class Sig, int Arity, class ObjCaster>
+void runFunctorTestCase() {
+    TestCaseFunctorImp<Functor03, Sig, Arity, ObjCaster>::run();
+}
+
+#if TEST_STD_VER >= 11
+// runTestCase - Run a test case for C++11 class functor types
+template <class Sig, int Arity, class ObjCaster, class ArgCaster = LValueCaster>
+void runFunctorTestCase11() {
+    TestCaseFunctorImp<Functor11, Sig, Arity, ObjCaster, ArgCaster>::run();
+}
+#endif
+
+// runTestCase - Run a test case for both function and functor types.
+template <class Sig, int Arity, class ArgCaster>
+void runTestCase() {
+    runFunctionTestCase<Sig, Arity, ArgCaster>();
+    runFunctorTestCase <Sig, Arity, LValueCaster, ArgCaster>();
+};
+
+int main() {
+    typedef void*& R;
+    typedef ArgType A;
+    typedef A const CA;
+
+    runTestCase< R(),                                   0, LValueCaster      >();
+    runTestCase< R(A&),                                 1, LValueCaster      >();
+    runTestCase< R(A&, A&),                             2, LValueCaster      >();
+    runTestCase< R(A&, A&, A&),                         3, LValueCaster      >();
+    runTestCase< R(CA&),                                1, ConstCaster       >();
+    runTestCase< R(CA&, CA&),                           2, ConstCaster       >();
+    runTestCase< R(CA&, CA&, CA&),                      3, ConstCaster       >();
+
+    runFunctionTestCase<R(...),                         0, LValueCaster      >();
+    runFunctionTestCase<R(A&, ...),                     1, LValueCaster      >();
+    runFunctionTestCase<R(A&, A&, ...),                 2, LValueCaster      >();
+    runFunctionTestCase<R(A&, A&, A&, ...),             3, LValueCaster      >();
+
+#if TEST_STD_VER >= 11
+    runFunctionTestCase11<R(A&&),                       1, MoveCaster        >();
+    runFunctionTestCase11<R(A&&, ...),                  1, MoveCaster        >();
+#endif
+
+    runFunctorTestCase<R(),                             0, LValueCaster      >();
+    runFunctorTestCase<R() const,                       0, ConstCaster       >();
+    runFunctorTestCase<R() volatile,                    0, VolatileCaster    >();
+    runFunctorTestCase<R() const volatile,              0, CVCaster          >();
+    runFunctorTestCase<R(A&),                           1, LValueCaster      >();
+    runFunctorTestCase<R(A&) const,                     1, ConstCaster       >();
+    runFunctorTestCase<R(A&) volatile,                  1, VolatileCaster    >();
+    runFunctorTestCase<R(A&) const volatile,            1, CVCaster          >();
+    runFunctorTestCase<R(A&, A&),                       2, LValueCaster      >();
+    runFunctorTestCase<R(A&, A&) const,                 2, ConstCaster       >();
+    runFunctorTestCase<R(A&, A&) volatile,              2, VolatileCaster    >();
+    runFunctorTestCase<R(A&, A&) const volatile,        2, CVCaster          >();
+    runFunctorTestCase<R(A&, A&, A&),                   3, LValueCaster      >();
+    runFunctorTestCase<R(A&, A&, A&) const,             3, ConstCaster       >();
+    runFunctorTestCase<R(A&, A&, A&) volatile,          3, VolatileCaster    >();
+    runFunctorTestCase<R(A&, A&, A&) const volatile,    3, CVCaster          >();
+    {
+    typedef ConstCaster CC;
+    runFunctorTestCase<R(CA&),                          1, LValueCaster,   CC>();
+    runFunctorTestCase<R(CA&) const,                    1, ConstCaster,    CC>();
+    runFunctorTestCase<R(CA&) volatile,                 1, VolatileCaster, CC>();
+    runFunctorTestCase<R(CA&) const volatile,           1, CVCaster,       CC>();
+    runFunctorTestCase<R(CA&, CA&),                     2, LValueCaster,   CC>();
+    runFunctorTestCase<R(CA&, CA&) const,               2, ConstCaster,    CC>();
+    runFunctorTestCase<R(CA&, CA&) volatile,            2, VolatileCaster, CC>();
+    runFunctorTestCase<R(CA&, CA&) const volatile,      2, CVCaster,       CC>();
+    runFunctorTestCase<R(CA&, CA&, CA&),                3, LValueCaster,   CC>();
+    runFunctorTestCase<R(CA&, CA&, CA&) const,          3, ConstCaster,    CC>();
+    runFunctorTestCase<R(CA&, CA&, CA&) volatile,       3, VolatileCaster, CC>();
+    runFunctorTestCase<R(CA&, CA&, CA&) const volatile, 3, CVCaster,       CC>();
+    }
+
+#if TEST_STD_VER >= 11
+    runFunctorTestCase11<R() &,                    0, LValueCaster          >();
+    runFunctorTestCase11<R() const &,              0, ConstCaster           >();
+    runFunctorTestCase11<R() volatile &,           0, VolatileCaster        >();
+    runFunctorTestCase11<R() const volatile &,     0, CVCaster              >();
+    runFunctorTestCase11<R() &&,                   0, MoveCaster            >();
+    runFunctorTestCase11<R() const &&,             0, MoveConstCaster       >();
+    runFunctorTestCase11<R() volatile &&,          0, MoveVolatileCaster    >();
+    runFunctorTestCase11<R() const volatile &&,    0, MoveCVCaster          >();
+    {
+    typedef MoveCaster MC;
+    runFunctorTestCase11<R(A&&) &,                 1, LValueCaster,       MC>();
+    runFunctorTestCase11<R(A&&) const &,           1, ConstCaster,        MC>();
+    runFunctorTestCase11<R(A&&) volatile &,        1, VolatileCaster,     MC>();
+    runFunctorTestCase11<R(A&&) const volatile &,  1, CVCaster,           MC>();
+    runFunctorTestCase11<R(A&&) &&,                1, MoveCaster,         MC>();
+    runFunctorTestCase11<R(A&&) const &&,          1, MoveConstCaster,    MC>();
+    runFunctorTestCase11<R(A&&) volatile &&,       1, MoveVolatileCaster, MC>();
+    runFunctorTestCase11<R(A&&) const volatile &&, 1, MoveCVCaster,       MC>();
+    }
+#endif
+}
diff --git a/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h b/libcxx/test/std/utilities/function.objects/func.require/invoke_helpers.h
new file mode 100644 (file)
index 0000000..0583b62
--- /dev/null
@@ -0,0 +1,317 @@
+#ifndef INVOKE_HELPERS_H
+#define INVOKE_HELPERS_H
+
+#include <type_traits>
+#include <cassert>
+#include <functional>
+
+#include "test_macros.h"
+
+template <int I>
+struct Int : public std::integral_constant<int, I> {};
+
+template <bool P>
+struct Bool : public std::integral_constant<bool, P> {};
+
+struct Q_None {
+    template <class T>
+    struct apply { typedef T type; };
+};
+
+struct Q_Const {
+    template <class T>
+    struct apply { typedef T const type; };
+};
+
+struct Q_Volatile {
+    template <class T>
+    struct apply { typedef T volatile type; };
+};
+
+struct Q_CV {
+    template <class T>
+    struct apply { typedef T const volatile type; };
+};
+
+// Caster - A functor object that performs cv-qualifier and value category
+//   conversions.
+//   QualTag - A metafunction type that applies cv-qualifiers to its argument.
+//   RValue - True if the resulting object should be an RValue reference.
+//            False otherwise.
+template <class QualTag, bool RValue = false>
+struct Caster {
+    template <class T>
+    struct apply {
+        typedef typename std::remove_reference<T>::type RawType;
+        typedef typename QualTag::template apply<RawType>::type CVType;
+#if TEST_STD_VER >= 11
+        typedef typename std::conditional<RValue,
+            CVType&&, CVType&
+        >::type type;
+#else
+        typedef CVType& type;
+#endif
+    };
+
+    template <class T>
+    typename apply<T>::type
+    operator()(T& obj) const {
+        typedef typename apply<T>::type OutType;
+        return static_cast<OutType>(obj);
+    }
+};
+
+typedef Caster<Q_None>           LValueCaster;
+typedef Caster<Q_Const>          ConstCaster;
+typedef Caster<Q_Volatile>       VolatileCaster;
+typedef Caster<Q_CV>             CVCaster;
+typedef Caster<Q_None,     true> MoveCaster;
+typedef Caster<Q_Const,    true> MoveConstCaster;
+typedef Caster<Q_Volatile, true> MoveVolatileCaster;
+typedef Caster<Q_CV,       true> MoveCVCaster;
+
+// A shorter name for 'static_cast'
+template <class QualType, class Tp>
+QualType C_(Tp& v) { return static_cast<QualType>(v); };
+
+//==============================================================================
+// ArgType - A non-copyable type intended to be used as a dummy argument type
+//   to test functions.
+struct ArgType {
+    int value;
+    explicit ArgType(int val = 0) : value(val) {}
+private:
+    ArgType(ArgType const&);
+    ArgType& operator=(ArgType const&);
+};
+
+//==============================================================================
+// DerivedFromBase - A type that derives from it's template argument 'Base'
+template <class Base>
+struct DerivedFromType : public Base {
+    DerivedFromType() : Base() {}
+    template <class Tp>
+    explicit DerivedFromType(Tp const& t) : Base(t) {}
+};
+
+//==============================================================================
+// DerefToType - A type that dereferences to it's template argument 'To'.
+//   The cv-ref qualifiers of the 'DerefToType' object do not propagate
+//   to the resulting 'To' object.
+template <class To>
+struct DerefToType {
+    To object;
+
+    DerefToType() {}
+
+    template <class Up>
+    explicit DerefToType(Up const& val) : object(val) {}
+
+    To& operator*() const volatile { return const_cast<To&>(object); }
+};
+
+//==============================================================================
+// DerefPropToType - A type that dereferences to it's template argument 'To'.
+//   The cv-ref qualifiers of the 'DerefPropToType' object propagate
+//   to the resulting 'To' object.
+template <class To>
+struct DerefPropType {
+    To object;
+
+    DerefPropType() {}
+
+    template <class Up>
+    explicit DerefPropType(Up const& val) : object(val) {}
+
+#if TEST_STD_VER < 11
+    To& operator*() { return object; }
+    To const& operator*() const { return object; }
+    To volatile& operator*() volatile  { return object; }
+    To const volatile& operator*() const volatile { return object; }
+#else
+    To& operator*() & { return object; }
+    To const& operator*() const & { return object; }
+    To volatile& operator*() volatile  & { return object; }
+    To const volatile& operator*() const volatile & { return object; }
+    To&& operator*() && { return static_cast<To &&>(object); }
+    To const&& operator*() const && { return static_cast<To const&&>(object); }
+    To volatile&& operator*() volatile  && { return static_cast<To volatile&&>(object); }
+    To const volatile&& operator*() const volatile && { return static_cast<To const volatile&&>(object); }
+#endif
+};
+
+//==============================================================================
+// MethodID - A type that uniquely identifies a member function for a class.
+//   This type is used to communicate between the member functions being tested
+//   and the tests invoking them.
+// - Test methods should call 'setUncheckedCall()' whenever they are invoked.
+// - Tests consume the unchecked call using checkCall(<return-value>)` to assert
+//   that the method has been called and that the return value of `__invoke`
+//   matches what the method actually returned.
+template <class T>
+struct MethodID {
+    typedef void* IDType;
+
+    static int dummy; // A dummy memory location.
+    static void* id; // The "ID" is the value of this pointer.
+    static bool unchecked_call; // Has a call happened that has not been checked.
+
+    static void*& setUncheckedCall() {
+        assert(unchecked_call == false);
+        unchecked_call = true;
+        return id;
+    }
+
+    static bool checkCalled(void*& return_value) {
+        bool old = unchecked_call;
+        unchecked_call = false;
+        return old && id == return_value && &id == &return_value;
+    }
+};
+
+template <class T> int   MethodID<T>::dummy = 0;
+template <class T> void* MethodID<T>::id = (void*)&MethodID<T>::dummy;
+template <class T> bool  MethodID<T>::unchecked_call = false;
+
+
+//==============================================================================
+// FunctionPtrID - Like MethodID but for free function pointers.
+template <class T, T*>
+struct FunctionPtrID {
+    static int dummy; // A dummy memory location.
+    static void* id; // The "ID" is the value of this pointer.
+    static bool unchecked_call; // Has a call happened that has not been checked.
+
+    static void*& setUncheckedCall() {
+        assert(unchecked_call == false);
+        unchecked_call = true;
+        return id;
+    }
+
+    static bool checkCalled(void*& return_value) {
+        bool old = unchecked_call;
+        unchecked_call = false;
+        return old && id == return_value && &id == &return_value;
+    }
+};
+
+template <class T, T* Ptr> int   FunctionPtrID<T, Ptr>::dummy = 0;
+template <class T, T* Ptr> void* FunctionPtrID<T, Ptr>::id = (void*)&FunctionPtrID<T, Ptr>::dummy;
+template <class T, T* Ptr> bool  FunctionPtrID<T, Ptr>::unchecked_call = false;
+
+//==============================================================================
+// BasicTest - The basic test structure for everything except
+// member object pointers.
+// ID - The "Function Identifier" type used either MethodID or FunctionPtrID.
+// Arity - The Arity of the call signature.
+// ObjectCaster - The object transformation functor type.
+// ArgCaster - The extra argument transformation functor type.
+template <class ID, int Arity, class ObjectCaster = LValueCaster,
+                               class ArgCaster    = LValueCaster>
+struct BasicTest {
+    template <class ObjectT>
+    void runTest(ObjectT& object) {
+        Int<Arity> A;
+        runTestImp(A, object);
+    }
+
+    template <class MethodPtr, class ObjectT>
+    void runTest(MethodPtr ptr, ObjectT& object) {
+        Int<Arity> A;
+        runTestImp(A, ptr, object);
+    }
+
+private:
+    typedef void*& CallRet;
+    ObjectCaster object_cast;
+    ArgCaster arg_cast;
+    ArgType a0, a1, a2;
+
+    //==========================================================================
+    //                       BULLET 1 AND 2 TEST METHODS
+    //==========================================================================
+    template <class MethodPtr, class ObjectT>
+    void runTestImp(Int<0>, MethodPtr ptr, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(ptr, object_cast(object)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(ptr, object_cast(object));
+        assert(ID::checkCalled(ret));
+    }
+
+    template <class MethodPtr, class ObjectT>
+    void runTestImp(Int<1>, MethodPtr ptr, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0));
+        assert(ID::checkCalled(ret));
+    }
+
+    template <class MethodPtr, class ObjectT>
+    void runTestImp(Int<2>, MethodPtr ptr, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1));
+        assert(ID::checkCalled(ret));
+    }
+
+    template <class MethodPtr, class ObjectT>
+    void runTestImp(Int<3>, MethodPtr ptr, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(ptr, object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+        assert(ID::checkCalled(ret));
+    }
+
+    //==========================================================================
+    //                       BULLET 5 TEST METHODS
+    //==========================================================================
+    template <class ObjectT>
+    void runTestImp(Int<0>, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(object_cast(object)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(object_cast(object));
+        assert(ID::checkCalled(ret));
+    }
+
+    template <class ObjectT>
+    void runTestImp(Int<1>, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(object_cast(object), arg_cast(a0)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(object_cast(object), arg_cast(a0));
+        assert(ID::checkCalled(ret));
+    }
+
+    template <class ObjectT>
+    void runTestImp(Int<2>, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1));
+        assert(ID::checkCalled(ret));
+    }
+
+    template <class ObjectT>
+    void runTestImp(Int<3>, ObjectT& object) {
+        static_assert((std::is_same<
+            decltype(std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2)))
+          , CallRet>::value), "");
+        assert(ID::unchecked_call == false);
+        CallRet ret = std::__invoke(object_cast(object), arg_cast(a0), arg_cast(a1), arg_cast(a2));
+        assert(ID::checkCalled(ret));
+    }
+};
+
+#endif // INVOKE_HELPERS_H