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