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