1 /**
2    Github issues.
3  */
4 module it.issues;
5 
6 import it;
7 
8 version(Posix) // because Windows doesn't have signinfo
9 @Tags("issue")
10 @("3")
11 @safe unittest {
12     shouldCompile(
13         C(
14             `
15                 #include <signal.h>
16             `
17         ),
18         D(
19             q{
20                 siginfo_t si;
21                 si._sifields._timer.si_tid = 2;
22                 static assert(is(typeof(si.si_signo) == int));
23                 static assert(is(typeof(si._sifields._timer.si_tid) == int),
24                               typeof(si._sifields._timer.si_tid).stringof);
25             }
26         ),
27     );
28 }
29 
30 
31 @Tags("issue")
32 @("4")
33 @safe unittest {
34     with(immutable IncludeSandbox()) {
35         writeFile("issue4.h",
36                   q{
37                       extern char *arr[9];
38                   });
39         writeFile("issue4.dpp",
40                   `
41                    #include "issue4.h"
42                   `);
43         runPreprocessOnly("issue4.dpp");
44         fileShouldContain("issue4.d", q{extern __gshared char*[9] arr;});
45     }
46 }
47 
48 @Tags("issue")
49 @("5")
50 @safe unittest {
51     shouldCompile(
52         C(
53             q{
54                 typedef enum zfs_error {
55                     EZFS_SUCCESS = 0,
56                     EZFS_NOMEM = 2000,
57                 };
58 
59                 typedef struct zfs_perm_node {
60                     char z_pname[4096];
61                 } zfs_perm_node_t;
62 
63                 typedef struct libzfs_handle libzfs_handle_t;
64             }
65         ),
66         D(
67             q{
68                 zfs_error e1 = EZFS_SUCCESS;
69                 zfs_error e2 = zfs_error.EZFS_SUCCESS;
70                 zfs_perm_node_t node;
71                 static assert(node.z_pname.sizeof == 4096);
72                 static assert(is(typeof(node.z_pname[0]) == char), (typeof(node.z_pname[0]).stringof));
73                 libzfs_handle_t* ptr;
74             }
75         ),
76     );
77 }
78 
79 @Tags("issue")
80 @("6")
81 @safe unittest {
82     with(immutable IncludeSandbox()) {
83         writeFile("issue6.h",
84                   q{
85                       char *getMessage();
86                   });
87         writeFile("issue6.dpp",
88                   `
89                    #include "issue6.h"
90                   `);
91         runPreprocessOnly("issue6.dpp");
92         fileShouldContain("issue6.d", q{char* getMessage() @nogc nothrow;});
93     }
94 }
95 
96 
97 @Tags("issue", "bitfield")
98 @("7.0")
99 @safe unittest {
100     shouldCompile(
101         C(
102             q{
103                 struct splitflags {
104                     int dryrun : 1;
105                     int import : 2;
106                     int name_flags;
107                     int foo: 3;
108                     int bar: 4;
109                     int suffix;
110                 };
111 
112                 struct other {
113                     int quux: 2;
114                     int toto: 3;
115                 };
116             }
117         ),
118         D(
119             q{
120                 static assert(splitflags.sizeof == 16);
121                 static assert(other.sizeof == 4);
122             }
123         ),
124     );
125 }
126 
127 @Tags("issue", "bitfield")
128 @("7.1")
129 @safe unittest {
130     shouldCompile(
131         C(
132             q{
133                 struct other {
134                     int a: 2;
135                     int b: 3;
136                     // field type of pointer to undeclared struct should not
137                     // affect the generated bitfields' syntax
138                     struct A *ptr;
139                 };
140             }
141         ),
142         D(
143             q{
144                 other o;
145             }
146         ),
147     );
148 }
149 
150 
151 
152 @Tags("issue")
153 @("10")
154 @safe unittest {
155     shouldCompile(
156         C(
157             q{
158                 enum silly_name {
159                     FOO,
160                     BAR,
161                     BAZ,
162                 };
163 
164                 extern void silly_name(enum silly_name thingie);
165             }
166         ),
167         D(
168             q{
169                 silly_name_(silly_name.FOO);
170             }
171         ),
172     );
173 }
174 
175 @Tags("issue")
176 @("11")
177 @safe unittest {
178     shouldCompile(
179         C(
180             q{
181                 struct Foo;
182                 typedef struct Foo* FooPtr;
183             }
184         ),
185         D(
186             q{
187                 FooPtr f = null;
188                 static assert(!__traits(compiles, Foo()));
189             }
190         ),
191     );
192 }
193 
194 @Tags("issue")
195 @("14")
196 @safe unittest {
197     import dpp.runtime.options: Options;
198     with(immutable IncludeSandbox()) {
199 
200         writeFile("foo.h",
201                   q{
202                       typedef int foo;
203                   });
204 
205         runPreprocessOnly("foo.h").shouldThrowWithMessage(
206             "No .dpp input file specified\n" ~ Options.usage);
207     }
208 }
209 
210 @Tags("issue", "preprocessor")
211 @("22.0")
212 @safe unittest {
213     shouldCompile(
214         C(
215             `
216                 typedef struct {
217                     #ifdef __USE_XOPEN
218                         int fds_bits[42];
219                         #define __FDS_BITS(set) ((set)->fds_bits)
220                     #else
221                         int __fds_bits[42];
222                         #define __FDS_BITS(set) ((set)->__fds_bits)
223                     #endif
224                 } fd_set;
225             `
226         ),
227         D(
228             q{
229                 fd_set set;
230                 __FDS_BITS(set)[0] = 42;
231             }
232         ),
233     );
234 }
235 
236 @Tags("issue", "preprocessor")
237 @("22.1")
238 @safe unittest {
239     shouldCompile(
240         C(
241             `
242                 #define SIZEOF(x) (sizeof(x))
243             `
244         ),
245         D(
246             q{
247                 int i;
248                 static assert(SIZEOF(i) == 4);
249             }
250         ),
251     );
252 }
253 
254 @Tags("issue", "preprocessor")
255 @("22.2")
256 @safe unittest {
257     shouldCompile(
258         C(
259             `
260                 typedef long int __fd_mask;
261                 #define __NFDBITS (8 * (int) sizeof (__fd_mask))
262             `
263         ),
264         D(
265             q{
266                 import std.conv;
267                 static assert(__NFDBITS == 8 * c_long.sizeof,
268                               text("expected ", 8 * c_long.sizeof, ", got: ", __NFDBITS));
269             }
270         ),
271     );
272 }
273 
274 @Tags("issue", "preprocessor")
275 @("22.3")
276 @safe unittest {
277     shouldCompile(
278         C(
279             `
280                 typedef struct clist { struct list* next; };
281                 #define clist_next(iter) (iter ? (iter)->next : NULL)
282             `
283         ),
284         D(
285             q{
286                 clist l;
287                 auto next = clist_next(&l);
288             }
289         ),
290     );
291 }
292 
293 
294 
295 @Tags("issue", "collision", "issue24")
296 @("24.0")
297 @safe unittest {
298     shouldCompile(
299         C(
300             q{
301                 struct Bar {
302                     void (*Foo)(void); // this should get renamed as Foo_
303                     struct Foo* (*whatever)(void);
304                 };
305             }
306         ),
307         D(
308             q{
309             }
310         ),
311     );
312 }
313 
314 @Tags("issue", "collision", "issue24")
315 @("24.1")
316 @safe unittest {
317     shouldCompile(
318         C(
319             q{
320                 int foo(int, struct foo_data**);
321                 struct foo { int dummy; };
322                 struct foo_data { int dummy; };
323             }
324         ),
325         D(
326             q{
327                 foo_data** data;
328                 int ret = foo_(42, data);
329                 foo s;
330                 s.dummy = 33;
331                 foo_data fd;
332                 fd.dummy = 77;
333             }
334         ),
335     );
336 }
337 
338 
339 @Tags("issue")
340 @("29.0")
341 @safe unittest {
342     shouldCompile(
343         C(
344             q{
345                 typedef struct {
346                     union {
347                         struct {
348                             double x;
349                             double y;
350                             double z;
351                         };
352                         double raw[3];
353                     };
354                 } vec3d_t;
355             }
356         ),
357         D(
358             q{
359                 vec3d_t v;
360                 static assert(v.sizeof == 24);
361                 v.raw[1] = 3.0;
362                 v.y = 4.0;
363             }
364         ),
365     );
366 }
367 
368 @Tags("issue")
369 @("29.1")
370 @safe unittest {
371     shouldCompile(
372         C(
373             q{
374                 typedef struct {
375                     struct {
376                         int x;
377                         int y;
378                     };
379 
380                     struct {
381                         int z;
382                     };
383                 } Struct;
384             }
385         ),
386         D(
387             q{
388                 Struct s;
389                 s.x = 2;
390                 s.y = 3;
391                 s.z = 4;
392             }
393         ),
394     );
395 }
396 
397 @Tags("issue")
398 @("29.2")
399 @safe unittest {
400     shouldCompile(
401         C(
402             q{
403                 struct Struct {
404                     union {
405                         unsigned long long int foo;
406                         struct {
407                             unsigned int low;
408                             unsigned int high;
409                         } foo32;
410                     };
411                 };
412             }
413         ),
414         D(
415             q{
416                 Struct s;
417                 s.foo = 42;
418                 s.foo32.low = 33;
419                 s.foo32.high = 77;
420             }
421         ),
422     );
423 }
424 
425 
426 @Tags("issue")
427 @("29.3")
428 @safe unittest {
429     shouldCompile(
430         C(
431             q{
432                 struct Struct {
433                     union {
434                         unsigned long long int foo;
435                         void *bar;
436                     };
437                 };
438             }
439         ),
440         D(
441             q{
442                 Struct s;
443                 s.foo = 42;
444                 s.bar = null;
445             }
446         ),
447     );
448 }
449 
450 @Tags("issue")
451 @("29.4")
452 @safe unittest {
453     shouldCompile(
454         C(
455             q{
456                 struct Struct {
457                     union {
458                         int a;
459                         struct {
460                             int b;
461                             union {
462                                 int c;
463                                 char d;
464                             };
465                         };
466                     };
467                 };
468             }
469         ),
470         D(
471             q{
472                 Struct s;
473                 s.a = 42;
474                 s.b = 1337;
475                 s.c = 7;
476                 s.d = 'D';
477             }
478         ),
479     );
480 }
481 
482 
483 
484 @Tags("issue")
485 @("33.0")
486 @safe unittest {
487     shouldCompile(
488         C(
489             q{
490                 void (*f)();
491             }
492         ),
493         D(
494             q{
495                 static extern(C) void printHello() { }
496                 f = &printHello;
497                 f();
498             }
499         ),
500     );
501 }
502 
503 @Tags("issue")
504 @("33.1")
505 @safe unittest {
506     shouldCompile(
507         C(
508             q{
509                 int (*f)();
510             }
511         ),
512         D(
513             q{
514                 static extern(C) int func() { return 42; }
515                 f = &func;
516                 int i = f();
517             }
518         ),
519     );
520 }
521 
522 
523 @Tags("issue", "bitfield")
524 @("35")
525 @safe unittest {
526     shouldCompile(
527         C(
528             q{
529                 struct Struct {
530                     int foo;
531                     int bar;
532                     int :32;
533                     int :31;
534                     int :3;
535                     int :27;
536                 };
537             }
538         ),
539         D(
540             q{
541                 Struct s;
542                 static assert(s.sizeof == 20);
543             }
544         ),
545     );
546 }
547 
548 @Tags("issue")
549 @("37")
550 @safe unittest {
551     shouldCompile(
552         C(
553             `
554                 #include "mmintrin.h"
555             `
556         ),
557         D(
558             q{
559             }
560         ),
561     );
562 }
563 
564 
565 @Tags("issue", "preprocessor")
566 @("39.0")
567 @safe unittest {
568     shouldCompile(
569         C(
570             `
571                 typedef long value;
572                 typedef long intnat;
573                 typedef unsigned long uintnat;
574                 #define Val_long(x) ((intnat) (((uintnat)(x) << 1)) + 1)
575                 #define Long_val(x)     ((x) >> 1)
576                 #define Val_int(x) Val_long(x)
577                 #define Int_val(x) ((int) Long_val(x))
578                 #define Bp_val(v) ((char *) (v))
579                 #define String_val(x) ((const char *) Bp_val(x))
580                 value caml_callback(value, value);
581                 char* strdup(const char* val);
582             `
583         ),
584         D(
585             q{
586                 static value* fib_closure = null;
587                 int n;
588                 auto val = Int_val(caml_callback(*fib_closure, Val_int(n)));
589                 char* str = strdup(String_val(caml_callback(*fib_closure, Val_int(n))));
590             }
591         ),
592     );
593 }
594 
595 @Tags("issue", "preprocessor")
596 @("39.1")
597 @safe unittest {
598     shouldCompile(
599         C(
600             `
601                 #define VOID_PTR(x) ( void* )(x)
602             `
603         ),
604         D(
605             q{
606                 auto val = VOID_PTR(42);
607                 static assert(is(typeof(val) == void*));
608             }
609         ),
610     );
611 }
612 
613 @Tags("issue", "preprocessor")
614 @("39.2")
615 @safe unittest {
616     shouldCompile(
617         C(
618             `
619                 typedef int myint;
620                 #define CAST(x) ( myint* )(x)
621             `
622         ),
623         D(
624             q{
625                 auto val = CAST(42);
626                 static assert(is(typeof(val) == int*));
627             }
628         ),
629     );
630 }
631 
632 @Tags("issue", "preprocessor")
633 @("40")
634 @safe unittest {
635     with(immutable IncludeSandbox()) {
636         writeFile("hdr1.h",
637                   q{
638                       typedef int myint;
639                   });
640         writeFile("hdr2.h",
641                   q{
642                       myint myfunc(void);
643                   });
644         writeFile("src.dpp",
645                   `
646                       #include "hdr1.h"
647                       #include "hdr2.h"
648                       void func() {
649                           myint _ = myfunc();
650                       }
651                   `);
652         runPreprocessOnly("src.dpp");
653         shouldCompile("src.d");
654     }
655 }
656 
657 
658 @Tags("issue")
659 @("43")
660 @safe unittest {
661     shouldCompile(
662         C(
663             q{
664                 // The declaration `int (f)(int x, int y)` is of a function
665                 // parameter that has the type of a binary function that
666                 // returns int. Because C is C, this is similar to writing
667                 // `int f[16]` in a parameter list but actually declaring
668                 // `int*`. The result is a parameter that's a function pointer
669                 // instead. To make things worse, if you put parens around the
670                 // parameter name as is done here, the cursor's type according
671                 // to libclang (in older versions) goes from FunctionProto to
672                 // Unexposed because "reasons".
673                 int binOp(int (f)(int x, int y), int a, int b);
674                 int thef(int x, int y);
675             }
676         ),
677         D(
678             q{
679                 binOp(&thef, 2, 3);
680             }
681         ),
682     );
683 }
684 
685 
686 @Tags("issue")
687 @("44.1")
688 @safe unittest {
689     shouldCompile(
690         C(
691             `
692                 #define macro(x) (x) + 42
693             `
694         ),
695         D(
696             q{
697                 static assert(macro_(0) == 42);
698                 static assert(macro_(1) == 43);
699             }
700         ),
701     );
702 }
703 
704 @Tags("issue")
705 @("44.2")
706 @safe unittest {
707     shouldCompile(
708         C(
709             `
710                 struct macro { int i };
711             `
712         ),
713         D(
714             q{
715             }
716         ),
717     );
718 }
719 
720 
721 @Tags("issue")
722 @("48")
723 @safe unittest {
724     shouldCompile(
725         C(
726             `
727                 #include <stddef.h>
728                 struct Struct {
729                     volatile int x;
730                     volatile size_t y;
731                 };
732             `
733         ),
734         D(
735             q{
736 
737             }
738         ),
739     );
740 }
741 
742 @Tags("issue", "preprocessor")
743 @("49")
744 @safe unittest {
745     shouldCompile(
746         C(
747             `
748                 #define func() ((void)0)
749                 void (func)(void);
750             `
751         ),
752         D(
753             q{
754                 // it gets renamed
755                 func_();
756             }
757         ),
758     );
759 }
760 
761 @Tags("issue")
762 @("53")
763 @safe unittest {
764     shouldCompile(
765         C(
766             q{
767                 typedef int bool;
768             }
769         ),
770         D(
771             q{
772 
773             }
774         ),
775     );
776 }
777 
778 @Tags("issue", "enum")
779 @("54")
780 @safe unittest {
781     shouldCompile(
782         C(
783             q{
784                 enum {
785                     SUCCESS,
786                 };
787                 typedef int boolean;
788             }
789         ),
790         D(
791             q{
792                 static assert(SUCCESS == 0);
793             }
794         ),
795     );
796 }
797 
798 
799 version(linux) // linux specific header in the test
800 @Tags("issue")
801 @("66")
802 @safe unittest {
803     shouldCompile(
804         C(
805             `
806                 #include <linux/ethtool.h>
807             `
808         ),
809         D(
810             q{
811             }
812         ),
813     );
814 }
815 
816 
817 @Tags("issue")
818 @("76")
819 @safe unittest {
820     shouldCompile(
821         Cpp(
822             q{
823                 template <typename T>
824                 struct Template {
825                     T payload;
826                 };
827             }
828         ),
829         D(
830             q{
831                 static assert(__traits(getProtection, Template!int.payload) == "public",
832                               __traits(getProtection, Template!int.payload));
833             }
834         ),
835     );
836 }
837 
838 
839 
840 @Tags("issue")
841 @("77")
842 @safe unittest {
843     with(immutable IncludeSandbox()) {
844         writeFile("hdr.h", "");
845         writeFile("app.dpp",
846                   `
847                       module mymodule;
848                       #include "hdr.h"
849                       void main() {
850                           static assert(__MODULE__ == "mymodule");
851                       }
852                   `);
853         runPreprocessOnly("app.dpp");
854         shouldCompile("app.d");
855     }
856 }
857 
858 @Tags("issue")
859 @("79")
860 unittest {
861     with(const IncludeSandbox()) {
862         writeHeaderAndApp("1st.h",
863                           `
864                               #include "2nd.h"
865                               #define BAR 33
866                               // before the BAR macro, BAR is 42. After, it's 33.
867                           `,
868                           D(""), // no need for .dpp source code
869         );
870         writeFile("2nd.h",
871                   `
872                       // These empty lines are important, since they push the enum
873                       // declaration down to have a higher line number than the BAR macro.
874                       // The bug had to do with ordering.
875                       enum TheEnum { BAR = 42 };
876                   `);
877         run("-c", inSandboxPath("app.dpp"), "--keep-pre-cpp-files");
878     }
879 }
880 
881 
882 @Tags("issue")
883 @("90.0")
884 @safe unittest {
885     shouldCompile(
886         C(
887             `
888                 #define TEST(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
889             `
890         ),
891         D(
892             q{
893             }
894         ),
895     );
896 }
897 
898 @Tags("issue")
899 @("90.1")
900 @safe unittest {
901     shouldCompile(
902         C(
903             `
904                 #define TEST(_ARR) ((int)(sizeof(_ARR)/sizeof(_ARR[0])))
905             `
906         ),
907         D(
908             q{
909                 int[8] ints;
910                 static assert(TEST(ints) == 8);
911             }
912         ),
913     );
914 }
915 
916 @Tags("issue")
917 @("91.0")
918 @safe unittest {
919     shouldCompile(
920         Cpp(
921             q{
922                 template <typename T, typename U> class Test {};
923                 void test(Test<unsigned short, unsigned int> a);
924             }
925         ),
926         D(
927             q{
928                 test(Test!(ushort, uint)());
929             }
930         ),
931     );
932 }
933 
934 @Tags("issue")
935 @("91.1")
936 @safe unittest {
937     shouldCompile(
938         Cpp(
939             q{
940                 template <typename T, int> class Test {};
941                 void test(Test<unsigned short, 42> a);
942             }
943         ),
944         D(
945             q{
946                 test(Test!(ushort, 42)());
947             }
948         ),
949     );
950 }
951 
952 
953 @Tags("issue")
954 @("93")
955 @safe unittest {
956     shouldCompile(
957         Cpp(
958             q{
959                 constexpr int x = sizeof(int) + (1) + sizeof(int);
960             }
961         ),
962         D(
963             q{
964                 static assert(x == 9);
965             }
966         ),
967     );
968 }
969 
970 
971 @Tags("issue")
972 @("95")
973 @safe unittest {
974     shouldCompile(
975         Cpp(
976             q{
977                 constexpr int x = sizeof(int) + alignof(int) + sizeof(int);
978             }
979         ),
980         D(
981             q{
982                 static assert(x == 12);
983             }
984         ),
985     );
986 }
987 
988 
989 @Tags("issue")
990 @("96")
991 @safe unittest {
992     shouldCompile(
993         Cpp(
994             q{
995                 template<unsigned long A, int B> class C{
996                     enum { value = 0 };
997                 };
998                 template<> class C<3,4> {
999                     enum { value = 1 };
1000                 };
1001             }
1002         ),
1003         D(
1004             q{
1005                 static assert(C!(0, 0).value == 0);
1006                 static assert(C!(0, 1).value == 0);
1007                 static assert(C!(1, 0).value == 0);
1008 
1009                 static assert(C!(3, 4).value == 1);
1010             }
1011         ),
1012     );
1013 }
1014 
1015 
1016 @Tags("issue")
1017 @("97")
1018 @safe unittest {
1019     shouldCompile(
1020         Cpp(
1021             q{
1022                 class T1 {
1023                 public:
1024                     int i;
1025                 };
1026 
1027                 template<int I>
1028                 class T2 {
1029                 public:
1030                     double d;
1031                 };
1032 
1033                 extern T1 a;
1034                 extern T2<3> b;
1035             }
1036         ),
1037         D(
1038             q{
1039                 a.i = 33;
1040                 b.d = 33.3;
1041             }
1042         ),
1043     );
1044 }
1045 
1046 
1047 @Tags("issue")
1048 @("99")
1049 @safe unittest {
1050     shouldCompile(
1051         Cpp(
1052             q{
1053                 class A {
1054                 public:
1055                     constexpr static int i = 0;
1056                     constexpr static int j = A::i;
1057                 };
1058             }
1059         ),
1060         D(
1061             q{
1062                 static assert(A.i == 0);
1063                 static assert(A.j == 0);
1064             }
1065         ),
1066     );
1067 }
1068 
1069 
1070 @ShouldFail("cursor.enumConstantValue returning 0 for `value = I`")
1071 @Tags("issue")
1072 @("100")
1073 @safe unittest {
1074     shouldCompile(
1075         Cpp(
1076             q{
1077                 class T1 {
1078                     enum { value = 42 };
1079                 };
1080 
1081                 template<int I>
1082                 class T2 {
1083                     enum { value = I };
1084                 };
1085             }
1086         ),
1087         D(
1088             q{
1089                 static assert(T1.value == 42);
1090                 static assert(T2!2.value == 2);
1091                 static assert(T2!3.value == 3);
1092             }
1093         ),
1094     );
1095 }
1096 
1097 
1098 @Tags("issue")
1099 @("101")
1100 @safe unittest {
1101     // SO tells me the standard insists upon unsigned long long
1102     // and apparently so does MSVC... but linux doesn't. idk why.
1103     // see: https://stackoverflow.com/a/16596909/1457000
1104     version(Windows)
1105         string type = "unsigned long long";
1106     else
1107         string type = "unsigned long";
1108     shouldCompile(
1109         Cpp(
1110             q{
1111                 // normally without the underscore
1112                 int operator "" _s(const wchar_t* __str, } ~ type ~ q{ __len);
1113             }
1114         ),
1115         D(
1116             q{
1117             }
1118         ),
1119     );
1120 }
1121 
1122 
1123 @Tags("issue")
1124 @("103.0")
1125 @safe unittest {
1126     with(immutable IncludeSandbox()) {
1127         writeFile("hdr.h",
1128                   "#define CONSTANT 42\n");
1129         writeFile("hdr.dpp",
1130                   `
1131                       #include "hdr.h"
1132                   `);
1133         writeFile("app.d",
1134                   q{
1135                       import hdr;
1136                       static assert(CONSTANT == 42);
1137                   });
1138 
1139         runPreprocessOnly("hdr.dpp");
1140         shouldCompile("app.d");
1141     }
1142 }
1143 
1144 
1145 @Tags("issue")
1146 @("103.1")
1147 @safe unittest {
1148     with(immutable IncludeSandbox()) {
1149         writeFile("hdr.h",
1150                   "#define OCTAL 00177\n");
1151         writeFile("hdr.dpp",
1152                   `
1153                       #include "hdr.h"
1154                   `);
1155         writeFile("app.d",
1156                   q{
1157                       import hdr;
1158                       static assert(OCTAL == 127);
1159                   });
1160 
1161         runPreprocessOnly("hdr.dpp");
1162         shouldCompile("app.d");
1163     }
1164 }
1165 
1166 
1167 @Tags("issue")
1168 @("103.2")
1169 @safe unittest {
1170     with(immutable IncludeSandbox()) {
1171         writeFile("hdr.h",
1172                   "#define STRING \"foobar\"\n");
1173         writeFile("hdr.dpp",
1174                   `
1175                       #include "hdr.h"
1176                   `);
1177         writeFile("app.d",
1178                   q{
1179                       import hdr;
1180                       static assert(STRING == "foobar");
1181                   });
1182 
1183         runPreprocessOnly("hdr.dpp");
1184         shouldCompile("app.d");
1185     }
1186 }
1187 
1188 
1189 @Tags("issue")
1190 @("103.3")
1191 @safe unittest {
1192     with(immutable IncludeSandbox()) {
1193         writeFile("hdr.h",
1194                   `
1195                       #define BASE 5
1196                       #define OPT0 (BASE * 16 + 0)
1197                       #define OPT1 (BASE * 16 + 1)
1198                   `
1199         );
1200         writeFile("hdr.dpp",
1201                   `
1202                       #include "hdr.h"
1203                   `);
1204         writeFile("app.d",
1205                   q{
1206                       import hdr;
1207                       static assert(BASE == 5);
1208                       static assert(OPT0 == 80);
1209                       static assert(OPT1 == 81);
1210                   });
1211 
1212         runPreprocessOnly("hdr.dpp");
1213         shouldCompile("app.d");
1214     }
1215 }
1216 
1217 
1218 
1219 @ShouldFail
1220 @Tags("issue")
1221 @("104")
1222 @safe unittest {
1223     shouldCompile(
1224         Cpp(
1225             q{
1226                 template <int> struct Struct{};
1227                 template<>
1228                 struct Struct<1 + 1> {
1229                     static constexpr auto value = 42;
1230                 };
1231             }
1232         ),
1233         D(
1234             q{
1235                 static assert(Struct!2.value == 42);
1236             }
1237         ),
1238    );
1239 }
1240 
1241 
1242 @Tags("issue")
1243 @("108")
1244 @safe unittest {
1245     shouldCompile(
1246         Cpp(
1247             q{
1248                 template<class T1, class T2, int I>
1249                 class A {};
1250 
1251                 template <typename CC> class C {};
1252 
1253                 template<>
1254                 class A<C<int>, double, 42> {};
1255             }
1256         ),
1257         D(
1258             q{
1259 
1260             }
1261         ),
1262     );
1263 }
1264 
1265 
1266 @Tags("issue")
1267 @("109")
1268 @safe unittest {
1269     shouldCompile(
1270         Cpp(
1271             q{
1272                 template<typename C> class Test
1273                 {
1274                     bool operator==(const Test<C>& x) const { return 0; }
1275                     bool operator<(const Test<C>& x)  const { return 0; }
1276                     bool operator>(const Test<C>& x)  const { return 0; }
1277                 };
1278             }
1279         ),
1280         D(
1281             q{
1282                 const t = Test!int();
1283                 const eq = t == t;
1284                 const lt = t < t;
1285                 const gt = t > t;
1286             }
1287         ),
1288     );
1289 }
1290 
1291 
1292 @Tags("issue")
1293 @("110")
1294 @safe unittest {
1295     shouldCompile(
1296         Cpp(
1297             q{
1298                 class A {
1299                     bool operator_a() const;
1300                 };
1301             }
1302         ),
1303         D(
1304             q{
1305                 auto a = new const A;
1306                 bool ret = a.operator_a();
1307             }
1308         ),
1309     );
1310 }
1311 
1312 
1313 
1314 @Tags("issue", "namespace")
1315 @("113")
1316 @safe unittest {
1317     shouldCompile(
1318         Cpp(
1319             q{
1320                 // the issue here was nested namespaces
1321                 namespace ns1 {
1322                     namespace ns2 {
1323                         struct Struct;
1324 
1325                         template<typename T>
1326                             struct Template {
1327                         };
1328 
1329                         class Class;  // should be ignored but isn't
1330                         class Class: public Template<Struct> {
1331                             int i;
1332                         };
1333                     }
1334                 }
1335             }
1336         ),
1337         D(
1338             q{
1339             }
1340         ),
1341     );
1342 }
1343 
1344 
1345 @Tags("issue")
1346 @("114")
1347 @safe unittest {
1348     shouldCompile(
1349         Cpp(
1350             q{
1351                 template<class T>
1352                 struct Foo {
1353                     template<class U>
1354                     Foo& operator=(U& other) {
1355                         return *this;
1356                     }
1357                 };
1358             }
1359         ),
1360         D(
1361             q{
1362                 Foo!int foo;
1363                 int i;
1364                 foo = i;
1365                 double d;
1366                 foo = d;
1367             }
1368         ),
1369     );
1370 }
1371 
1372 
1373 @Tags("issue")
1374 @("115")
1375 @safe unittest {
1376     shouldCompile(
1377         Cpp(
1378             q{
1379                 template<class T>
1380                 class Foo {
1381                     T value;
1382                 public:
1383                     Foo(T value);
1384                 };
1385 
1386                 template<class T>
1387                 Foo<T>::Foo(T val) {
1388                     value = val;
1389                 }
1390             }
1391         ),
1392         D(
1393             q{
1394                 auto fooI = Foo!int(42);
1395                 auto fooD = Foo!double(33.3);
1396             }
1397         ),
1398     );
1399 }
1400 
1401 
1402 @Tags("issue")
1403 @("116")
1404 @safe unittest {
1405     shouldCompile(
1406         Cpp(
1407             q{
1408                 struct Foo;
1409                 struct Foo { int i; };
1410             }
1411         ),
1412         D(
1413             q{
1414                 static assert(is(typeof(Foo.i) == int));
1415             }
1416         ),
1417     );
1418 }
1419 
1420 
1421 @Tags("issue")
1422 @("119.0")
1423 @safe unittest {
1424     shouldCompile(
1425         Cpp(
1426             q{
1427                 struct Struct {
1428                     enum Enum { foo, bar, baz };
1429                 };
1430 
1431                 void fun(Struct::Enum);
1432             }
1433         ),
1434         D(
1435             q{
1436             }
1437         ),
1438     );
1439 }
1440 
1441 
1442 @Tags("issue")
1443 @("119.1")
1444 @safe unittest {
1445     shouldCompile(
1446         Cpp(
1447             q{
1448                 struct Struct {
1449                     enum class Enum { foo, bar, baz };
1450                 };
1451             }
1452         ),
1453         D(
1454             q{
1455                 auto f = Struct.Enum.foo;
1456                 static assert(!__traits(compiles, Struct.foo));
1457             }
1458         ),
1459     );
1460 }
1461 
1462 
1463 @ShouldFail("libclang fails to tokenise this for some reason")
1464 @Tags("issue", "libclang")
1465 @("119.2")
1466 @safe unittest {
1467     with(immutable IncludeSandbox()) {
1468 
1469         writeFile("util.hpp",
1470                   `
1471                       #define MAKE_ENUM_CLASS(type, values) enum class type { values };
1472                   `);
1473 
1474         writeFile("hdr.hpp",
1475                   `
1476                       #include "util.hpp"
1477                       #define VALUES X(foo) X(bar) X(baz)
1478                       #define X(n) n,
1479                           MAKE_ENUM_CLASS(Enum, VALUES)
1480                       #undef X
1481                   `);
1482 
1483         writeFile("app.dpp",
1484                   `
1485                   #include "hdr.hpp"
1486                   void main() {
1487                       auto f = Enum.foo;
1488                       static assert(!__traits(compiles, foo));
1489                   }
1490                   `);
1491 
1492         runPreprocessOnly(["app.dpp"]);
1493         shouldCompile("app.d");
1494     }
1495 }
1496 
1497 
1498 @Tags("issue")
1499 @("134")
1500 @safe unittest {
1501     shouldCompile(
1502         Cpp(
1503             q{
1504                 struct Foo {
1505                     double fun(int i) const;
1506                 };
1507 
1508                 double Foo::fun(int i) const {
1509                     return i * 2;
1510                 }
1511             }
1512         ),
1513         D(
1514             q{
1515                 auto foo = Foo();
1516                 double d = foo.fun(42);
1517             }
1518         ),
1519     );
1520 }
1521 
1522 
1523 @Tags("namespace", "issue")
1524 @("149")
1525 @safe unittest {
1526     shouldCompile(
1527         Cpp(
1528             q{
1529                 namespace ns {
1530                     struct Struct;
1531 
1532                     template<typename T>
1533                     struct Template { };
1534 
1535                     // The `Struct` template parameter must be translated properly
1536                     // and was showing up as ns.Struct
1537                     class Class: public Template<Struct> {
1538                         int i;
1539                     };
1540                 }
1541             }
1542         ),
1543         D(
1544             q{
1545             }
1546         ),
1547     );
1548 }
1549 
1550 
1551 @Tags("issue")
1552 @("150")
1553 @safe unittest {
1554     shouldCompile(
1555         Cpp(
1556             q{
1557                 struct Foo {
1558                     int a, b, c;
1559                 };
1560 
1561                 struct Bar {
1562                     Foo& foo;
1563                 };
1564             }
1565         ),
1566         D(
1567             q{
1568                 import std.conv: text;
1569                 static assert(Foo.sizeof == 12, Foo.sizeof.text);
1570                 static assert(Foo.alignof == 4, Foo.alignof.text);
1571                 static assert(Bar.sizeof == 8, Bar.sizeof.text);
1572                 static assert(Bar.alignof == 8, Bar.alignof.text);
1573             }
1574         ),
1575     );
1576 }
1577 
1578 
1579 @Tags("issue")
1580 @("151")
1581 @safe unittest {
1582     shouldRun(
1583         Cpp(
1584             q{
1585                 struct Foo {
1586                     long data;
1587                 };
1588 
1589                 struct Bar {
1590                     static long numDtors;
1591                     long data;
1592                     ~Bar();
1593                 };
1594 
1595                 Foo makeFoo();
1596                 Bar makeBar();
1597             }
1598         ),
1599         Cpp(
1600             q{
1601                 Foo makeFoo() { return {}; }
1602                 Bar makeBar() { return {}; }
1603                 Bar::~Bar() { ++numDtors; }
1604                 long Bar::numDtors;
1605             }
1606         ),
1607         D(
1608             q{
1609                 import std.conv: text;
1610 
1611                 auto foo = makeFoo;
1612                 assert(foo.data == 0, foo.data.text);
1613 
1614                 {
1615                     auto bar = makeBar;
1616                     assert(bar.data == 0, bar.data.text);
1617                     bar.data = 42;
1618                     assert(bar.numDtors == 0, bar.numDtors.text);
1619                 }
1620 
1621                 assert(Bar.numDtors == 1, Bar.numDtors.text);
1622             }
1623         ),
1624     );
1625 }
1626 
1627 
1628 @("missing.template.parameter")
1629 @safe unittest {
1630     shouldCompile(
1631         Cpp(
1632             q{
1633                 namespace myns {
1634                     template<typename T>
1635                     struct vector {
1636                         T* elements;
1637                         long size;
1638                     };
1639                 }
1640 
1641                 struct Problem {
1642                     // In the issue this gets emitted as `vector values`
1643                     // instead of `vector!double values`
1644                     myns::vector<double> values;
1645                 };
1646 
1647                 Problem createProblem();
1648             }
1649         ),
1650         D(
1651             q{
1652             }
1653         ),
1654    );
1655 }
1656 
1657 @Tags("issue")
1658 @("168")
1659 // @("gcc.__extention__")
1660 // Examples:
1661 //    /usr/include/netinet/in.h
1662 //    /usr/include/x86_64-linux-gnu/bits/cpu-set.h
1663 @safe unittest {
1664     shouldCompile(
1665         C(
1666             `
1667                 #define FOO(bar) {__extension__({bar;})
1668             `
1669         ),
1670         D(
1671             q{
1672             }
1673         )
1674     );
1675 }
1676 
1677 
1678 @Tags("issue")
1679 @("172")
1680 @safe unittest {
1681     shouldCompile(
1682         Cpp(
1683             q{
1684                 struct virtual_base {
1685                     virtual_base() = default;
1686                     virtual ~virtual_base() = default;
1687                     virtual_base(virtual_base&&) = default;
1688                     virtual_base(const virtual_base&) = default;
1689                     virtual_base& operator=(virtual_base&&) = default;
1690                     virtual_base& operator=(const virtual_base&) = default;
1691                 };
1692             }
1693         ),
1694         D(
1695             q{
1696             }
1697         )
1698     );
1699 }
1700 
1701 
1702 @HiddenTest("Needs the cl_platform.h header on the machine")
1703 @Tags("issue")
1704 @("175")
1705 @safe unittest {
1706     shouldCompile(
1707         C(
1708             `
1709 #include "CL/cl_platform.h"
1710             `
1711         ),
1712         D(
1713             q{
1714             }
1715         )
1716     );
1717 }
1718 
1719 
1720 @Tags("issue")
1721 @("207")
1722 @safe unittest {
1723     shouldCompile(
1724         C(
1725             `
1726                 #define FOO 1
1727                 #define BAR 2
1728                 #define BAZ 4
1729                 #define ALL ( \
1730                     FOO | \
1731                     BAR | \
1732                     BAZ \
1733                 )
1734             `
1735         ),
1736         D(
1737             q{
1738                 static assert(ALL == 7);
1739             }
1740         )
1741     );
1742 }
1743 
1744 
1745 version(Linux) {
1746     @Tags("issue")
1747         @("229.0")
1748         @safe unittest {
1749         with(immutable IncludeSandbox()) {
1750             writeFile(`app.dpp`,
1751                       `
1752                           module foo.linux.bar;
1753                       `
1754             );
1755             runPreprocessOnly("app.dpp");
1756             shouldNotCompile("app.d");
1757         }
1758     }
1759 
1760 
1761     @Tags("issue")
1762         @("229.1")
1763         @safe unittest {
1764         with(immutable IncludeSandbox()) {
1765             writeFile(`app.dpp`,
1766                       `
1767                           #undef linux
1768                           module foo.linux.bar;
1769                       `
1770             );
1771             runPreprocessOnly("app.dpp");
1772             shouldCompile("app.d");
1773         }
1774     }
1775 }
1776 
1777 
1778 
1779 @Tags("issue")
1780 @("237")
1781 @safe unittest {
1782     shouldCompile(
1783         C(
1784             `
1785             #define GPIO_AFR(n, af)			((af) << ((n) * 4))
1786             #define GPIO_AFR_MASK(n)		(0xf << ((n) * 4))
1787             `
1788         ),
1789         D(
1790             q{
1791             }
1792         )
1793     );
1794 }