]> git.proxmox.com Git - rustc.git/blame - src/llvm/include/llvm/ADT/VariadicFunction.h
Imported Upstream version 1.0.0+dfsg1
[rustc.git] / src / llvm / include / llvm / ADT / VariadicFunction.h
CommitLineData
223e47cc
LB
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
970d7e83
LB
14#ifndef LLVM_ADT_VARIADICFUNCTION_H
15#define LLVM_ADT_VARIADICFUNCTION_H
223e47cc
LB
16
17#include "llvm/ADT/ArrayRef.h"
18
19namespace 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/// \brief 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.
104template <typename ResultT, typename ArgT,
105 ResultT (*Func)(ArrayRef<const ArgT *>)>
106struct VariadicFunction {
107 ResultT operator()() const {
1a4d82fc 108 return Func(None);
223e47cc
LB
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 }
116 LLVM_DEFINE_OVERLOAD(1)
117 LLVM_DEFINE_OVERLOAD(2)
118 LLVM_DEFINE_OVERLOAD(3)
119 LLVM_DEFINE_OVERLOAD(4)
120 LLVM_DEFINE_OVERLOAD(5)
121 LLVM_DEFINE_OVERLOAD(6)
122 LLVM_DEFINE_OVERLOAD(7)
123 LLVM_DEFINE_OVERLOAD(8)
124 LLVM_DEFINE_OVERLOAD(9)
125 LLVM_DEFINE_OVERLOAD(10)
126 LLVM_DEFINE_OVERLOAD(11)
127 LLVM_DEFINE_OVERLOAD(12)
128 LLVM_DEFINE_OVERLOAD(13)
129 LLVM_DEFINE_OVERLOAD(14)
130 LLVM_DEFINE_OVERLOAD(15)
131 LLVM_DEFINE_OVERLOAD(16)
132 LLVM_DEFINE_OVERLOAD(17)
133 LLVM_DEFINE_OVERLOAD(18)
134 LLVM_DEFINE_OVERLOAD(19)
135 LLVM_DEFINE_OVERLOAD(20)
136 LLVM_DEFINE_OVERLOAD(21)
137 LLVM_DEFINE_OVERLOAD(22)
138 LLVM_DEFINE_OVERLOAD(23)
139 LLVM_DEFINE_OVERLOAD(24)
140 LLVM_DEFINE_OVERLOAD(25)
141 LLVM_DEFINE_OVERLOAD(26)
142 LLVM_DEFINE_OVERLOAD(27)
143 LLVM_DEFINE_OVERLOAD(28)
144 LLVM_DEFINE_OVERLOAD(29)
145 LLVM_DEFINE_OVERLOAD(30)
146 LLVM_DEFINE_OVERLOAD(31)
147 LLVM_DEFINE_OVERLOAD(32)
148#undef LLVM_DEFINE_OVERLOAD
149};
150
151template <typename ResultT, typename Param0T, typename ArgT,
152 ResultT (*Func)(Param0T, ArrayRef<const ArgT *>)>
153struct VariadicFunction1 {
154 ResultT operator()(Param0T P0) const {
1a4d82fc 155 return Func(P0, None);
223e47cc
LB
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 }
163 LLVM_DEFINE_OVERLOAD(1)
164 LLVM_DEFINE_OVERLOAD(2)
165 LLVM_DEFINE_OVERLOAD(3)
166 LLVM_DEFINE_OVERLOAD(4)
167 LLVM_DEFINE_OVERLOAD(5)
168 LLVM_DEFINE_OVERLOAD(6)
169 LLVM_DEFINE_OVERLOAD(7)
170 LLVM_DEFINE_OVERLOAD(8)
171 LLVM_DEFINE_OVERLOAD(9)
172 LLVM_DEFINE_OVERLOAD(10)
173 LLVM_DEFINE_OVERLOAD(11)
174 LLVM_DEFINE_OVERLOAD(12)
175 LLVM_DEFINE_OVERLOAD(13)
176 LLVM_DEFINE_OVERLOAD(14)
177 LLVM_DEFINE_OVERLOAD(15)
178 LLVM_DEFINE_OVERLOAD(16)
179 LLVM_DEFINE_OVERLOAD(17)
180 LLVM_DEFINE_OVERLOAD(18)
181 LLVM_DEFINE_OVERLOAD(19)
182 LLVM_DEFINE_OVERLOAD(20)
183 LLVM_DEFINE_OVERLOAD(21)
184 LLVM_DEFINE_OVERLOAD(22)
185 LLVM_DEFINE_OVERLOAD(23)
186 LLVM_DEFINE_OVERLOAD(24)
187 LLVM_DEFINE_OVERLOAD(25)
188 LLVM_DEFINE_OVERLOAD(26)
189 LLVM_DEFINE_OVERLOAD(27)
190 LLVM_DEFINE_OVERLOAD(28)
191 LLVM_DEFINE_OVERLOAD(29)
192 LLVM_DEFINE_OVERLOAD(30)
193 LLVM_DEFINE_OVERLOAD(31)
194 LLVM_DEFINE_OVERLOAD(32)
195#undef LLVM_DEFINE_OVERLOAD
196};
197
198template <typename ResultT, typename Param0T, typename Param1T, typename ArgT,
199 ResultT (*Func)(Param0T, Param1T, ArrayRef<const ArgT *>)>
200struct VariadicFunction2 {
201 ResultT operator()(Param0T P0, Param1T P1) const {
1a4d82fc 202 return Func(P0, P1, None);
223e47cc
LB
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 }
211 LLVM_DEFINE_OVERLOAD(1)
212 LLVM_DEFINE_OVERLOAD(2)
213 LLVM_DEFINE_OVERLOAD(3)
214 LLVM_DEFINE_OVERLOAD(4)
215 LLVM_DEFINE_OVERLOAD(5)
216 LLVM_DEFINE_OVERLOAD(6)
217 LLVM_DEFINE_OVERLOAD(7)
218 LLVM_DEFINE_OVERLOAD(8)
219 LLVM_DEFINE_OVERLOAD(9)
220 LLVM_DEFINE_OVERLOAD(10)
221 LLVM_DEFINE_OVERLOAD(11)
222 LLVM_DEFINE_OVERLOAD(12)
223 LLVM_DEFINE_OVERLOAD(13)
224 LLVM_DEFINE_OVERLOAD(14)
225 LLVM_DEFINE_OVERLOAD(15)
226 LLVM_DEFINE_OVERLOAD(16)
227 LLVM_DEFINE_OVERLOAD(17)
228 LLVM_DEFINE_OVERLOAD(18)
229 LLVM_DEFINE_OVERLOAD(19)
230 LLVM_DEFINE_OVERLOAD(20)
231 LLVM_DEFINE_OVERLOAD(21)
232 LLVM_DEFINE_OVERLOAD(22)
233 LLVM_DEFINE_OVERLOAD(23)
234 LLVM_DEFINE_OVERLOAD(24)
235 LLVM_DEFINE_OVERLOAD(25)
236 LLVM_DEFINE_OVERLOAD(26)
237 LLVM_DEFINE_OVERLOAD(27)
238 LLVM_DEFINE_OVERLOAD(28)
239 LLVM_DEFINE_OVERLOAD(29)
240 LLVM_DEFINE_OVERLOAD(30)
241 LLVM_DEFINE_OVERLOAD(31)
242 LLVM_DEFINE_OVERLOAD(32)
243#undef LLVM_DEFINE_OVERLOAD
244};
245
246template <typename ResultT, typename Param0T, typename Param1T,
247 typename Param2T, typename ArgT,
248 ResultT (*Func)(Param0T, Param1T, Param2T, ArrayRef<const ArgT *>)>
249struct VariadicFunction3 {
250 ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const {
1a4d82fc 251 return Func(P0, P1, P2, None);
223e47cc
LB
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 }
260 LLVM_DEFINE_OVERLOAD(1)
261 LLVM_DEFINE_OVERLOAD(2)
262 LLVM_DEFINE_OVERLOAD(3)
263 LLVM_DEFINE_OVERLOAD(4)
264 LLVM_DEFINE_OVERLOAD(5)
265 LLVM_DEFINE_OVERLOAD(6)
266 LLVM_DEFINE_OVERLOAD(7)
267 LLVM_DEFINE_OVERLOAD(8)
268 LLVM_DEFINE_OVERLOAD(9)
269 LLVM_DEFINE_OVERLOAD(10)
270 LLVM_DEFINE_OVERLOAD(11)
271 LLVM_DEFINE_OVERLOAD(12)
272 LLVM_DEFINE_OVERLOAD(13)
273 LLVM_DEFINE_OVERLOAD(14)
274 LLVM_DEFINE_OVERLOAD(15)
275 LLVM_DEFINE_OVERLOAD(16)
276 LLVM_DEFINE_OVERLOAD(17)
277 LLVM_DEFINE_OVERLOAD(18)
278 LLVM_DEFINE_OVERLOAD(19)
279 LLVM_DEFINE_OVERLOAD(20)
280 LLVM_DEFINE_OVERLOAD(21)
281 LLVM_DEFINE_OVERLOAD(22)
282 LLVM_DEFINE_OVERLOAD(23)
283 LLVM_DEFINE_OVERLOAD(24)
284 LLVM_DEFINE_OVERLOAD(25)
285 LLVM_DEFINE_OVERLOAD(26)
286 LLVM_DEFINE_OVERLOAD(27)
287 LLVM_DEFINE_OVERLOAD(28)
288 LLVM_DEFINE_OVERLOAD(29)
289 LLVM_DEFINE_OVERLOAD(30)
290 LLVM_DEFINE_OVERLOAD(31)
291 LLVM_DEFINE_OVERLOAD(32)
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
970d7e83 331#endif // LLVM_ADT_VARIADICFUNCTION_H