241 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// <functional>10 11// INVOKE (f, t1, t2, ..., tN)12 13//------------------------------------------------------------------------------14// TESTING INVOKE(f, t1, t2, ..., tN)15// - Bullet 7 -- f(t2, ..., tN)16//17// Overview:18// Bullet 7 handles the cases where the first argument is not a member19// function.20//21// Concerns:22// 1) Different types of callable objects are supported. Including23// 1a) Free Function pointers and references.24// 1b) Classes which provide a call operator25// 1c) lambdas26// 2) The callable objects are perfect forwarded.27// 3) The arguments are perfect forwarded.28// 4) Signatures which include varargs are supported.29// 5) In C++03 3 extra arguments should be allowed.30//31// Plan:32// 1) Define a set of free functions, 'SF', and class types with call33// operators, 'SC', that address concerns 4 and 5. The free functions should34// return 'FunctionID::setUncheckedCall()' and the call operators should35// return 'MethodID::setUncheckedCall()'.36//37// 2) For each function 'f' in 'SF' and 'SC' attempt to call 'f'38// using the correct number of arguments and cv-ref qualifiers. Check that39// 'f' has been called using 'FunctionID::checkCall()' if 'f' is a free40// function and 'MethodID::checkCall()' otherwise.41 42 43 44#include <functional>45#include <type_traits>46#include <cassert>47 48#include "test_macros.h"49#include "invoke_helpers.h"50 51 52//==============================================================================53// freeFunction03 - A C++03 free function.54void*& freeFunction03() {55 return FunctionPtrID<void*&(), freeFunction03>::setUncheckedCall();56}57 58void*& freeFunction03(...) {59 return FunctionPtrID<void*&(...), freeFunction03>::setUncheckedCall();60}61 62template <class A0>63void*& freeFunction03(A0&) {64 return FunctionPtrID<void*&(A0&), freeFunction03>::setUncheckedCall();65}66 67 68template <class A0>69void*& freeFunction03(A0&, ...) {70 return FunctionPtrID<void*&(A0&, ...), freeFunction03>::setUncheckedCall();71}72 73template <class A0, class A1>74void*& freeFunction03(A0&, A1&) {75 return FunctionPtrID<void*&(A0&, A1&), freeFunction03>::setUncheckedCall();76}77 78 79template <class A0, class A1>80void*& freeFunction03(A0&, A1&, ...) {81 return FunctionPtrID<void*&(A0&, A1&, ...), freeFunction03>::setUncheckedCall();82}83 84template <class A0, class A1, class A2>85void*& freeFunction03(A0&, A1&, A2&) {86 return FunctionPtrID<void*&(A0&, A1&, A2&), freeFunction03>::setUncheckedCall();87}88 89template <class A0, class A1, class A2>90void*& freeFunction03(A0&, A1&, A2&, ...) {91 return FunctionPtrID<void*&(A0&, A1&, A2&, ...), freeFunction03>::setUncheckedCall();92}93 94//==============================================================================95// Functor03 - C++03 compatible functor object96struct Functor03 {97 typedef void*& R;98 typedef Functor03 C;99#define F(Args, ...) \100 __VA_ARGS__ R operator() Args { return MethodID<R(C::*) Args>::setUncheckedCall(); } \101 __VA_ARGS__ R operator() Args const { return MethodID<R(C::*) Args const>::setUncheckedCall(); } \102 __VA_ARGS__ R operator() Args volatile { return MethodID<R(C::*) Args volatile>::setUncheckedCall(); } \103 __VA_ARGS__ R operator() Args const volatile { return MethodID<R(C::*) Args const volatile>::setUncheckedCall(); }104#105 F(())106 F((A0&), template <class A0>)107 F((A0&, A1&), template <class A0, class A1>)108 F((A0&, A1&, A2&), template <class A0, class A1, class A2>)109#undef F110public:111 Functor03() {}112private:113 Functor03(Functor03 const&);114 Functor03& operator=(Functor03 const&);115};116 117 118//==============================================================================119// TestCaseFunctorImp - A test case for an operator() class method.120// ClassType - The type of the call object.121// CallSig - The function signature of the call operator being tested.122// Arity - the arity of 'CallSig'123// ObjCaster - Transformation function applied to call object.124// ArgCaster - Transformation function applied to the extra arguments.125template <class ClassType, class CallSig, int Arity,126 class ObjCaster, class ArgCaster = LValueCaster>127struct TestCaseFunctorImp {128public:129 static void run() {130 typedef MethodID<CallSig ClassType::*> MID;131 BasicTest<MID, Arity, ObjCaster, ArgCaster> t;132 typedef ClassType T;133 typedef DerivedFromType<T> D;134 T obj;135 D der;136 t.runTest(obj);137 t.runTest(der);138 }139};140 141//==============================================================================142// TestCaseFreeFunction - A test case for a free function.143// CallSig - The function signature of the free function being tested.144// FnPtr - The function being tested.145// Arity - the arity of 'CallSig'146// ArgCaster - Transformation function to be applied to the extra arguments.147template <class CallSig, CallSig* FnPtr, int Arity, class ArgCaster>148struct TestCaseFreeFunction {149public:150 static void run() {151 typedef FunctionPtrID<CallSig, FnPtr> FID;152 BasicTest<FID, Arity, LValueCaster, ArgCaster> t;153 154 DerefToType<CallSig*> deref_to(FnPtr);155 DerefToType<CallSig&> deref_to_ref(*FnPtr);156 157 t.runTest(FnPtr);158 t.runTest(*FnPtr);159 t.runTest(deref_to);160 t.runTest(deref_to_ref);161 }162};163 164//==============================================================================165// runTest Helpers166//==============================================================================167template <class Sig, int Arity, class ArgCaster>168void runFunctionTestCase() {169 TestCaseFreeFunction<Sig, freeFunction03, Arity, ArgCaster>();170}171 172template <class Sig, int Arity, class ObjCaster, class ArgCaster>173void runFunctorTestCase() {174 TestCaseFunctorImp<Functor03, Sig, Arity, ObjCaster, ArgCaster>::run();175}176 177template <class Sig, int Arity, class ObjCaster>178void runFunctorTestCase() {179 TestCaseFunctorImp<Functor03, Sig, Arity, ObjCaster>::run();180}181 182// runTestCase - Run a test case for both function and functor types.183template <class Sig, int Arity, class ArgCaster>184void runTestCase() {185 runFunctionTestCase<Sig, Arity, ArgCaster>();186 runFunctorTestCase <Sig, Arity, LValueCaster, ArgCaster>();187};188 189int main(int, char**) {190 typedef void*& R;191 typedef ArgType A;192 typedef A const CA;193 194 runTestCase< R(), 0, LValueCaster >();195 runTestCase< R(A&), 1, LValueCaster >();196 runTestCase< R(A&, A&), 2, LValueCaster >();197 runTestCase< R(A&, A&, A&), 3, LValueCaster >();198 runTestCase< R(CA&), 1, ConstCaster >();199 runTestCase< R(CA&, CA&), 2, ConstCaster >();200 runTestCase< R(CA&, CA&, CA&), 3, ConstCaster >();201 202 runFunctionTestCase<R(...), 0, LValueCaster >();203 runFunctionTestCase<R(A&, ...), 1, LValueCaster >();204 runFunctionTestCase<R(A&, A&, ...), 2, LValueCaster >();205 runFunctionTestCase<R(A&, A&, A&, ...), 3, LValueCaster >();206 207 runFunctorTestCase<R(), 0, LValueCaster >();208 runFunctorTestCase<R() const, 0, ConstCaster >();209 runFunctorTestCase<R() volatile, 0, VolatileCaster >();210 runFunctorTestCase<R() const volatile, 0, CVCaster >();211 runFunctorTestCase<R(A&), 1, LValueCaster >();212 runFunctorTestCase<R(A&) const, 1, ConstCaster >();213 runFunctorTestCase<R(A&) volatile, 1, VolatileCaster >();214 runFunctorTestCase<R(A&) const volatile, 1, CVCaster >();215 runFunctorTestCase<R(A&, A&), 2, LValueCaster >();216 runFunctorTestCase<R(A&, A&) const, 2, ConstCaster >();217 runFunctorTestCase<R(A&, A&) volatile, 2, VolatileCaster >();218 runFunctorTestCase<R(A&, A&) const volatile, 2, CVCaster >();219 runFunctorTestCase<R(A&, A&, A&), 3, LValueCaster >();220 runFunctorTestCase<R(A&, A&, A&) const, 3, ConstCaster >();221 runFunctorTestCase<R(A&, A&, A&) volatile, 3, VolatileCaster >();222 runFunctorTestCase<R(A&, A&, A&) const volatile, 3, CVCaster >();223 {224 typedef ConstCaster CC;225 runFunctorTestCase<R(CA&), 1, LValueCaster, CC>();226 runFunctorTestCase<R(CA&) const, 1, ConstCaster, CC>();227 runFunctorTestCase<R(CA&) volatile, 1, VolatileCaster, CC>();228 runFunctorTestCase<R(CA&) const volatile, 1, CVCaster, CC>();229 runFunctorTestCase<R(CA&, CA&), 2, LValueCaster, CC>();230 runFunctorTestCase<R(CA&, CA&) const, 2, ConstCaster, CC>();231 runFunctorTestCase<R(CA&, CA&) volatile, 2, VolatileCaster, CC>();232 runFunctorTestCase<R(CA&, CA&) const volatile, 2, CVCaster, CC>();233 runFunctorTestCase<R(CA&, CA&, CA&), 3, LValueCaster, CC>();234 runFunctorTestCase<R(CA&, CA&, CA&) const, 3, ConstCaster, CC>();235 runFunctorTestCase<R(CA&, CA&, CA&) volatile, 3, VolatileCaster, CC>();236 runFunctorTestCase<R(CA&, CA&, CA&) const volatile, 3, CVCaster, CC>();237 }238 239 return 0;240}241