1 module it.c.compile.function_;
2 
3 import it;
4 
5 @("nn_strerror")
6 @safe unittest {
7     shouldCompile(
8         C(
9             q{
10                 const char *nn_strerror (int errnum);
11             }
12         ),
13 
14         D(
15             q{
16                 int err = 42;
17                 const(char)* str = nn_strerror(err);
18             }
19         ),
20     );
21 }
22 
23 
24 @("int function(const(char)*)")
25 @safe unittest {
26     shouldCompile(
27         C(
28             q{
29                 typedef int (*function_t)(const char*);
30             }
31         ),
32         D(
33             q{
34                 int ret = function_t.init("foobar".ptr);
35             }
36         ),
37     );
38 }
39 
40 @("const(char)* function(double, int)")
41 @safe unittest {
42     shouldCompile(
43         C(
44             q{
45                 typedef const char* (*function_t)(double, int);
46             }
47 
48         ),
49         D(
50             q{
51                 const(char)* ret = function_t.init(33.3, 42);
52             }
53         ),
54     );
55 }
56 
57 @("void function()")
58 @safe unittest {
59     shouldCompile(
60         C(
61             q{
62                 typedef void (*function_t)(void);
63             }
64         ),
65         D(
66             q{
67                 import std.traits;
68                 import std.meta;
69                 auto f = function_t();
70                 static assert(is(ReturnType!f == void));
71                 static assert(is(Parameters!f == AliasSeq!()));
72             }
73         ),
74     );
75 }
76 
77 @("variadic")
78 @safe unittest {
79     shouldCompile(
80         C(
81             q{
82                 void fun(int, ...);
83             }
84         ),
85         D(
86             q{
87                 fun(42);
88                 fun(42, 33);
89                 fun(42, 33.3);
90                 fun(42, "foobar".ptr);
91             }
92         ),
93     );
94 }
95 
96 @("old uts")
97 @safe unittest {
98     shouldCompile(
99         C(
100             q{
101                 struct Foo { int value; };
102                 struct Bar { int value; };
103                 struct Foo addFoos(struct Foo* foo1, struct Foo* foo2);
104                 struct Bar addBars(const struct Bar* bar1, const struct Bar* bar2);
105                 const char *nn_strerror (int errnum);
106             }
107         ),
108         D(
109             q{
110 
111                 auto f1 = Foo(2);
112                 auto f2 = Foo(3);
113                 Foo f = addFoos(&f1, &f2);
114                 const b1 = Bar(2);
115                 const b2 = Bar(3);
116                 Bar b = addBars(&b1, &b2);
117                 const(char*) msg = nn_strerror(42);
118             }
119         ),
120     );
121 }
122 
123 @("unexposed function pointer variable")
124 @safe unittest {
125     shouldCompile(
126         C(
127             q{
128                 int (*func_t) (int, int);
129             }
130         ),
131         D(
132             q{
133                 int res = func_t.init(2, 3);
134             }
135         ),
136     );
137 }
138 
139 
140 @("enum param")
141 @safe unittest {
142     shouldCompile(
143         C(
144             q{
145                 enum Enum { foo, bar, baz };
146                 void fun(enum Enum e);
147                 enum Enum gun(int i);
148             }
149         ),
150         D(
151             q{
152                 fun(Enum.foo);
153                 Enum ret = gun(42);
154             }
155          ),
156     );
157 }
158 
159 @("typedef enum param")
160 @safe unittest {
161     shouldCompile(
162         C(
163             q{
164                 typedef enum { foo, bar, baz } Enum;
165                 void fun(Enum e);
166                 Enum gun(int i);
167             }
168         ),
169         D(
170             q{
171                 fun(Enum.foo);
172                 Enum ret = gun(42);
173             }
174          ),
175     );
176 }
177 
178 @("enum param function pointer")
179 @safe unittest {
180     shouldCompile(
181         C(
182             q{
183                 enum Enum { foo, bar, baz };
184                 typedef void (*fun)(enum Enum e);
185                 typedef enum Enum (*gun)(int i);
186             }
187         ),
188         D(
189             q{
190                 fun.init(Enum.foo);
191                 Enum ret = gun.init(42);
192             }
193          ),
194     );
195 }
196 
197 @("typedef enum param function pointer")
198 @safe unittest {
199     shouldCompile(
200         C(
201             q{
202                 typedef enum { foo, bar, baz } Enum;
203                 typedef void (*fun)(Enum e);
204                 typedef Enum (*gun)(int i);
205             }
206         ),
207         D(
208             q{
209                 fun.init(Enum.foo);
210                 Enum ret = gun.init(42);
211             }
212          ),
213     );
214 }
215 
216 @("enum param function var")
217 @safe unittest {
218     shouldCompile(
219         C(
220             q{
221                 enum Enum { foo, bar, baz };
222                 void (*fun)(enum Enum e);
223                 enum Enum (*gun)(int i);
224             }
225         ),
226         D(
227             q{
228                 fun(Enum.foo);
229                 Enum ret = gun(42);
230             }
231          ),
232     );
233 }
234 
235 @("typedef enum param function var")
236 @safe unittest {
237     shouldCompile(
238         C(
239             q{
240                 typedef enum { foo, bar, baz } Enum;
241                 void (*fun)(Enum e);
242                 Enum (*gun)(int i);
243             }
244         ),
245         D(
246             q{
247                 fun(Enum.foo);
248                 Enum ret = gun(42);
249             }
250          ),
251     );
252 }
253 
254 
255 @("return pointer to const struct")
256 @safe unittest {
257     shouldCompile(
258         C(
259             q{
260                 typedef struct Foo { int dummy; } Foo;
261                 const Foo* create_foo(int dummy);
262             }
263         ),
264         D(
265             q{
266                 const(Foo)* foo = create_foo(42);
267             }
268          ),
269     );
270 
271 }
272 
273 @Tags("FunctionNoProto")
274 @("function pointer with no parameter types return type unknown struct")
275 @safe unittest {
276     shouldCompile(
277         C(
278             q{
279                 struct Struct {
280                     struct Foo* (*func)();
281                 };
282             }
283         ),
284         D(
285             q{
286                 Struct s;
287                 Foo* foo = s.func();
288             }
289          ),
290     );
291 }
292 
293 @Tags("FunctionNoProto")
294 @("function pointer with no parameter types return type int")
295 @safe unittest {
296     shouldCompile(
297         C(
298             q{
299                 struct Struct {
300                     int (*func)();
301                 };
302             }
303         ),
304         D(
305             q{
306                 Struct s;
307                 int i = s.func();
308             }
309          ),
310     );
311 }
312 
313 
314 
315 @("@nogc nothrow")
316 unittest {
317     shouldCompile(
318         C(
319             q{
320                 void fun(void);
321             }
322         ),
323         D(
324             q{
325                 static void wrapper() @nogc nothrow {
326                     fun();
327                 }
328             }
329         ),
330    );
331 }
332 
333 
334 @("__printf")
335 unittest {
336     shouldCompile(
337         C(
338             `
339                 #define __printf(a, b) __attribute__((format(printf, a, b)))
340                 __printf(1, 2)
341                 void myprintf(const char* fmt, ...);
342             `
343         ),
344         D(
345             q{
346                 auto foo = 42;
347                 myprintf("%d", foo);
348             }
349         ),
350    );
351 }