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 @HiddenTest("Failing with dmd 2.100.1")
271 @("parameter.exception_ptr")
272 @safe unittest {
273 
274     with(immutable IncludeSandbox()) {
275         writeFile("hdr.hpp",
276                   q{
277                       namespace oops {
278                           namespace le_exception_ptr {
279                               class exception_ptr;
280                           }
281                           using le_exception_ptr::exception_ptr;
282                       }
283 
284                       // make sure the parameter gets translated correctly
285                       // It's referred to as oops::exception_ptr and that's what
286                       // libclang will see, but its real name is
287                       // oops::le_exception_ptr::exception_ptr
288                       void fun(const oops::exception_ptr&);
289                   });
290         writeFile("app.dpp",
291                   `
292                       #include "hdr.hpp"
293                       struct exception_ptr;
294                       void main() {
295                       }
296                   `);
297         runPreprocessOnly(["--ignore-ns", "oops", "app.dpp"]);
298         shouldCompile("app.d");
299     }
300 }
301 
302 
303 @("std::function")
304 @safe unittest {
305 
306     with(immutable IncludeSandbox()) {
307         writeFile("hdr.hpp",
308                   q{
309                       // analogous to std::function
310                       namespace oops {
311                           template<typename> struct function;
312                           template<typename R, typename... Args>
313                           struct function<R(Args...)> {};
314                       }
315 
316                       using Func1D = oops::function<double(double)>;
317 
318                       struct Solver {
319                           double solve(const Func1D&, double, double);
320                       };
321 
322                       // It's important that the return type be explicitly
323                       // oops::function* instead of Func1D
324                       oops::function<double(double)>* newFunction1D(int);
325                   });
326         writeFile("app.dpp",
327                   `
328                       #include "hdr.hpp"
329                       import std.traits: Parameters;
330 
331                       struct function_(T) {}
332 
333                       alias FuncPtr = extern(C++) double function(double);
334                       alias FuncType = typeof(*(FuncPtr.init));
335                       alias ParamType = Parameters!(Solver.solve)[0];
336                       pragma(msg, "ParamType: ", ParamType);
337                       static assert(is(ParamType == const(function_!FuncType)));
338 
339                       void main() {
340                           auto f = newFunction1D(42);
341                       }
342                   `);
343         runPreprocessOnly(["--hard-fail", "--detailed-untranslatable", "--ignore-ns", "oops", "app.dpp"]);
344         shouldCompile("app.d");
345     }
346 }