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 }