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 
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                   `
605                   #ifndef _ENUM_H
606                   #define _ENUM_H
607                       typedef enum {
608                           only_value,
609                       } Enum;
610                   #endif
611                   `);
612 
613         writeFile("hdr1.h",
614                   `
615                       #include "enum.h"
616                   `);
617 
618         writeFile("hdr2.h",
619                   `
620                       #include "enum.h"
621                   `);
622 
623         writeFile("app.dpp",
624                   `
625                       #include "hdr1.h"
626                       #include "hdr2.h"
627                   `);
628 
629         runPreprocessOnly("app.dpp");
630         shouldCompile("app.d");
631     }
632 
633 }
634 
635 @("gregset_t")
636 @safe unittest {
637     shouldCompile(
638         C(
639             `
640                 typedef long long int greg_t;
641                 #define __NGREG 23
642                 typedef greg_t gregset_t[__NGREG];
643             `
644         ),
645         D(
646             q{
647                 static assert(greg_t.sizeof == 8);
648                 static assert(gregset_t.sizeof == 23 * 8);
649             }
650         ),
651     );
652 }
653 
654 
655 @("nv_alloc_ops")
656 @safe unittest {
657     shouldCompile(
658         C(
659             q{
660                 typedef struct Inner_ Inner;
661 
662                 typedef struct Outer {
663                     const Inner *nva_ops;
664                 } Outer;
665 
666                 struct Inner_ {
667                     int dummy;
668                 };
669             }
670         ),
671         D(
672             q{
673             }
674         ),
675     );
676 }
677 
678 @("va_list")
679 @safe unittest {
680     shouldCompile(
681         C(
682             `
683                 #include <stdarg.h>
684                 typedef struct Struct {
685                     int (*func)(int, va_list);
686                 };
687             `
688         ),
689         D(
690             q{
691             }
692         ),
693     );
694 }
695 
696 
697 @("ASN1_ITEM")
698 @safe unittest {
699     shouldCompile(
700         C(
701             q{
702                 struct Foo_st;
703                 typedef struct Foo_st Foo;
704                 extern const Foo gVar;
705             }
706         ),
707         D(
708             q{
709 
710             }
711         ),
712     );
713 }
714 
715 
716 @("X509_get0_extensions")
717 @safe unittest {
718     shouldCompile(
719         C(
720             q{
721                 typedef struct { int dummy; } Param;
722                 struct Ret;
723                 const struct Ret *func(const Param *x);
724             }
725         ),
726         D(
727             q{
728 
729             }
730         ),
731     );
732 }
733 
734 
735 @("double semicolon after function declaration")
736 @safe unittest {
737     shouldCompile(
738         C(
739             q{
740                 void foo(void);;
741             }
742         ),
743         D(
744             q{
745 
746             }
747         ),
748     );
749 }
750 
751 
752 @("_Bool")
753 @safe unittest {
754     shouldCompile(
755         C(
756             `
757                 #include <stdbool.h>
758                 typedef bool handler_t(int, double);
759             `
760         ),
761         D(
762             q{
763                 handler_t handler;
764                 bool b = handler(42, 33.3);
765             }
766         ),
767     );
768 }