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
operatorCaster67 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>
makeConst(Tp & ref)84 Tp const& makeConst(Tp& ref) { return ref; }
85
86 template <class Tp>
makeConst(Tp * ptr)87 Tp const* makeConst(Tp* ptr) { return ptr; }
88
89 template <class Tp>
makeConst(std::reference_wrapper<Tp> & ref)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>
makeVolatile(Tp & ref)95 Tp volatile& makeVolatile(Tp& ref) { return ref; }
96
97 template <class Tp>
makeVolatile(Tp * ptr)98 Tp volatile* makeVolatile(Tp* ptr) { return ptr; }
99
100 template <class Tp>
makeVolatile(std::reference_wrapper<Tp> & ref)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>
makeCV(Tp & ref)106 Tp const volatile& makeCV(Tp& ref) { return ref; }
107
108 template <class Tp>
makeCV(Tp * ptr)109 Tp const volatile* makeCV(Tp* ptr) { return ptr; }
110
111 template <class Tp>
makeCV(std::reference_wrapper<Tp> & ref)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>
C_(Tp & v)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;
valueArgType125 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 {
DerivedFromTypeDerivedFromType135 DerivedFromType() : Base() {}
136 template <class Tp>
DerivedFromTypeDerivedFromType137 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
DerefToTypeDerefToType148 DerefToType() {}
149
150 template <class Up>
DerefToTypeDerefToType151 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
DerefPropTypeDerefPropType164 DerefPropType() {}
165
166 template <class Up>
DerefPropTypeDerefPropType167 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
setUncheckedCallMethodID202 static void*& setUncheckedCall() {
203 assert(unchecked_call == false);
204 unchecked_call = true;
205 return id;
206 }
207
checkCalledMethodID208 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
setUncheckedCallFunctionPtrID228 static void*& setUncheckedCall() {
229 assert(unchecked_call == false);
230 unchecked_call = true;
231 return id;
232 }
233
checkCalledFunctionPtrID234 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>
runTestBasicTest256 void runTest(ObjectT& object) {
257 Int<Arity> A;
258 runTestImp(A, object);
259 }
260
261 template <class MethodPtr, class ObjectT>
runTestBasicTest262 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>
runTestImpBasicTest277 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>
runTestImpBasicTest299 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>
runTestImpBasicTest321 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>
runTestImpBasicTest343 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>
runTestImpBasicTest368 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>
runTestImpBasicTest390 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>
runTestImpBasicTest412 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>
runTestImpBasicTest434 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