1 /** 2 C++ tests that must run 3 */ 4 module it.cpp.run; 5 6 import it; 7 8 @Tags("run") 9 @("ctor") 10 @safe unittest { 11 shouldCompileAndRun( 12 Cpp( 13 q{ 14 struct Struct { 15 void *data; 16 17 Struct(); 18 Struct(int i); 19 Struct(const Struct&); 20 Struct(Struct&&); 21 22 int number() const; 23 }; 24 } 25 ), 26 Cpp( 27 ` 28 #include <iostream> 29 using namespace std; 30 Struct::Struct(int i) { 31 cout << "C++: int ctor" << endl; 32 data = new int(i); 33 } 34 Struct::Struct(const Struct& other) { 35 cout << "C++: copy ctor" << endl; 36 data = new int(*reinterpret_cast<int*>(other.data) - 1); 37 } 38 Struct::Struct(Struct&& other) { 39 cout << "C++: move ctor" << endl; 40 data = other.data; 41 *reinterpret_cast<int*>(data) = number() + 1; 42 } 43 int Struct::number() const { return *reinterpret_cast<int*>(data); } 44 ` 45 ), 46 D( 47 q{ 48 import std.stdio; 49 import std.process; 50 51 const dCompiler = environment.get("DC", "dmd"); 52 53 writeln("D: Testing int ctor"); 54 auto cs = const Struct(42); 55 assert(cs.number() == 42); 56 assert(*(cast(int*)cs.data) == 42); 57 auto ms = Struct(7); 58 59 writeln("D: Testing copy ctor"); 60 { 61 auto s = Struct(cs); 62 assert(s.number() == 41); 63 assert(cs.data !is s.data); 64 } 65 { 66 auto s = Struct(ms); 67 assert(s.number() == 6); 68 assert(cs.data !is s.data); 69 } 70 71 writeln("D: Testing move ctor"); 72 auto tmp = Struct(33); 73 const oldTmpData = tmp.data; 74 auto mv1 = Struct(dpp.move(tmp)); 75 assert(mv1.number() == 34); 76 assert(mv1.data is oldTmpData); 77 assert(tmp.data is null); 78 79 static assert(!__traits(compiles, Struct(dpp.move(cs)))); 80 81 if(dCompiler != "dmd") { 82 auto mv2 = Struct(Struct(77)); 83 assert(mv2.number() == 78); 84 } 85 86 static assert(!__traits(compiles, Struct())); 87 } 88 ), 89 ); 90 } 91 92 93 @Tags("run") 94 @("dtor") 95 @safe unittest { 96 shouldCompileAndRun( 97 Cpp( 98 q{ 99 struct Struct { 100 static int numStructs; 101 Struct(int i); 102 ~Struct(); 103 }; 104 105 struct DeletedDtor { 106 ~DeletedDtor() = delete; 107 }; 108 } 109 ), 110 Cpp( 111 q{ 112 int Struct::numStructs; 113 // the i parameter is to force D to call a constructor, 114 // since Struct() just blasts it with Struct.init 115 Struct::Struct(int i) { numStructs += i; } 116 Struct::~Struct() { --numStructs; } 117 } 118 ), 119 D( 120 q{ 121 import std.conv: text; 122 assert(Struct.numStructs == 0, Struct.numStructs.text); 123 { 124 auto s1 = Struct(3); 125 assert(Struct.numStructs == 3, Struct.numStructs.text); 126 127 { 128 auto s2 = Struct(2); 129 assert(Struct.numStructs == 5, Struct.numStructs.text); 130 } 131 132 assert(Struct.numStructs == 4, Struct.numStructs.text); 133 } 134 135 assert(Struct.numStructs == 3, Struct.numStructs.text); 136 } 137 ), 138 ); 139 } 140 141 142 @Tags("run") 143 @("function") 144 @safe unittest { 145 shouldCompileAndRun( 146 Cpp( 147 q{ 148 int add(int i, int j); 149 150 struct Adder { 151 int i; 152 Adder(int i); 153 int add(int j); 154 }; 155 } 156 ), 157 Cpp( 158 q{ 159 int add(int i, int j) { return i + j; } 160 Adder::Adder(int i):i(i + 10) {} 161 int Adder::add(int j) { return i + j; } 162 } 163 ), 164 D( 165 q{ 166 import std.conv: text; 167 import std.exception: assertThrown; 168 import core.exception: AssertError; 169 170 assert(add(2, 3) == 5, "add(2, 3) should be 5"); 171 172 void func() { 173 assert(add(2, 3) == 7); 174 } 175 assertThrown!AssertError(func(), "add(2, 3) should not be 7"); 176 177 auto adder = Adder(3); 178 assert(adder.add(4) == 17, "Adder(3).add(4) should be 17 not " ~ text(adder.add(4))); 179 } 180 ), 181 ); 182 } 183 184 @Tags("run", "collision") 185 @("collisions") 186 @safe unittest { 187 shouldRun( 188 Cpp( 189 q{ 190 struct foo { 191 int i; 192 }; 193 int foo(int i, int j); 194 struct foo add_foo_ptrs(const struct foo* f1, const struct foo* f2); 195 196 union bar { 197 int i; 198 double d; 199 }; 200 int bar(int i); 201 202 enum baz { one, two, three }; 203 int baz(); 204 205 enum other { four, five }; 206 int other; 207 } 208 ), 209 Cpp( 210 q{ 211 int foo(int i, int j) { return i + j + 1; } 212 struct foo add_foo_ptrs(const struct foo* f1, const struct foo* f2) { 213 struct foo ret; 214 ret.i = f1->i + f2->i; 215 return ret; 216 } 217 int bar(int i) { return i * 2; } 218 int baz() { return 42; } 219 } 220 ), 221 D( 222 q{ 223 assert(foo_(2, 3) == 6); 224 assert(bar_(4) == 8); 225 assert(baz_ == 42); 226 227 auto f1 = foo(2); 228 auto f2 = foo(3); 229 assert(add_foo_ptrs(&f1, &f2) == foo(5)); 230 231 bar b; 232 b.i = 42; 233 b.d = 33.3; 234 235 baz z1 = two; 236 baz z2 = baz.one; 237 238 other_ = 77; 239 other o1 = other.four; 240 other o2 = five; 241 242 import std.exception: assertThrown; 243 import core.exception: AssertError; 244 void func() { 245 assert(foo_(2, 3) == 7); 246 } 247 assertThrown!AssertError(func()); 248 } 249 ), 250 ); 251 } 252 253 254 @HiddenTest("Passes on Travis, crashes on my machine") 255 @Tags("run") 256 @("operators") 257 @safe unittest { 258 shouldRun( 259 Cpp( 260 q{ 261 struct Struct { 262 int i; 263 Struct(int i); 264 265 // Unary operators 266 Struct operator+ () const; 267 Struct operator- () const; 268 Struct operator* () const; 269 Struct operator& () const; 270 Struct operator->() const; 271 Struct operator~ () const; 272 bool operator! () const; 273 Struct operator++() const; 274 Struct operator--() const; 275 Struct operator++(int) const; // not defined on purpose 276 Struct operator--(int) const; // not defined on purpose 277 278 // Binary operators 279 Struct operator+ (const Struct& other) const; 280 Struct operator- (const Struct& other) const; 281 Struct operator* (const Struct& other) const; 282 Struct operator/ (const Struct& other) const; 283 Struct operator% (const Struct& other) const; 284 Struct operator^ (const Struct& other) const; 285 Struct operator& (const Struct& other) const; 286 Struct operator| (const Struct& other) const; 287 Struct operator>> (const Struct& other) const; 288 Struct operator<< (const Struct& other) const; 289 Struct operator&& (const Struct& other) const; 290 Struct operator|| (const Struct& other) const; 291 Struct operator->*(const Struct& other) const; 292 Struct operator, (const Struct& other) const; 293 294 // assignment 295 void operator= (const Struct& other); 296 void operator+= (int j); 297 void operator-= (int j); 298 void operator*= (int j); 299 void operator/= (int j); 300 void operator%= (int j); 301 void operator^= (int j); 302 void operator&= (int j); 303 void operator|= (int j); 304 void operator>>=(int j); 305 void operator<<=(int j); 306 307 // special 308 int operator()(int j) const; 309 int operator[](int j) const; 310 311 // comparison 312 bool operator==(int j) const; 313 bool operator!=(const Struct& other) const; // not defined on purpose 314 bool operator>=(const Struct& other) const; // not defined on purpose 315 bool operator<=(const Struct& other) const; // not defined on purpose 316 bool operator> (const Struct& other) const; 317 bool operator< (const Struct& other) const; 318 319 // conversion 320 operator int() const; 321 322 // allocation 323 static void* operator new(unsigned long); 324 static void* operator new[](unsigned long); 325 static void operator delete(void*); 326 static void operator delete[](void*); 327 }; 328 329 struct Stream {}; 330 Stream& operator<<(Stream& stream, const Struct& s); 331 } 332 ), 333 Cpp( 334 q{ 335 Struct::Struct(int i):i{i} {} 336 Struct Struct::operator+ () const { return { +i }; } 337 Struct Struct::operator- () const { return { -i }; } 338 Struct Struct::operator* () const { return { i * 3 }; } 339 Struct Struct::operator& () const { return { i / 4 }; } 340 Struct Struct::operator->() const { return { i / 3 }; } 341 Struct Struct::operator~ () const { return { i + 9 }; } 342 bool Struct::operator! () const { return i != 7; } 343 Struct Struct::operator++() const { return { i + 1 }; } 344 Struct Struct::operator--() const { return { i - 1 }; } 345 346 Struct Struct::operator+ (const Struct& other) const { return { i + other.i }; } 347 Struct Struct::operator- (const Struct& other) const { return { i - other.i }; } 348 Struct Struct::operator* (const Struct& other) const { return { i * other.i }; } 349 Struct Struct::operator/ (const Struct& other) const { return { i / other.i }; } 350 Struct Struct::operator% (const Struct& other) const { return { i % other.i }; } 351 Struct Struct::operator^ (const Struct& other) const { return { i + other.i + 2 }; } 352 Struct Struct::operator& (const Struct& other) const { return { i * other.i + 1 }; } 353 Struct Struct::operator| (const Struct& other) const { return { i + other.i + 1 }; } 354 Struct Struct::operator<< (const Struct& other) const { return { i + other.i }; } 355 Struct Struct::operator>> (const Struct& other) const { return { i - other.i }; } 356 Struct Struct::operator&& (const Struct& other) const { return { i && other.i }; } 357 Struct Struct::operator|| (const Struct& other) const { return { i || other.i }; } 358 Struct Struct::operator->*(const Struct& other) const { return { i - other.i }; } 359 Struct Struct::operator, (const Struct& other) const { return { i - other.i - 1 }; } 360 361 void Struct::operator= (const Struct& other) { i = other.i + 10; }; 362 void Struct::operator+=(int j) { i += j; }; 363 void Struct::operator-=(int j) { i -= j; }; 364 void Struct::operator*=(int j) { i *= j; }; 365 void Struct::operator/=(int j) { i /= j; }; 366 void Struct::operator%=(int j) { i %= j; }; 367 void Struct::operator^=(int j) { i ^= j; }; 368 void Struct::operator&=(int j) { i &= j; }; 369 void Struct::operator|=(int j) { i |= j; }; 370 void Struct::operator>>=(int j) { i >>= j; }; 371 void Struct::operator<<=(int j) { i <<= j; }; 372 373 int Struct::operator()(int j) const { return i * j; } 374 int Struct::operator[](int j) const { return i / j; } 375 376 bool Struct::operator==(int j) const { return i == j; } 377 bool Struct::operator<(const Struct& other) const { return i < other.i; } 378 bool Struct::operator>(const Struct& other) const { return i > other.i; } 379 380 Struct::operator int() const { return i + 1; } 381 382 void* Struct::operator new(unsigned long count) { return new int{static_cast<int>(count)}; } 383 void* Struct::operator new[](unsigned long count) { return new int{static_cast<int>(count + 1)}; } 384 void Struct::operator delete(void*) {} 385 void Struct::operator delete[](void*) {} 386 387 Stream& operator<<(Stream& stream, const Struct& s) { return stream; } 388 } 389 ), 390 D( 391 q{ 392 import std.conv: text; 393 394 // unary 395 assert(+Struct(-4) == -4); 396 assert(-Struct(4) == -4); 397 assert(-Struct(-5) == 5); 398 assert(*Struct(2) == 6); 399 assert(Struct(8).opCppAmpersand == 2); 400 assert(Struct(9).opCppArrow == 3); 401 assert(~Struct(7) == 16); 402 assert(Struct(9).opCppBang); 403 404 assert(++Struct(2) == 3); 405 assert(--Struct(5) == 4); 406 407 // binary 408 auto s0 = const Struct(0); 409 auto s2 = const Struct(2); 410 auto s3 = const Struct(3); 411 412 assert(s2 + s3 == 5); 413 assert(s3 - s2 == 1); 414 assert(Struct(5) - s2 == 3); 415 assert(s2 * s3 == 6); 416 assert(Struct(11) / s3 == 3) ; 417 418 assert(Struct(5) % s2 == 1); 419 assert(Struct(6) % s2 == 0); 420 421 assert((Struct(4) ^ s2) == 8); 422 assert((Struct(4) & s2) == 9); 423 assert((Struct(4) | s2) == 7); 424 425 assert(Struct(7) >> s2 == 5); 426 assert(Struct(3) << s3 == 6); 427 428 assert(Struct(5).opCppArrowStar(s2) == 3); 429 assert(Struct(5).opCppComma(s2) == 2); 430 431 // assignment 432 { 433 auto s = Struct(5); 434 s = s2; assert(s == 12); 435 } 436 437 { 438 auto s = Struct(2); 439 s += 3; assert(s == 5); 440 s -= 2; assert(s == 3); 441 s *= 2; assert(s == 6); 442 s /= 3; assert(s == 2); 443 s = s3; 444 s %= 2; assert(s == 1); 445 s ^= 1; assert(s == 0); 446 s &= 1; assert(s == 0); 447 s |= 1; assert(s == 1); 448 s.i = 8; 449 s >>= 2; assert(s == 2); 450 s <<= 1; assert(s == 4); 451 } 452 453 // special 454 assert(Struct(2)(3) == 6); 455 assert(Struct(7)[2] == 3); 456 457 // comparison (== already done everywhere above) 458 assert(Struct(3) < Struct(5)); 459 assert(Struct(5) > Struct(3)); 460 assert(Struct(3) <= Struct(5)); 461 assert(Struct(3) <= Struct(3)); 462 assert(Struct(5) > Struct(3)); 463 assert(Struct(5) >= Struct(5)); 464 465 // conversion 466 assert(cast(int) Struct(7) == 8); 467 assert( cast(bool) Struct(7)); 468 assert(!cast(bool) Struct(3)); 469 470 // allocation 471 assert(*(cast(int*) Struct.opCppNew(5)) == 5); 472 assert(*(cast(int*) Struct.opCppNewArray(5)) == 6); 473 Struct.opCppDelete(null); 474 Struct.opCppDeleteArray(null); 475 476 // free function 477 Stream stream; 478 stream.opCppLShift(s2); 479 } 480 ), 481 ); 482 } 483 484 @Tags("run") 485 @("templates") 486 @safe unittest { 487 shouldRun( 488 Cpp( 489 q{ 490 template<typename T> 491 class vector { 492 T _values[10]; 493 int _numValues = 0; 494 495 public: 496 void push_back(T value) { 497 _values[_numValues++] = value; 498 } 499 500 int numValues() { return _numValues; } 501 T value(int i) { return _values[i]; } 502 }; 503 } 504 ), 505 Cpp( 506 ` 507 #if __clang__ 508 [[clang::optnone]] 509 #elif __GNUC__ 510 __attribute__((optimize("O0"))) 511 #endif 512 __attribute((used, noinline)) 513 static void instantiate() { 514 vector<int> v; 515 v.push_back(42); 516 v.value(0); 517 v.numValues(); 518 } 519 ` 520 ), 521 D( 522 q{ 523 vector!int v; 524 assert(v.numValues == 0); 525 526 v.push_back(4); 527 assert(v.numValues == 1); 528 assert(v.value(0) == 4); 529 530 v.push_back(2); 531 assert(v.numValues == 2); 532 assert(v.value(0) == 4); 533 assert(v.value(1) == 2); 534 535 foreach(i; 2 .. v.numValues) 536 assert(v.value(i) == 0); 537 } 538 ), 539 ); 540 } 541 542 543 @Tags("run") 544 @("namespaces") 545 @safe unittest { 546 shouldRun( 547 Cpp( 548 q{ 549 namespace ns0 { 550 int foo(); 551 int bar(); 552 namespace ns1 { 553 int baz(); 554 } 555 } 556 557 namespace other { 558 int quux(); 559 } 560 561 // can reopen namespace 562 namespace ns0 { 563 int toto(); 564 } 565 } 566 ), 567 Cpp( 568 q{ 569 namespace ns0 { 570 int foo() { return 1; } 571 int bar() { return 2; } 572 namespace ns1 { 573 int baz() { return 3; } 574 } 575 } 576 577 namespace other { 578 int quux() { return 4; } 579 } 580 581 // can reopen namespace 582 namespace ns0 { 583 int toto() { return 5; } 584 } 585 } 586 ), 587 D( 588 q{ 589 assert(foo == 1); 590 assert(bar == 2); 591 assert(baz == 3); 592 assert(quux == 4); 593 assert(toto == 5); 594 } 595 ), 596 ); 597 } 598 599 600 @HiddenTest("Passes with gcc but fails with clang due to destructor mangling") 601 @Tags("run") 602 @("std.allocator") 603 @safe unittest { 604 shouldRun( 605 Cpp( 606 q{ 607 namespace impl_cpp { 608 template <typename T> 609 class new_allocator { 610 public: 611 new_allocator() {} 612 ~new_allocator() {} 613 T* allocate(int size, const void* = static_cast<const void*>(0)) { 614 return static_cast<T*>(::operator new(size * sizeof(T))); 615 } 616 void deallocate(T* ptr, int size) { 617 ::operator delete(ptr); 618 } 619 }; 620 } 621 622 namespace std { 623 template <typename T> 624 using allocator_base = impl_cpp::new_allocator<T>; 625 } 626 627 namespace std { 628 template <typename T> 629 class allocator: public allocator_base<T> { 630 public: 631 allocator() {} 632 ~allocator() {} 633 }; 634 } 635 } 636 ), 637 Cpp( 638 ` 639 #if __clang__ 640 [[clang::optnone]] 641 #elif __GNUC__ 642 __attribute__((optimize("O0"))) 643 #endif 644 __attribute((used, noinline)) 645 static void dummy() { 646 { 647 std::allocator<int> _; 648 (void) std::allocator<int>(_); 649 } 650 } 651 ` 652 ), 653 D( 654 q{ 655 // import std.conv: text; 656 allocator!int intAllocator = void; 657 // below can't work until `alias this` is implemented 658 // enum numInts = 1; 659 // int* i = intAllocator.allocate(numInts); 660 // intAllocator.construct(i, 42); 661 // assert(*i == 42, text("i was actually ", *i)); 662 // intAllocator.deallocate(i, numInts); 663 } 664 ), 665 ); 666 }