1 /** 2 Integration tests that stem from failues in real-life C projects 3 */ 4 module it.c.compile.projects; 5 6 import it; 7 8 @("multicharacter_literal") 9 @safe unittest { 10 shouldCompile( 11 C( 12 ` 13 #define test 'ABCD' 14 ` 15 ), 16 17 D( 18 q{ 19 static assert(test == 1094861636); // determined by printf("%d\n", 'ABCD'); in C 20 } 21 ) 22 ); 23 } 24 25 @("nn_get_statistic") 26 @safe unittest { 27 shouldCompile( 28 C( 29 // the original uses regular uint64_t, let's beat any special cases 30 // defining our own 31 q{ 32 typedef unsigned long int __my_uint64_t; 33 typedef __my_uint64_t my_uint64_t; 34 my_uint64_t nn_get_statistic (int s, int stat); 35 } 36 ), 37 38 D( 39 q{ 40 int s; 41 int stat; 42 my_uint64_t ret = nn_get_statistic(s, stat); 43 } 44 ) 45 ); 46 } 47 48 @("Lstring literals (seen in Windows)") 49 @safe unittest { 50 shouldCompile( 51 C( 52 ` 53 #define test L"testing" 54 ` 55 ), 56 57 D( 58 q{ 59 wstring s = test; 60 } 61 ) 62 ); 63 } 64 65 @("lowercase integer suffices") 66 @safe unittest { 67 shouldCompile( 68 C( 69 ` 70 #define test 100l 71 #define test2 100ll 72 ` 73 ), 74 75 D( 76 q{ 77 auto t = test; 78 auto t2 = test2; 79 } 80 ) 81 ); 82 } 83 84 @("__io_read_fn") 85 @safe unittest { 86 shouldCompile( 87 C( 88 q{ 89 typedef long long __ssize_t; 90 typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, long __nbytes); 91 } 92 ), 93 94 D( 95 q{ 96 void* cookie; 97 char[1024] buf; 98 __ssize_t ret = __io_read_fn.init(cookie, buf.ptr, buf.length); 99 } 100 ), 101 ); 102 } 103 104 @("timer_t") 105 @safe unittest { 106 shouldCompile( 107 C( 108 // the original uses regular uint64_t, let's beat any special cases 109 // defining our own 110 ` 111 #define __TIMER_T_TYPE void * 112 typedef __TIMER_T_TYPE __timer_t; 113 ` 114 ), 115 116 D( 117 q{ 118 __timer_t timer = null; 119 } 120 ), 121 ); 122 } 123 124 125 @("curl_multi_wait") 126 @safe unittest { 127 shouldCompile( 128 C( 129 q{ 130 typedef enum { CURLM_OK } CURLMcode; 131 typedef int curl_socket_t; 132 133 struct curl_waitfd { 134 curl_socket_t fd; 135 short events; 136 short revents; /* not supported yet */ 137 }; 138 139 typedef struct { int dummy; } CURLM; 140 CURLMcode curl_multi_wait(CURLM *multi_handle, 141 struct curl_waitfd extra_fds[], 142 unsigned int extra_nfds, 143 int timeout_ms, 144 int *ret); 145 } 146 ), 147 148 D( 149 q{ 150 CURLM handle; 151 curl_waitfd[] extra_fds; 152 int ret; 153 CURLMcode code = curl_multi_wait(&handle, extra_fds.ptr, 42u, 33, &ret); 154 } 155 ), 156 ); 157 } 158 159 @("__sigset_t") 160 @safe unittest { 161 shouldCompile( 162 // the original uses regular uint64_t, let's beat any special cases 163 // defining our own 164 C( 165 ` 166 #define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int))) 167 typedef struct 168 { 169 unsigned long int __val[_SIGSET_NWORDS]; 170 } __sigset_t; 171 ` 172 ), 173 D( 174 q{ 175 auto s = __sigset_t(); 176 ++s.__val[7]; 177 } 178 ), 179 ); 180 } 181 182 183 @("_IO_flockfile") 184 @safe unittest { 185 shouldCompile( 186 C( 187 ` 188 struct _IO_FILE { int dummy; }; 189 extern void _IO_flockfile (struct _IO_FILE *); 190 #define _IO_flockfile(_fp) 191 ` 192 ), 193 D( 194 q{ 195 _IO_FILE file; 196 _IO_flockfile(&file); 197 } 198 ), 199 ); 200 } 201 202 203 @("struct with union") 204 @safe unittest { 205 shouldCompile( 206 C( 207 q{ 208 struct Struct { 209 union { 210 void *ptr; 211 int i; 212 } data; 213 }; 214 typedef struct Struct Struct; 215 } 216 ), 217 218 D( 219 q{ 220 Struct s; 221 s.data.ptr = null; 222 s.data.i = 42; 223 } 224 ), 225 ); 226 } 227 228 @("const char* const") 229 @safe unittest { 230 shouldCompile( 231 C( 232 q{ 233 struct Struct { 234 const char * const *protocols; 235 }; 236 typedef struct Struct Struct; 237 } 238 ), 239 240 D( 241 q{ 242 Struct s; 243 static assert(is(typeof(s.protocols) == const(char*)*), 244 "Expected const(char*)*, not " ~ 245 typeof(s.protocols).stringof); 246 } 247 ), 248 ); 249 } 250 251 @("forward declaration") 252 @safe unittest { 253 shouldCompile( 254 C( 255 q{ 256 struct Struct; 257 void fun(struct Struct* s); 258 struct Struct* make_struct(void); 259 } 260 ), 261 262 D( 263 q{ 264 Struct* s = make_struct(); 265 fun(s); 266 } 267 ), 268 ); 269 } 270 271 272 @("restrict") 273 @safe unittest { 274 shouldCompile( 275 C( 276 q{ 277 struct FILE { int dummy; }; 278 extern struct FILE *fopen(const char *restrict filename, 279 const char *restrict modes); 280 } 281 ), 282 283 D( 284 q{ 285 import std.string; 286 fopen("foo.txt".toStringz, "w".toStringz); 287 } 288 ), 289 ); 290 } 291 292 293 @("return type typedefd enum") 294 @safe unittest { 295 shouldCompile( 296 C( 297 q{ 298 typedef struct { int dummy; } CURL; 299 300 typedef enum { 301 CURLIOE_OK, /* I/O operation successful */ 302 } curlioerr; 303 304 typedef curlioerr (*curl_ioctl_callback)(CURL *handle, 305 int cmd, 306 void *clientp); 307 } 308 ), 309 D( 310 q{ 311 CURL handle; 312 auto func = curl_ioctl_callback.init; 313 curlioerr err = func(&handle, 42, null); 314 } 315 ), 316 ); 317 } 318 319 320 @("curl_slist") 321 @safe unittest { 322 shouldCompile( 323 C( 324 q{ 325 struct curl_httppost { 326 struct curl_slist *contentheader; 327 }; 328 struct curl_slist { 329 char *data; 330 struct curl_slist *next; 331 }; 332 } 333 ), 334 D( 335 q{ 336 curl_httppost p; 337 p.contentheader.data = null; 338 p.contentheader.next = null; 339 curl_slist l; 340 l.data = null; 341 l.next = null; 342 } 343 ), 344 ); 345 } 346 347 @("struct var collision with var before") 348 @safe unittest { 349 shouldCompile( 350 C( 351 q{ 352 extern int foo; 353 struct foo { int dummy; }; 354 } 355 ), 356 D( 357 q{ 358 auto u = foo(44); 359 foo_ = 42; 360 } 361 ), 362 ); 363 } 364 365 @("struct function collision with function before") 366 @safe unittest { 367 shouldCompile( 368 C( 369 q{ 370 void foo(void); 371 struct foo { int dummy; }; 372 } 373 ), 374 D( 375 q{ 376 auto u = foo(44); 377 foo_(); 378 } 379 ), 380 ); 381 } 382 383 384 @("union var collision") 385 @safe unittest { 386 shouldCompile( 387 C( 388 q{ 389 union foo { int dummy; }; 390 extern int foo; 391 } 392 ), 393 D( 394 q{ 395 auto u = foo(44); 396 foo_ = 42; 397 } 398 ), 399 ); 400 } 401 402 @("enum var collision") 403 @safe unittest { 404 shouldCompile( 405 C( 406 q{ 407 enum foo { one, two, three }; 408 extern int foo; 409 } 410 ), 411 D( 412 q{ 413 auto e = foo.three; 414 foo_ = 42; 415 } 416 ), 417 ); 418 } 419 420 @("use int for enum parameter") 421 @safe unittest { 422 shouldCompile( 423 C( 424 q{ 425 typedef enum { 426 foo, 427 bar, 428 } Enum; 429 void func(Enum e); 430 } 431 ), 432 D( 433 q{ 434 func(Enum.bar); 435 } 436 ), 437 ); 438 } 439 440 @("pthread struct") 441 @safe unittest { 442 with(immutable IncludeSandbox()) { 443 writeFile("hdr.h", 444 q{ 445 typedef struct { 446 void (*routine)(void*); 447 } Struct; 448 } 449 ); 450 writeFile("app.dpp", 451 ` 452 #include "hdr.h" 453 extern(C) void foo(void*) {} 454 455 void main() { 456 Struct s; 457 s.routine = &foo; 458 } 459 ` 460 ); 461 462 runPreprocessOnly("app.dpp"); 463 shouldCompile("app.d"); 464 } 465 } 466 467 468 @("multiple headers with the same typedef") 469 @safe unittest { 470 with(const IncludeSandbox()) { 471 writeFile("hdr1.h", 472 q{ 473 typedef long time_t; 474 typedef long time_t; 475 } 476 ), 477 478 writeFile("hdr2.h", 479 q{ 480 typedef long time_t; 481 typedef long time_t; 482 } 483 ), 484 485 writeFile("app.dpp", 486 ` 487 #include "hdr1.h" 488 #include "hdr2.h" 489 void main() { 490 time_t var = 42; 491 } 492 `); 493 494 runPreprocessOnly("app.dpp"); 495 shouldCompile("app.d"); 496 } 497 } 498 499 @("jmp_buf") 500 @safe unittest { 501 shouldCompile( 502 C( 503 q{ 504 typedef long int __jmp_buf[8]; 505 } 506 ), 507 508 D( 509 q{ 510 __jmp_buf buf; 511 static assert(buf.length == 8); 512 } 513 ), 514 ); 515 } 516 517 @("__pthread_unwind_buf_t") 518 @safe unittest { 519 shouldCompile( 520 C( 521 q{ 522 typedef long int __jmp_buf[8]; 523 typedef struct { 524 struct { 525 __jmp_buf __cancel_jmp_buf; 526 int __mask_was_saved; 527 } __cancel_jmp_buf[1]; 528 void *__pad[4]; 529 } __pthread_unwind_buf_t __attribute__ ((__aligned__)); 530 } 531 ), 532 533 D( 534 q{ 535 __pthread_unwind_buf_t buf; 536 } 537 ), 538 ); 539 } 540 541 542 @("struct pointer to unknown struct that is defined by a later header") 543 @safe unittest { 544 with(immutable IncludeSandbox()) { 545 writeFile("hdr1.h", 546 q{ 547 typedef struct Foo { 548 struct Bar* bar; 549 } Foo; 550 }); 551 writeFile("hdr2.h", 552 q{ 553 struct Bar; 554 }); 555 writeFile("app.dpp", 556 ` 557 #include "hdr1.h" 558 #include "hdr2.h" 559 void main() { 560 Foo f; 561 f.bar = null; 562 } 563 `); 564 runPreprocessOnly("app.dpp"); 565 shouldCompile("app.d"); 566 } 567 } 568 569 @("typedef struct pointer with no declaration") 570 @safe unittest { 571 shouldCompile( 572 C( 573 q{ 574 typedef struct _Foo Foo; 575 typedef Foo *FooPtr; 576 } 577 ), 578 D( 579 q{ 580 void fun(FooPtr ptr) { } 581 FooPtr ptr; 582 fun(ptr); 583 } 584 ), 585 ); 586 } 587 588 @("extern global variable with undefined macro") 589 @safe unittest { 590 with(immutable IncludeSandbox()) { 591 writeFile("hdr.h", 592 q{ 593 // EXPORT_VAR not defined anywhere 594 typedef struct _Foo Foo; 595 typedef Foo *FooPtr; 596 EXPORT_VAR FooPtr theFoo; 597 }); 598 writeFile("app.dpp", 599 ` 600 #include "hdr.h" 601 `); 602 try { 603 runPreprocessOnly("app.dpp"); 604 assert(0, "Should not get here"); 605 } catch(Exception e) { 606 "unknown type name 'EXPORT_VAR'".shouldBeIn(e.msg); 607 } 608 } 609 } 610 611 @("angle brackets headers with more angle brackets") 612 @safe unittest { 613 614 with(immutable IncludeSandbox()) { 615 616 writeFile("includes/libfoo/libfoo.h", 617 ` 618 #include <libfoo/libfoo-common.h> 619 #include <libfoo/libfoo-host.h> 620 `); 621 622 writeFile("includes/libfoo/libfoo-common.h", 623 ` 624 #define EXPORT_VAR extern 625 `); 626 627 writeFile("includes/libfoo/libfoo-host.h", 628 q{ 629 typedef struct _Foo Foo; 630 typedef Foo *FooPtr; 631 }); 632 633 writeFile("app.dpp", 634 ` 635 #include <libfoo/libfoo.h> 636 void func(FooPtr foo) { 637 assert(foo is null); 638 } 639 `); 640 641 runPreprocessOnly( 642 "--include-path", 643 inSandboxPath("includes"), 644 "app.dpp"); 645 646 shouldCompile("app.d"); 647 } 648 } 649 650 651 @("double enum typedef") 652 @safe unittest { 653 654 with(immutable IncludeSandbox()) { 655 656 writeFile("enum.h", 657 ` 658 #ifndef _ENUM_H 659 #define _ENUM_H 660 typedef enum { 661 only_value, 662 } Enum; 663 #endif 664 `); 665 666 writeFile("hdr1.h", 667 ` 668 #include "enum.h" 669 `); 670 671 writeFile("hdr2.h", 672 ` 673 #include "enum.h" 674 `); 675 676 writeFile("app.dpp", 677 ` 678 #include "hdr1.h" 679 #include "hdr2.h" 680 `); 681 682 runPreprocessOnly("app.dpp"); 683 shouldCompile("app.d"); 684 } 685 686 } 687 688 @("gregset_t") 689 @safe unittest { 690 shouldCompile( 691 C( 692 ` 693 typedef long long int greg_t; 694 #define __NGREG 23 695 typedef greg_t gregset_t[__NGREG]; 696 ` 697 ), 698 D( 699 q{ 700 static assert(greg_t.sizeof == 8); 701 static assert(gregset_t.sizeof == 23 * 8); 702 } 703 ), 704 ); 705 } 706 707 708 @("nv_alloc_ops") 709 @safe unittest { 710 shouldCompile( 711 C( 712 q{ 713 typedef struct Inner_ Inner; 714 715 typedef struct Outer { 716 const Inner *nva_ops; 717 } Outer; 718 719 struct Inner_ { 720 int dummy; 721 }; 722 } 723 ), 724 D( 725 q{ 726 } 727 ), 728 ); 729 } 730 731 @("va_list") 732 @safe unittest { 733 shouldCompile( 734 C( 735 ` 736 #include <stdarg.h> 737 typedef struct Struct { 738 int (*func)(int, va_list); 739 }; 740 ` 741 ), 742 D( 743 q{ 744 } 745 ), 746 ); 747 } 748 749 750 @("ASN1_ITEM") 751 @safe unittest { 752 shouldCompile( 753 C( 754 q{ 755 struct Foo_st; 756 typedef struct Foo_st Foo; 757 extern const Foo gVar; 758 } 759 ), 760 D( 761 q{ 762 763 } 764 ), 765 ); 766 } 767 768 769 @("X509_get0_extensions") 770 @safe unittest { 771 shouldCompile( 772 C( 773 q{ 774 typedef struct { int dummy; } Param; 775 struct Ret; 776 const struct Ret *func(const Param *x); 777 } 778 ), 779 D( 780 q{ 781 782 } 783 ), 784 ); 785 } 786 787 788 @("double semicolon after function declaration") 789 @safe unittest { 790 shouldCompile( 791 C( 792 q{ 793 void foo(void);; 794 } 795 ), 796 D( 797 q{ 798 799 } 800 ), 801 ); 802 } 803 804 805 @("_Bool") 806 @safe unittest { 807 shouldCompile( 808 C( 809 ` 810 #include <stdbool.h> 811 typedef bool handler_t(int, double); 812 ` 813 ), 814 D( 815 q{ 816 handler_t handler; 817 bool b = handler(42, 33.3); 818 } 819 ), 820 ); 821 } 822 823 @("(unsigned) long long C suffixes") 824 @safe unittest { 825 shouldCompile( 826 C( 827 ` 828 #define A 1LL 829 #define B 2ll 830 #define C 3LLU 831 #define D 4LLu 832 #define E 5llU 833 #define F 6llu 834 #define G 7ULL 835 #define H 8Ull 836 #define I 9uLL 837 #define J 10ull 838 ` 839 ), 840 D( 841 q{ 842 auto a = A; 843 auto b = B; 844 auto c = C; 845 auto d = D; 846 auto e = E; 847 auto f = F; 848 auto g = G; 849 auto h = H; 850 auto i = I; 851 auto j = J; 852 } 853 ), 854 ); 855 } 856 857 @("Casting when type has attribute") 858 @safe unittest { 859 shouldCompile( 860 C( 861 ` 862 typedef unsigned int gfp_t; 863 864 #define DUMMY ((__force gfp_t) 7) 865 #define __force 866 ` 867 ), 868 D( 869 q{ 870 auto a = DUMMY; 871 } 872 ), 873 ); 874 } 875 876 @("Accessing nested aggregates") 877 @safe unittest { 878 shouldCompile( 879 C( 880 q{ 881 struct A { 882 struct B { 883 int a; 884 struct C { 885 int b; 886 enum E {Mon, Tue}; 887 } c_obj1; 888 } b_obj; 889 890 union U { 891 int v1; 892 char v2; 893 }; 894 895 struct C c_obj2; 896 }; 897 898 void f(struct C *); 899 void g(struct B *); 900 void h(union U *); 901 void i(enum E); 902 } 903 ), 904 D( 905 q{ 906 A a_obj; 907 a_obj.b_obj.c_obj1.b = 3; 908 909 A.B.C.E day = A.B.C.E.Mon; 910 } 911 ), 912 ); 913 } 914 915 @("C preprocessor warnings should not be written to file") 916 @safe unittest { 917 918 with(immutable IncludeSandbox()) { 919 920 writeFile("hdr.h", 921 ` 922 #define A B(__VA_ARGS__) 923 `); 924 925 writeFile("app.dpp", 926 ` 927 #include "hdr.h" 928 `); 929 930 runPreprocessOnly("app.dpp"); 931 shouldCompile("app.d"); 932 } 933 } 934 935 936 @("Extern void variable") 937 @safe unittest { 938 shouldCompile( 939 C( 940 q{ 941 extern void v; 942 extern const void cv; 943 } 944 ), 945 D( 946 q{ 947 static assert(is(typeof(v) == void*), 948 "Expected void*, not " ~ 949 typeof(v).stringof); 950 951 static assert(is(typeof(cv) == const(void*)), 952 "Expected const(void*), not " ~ 953 typeof(cv).stringof); 954 } 955 ), 956 ); 957 }