1 /**
2    Integration tests that stem from failues in real-life C projects
3  */
4 module it.c.compile.projects;
5 
6 import it;
7 
8 @("nn_get_statistic")
9 @safe unittest {
10     shouldCompile(
11         C(
12             // the original uses regular uint64_t, let's beat any special cases
13             // defining our own
14             q{
15                 typedef unsigned long int __my_uint64_t;
16                 typedef __my_uint64_t my_uint64_t;
17                 my_uint64_t nn_get_statistic (int s, int stat);
18             }
19         ),
20 
21         D(
22             q{
23                 int s;
24                 int stat;
25                 my_uint64_t ret = nn_get_statistic(s, stat);
26             }
27         )
28     );
29 }
30 
31 @("__io_read_fn")
32 @safe unittest {
33     shouldCompile(
34         C(
35             q{
36                 typedef long long __ssize_t;
37                 typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, long __nbytes);
38             }
39         ),
40 
41         D(
42             q{
43                 void* cookie;
44                 char[1024] buf;
45                 __ssize_t ret = __io_read_fn.init(cookie, buf.ptr, buf.length);
46             }
47         ),
48     );
49 }
50 
51 @("timer_t")
52 @safe unittest {
53     shouldCompile(
54         C(
55             // the original uses regular uint64_t, let's beat any special cases
56             // defining our own
57             `
58                 #define __TIMER_T_TYPE void *
59                 typedef __TIMER_T_TYPE __timer_t;
60             `
61         ),
62 
63         D(
64             q{
65                 __timer_t timer = null;
66             }
67         ),
68     );
69 }
70 
71 
72 @("curl_multi_wait")
73 @safe unittest {
74     shouldCompile(
75         C(
76             q{
77                 typedef enum { CURLM_OK } CURLMcode;
78                 typedef int curl_socket_t;
79 
80                 struct curl_waitfd {
81                     curl_socket_t fd;
82                     short events;
83                     short revents; /* not supported yet */
84                 };
85 
86                 typedef struct { int dummy; } CURLM;
87                 CURLMcode curl_multi_wait(CURLM *multi_handle,
88                                           struct curl_waitfd extra_fds[],
89                                           unsigned int extra_nfds,
90                                           int timeout_ms,
91                                           int *ret);
92             }
93         ),
94 
95         D(
96             q{
97                 CURLM handle;
98                 curl_waitfd[] extra_fds;
99                 int ret;
100                 CURLMcode code = curl_multi_wait(&handle, extra_fds.ptr, 42u, 33, &ret);
101             }
102          ),
103     );
104 }
105 
106 @("__sigset_t")
107 @safe unittest {
108     shouldCompile(
109         // the original uses regular uint64_t, let's beat any special cases
110         // defining our own
111         C(
112              `
113                  #define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int)))
114                  typedef struct
115                  {
116                      unsigned long int __val[_SIGSET_NWORDS];
117                  } __sigset_t;
118              `
119         ),
120         D(
121             q{
122                 auto s = __sigset_t();
123                 ++s.__val[7];
124             }
125         ),
126     );
127 }
128 
129 
130 @("_IO_flockfile")
131 @safe unittest {
132     shouldCompile(
133         C(
134             `
135                 struct _IO_FILE { int dummy; };
136                 extern void _IO_flockfile (struct _IO_FILE *);
137                 #define _IO_flockfile(_fp)
138             `
139         ),
140         D(
141             q{
142                 _IO_FILE file;
143                 _IO_flockfile(&file);
144             }
145         ),
146     );
147 }
148 
149 @Tags("notravis")
150 @("struct with union")
151 @safe unittest {
152     shouldCompile(
153         C(
154             q{
155                 struct Struct {
156                     union {
157                         void *ptr;
158                         int i;
159                     } data;
160                 };
161                 typedef struct Struct Struct;
162             }
163         ),
164 
165         D(
166             q{
167                 Struct s;
168                 s.data.ptr = null;
169                 s.data.i = 42;
170             }
171         ),
172     );
173 }
174 
175 @("const char* const")
176 @safe unittest {
177     shouldCompile(
178         C(
179             q{
180                 struct Struct {
181                     const char * const *protocols;
182                 };
183                 typedef struct Struct Struct;
184             }
185         ),
186 
187         D(
188             q{
189                 Struct s;
190                 static assert(is(typeof(s.protocols) == const(char*)*),
191                               "Expected const(char*)*, not " ~
192                               typeof(s.protocols).stringof);
193             }
194         ),
195      );
196 }
197 
198 @("forward declaration")
199 @safe unittest {
200     shouldCompile(
201         C(
202             q{
203                 struct Struct;
204                 void fun(struct Struct* s);
205                 struct Struct* make_struct(void);
206             }
207         ),
208 
209         D(
210             q{
211                 Struct* s = make_struct();
212                 fun(s);
213             }
214         ),
215     );
216 }
217 
218 
219 @("restrict")
220 @safe unittest {
221     shouldCompile(
222         C(
223             q{
224                 struct FILE { int dummy; };
225                 extern struct FILE *fopen(const char *restrict filename,
226                                           const char *restrict modes);
227             }
228         ),
229 
230         D(
231             q{
232                 import std.string;
233                 fopen("foo.txt".toStringz, "w".toStringz);
234             }
235         ),
236     );
237 }
238 
239 
240 @("return type typedefd enum")
241 @safe unittest {
242     shouldCompile(
243         C(
244             q{
245                 typedef struct { int dummy; } CURL;
246 
247                 typedef enum {
248                     CURLIOE_OK,            /* I/O operation successful */
249                 } curlioerr;
250 
251                 typedef curlioerr (*curl_ioctl_callback)(CURL *handle,
252                                                          int cmd,
253                                                          void *clientp);
254             }
255         ),
256         D(
257             q{
258                 CURL handle;
259                 auto func = curl_ioctl_callback.init;
260                 curlioerr err = func(&handle, 42, null);
261             }
262         ),
263     );
264 }
265 
266 
267 @("curl_slist")
268 @safe unittest {
269     shouldCompile(
270         C(
271             q{
272                    struct curl_httppost {
273                        struct curl_slist *contentheader;
274                    };
275                    struct curl_slist {
276                        char *data;
277                        struct curl_slist *next;
278                    };
279                }
280         ),
281         D(
282             q{
283                 curl_httppost p;
284                 p.contentheader.data = null;
285                 p.contentheader.next = null;
286                 curl_slist l;
287                 l.data = null;
288                 l.next = null;
289             }
290         ),
291     );
292 }
293 
294 @("struct var collision with var before")
295 @safe unittest {
296     shouldCompile(
297         C(
298             q{
299                 extern int foo;
300                 struct foo { int dummy; };
301             }
302         ),
303         D(
304             q{
305                 auto u = foo(44);
306                 foo_ = 42;
307             }
308         ),
309     );
310 }
311 
312 @("struct function collision with function before")
313 @safe unittest {
314     shouldCompile(
315         C(
316             q{
317                 void foo(void);
318                 struct foo { int dummy; };
319             }
320         ),
321         D(
322             q{
323                 auto u = foo(44);
324                 foo_();
325             }
326         ),
327     );
328 }
329 
330 
331 @("union var collision")
332 @safe unittest {
333     shouldCompile(
334         C(
335             q{
336                 union foo { int dummy; };
337                 extern int foo;
338             }
339         ),
340         D(
341             q{
342                 auto u = foo(44);
343                 foo_ = 42;
344             }
345         ),
346     );
347 }
348 
349 @("enum var collision")
350 @safe unittest {
351     shouldCompile(
352         C(
353             q{
354                 enum foo { one, two, three };
355                 extern int foo;
356             }
357         ),
358         D(
359             q{
360                 auto e = foo.three;
361                 foo_ = 42;
362             }
363         ),
364     );
365 }
366 
367 @("use int for enum parameter")
368 @safe unittest {
369     shouldCompile(
370         C(
371             q{
372                 typedef enum {
373                     foo,
374                     bar,
375                 } Enum;
376                 void func(Enum e);
377             }
378         ),
379         D(
380             q{
381                 func(Enum.bar);
382             }
383         ),
384     );
385 }
386 
387 @("pthread struct")
388 @safe unittest {
389     with(immutable IncludeSandbox()) {
390         writeFile("hdr.h",
391                q{
392                    typedef struct {
393                        void (*routine)(void*);
394                    } Struct;
395                }
396         );
397         writeFile("app.dpp",
398                   `
399                       #include "hdr.h"
400                       extern(C) void foo(void*) {}
401 
402                       void main() {
403                           Struct s;
404                           s.routine = &foo;
405                       }
406                   `
407         );
408 
409         runPreprocessOnly("app.dpp");
410         shouldCompile("app.d");
411     }
412 }
413 
414 
415 @("multiple headers with the same typedef")
416 @safe unittest {
417     with(const IncludeSandbox()) {
418         writeFile("hdr1.h",
419                   q{
420                       typedef long time_t;
421                       typedef long time_t;
422             }
423         ),
424 
425         writeFile("hdr2.h",
426                   q{
427                       typedef long time_t;
428                       typedef long time_t;
429             }
430         ),
431 
432         writeFile("app.dpp",
433                   `
434                       #include "hdr1.h"
435                       #include "hdr2.h"
436                       void main() {
437                           time_t var = 42;
438                       }
439                   `);
440 
441         runPreprocessOnly("app.dpp");
442         shouldCompile("app.d");
443     }
444 }
445 
446 @("jmp_buf")
447 @safe unittest {
448     shouldCompile(
449         C(
450             q{
451                 typedef long int __jmp_buf[8];
452             }
453         ),
454 
455         D(
456             q{
457                 __jmp_buf buf;
458                 static assert(buf.length == 8);
459             }
460         ),
461     );
462 }
463 
464 @("__pthread_unwind_buf_t")
465 @safe unittest {
466     shouldCompile(
467         C(
468             q{
469                 typedef long int __jmp_buf[8];
470                 typedef struct {
471                     struct {
472                         __jmp_buf __cancel_jmp_buf;
473                         int __mask_was_saved;
474                     } __cancel_jmp_buf[1];
475                     void *__pad[4];
476                 } __pthread_unwind_buf_t __attribute__ ((__aligned__));
477             }
478         ),
479 
480         D(
481             q{
482                 __pthread_unwind_buf_t buf;
483             }
484         ),
485     );
486 }
487 
488 
489 @("struct pointer to unknown struct that is defined by a later header")
490 @safe unittest {
491     with(immutable IncludeSandbox()) {
492         writeFile("hdr1.h",
493                   q{
494                       typedef struct Foo {
495                           struct Bar* bar;
496                       } Foo;
497                   });
498         writeFile("hdr2.h",
499                   q{
500                       struct Bar;
501                   });
502         writeFile("app.dpp",
503                   `
504                       #include "hdr1.h"
505                       #include "hdr2.h"
506                       void main() {
507                           Foo f;
508                           f.bar = null;
509                       }
510                   `);
511         runPreprocessOnly("app.dpp");
512         shouldCompile("app.d");
513     }
514 }
515 
516 @("typedef struct pointer with no declaration")
517 @safe unittest {
518     shouldCompile(
519         C(
520             q{
521                 typedef struct _Foo Foo;
522                 typedef Foo *FooPtr;
523             }
524         ),
525         D(
526             q{
527                 void fun(FooPtr ptr) { }
528                 FooPtr ptr;
529                 fun(ptr);
530             }
531         ),
532     );
533 }
534 
535 @("extern global variable with undefined macro")
536 @safe unittest {
537     with(immutable IncludeSandbox()) {
538         writeFile("hdr.h",
539                   q{
540                       // EXPORT_VAR not defined anywhere
541                       typedef struct _Foo Foo;
542                       typedef Foo *FooPtr;
543                       EXPORT_VAR FooPtr theFoo;
544                   });
545         writeFile("app.dpp",
546                   `
547                       #include "hdr.h"
548                   `);
549         try {
550             runPreprocessOnly("app.dpp");
551             assert(0, "Should not get here");
552         } catch(Exception e) {
553             "unknown type name 'EXPORT_VAR'".shouldBeIn(e.msg);
554         }
555     }
556 }
557 
558 @("angle brackets headers with more angle brackets")
559 @safe unittest {
560 
561     with(immutable IncludeSandbox()) {
562 
563         writeFile("includes/libfoo/libfoo.h",
564                   `
565                       #include <libfoo/libfoo-common.h>
566                       #include <libfoo/libfoo-host.h>
567                   `);
568 
569         writeFile("includes/libfoo/libfoo-common.h",
570                   `
571                       #define EXPORT_VAR extern
572                   `);
573 
574         writeFile("includes/libfoo/libfoo-host.h",
575                   q{
576                       typedef struct _Foo Foo;
577                       typedef Foo *FooPtr;
578                   });
579 
580         writeFile("app.dpp",
581                   `
582                       #include <libfoo/libfoo.h>
583                       void func(FooPtr foo) {
584                           assert(foo is null);
585                       }
586                   `);
587 
588         runPreprocessOnly(
589             "--include-path",
590             inSandboxPath("includes"),
591             "app.dpp");
592 
593         shouldCompile("app.d");
594     }
595 }
596 
597 
598 @("double enum typedef")
599 @safe unittest {
600 
601     with(immutable IncludeSandbox()) {
602 
603         writeFile("enum.h",
604                   q{
605                       typedef enum {
606                           only_value,
607                       } Enum;
608                   });
609 
610         writeFile("hdr1.h",
611                   `
612                       #include "enum.h"
613                   `);
614 
615         writeFile("hdr2.h",
616                   `
617                       #include "enum.h"
618                   `);
619 
620         writeFile("app.dpp",
621                   `
622                       #include "hdr1.h"
623                       #include "hdr2.h"
624                   `);
625 
626         runPreprocessOnly("app.dpp");
627         shouldCompile("app.d");
628     }
629 
630 }
631 
632 @("gregset_t")
633 @safe unittest {
634     shouldCompile(
635         C(
636             `
637                 typedef long long int greg_t;
638                 #define __NGREG 23
639                 typedef greg_t gregset_t[__NGREG];
640             `
641         ),
642         D(
643             q{
644                 static assert(greg_t.sizeof == 8);
645                 static assert(gregset_t.sizeof == 23 * 8);
646             }
647         ),
648     );
649 }
650 
651 
652 @("nv_alloc_ops")
653 @safe unittest {
654     shouldCompile(
655         C(
656             q{
657                 typedef struct Inner_ Inner;
658 
659                 typedef struct Outer {
660                     const Inner *nva_ops;
661                 } Outer;
662 
663                 struct Inner_ {
664                     int dummy;
665                 };
666             }
667         ),
668         D(
669             q{
670             }
671         ),
672     );
673 }
674 
675 @("va_list")
676 @safe unittest {
677     shouldCompile(
678         C(
679             `
680                 #include <stdarg.h>
681                 typedef struct Struct {
682                     int (*func)(int, va_list);
683                 };
684             `
685         ),
686         D(
687             q{
688             }
689         ),
690     );
691 }
692 
693 
694 @("ASN1_ITEM")
695 @safe unittest {
696     shouldCompile(
697         C(
698             q{
699                 struct Foo_st;
700                 typedef struct Foo_st Foo;
701                 extern const Foo gVar;
702             }
703         ),
704         D(
705             q{
706 
707             }
708         ),
709     );
710 }
711 
712 
713 @("X509_get0_extensions")
714 @safe unittest {
715     shouldCompile(
716         C(
717             q{
718                 typedef struct { int dummy; } Param;
719                 struct Ret;
720                 const struct Ret *func(const Param *x);
721             }
722         ),
723         D(
724             q{
725 
726             }
727         ),
728     );
729 }
730 
731 
732 @("double semicolon after function declaration")
733 @safe unittest {
734     shouldCompile(
735         C(
736             q{
737                 void foo(void);;
738             }
739         ),
740         D(
741             q{
742 
743             }
744         ),
745     );
746 }
747 
748 
749 @("_Bool")
750 @safe unittest {
751     shouldCompile(
752         C(
753             `
754                 #include <stdbool.h>
755                 typedef bool handler_t(int, double);
756             `
757         ),
758         D(
759             q{
760                 handler_t handler;
761                 bool b = handler(42, 33.3);
762             }
763         ),
764     );
765 }