LLVM  8.0.1
VariadicFunction.h
Go to the documentation of this file.
1 //===--- VariadicFunctions.h - Variadic Functions ---------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements compile-time type-safe variadic functions.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_ADT_VARIADICFUNCTION_H
15 #define LLVM_ADT_VARIADICFUNCTION_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 
19 namespace llvm {
20 
21 // Define macros to aid in expanding a comma separated series with the index of
22 // the series pasted onto the last token.
23 #define LLVM_COMMA_JOIN1(x) x ## 0
24 #define LLVM_COMMA_JOIN2(x) LLVM_COMMA_JOIN1(x), x ## 1
25 #define LLVM_COMMA_JOIN3(x) LLVM_COMMA_JOIN2(x), x ## 2
26 #define LLVM_COMMA_JOIN4(x) LLVM_COMMA_JOIN3(x), x ## 3
27 #define LLVM_COMMA_JOIN5(x) LLVM_COMMA_JOIN4(x), x ## 4
28 #define LLVM_COMMA_JOIN6(x) LLVM_COMMA_JOIN5(x), x ## 5
29 #define LLVM_COMMA_JOIN7(x) LLVM_COMMA_JOIN6(x), x ## 6
30 #define LLVM_COMMA_JOIN8(x) LLVM_COMMA_JOIN7(x), x ## 7
31 #define LLVM_COMMA_JOIN9(x) LLVM_COMMA_JOIN8(x), x ## 8
32 #define LLVM_COMMA_JOIN10(x) LLVM_COMMA_JOIN9(x), x ## 9
33 #define LLVM_COMMA_JOIN11(x) LLVM_COMMA_JOIN10(x), x ## 10
34 #define LLVM_COMMA_JOIN12(x) LLVM_COMMA_JOIN11(x), x ## 11
35 #define LLVM_COMMA_JOIN13(x) LLVM_COMMA_JOIN12(x), x ## 12
36 #define LLVM_COMMA_JOIN14(x) LLVM_COMMA_JOIN13(x), x ## 13
37 #define LLVM_COMMA_JOIN15(x) LLVM_COMMA_JOIN14(x), x ## 14
38 #define LLVM_COMMA_JOIN16(x) LLVM_COMMA_JOIN15(x), x ## 15
39 #define LLVM_COMMA_JOIN17(x) LLVM_COMMA_JOIN16(x), x ## 16
40 #define LLVM_COMMA_JOIN18(x) LLVM_COMMA_JOIN17(x), x ## 17
41 #define LLVM_COMMA_JOIN19(x) LLVM_COMMA_JOIN18(x), x ## 18
42 #define LLVM_COMMA_JOIN20(x) LLVM_COMMA_JOIN19(x), x ## 19
43 #define LLVM_COMMA_JOIN21(x) LLVM_COMMA_JOIN20(x), x ## 20
44 #define LLVM_COMMA_JOIN22(x) LLVM_COMMA_JOIN21(x), x ## 21
45 #define LLVM_COMMA_JOIN23(x) LLVM_COMMA_JOIN22(x), x ## 22
46 #define LLVM_COMMA_JOIN24(x) LLVM_COMMA_JOIN23(x), x ## 23
47 #define LLVM_COMMA_JOIN25(x) LLVM_COMMA_JOIN24(x), x ## 24
48 #define LLVM_COMMA_JOIN26(x) LLVM_COMMA_JOIN25(x), x ## 25
49 #define LLVM_COMMA_JOIN27(x) LLVM_COMMA_JOIN26(x), x ## 26
50 #define LLVM_COMMA_JOIN28(x) LLVM_COMMA_JOIN27(x), x ## 27
51 #define LLVM_COMMA_JOIN29(x) LLVM_COMMA_JOIN28(x), x ## 28
52 #define LLVM_COMMA_JOIN30(x) LLVM_COMMA_JOIN29(x), x ## 29
53 #define LLVM_COMMA_JOIN31(x) LLVM_COMMA_JOIN30(x), x ## 30
54 #define LLVM_COMMA_JOIN32(x) LLVM_COMMA_JOIN31(x), x ## 31
55 
56 /// Class which can simulate a type-safe variadic function.
57 ///
58 /// The VariadicFunction class template makes it easy to define
59 /// type-safe variadic functions where all arguments have the same
60 /// type.
61 ///
62 /// Suppose we need a variadic function like this:
63 ///
64 /// ResultT Foo(const ArgT &A_0, const ArgT &A_1, ..., const ArgT &A_N);
65 ///
66 /// Instead of many overloads of Foo(), we only need to define a helper
67 /// function that takes an array of arguments:
68 ///
69 /// ResultT FooImpl(ArrayRef<const ArgT *> Args) {
70 /// // 'Args[i]' is a pointer to the i-th argument passed to Foo().
71 /// ...
72 /// }
73 ///
74 /// and then define Foo() like this:
75 ///
76 /// const VariadicFunction<ResultT, ArgT, FooImpl> Foo;
77 ///
78 /// VariadicFunction takes care of defining the overloads of Foo().
79 ///
80 /// Actually, Foo is a function object (i.e. functor) instead of a plain
81 /// function. This object is stateless and its constructor/destructor
82 /// does nothing, so it's safe to create global objects and call Foo(...) at
83 /// any time.
84 ///
85 /// Sometimes we need a variadic function to have some fixed leading
86 /// arguments whose types may be different from that of the optional
87 /// arguments. For example:
88 ///
89 /// bool FullMatch(const StringRef &S, const RE &Regex,
90 /// const ArgT &A_0, ..., const ArgT &A_N);
91 ///
92 /// VariadicFunctionN is for such cases, where N is the number of fixed
93 /// arguments. It is like VariadicFunction, except that it takes N more
94 /// template arguments for the types of the fixed arguments:
95 ///
96 /// bool FullMatchImpl(const StringRef &S, const RE &Regex,
97 /// ArrayRef<const ArgT *> Args) { ... }
98 /// const VariadicFunction2<bool, const StringRef&,
99 /// const RE&, ArgT, FullMatchImpl>
100 /// FullMatch;
101 ///
102 /// Currently VariadicFunction and friends support up-to 3
103 /// fixed leading arguments and up-to 32 optional arguments.
104 template <typename ResultT, typename ArgT,
105  ResultT (*Func)(ArrayRef<const ArgT *>)>
107  ResultT operator()() const {
108  return Func(None);
109  }
110 
111 #define LLVM_DEFINE_OVERLOAD(N) \
112  ResultT operator()(LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
113  const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
114  return Func(makeArrayRef(Args)); \
115  }
148 #undef LLVM_DEFINE_OVERLOAD
149 };
150 
151 template <typename ResultT, typename Param0T, typename ArgT,
152  ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
154  ResultT operator()(Param0T P0) const {
155  return Func(P0, None);
156  }
157 
158 #define LLVM_DEFINE_OVERLOAD(N) \
159  ResultT operator()(Param0T P0, LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
160  const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
161  return Func(P0, makeArrayRef(Args)); \
162  }
195 #undef LLVM_DEFINE_OVERLOAD
196 };
197 
198 template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
199  ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
201  ResultT operator()(Param0T P0, Param1T P1) const {
202  return Func(P0, P1, None);
203  }
204 
205 #define LLVM_DEFINE_OVERLOAD(N) \
206  ResultT operator()(Param0T P0, Param1T P1, \
207  LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
208  const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
209  return Func(P0, P1, makeArrayRef(Args)); \
210  }
243 #undef LLVM_DEFINE_OVERLOAD
244 };
245 
246 template <typename ResultT, typename Param0T, typename Param1T,
247  typename Param2T, typename ArgT,
248  ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
250  ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
251  return Func(P0, P1, P2, None);
252  }
253 
254 #define LLVM_DEFINE_OVERLOAD(N) \
255  ResultT operator()(Param0T P0, Param1T P1, Param2T P2, \
256  LLVM_COMMA_JOIN ## N(const ArgT &A)) const { \
257  const ArgT *const Args[] = { LLVM_COMMA_JOIN ## N(&A) }; \
258  return Func(P0, P1, P2, makeArrayRef(Args)); \
259  }
292 #undef LLVM_DEFINE_OVERLOAD
293 };
294 
295 // Cleanup the macro namespace.
296 #undef LLVM_COMMA_JOIN1
297 #undef LLVM_COMMA_JOIN2
298 #undef LLVM_COMMA_JOIN3
299 #undef LLVM_COMMA_JOIN4
300 #undef LLVM_COMMA_JOIN5
301 #undef LLVM_COMMA_JOIN6
302 #undef LLVM_COMMA_JOIN7
303 #undef LLVM_COMMA_JOIN8
304 #undef LLVM_COMMA_JOIN9
305 #undef LLVM_COMMA_JOIN10
306 #undef LLVM_COMMA_JOIN11
307 #undef LLVM_COMMA_JOIN12
308 #undef LLVM_COMMA_JOIN13
309 #undef LLVM_COMMA_JOIN14
310 #undef LLVM_COMMA_JOIN15
311 #undef LLVM_COMMA_JOIN16
312 #undef LLVM_COMMA_JOIN17
313 #undef LLVM_COMMA_JOIN18
314 #undef LLVM_COMMA_JOIN19
315 #undef LLVM_COMMA_JOIN20
316 #undef LLVM_COMMA_JOIN21
317 #undef LLVM_COMMA_JOIN22
318 #undef LLVM_COMMA_JOIN23
319 #undef LLVM_COMMA_JOIN24
320 #undef LLVM_COMMA_JOIN25
321 #undef LLVM_COMMA_JOIN26
322 #undef LLVM_COMMA_JOIN27
323 #undef LLVM_COMMA_JOIN28
324 #undef LLVM_COMMA_JOIN29
325 #undef LLVM_COMMA_JOIN30
326 #undef LLVM_COMMA_JOIN31
327 #undef LLVM_COMMA_JOIN32
328 
329 } // end namespace llvm
330 
331 #endif // LLVM_ADT_VARIADICFUNCTION_H
const NoneType None
Definition: None.h:24
This class represents lattice values for constants.
Definition: AllocatorList.h:24
ResultT operator()() const
ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
#define LLVM_DEFINE_OVERLOAD(N)
ResultT operator()(Param0T P0, Param1T P1) const
ResultT operator()(Param0T P0) const
Class which can simulate a type-safe variadic function.