1 module it.cpp.opaque;
2 
3 
4 import it;
5 
6 
7 @("field.private")
8 @safe unittest {
9     shouldCompile(
10         Cpp(
11             q{
12                 namespace myns {
13                     template<typename T>
14                     struct vector {
15                         T* elements;
16                         long size;
17                     };
18                 }
19 
20                 struct Problem {
21                     long length();
22                 private:
23                     myns::vector<double> values;
24                 };
25 
26                 Problem createProblem();
27             }
28         ),
29         D(
30             q{
31                 // this should have been ignored
32                 static assert(!is(vector!double));
33                 static assert(Problem.sizeof == 16);
34                 auto problem = Problem();
35                 long l = problem.length();
36             }
37         ),
38         ["--ignore-ns", "myns"],
39    );
40 }
41 
42 
43 @("field.public")
44 @safe unittest {
45     with(immutable IncludeSandbox()) {
46         writeFile("hdr.hpp",
47                   q{
48                       namespace oops {
49                           struct Date {};
50                       }
51 
52                       struct DateUser {
53                           // Using it as a parameter caused dpp to define it for
54                           // the user in `Context.declaredUnknownStructs`/
55                           // This prevents the user from defining it.
56                           void fun(oops::Date*);
57                       };
58 
59                       struct Foo {
60                           // these need to be made opaque
61                           oops::Date start;
62                           oops::Date end;
63                       };
64 
65                   });
66         writeFile("app.dpp",
67                   `
68                       #include "hdr.hpp"
69                       struct Date{} // the definition will be skipped
70                       void main() {
71                       }
72                   `);
73         runPreprocessOnly(["--ignore-ns", "oops", "app.dpp"]);
74         shouldCompile("app.d");
75     }
76 }
77 
78 
79 @("field.static")
80 @safe unittest {
81     shouldCompile(
82         Cpp(
83             q{
84                 namespace oops {
85                     struct Widget {};
86                 }
87 
88                 class Foo {
89                 private:
90                     // this is private so shouldn't show up
91                     static oops::Widget widget;
92                 };
93             }
94         ),
95         D(
96             q{
97             }
98         ),
99         ["--ignore-ns", "oops"],
100    );
101 }
102 
103 
104 @ShouldFail
105 @("base")
106 @safe unittest {
107     shouldCompile(
108         Cpp(
109             q{
110                 namespace myns {
111                     struct Base{};
112                 }
113 
114                 struct Derived: public myns::Base {
115 
116                 };
117             }
118         ),
119         D(
120             q{
121                 auto derived = Derived();
122             }
123         ),
124         ["--ignore-ns", "myns"],
125    );
126 }
127 
128 
129 @("parameter.ref.const")
130 @safe unittest {
131     with(immutable IncludeSandbox()) {
132         writeFile("hdr.hpp",
133                   q{
134                       namespace myns {
135                           struct Forbidden{};
136                       }
137 
138                       struct Foo {
139                           void fun(const myns::Forbidden&);
140                       };
141                   });
142         writeFile("app.dpp",
143                   `
144                       #include "hdr.hpp"
145                       struct Forbidden;
146                       void main() {
147                       }
148                   `);
149         runPreprocessOnly(["--ignore-ns", "myns", "app.dpp"]);
150         shouldCompile("app.d");
151     }
152 }
153 
154 
155 @("parameter.value")
156 @safe unittest {
157     shouldCompile(
158         Cpp(
159             q{
160                 namespace myns {
161                     struct Forbidden{
162                         int i;
163                     };
164                 }
165 
166                 struct Foo {
167                     void fun(myns::Forbidden);
168                 };
169             }
170         ),
171         D(
172             q{
173                 dpp.Opaque!4 forbidden = void;
174                 auto foo = Foo();
175                 foo.fun(forbidden);
176             }
177         ),
178         ["--ignore-ns", "myns"],
179    );
180 }
181 
182 
183 
184 @("return.ref.const")
185 @safe unittest {
186 
187     with(immutable IncludeSandbox()) {
188         writeFile("hdr.hpp",
189                   q{
190                       namespace myns {
191                           struct Forbidden{};
192                       }
193 
194                       struct Foo {
195                           const myns::Forbidden& fun();
196                       };
197                   });
198         writeFile("app.dpp",
199                   `
200                       #include "hdr.hpp"
201                       struct Forbidden;
202                       void main() {
203                       }
204                   `);
205         runPreprocessOnly(["--ignore-ns", "myns", "app.dpp"]);
206         shouldCompile("app.d");
207     }
208 }
209 
210 
211 @("return.value")
212 @safe unittest {
213     shouldCompile(
214         Cpp(
215             q{
216                 namespace myns {
217                     struct Forbidden{
218                         int i;
219                     };
220                 }
221 
222                 struct Foo {
223                     myns::Forbidden fun();
224                 };
225             }
226         ),
227         D(
228             q{
229                 auto foo = Foo();
230                 auto blob = foo.fun();
231                 static assert(is(typeof(blob.bytes) == void[4]));
232             }
233         ),
234         ["--ignore-ns", "myns"],
235    );
236 }
237 
238 
239 @("parameter.vector")
240 @safe unittest {
241 
242     with(immutable IncludeSandbox()) {
243         writeFile("hdr.hpp",
244                   q{
245                       namespace oops {
246                           template<typename T>
247                               struct vector {};
248                       }
249 
250                       namespace myns {
251                           struct Foo {};
252                       }
253 
254                       // make sure the paremeter gets translated correctly
255                       void fun(oops::vector<myns::Foo>&);
256                   });
257         writeFile("app.dpp",
258                   `
259                       #include "hdr.hpp"
260                       struct vector(T);
261                       void main() {
262                       }
263                   `);
264         runPreprocessOnly(["--ignore-ns", "oops", "app.dpp"]);
265         shouldCompile("app.d");
266     }
267 }
268 
269 
270 @("parameter.exception_ptr")
271 @safe unittest {
272 
273     with(immutable IncludeSandbox()) {
274         writeFile("hdr.hpp",
275                   q{
276                       namespace oops {
277                           namespace le_exception_ptr {
278                               class exception_ptr;
279                           }
280                           using le_exception_ptr::exception_ptr;
281                       }
282 
283                       // make sure the parameter gets translated correctly
284                       // It's referred to as oops::exception_ptr and that's what
285                       // libclang will see, but its real name is
286                       // oops::le_exception_ptr::exception_ptr
287                       void fun(const oops::exception_ptr&);
288                   });
289         writeFile("app.dpp",
290                   `
291                       #include "hdr.hpp"
292                       struct exception_ptr;
293                       void main() {
294                       }
295                   `);
296         runPreprocessOnly(["--ignore-ns", "oops", "app.dpp"]);
297         shouldCompile("app.d");
298     }
299 }
300 
301 
302 @("std::function")
303 @safe unittest {
304 
305     with(immutable IncludeSandbox()) {
306         writeFile("hdr.hpp",
307                   q{
308                       // analogous to std::function
309                       namespace oops {
310                           template<typename> struct function;
311                           template<typename R, typename... Args>
312                           struct function<R(Args...)> {};
313                       }
314 
315                       using Func1D = oops::function<double(double)>;
316 
317                       struct Solver {
318                           double solve(const Func1D&, double, double);
319                       };
320 
321                       // It's important that the return type be explicitly
322                       // oops::function* instead of Func1D
323                       oops::function<double(double)>* newFunction1D(int);
324                   });
325         writeFile("app.dpp",
326                   `
327                       #include "hdr.hpp"
328                       import std.traits: Parameters;
329 
330                       struct function_(T) {}
331 
332                       alias FuncPtr = extern(C++) double function(double);
333                       alias FuncType = typeof(*(FuncPtr.init));
334                       alias ParamType = Parameters!(Solver.solve)[0];
335                       pragma(msg, "ParamType: ", ParamType);
336                       static assert(is(ParamType == const(function_!FuncType)));
337 
338                       void main() {
339                           auto f = newFunction1D(42);
340                       }
341                   `);
342         runPreprocessOnly(["--hard-fail", "--detailed-untranslatable", "--ignore-ns", "oops", "app.dpp"]);
343         shouldCompile("app.d");
344     }
345 }