1 module it.c.compile.preprocessor;
2 
3 
4 import it;
5 
6 
7 @("simple macro")
8 @safe unittest {
9     shouldCompile(
10         C(
11             `
12                 #define FOO 5
13             `
14         ),
15         D(
16             q{
17                 int[FOO] foos;
18                 static assert(foos.length == 5, "Wrong length for foos");
19             }
20         )
21     );
22 }
23 
24 @("define macro, undefine, then define again")
25 @safe unittest {
26     shouldCompile(
27         C(
28             `
29                 #define FOO foo
30                 #undef FOO
31                 #define FOO bar
32                 int FOO(int i);
33             `
34         ),
35         D(
36             q{
37                 int i = bar(2);
38             }
39         )
40     );
41 }
42 
43 
44 @("include guards")
45 @safe unittest {
46     with(immutable IncludeSandbox()) {
47         writeFile("hdr.h",
48                   `#ifndef HAHA
49                    #    define HAHA
50                    int inc(int);
51                    #endif`);
52         writeFile("foo.dpp",
53                   `#include "hdr.h"
54                    import bar;
55                    int func(int i) { return inc(i) * 2; }`);
56         writeFile("bar.dpp",
57                   `#include "hdr.h";
58                    int func(int i) { return inc(i) * 3; }`);
59 
60         runPreprocessOnly("foo.dpp");
61         runPreprocessOnly("bar.dpp");
62         shouldCompile("foo.d");
63     }
64 }
65 
66 
67 @("octal.whitespace")
68 @safe unittest {
69     shouldCompile(
70         C(
71             `
72                 #define FOO	   00
73             `
74         ),
75         D(
76             q{
77             }
78         )
79     );
80 
81 }
82 
83 
84 @("elaborate")
85 @safe unittest {
86     shouldCompile(
87         C(
88             `
89                 struct Foo {};
90                 #define STRUCT_HEAD \
91                     int count; \
92                     struct Foo *foo;
93             `
94         ),
95         D(
96             q{
97                 static struct Derived {
98                     STRUCT_HEAD
99                 }
100 
101                 auto d = Derived();
102                 d.count = 42;
103                 d.foo = null;
104             }
105         )
106     );
107 }
108 
109 
110 version(Posix)  // FIXME
111 @("multiline")
112 @safe unittest {
113     shouldCompile(
114         C(
115             `
116                 // WARNING: don't attempt to tidy up the formatting here or the
117                 // test is actually changed
118 #define void_to_int_ptr(x) ( \
119     (int *) x \
120 )
121             `
122         ),
123         D(
124             q{
125                 import std.stdio: writeln;
126                 int a = 7;
127                 void *p = &a;
128                 auto intPtr = void_to_int_ptr(p);
129             }
130         )
131     );
132 }
133 
134 @("func")
135 @safe unittest {
136     with(immutable IncludeSandbox()) {
137         writeFile("hdr.h",
138                   `#define FOO(x) ((x) * 2)
139                    #define BAR(x, y) ((x) + (y))
140                    #define BAZ(prefix, ...) text(prefix, __VA_ARGS__)
141                    #define STR(x) #x
142                    #define ARGH(x) STR(I like spaces x)
143                    #define NOARGS() ((short) 42)`);
144 
145         writeFile("foo.dpp",
146                   [`#include "hdr.h"`,
147                    `import std.conv : text;`]);
148         writeFile("bar.d",
149                   q{
150                       import foo;
151                       static assert(FOO(2) == 4);
152                       static assert(FOO(3) == 6);
153                       static assert(BAR(2, 3) == 5);
154                       static assert(BAR(3, 4) == 7);
155                       static assert(BAZ("prefix_", 42, "foo") == "prefix_42foo");
156                       static assert(BAZ("prefix_", 42, "foo", "bar") == "prefix_42foobar");
157                       static assert(NOARGS() == 42);
158                   });
159 
160         runPreprocessOnly("--function-macros", "foo.dpp");
161         shouldCompile("foo.d");
162         shouldCompile("bar.d");
163     }
164 }
165 
166 @("cast.param")
167 @safe unittest {
168     shouldCompile(
169         C(
170             `
171                 #define MEMBER_SIZE(T, member) sizeof(((T*)0)-> member)
172                 struct Struct { int i; };
173             `
174         ),
175         D(
176             q{
177                 static assert(MEMBER_SIZE(Struct, i) == 4);
178             }
179         ),
180     );
181 }
182 
183 @("cast.uchar")
184 @safe unittest {
185     shouldCompile(
186         C(
187             `
188                 #define CHAR_MASK(c) ((unsigned char)((c) & 0xff))
189             `
190         ),
191         D(
192             q{
193                 static assert(CHAR_MASK(0xab) == 0xab);
194                 static assert(CHAR_MASK(0xf1) == 0xf1);
195                 static assert(CHAR_MASK(0x1f) == 0x1f);
196                 static assert(CHAR_MASK(0xff) == 0xff);
197             }
198         ),
199     );
200 }
201 
202 @("dowhile")
203 @safe unittest {
204     shouldCompile(
205         C(
206             `
207 #define Py_BUILD_ASSERT(cond)  do {         \
208         (void)Py_BUILD_ASSERT_EXPR(cond);   \
209     } while(0)
210             `
211         ),
212         D(
213             q{
214             }
215         ),
216         ["--function-macros"],
217     );
218 
219 }
220 
221 @("vartype")
222 @safe unittest {
223     shouldCompile(
224         C(
225             `
226                 #define DOC_VAR(name) static const char name[]
227             `
228         ),
229         D(
230             q{
231             }
232         ),
233         ["--function-macros"],
234     );
235 }