blob a359bcde (66742B) - Raw
1 /* 2 * Copyright (c) 2015 Andrew Kelley 3 * 4 * This file is part of zig, which is MIT licensed. 5 * See http://opensource.org/licenses/MIT 6 */ 7 8 #include "list.hpp" 9 #include "buffer.hpp" 10 #include "os.hpp" 11 #include "error.hpp" 12 #include "config.h" 13 14 #include <stdio.h> 15 #include <stdarg.h> 16 17 struct TestSourceFile { 18 const char *relative_path; 19 const char *source_code; 20 }; 21 22 enum AllowWarnings { 23 AllowWarningsNo, 24 AllowWarningsYes, 25 }; 26 27 struct TestCase { 28 const char *case_name; 29 const char *output; 30 ZigList<TestSourceFile> source_files; 31 ZigList<const char *> compile_errors; 32 ZigList<const char *> compiler_args; 33 ZigList<const char *> program_args; 34 bool is_parseh; 35 bool is_self_hosted; 36 bool is_release_mode; 37 bool is_debug_safety; 38 AllowWarnings allow_warnings; 39 }; 40 41 static ZigList<TestCase*> test_cases = {0}; 42 static const char *tmp_source_path = ".tmp_source.zig"; 43 static const char *tmp_h_path = ".tmp_header.h"; 44 45 #if defined(_WIN32) 46 static const char *tmp_exe_path = "./.tmp_exe.exe"; 47 static const char *zig_exe = "./zig.exe"; 48 #define NL "\r\n" 49 #else 50 static const char *tmp_exe_path = "./.tmp_exe"; 51 static const char *zig_exe = "./zig"; 52 #define NL "\n" 53 #endif 54 55 static void add_source_file(TestCase *test_case, const char *path, const char *source) { 56 test_case->source_files.add_one(); 57 test_case->source_files.last().relative_path = path; 58 test_case->source_files.last().source_code = source; 59 } 60 61 static TestCase *add_simple_case(const char *case_name, const char *source, const char *output) { 62 TestCase *test_case = allocate<TestCase>(1); 63 test_case->case_name = case_name; 64 test_case->output = output; 65 66 test_case->source_files.resize(1); 67 test_case->source_files.at(0).relative_path = tmp_source_path; 68 test_case->source_files.at(0).source_code = source; 69 70 test_case->compiler_args.append("build"); 71 test_case->compiler_args.append(tmp_source_path); 72 test_case->compiler_args.append("--export"); 73 test_case->compiler_args.append("exe"); 74 test_case->compiler_args.append("--name"); 75 test_case->compiler_args.append("test"); 76 test_case->compiler_args.append("--output"); 77 test_case->compiler_args.append(tmp_exe_path); 78 test_case->compiler_args.append("--release"); 79 test_case->compiler_args.append("--strip"); 80 test_case->compiler_args.append("--color"); 81 test_case->compiler_args.append("on"); 82 test_case->compiler_args.append("--check-unused"); 83 84 test_cases.append(test_case); 85 86 return test_case; 87 } 88 89 static TestCase *add_simple_case_libc(const char *case_name, const char *source, const char *output) { 90 TestCase *tc = add_simple_case(case_name, source, output); 91 tc->compiler_args.append("--library"); 92 tc->compiler_args.append("c"); 93 return tc; 94 } 95 96 static TestCase *add_compile_fail_case(const char *case_name, const char *source, size_t count, ...) { 97 va_list ap; 98 va_start(ap, count); 99 100 TestCase *test_case = allocate<TestCase>(1); 101 test_case->case_name = case_name; 102 test_case->source_files.resize(1); 103 test_case->source_files.at(0).relative_path = tmp_source_path; 104 test_case->source_files.at(0).source_code = source; 105 106 for (size_t i = 0; i < count; i += 1) { 107 const char *arg = va_arg(ap, const char *); 108 test_case->compile_errors.append(arg); 109 } 110 111 test_case->compiler_args.append("build"); 112 test_case->compiler_args.append(tmp_source_path); 113 114 test_case->compiler_args.append("--name"); 115 test_case->compiler_args.append("test"); 116 117 test_case->compiler_args.append("--export"); 118 test_case->compiler_args.append("obj"); 119 120 test_case->compiler_args.append("--output"); 121 test_case->compiler_args.append(tmp_exe_path); 122 123 test_case->compiler_args.append("--release"); 124 test_case->compiler_args.append("--strip"); 125 test_case->compiler_args.append("--check-unused"); 126 127 test_cases.append(test_case); 128 129 va_end(ap); 130 131 return test_case; 132 } 133 134 static void add_debug_safety_case(const char *case_name, const char *source) { 135 { 136 TestCase *test_case = allocate<TestCase>(1); 137 test_case->is_debug_safety = true; 138 test_case->case_name = buf_ptr(buf_sprintf("%s (debug)", case_name)); 139 test_case->source_files.resize(1); 140 test_case->source_files.at(0).relative_path = tmp_source_path; 141 test_case->source_files.at(0).source_code = source; 142 143 test_case->compiler_args.append("build"); 144 test_case->compiler_args.append(tmp_source_path); 145 146 test_case->compiler_args.append("--name"); 147 test_case->compiler_args.append("test"); 148 149 test_case->compiler_args.append("--export"); 150 test_case->compiler_args.append("exe"); 151 152 test_case->compiler_args.append("--output"); 153 test_case->compiler_args.append(tmp_exe_path); 154 155 test_cases.append(test_case); 156 } 157 { 158 TestCase *test_case = allocate<TestCase>(1); 159 test_case->case_name = buf_ptr(buf_sprintf("%s (release)", case_name)); 160 test_case->source_files.resize(1); 161 test_case->source_files.at(0).relative_path = tmp_source_path; 162 test_case->source_files.at(0).source_code = source; 163 test_case->output = ""; 164 165 test_case->compiler_args.append("build"); 166 test_case->compiler_args.append(tmp_source_path); 167 168 test_case->compiler_args.append("--name"); 169 test_case->compiler_args.append("test"); 170 171 test_case->compiler_args.append("--export"); 172 test_case->compiler_args.append("exe"); 173 174 test_case->compiler_args.append("--output"); 175 test_case->compiler_args.append(tmp_exe_path); 176 177 test_case->compiler_args.append("--release"); 178 179 test_cases.append(test_case); 180 } 181 } 182 183 static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warnings, 184 const char *source, size_t count, ...) 185 { 186 va_list ap; 187 va_start(ap, count); 188 189 TestCase *test_case = allocate<TestCase>(1); 190 test_case->case_name = case_name; 191 test_case->is_parseh = true; 192 test_case->allow_warnings = allow_warnings; 193 194 test_case->source_files.resize(1); 195 test_case->source_files.at(0).relative_path = tmp_h_path; 196 test_case->source_files.at(0).source_code = source; 197 198 for (size_t i = 0; i < count; i += 1) { 199 const char *arg = va_arg(ap, const char *); 200 test_case->compile_errors.append(arg); 201 } 202 203 test_case->compiler_args.append("parseh"); 204 test_case->compiler_args.append(tmp_h_path); 205 //test_case->compiler_args.append("--verbose"); 206 207 test_cases.append(test_case); 208 209 va_end(ap); 210 return test_case; 211 } 212 213 static void add_compiling_test_cases(void) { 214 add_simple_case_libc("hello world with libc", R"SOURCE( 215 const c = @cImport(@cInclude("stdio.h")); 216 export fn main(argc: c_int, argv: &&u8) -> c_int { 217 c.puts(c"Hello, world!"); 218 return 0; 219 } 220 )SOURCE", "Hello, world!" NL); 221 222 { 223 TestCase *tc = add_simple_case("multiple files with private function", R"SOURCE( 224 use @import("std").io; 225 use @import("foo.zig"); 226 227 pub fn main(args: [][]u8) -> %void { 228 privateFunction(); 229 %%stdout.printf("OK 2\n"); 230 } 231 232 fn privateFunction() { 233 printText(); 234 } 235 )SOURCE", "OK 1\nOK 2\n"); 236 237 add_source_file(tc, "foo.zig", R"SOURCE( 238 use @import("std").io; 239 240 // purposefully conflicting function with main.zig 241 // but it's private so it should be OK 242 fn privateFunction() { 243 %%stdout.printf("OK 1\n"); 244 } 245 246 pub fn printText() { 247 privateFunction(); 248 } 249 )SOURCE"); 250 } 251 252 { 253 TestCase *tc = add_simple_case("import segregation", R"SOURCE( 254 use @import("foo.zig"); 255 use @import("bar.zig"); 256 257 pub fn main(args: [][]u8) -> %void { 258 foo_function(); 259 bar_function(); 260 } 261 )SOURCE", "OK\nOK\n"); 262 263 add_source_file(tc, "foo.zig", R"SOURCE( 264 use @import("std").io; 265 pub fn foo_function() { 266 %%stdout.printf("OK\n"); 267 } 268 )SOURCE"); 269 270 add_source_file(tc, "bar.zig", R"SOURCE( 271 use @import("other.zig"); 272 use @import("std").io; 273 274 pub fn bar_function() { 275 if (foo_function()) { 276 %%stdout.printf("OK\n"); 277 } 278 } 279 )SOURCE"); 280 281 add_source_file(tc, "other.zig", R"SOURCE( 282 pub fn foo_function() -> bool { 283 // this one conflicts with the one from foo 284 return true; 285 } 286 )SOURCE"); 287 } 288 289 { 290 TestCase *tc = add_simple_case("two files use import each other", R"SOURCE( 291 use @import("a.zig"); 292 293 pub fn main(args: [][]u8) -> %void { 294 ok(); 295 } 296 )SOURCE", "OK\n"); 297 298 add_source_file(tc, "a.zig", R"SOURCE( 299 use @import("b.zig"); 300 const io = @import("std").io; 301 302 pub const a_text = "OK\n"; 303 304 pub fn ok() { 305 %%io.stdout.printf(b_text); 306 } 307 )SOURCE"); 308 309 add_source_file(tc, "b.zig", R"SOURCE( 310 use @import("a.zig"); 311 312 pub const b_text = a_text; 313 )SOURCE"); 314 } 315 316 317 318 add_simple_case("hello world without libc", R"SOURCE( 319 const io = @import("std").io; 320 321 pub fn main(args: [][]u8) -> %void { 322 %%io.stdout.printf("Hello, world!\n"); 323 } 324 )SOURCE", "Hello, world!\n"); 325 326 327 add_simple_case_libc("number literals", R"SOURCE( 328 const c = @cImport(@cInclude("stdio.h")); 329 330 export fn main(argc: c_int, argv: &&u8) -> c_int { 331 c.printf(c"\n"); 332 333 c.printf(c"0: %llu\n", 334 u64(0)); 335 c.printf(c"320402575052271: %llu\n", 336 u64(320402575052271)); 337 c.printf(c"0x01236789abcdef: %llu\n", 338 u64(0x01236789abcdef)); 339 c.printf(c"0xffffffffffffffff: %llu\n", 340 u64(0xffffffffffffffff)); 341 c.printf(c"0x000000ffffffffffffffff: %llu\n", 342 u64(0x000000ffffffffffffffff)); 343 c.printf(c"0o1777777777777777777777: %llu\n", 344 u64(0o1777777777777777777777)); 345 c.printf(c"0o0000001777777777777777777777: %llu\n", 346 u64(0o0000001777777777777777777777)); 347 c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", 348 u64(0b1111111111111111111111111111111111111111111111111111111111111111)); 349 c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", 350 u64(0b0000001111111111111111111111111111111111111111111111111111111111111111)); 351 352 c.printf(c"\n"); 353 354 c.printf(c"0.0: %a\n", 355 f64(0.0)); 356 c.printf(c"0e0: %a\n", 357 f64(0e0)); 358 c.printf(c"0.0e0: %a\n", 359 f64(0.0e0)); 360 c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n", 361 f64(000000000000000000000000000000000000000000000000000000000.0e0)); 362 c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n", 363 f64(0.000000000000000000000000000000000000000000000000000000000e0)); 364 c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n", 365 f64(0.0e000000000000000000000000000000000000000000000000000000000)); 366 c.printf(c"1.0: %a\n", 367 f64(1.0)); 368 c.printf(c"10.0: %a\n", 369 f64(10.0)); 370 c.printf(c"10.5: %a\n", 371 f64(10.5)); 372 c.printf(c"10.5e5: %a\n", 373 f64(10.5e5)); 374 c.printf(c"10.5e+5: %a\n", 375 f64(10.5e+5)); 376 c.printf(c"50.0e-2: %a\n", 377 f64(50.0e-2)); 378 c.printf(c"50e-2: %a\n", 379 f64(50e-2)); 380 381 c.printf(c"\n"); 382 383 c.printf(c"0x1.0: %a\n", 384 f64(0x1.0)); 385 c.printf(c"0x10.0: %a\n", 386 f64(0x10.0)); 387 c.printf(c"0x100.0: %a\n", 388 f64(0x100.0)); 389 c.printf(c"0x103.0: %a\n", 390 f64(0x103.0)); 391 c.printf(c"0x103.7: %a\n", 392 f64(0x103.7)); 393 c.printf(c"0x103.70: %a\n", 394 f64(0x103.70)); 395 c.printf(c"0x103.70p4: %a\n", 396 f64(0x103.70p4)); 397 c.printf(c"0x103.70p5: %a\n", 398 f64(0x103.70p5)); 399 c.printf(c"0x103.70p+5: %a\n", 400 f64(0x103.70p+5)); 401 c.printf(c"0x103.70p-5: %a\n", 402 f64(0x103.70p-5)); 403 404 c.printf(c"\n"); 405 406 c.printf(c"0b10100.00010e0: %a\n", 407 f64(0b10100.00010e0)); 408 c.printf(c"0o10700.00010e0: %a\n", 409 f64(0o10700.00010e0)); 410 411 return 0; 412 } 413 )SOURCE", R"OUTPUT( 414 0: 0 415 320402575052271: 320402575052271 416 0x01236789abcdef: 320402575052271 417 0xffffffffffffffff: 18446744073709551615 418 0x000000ffffffffffffffff: 18446744073709551615 419 0o1777777777777777777777: 18446744073709551615 420 0o0000001777777777777777777777: 18446744073709551615 421 0b1111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 422 0b0000001111111111111111111111111111111111111111111111111111111111111111: 18446744073709551615 423 424 0.0: 0x0p+0 425 0e0: 0x0p+0 426 0.0e0: 0x0p+0 427 000000000000000000000000000000000000000000000000000000000.0e0: 0x0p+0 428 0.000000000000000000000000000000000000000000000000000000000e0: 0x0p+0 429 0.0e000000000000000000000000000000000000000000000000000000000: 0x0p+0 430 1.0: 0x1p+0 431 10.0: 0x1.4p+3 432 10.5: 0x1.5p+3 433 10.5e5: 0x1.0059p+20 434 10.5e+5: 0x1.0059p+20 435 50.0e-2: 0x1p-1 436 50e-2: 0x1p-1 437 438 0x1.0: 0x1p+0 439 0x10.0: 0x1p+4 440 0x100.0: 0x1p+8 441 0x103.0: 0x1.03p+8 442 0x103.7: 0x1.037p+8 443 0x103.70: 0x1.037p+8 444 0x103.70p4: 0x1.037p+12 445 0x103.70p5: 0x1.037p+13 446 0x103.70p+5: 0x1.037p+13 447 0x103.70p-5: 0x1.037p+3 448 449 0b10100.00010e0: 0x1.41p+4 450 0o10700.00010e0: 0x1.1c0001p+12 451 )OUTPUT"); 452 453 add_simple_case("order-independent declarations", R"SOURCE( 454 const io = @import("std").io; 455 const z = io.stdin_fileno; 456 const x : @typeOf(y) = 1234; 457 const y : u16 = 5678; 458 pub fn main(args: [][]u8) -> %void { 459 var x_local : i32 = print_ok(x); 460 } 461 fn print_ok(val: @typeOf(x)) -> @typeOf(foo) { 462 %%io.stdout.printf("OK\n"); 463 return 0; 464 } 465 const foo : i32 = 0; 466 )SOURCE", "OK\n"); 467 468 add_simple_case("for loops", R"SOURCE( 469 const io = @import("std").io; 470 471 pub fn main(args: [][]u8) -> %void { 472 const array = []u8 {9, 8, 7, 6}; 473 for (array) |item| { 474 %%io.stdout.printInt(@typeOf(item), item); 475 %%io.stdout.printf("\n"); 476 } 477 for (array) |item, index| { 478 %%io.stdout.printInt(@typeOf(index), index); 479 %%io.stdout.printf("\n"); 480 } 481 const unknown_size: []u8 = array; 482 for (unknown_size) |item| { 483 %%io.stdout.printInt(@typeOf(item), item); 484 %%io.stdout.printf("\n"); 485 } 486 for (unknown_size) |item, index| { 487 %%io.stdout.printInt(@typeOf(index), index); 488 %%io.stdout.printf("\n"); 489 } 490 } 491 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n"); 492 493 add_simple_case_libc("expose function pointer to C land", R"SOURCE( 494 const c = @cImport(@cInclude("stdlib.h")); 495 496 export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int { 497 const a_int = (&i32)(a ?? @unreachable()); 498 const b_int = (&i32)(b ?? @unreachable()); 499 if (*a_int < *b_int) { 500 -1 501 } else if (*a_int > *b_int) { 502 1 503 } else { 504 c_int(0) 505 } 506 } 507 508 export fn main(args: c_int, argv: &&u8) -> c_int { 509 var array = []u32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 }; 510 511 c.qsort((&c_void)(&array[0]), c_ulong(array.len), @sizeOf(i32), compare_fn); 512 513 for (array) |item, i| { 514 if (item != i) { 515 c.abort(); 516 } 517 } 518 519 return 0; 520 } 521 )SOURCE", ""); 522 523 524 525 add_simple_case_libc("casting between float and integer types", R"SOURCE( 526 const c = @cImport(@cInclude("stdio.h")); 527 export fn main(argc: c_int, argv: &&u8) -> c_int { 528 const small: f32 = 3.25; 529 const x: f64 = small; 530 const y = i32(x); 531 const z = f64(y); 532 c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4)); 533 return 0; 534 } 535 )SOURCE", "3.25\n3\n3.00\n-0.40\n"); 536 537 538 add_simple_case("incomplete struct parameter top level decl", R"SOURCE( 539 const io = @import("std").io; 540 const A = struct { 541 b: B, 542 }; 543 544 const B = struct { 545 c: C, 546 }; 547 548 const C = struct { 549 x: i32, 550 551 fn d(c: &const C) { 552 %%io.stdout.printf("OK\n"); 553 } 554 }; 555 556 fn foo(a: A) { 557 a.b.c.d(); 558 } 559 560 pub fn main(args: [][]u8) -> %void { 561 const a = A { 562 .b = B { 563 .c = C { 564 .x = 13, 565 }, 566 }, 567 }; 568 foo(a); 569 } 570 571 )SOURCE", "OK\n"); 572 573 574 add_simple_case("same named methods in incomplete struct", R"SOURCE( 575 const io = @import("std").io; 576 577 const Foo = struct { 578 field1: Bar, 579 580 fn method(a: &const Foo) -> bool { true } 581 }; 582 583 const Bar = struct { 584 field2: i32, 585 586 fn method(b: &const Bar) -> bool { true } 587 }; 588 589 pub fn main(args: [][]u8) -> %void { 590 const bar = Bar {.field2 = 13,}; 591 const foo = Foo {.field1 = bar,}; 592 if (!foo.method()) { 593 %%io.stdout.printf("BAD\n"); 594 } 595 if (!bar.method()) { 596 %%io.stdout.printf("BAD\n"); 597 } 598 %%io.stdout.printf("OK\n"); 599 } 600 )SOURCE", "OK\n"); 601 602 603 add_simple_case("defer with only fallthrough", R"SOURCE( 604 const io = @import("std").io; 605 pub fn main(args: [][]u8) -> %void { 606 %%io.stdout.printf("before\n"); 607 defer %%io.stdout.printf("defer1\n"); 608 defer %%io.stdout.printf("defer2\n"); 609 defer %%io.stdout.printf("defer3\n"); 610 %%io.stdout.printf("after\n"); 611 } 612 )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n"); 613 614 615 add_simple_case("defer with return", R"SOURCE( 616 const io = @import("std").io; 617 pub fn main(args: [][]u8) -> %void { 618 %%io.stdout.printf("before\n"); 619 defer %%io.stdout.printf("defer1\n"); 620 defer %%io.stdout.printf("defer2\n"); 621 if (args.len == 1) return; 622 defer %%io.stdout.printf("defer3\n"); 623 %%io.stdout.printf("after\n"); 624 } 625 )SOURCE", "before\ndefer2\ndefer1\n"); 626 627 628 add_simple_case("%defer and it fails", R"SOURCE( 629 const io = @import("std").io; 630 pub fn main(args: [][]u8) -> %void { 631 do_test() %% return; 632 } 633 fn do_test() -> %void { 634 %%io.stdout.printf("before\n"); 635 defer %%io.stdout.printf("defer1\n"); 636 %defer %%io.stdout.printf("deferErr\n"); 637 %return its_gonna_fail(); 638 defer %%io.stdout.printf("defer3\n"); 639 %%io.stdout.printf("after\n"); 640 } 641 error IToldYouItWouldFail; 642 fn its_gonna_fail() -> %void { 643 return error.IToldYouItWouldFail; 644 } 645 )SOURCE", "before\ndeferErr\ndefer1\n"); 646 647 648 add_simple_case("%defer and it passes", R"SOURCE( 649 const io = @import("std").io; 650 pub fn main(args: [][]u8) -> %void { 651 do_test() %% return; 652 } 653 fn do_test() -> %void { 654 %%io.stdout.printf("before\n"); 655 defer %%io.stdout.printf("defer1\n"); 656 %defer %%io.stdout.printf("deferErr\n"); 657 %return its_gonna_pass(); 658 defer %%io.stdout.printf("defer3\n"); 659 %%io.stdout.printf("after\n"); 660 } 661 fn its_gonna_pass() -> %void { } 662 )SOURCE", "before\nafter\ndefer3\ndefer1\n"); 663 664 665 { 666 TestCase *tc = add_simple_case("@embedFile", R"SOURCE( 667 const foo_txt = @embedFile("foo.txt"); 668 const io = @import("std").io; 669 670 pub fn main(args: [][]u8) -> %void { 671 %%io.stdout.printf(foo_txt); 672 } 673 )SOURCE", "1234\nabcd\n"); 674 675 add_source_file(tc, "foo.txt", "1234\nabcd\n"); 676 } 677 } 678 679 680 //////////////////////////////////////////////////////////////////////////////////// 681 682 static void add_compile_failure_test_cases(void) { 683 add_compile_fail_case("multiple function definitions", R"SOURCE( 684 fn a() {} 685 fn a() {} 686 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'a'"); 687 688 add_compile_fail_case("unreachable with return", R"SOURCE( 689 fn a() -> unreachable {return;} 690 )SOURCE", 1, ".tmp_source.zig:2:24: error: expected type 'unreachable', found 'void'"); 691 692 add_compile_fail_case("control reaches end of non-void function", R"SOURCE( 693 fn a() -> i32 {} 694 )SOURCE", 1, ".tmp_source.zig:2:15: error: expected type 'i32', found 'void'"); 695 696 add_compile_fail_case("undefined function call", R"SOURCE( 697 fn a() { 698 b(); 699 } 700 )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'"); 701 702 add_compile_fail_case("wrong number of arguments", R"SOURCE( 703 fn a() { 704 b(1); 705 } 706 fn b(a: i32, b: i32, c: i32) { } 707 )SOURCE", 1, ".tmp_source.zig:3:6: error: expected 3 arguments, found 1"); 708 709 add_compile_fail_case("invalid type", R"SOURCE( 710 fn a() -> bogus {} 711 )SOURCE", 1, ".tmp_source.zig:2:11: error: use of undeclared identifier 'bogus'"); 712 713 add_compile_fail_case("pointer to unreachable", R"SOURCE( 714 fn a() -> &unreachable {} 715 )SOURCE", 1, ".tmp_source.zig:2:12: error: pointer to unreachable not allowed"); 716 717 add_compile_fail_case("unreachable code", R"SOURCE( 718 fn a() { 719 return; 720 b(); 721 } 722 723 fn b() {} 724 )SOURCE", 1, ".tmp_source.zig:4:6: error: unreachable code"); 725 726 add_compile_fail_case("bad import", R"SOURCE( 727 const bogus = @import("bogus-does-not-exist.zig"); 728 )SOURCE", 1, ".tmp_source.zig:2:15: error: unable to find 'bogus-does-not-exist.zig'"); 729 730 add_compile_fail_case("undeclared identifier", R"SOURCE( 731 fn a() { 732 b + 733 c 734 } 735 )SOURCE", 2, 736 ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'", 737 ".tmp_source.zig:4:5: error: use of undeclared identifier 'c'"); 738 739 add_compile_fail_case("parameter redeclaration", R"SOURCE( 740 fn f(a : i32, a : i32) { 741 } 742 )SOURCE", 1, ".tmp_source.zig:2:15: error: redeclaration of variable 'a'"); 743 744 add_compile_fail_case("local variable redeclaration", R"SOURCE( 745 fn f() { 746 const a : i32 = 0; 747 const a = 0; 748 } 749 )SOURCE", 1, ".tmp_source.zig:4:5: error: redeclaration of variable 'a'"); 750 751 add_compile_fail_case("local variable redeclares parameter", R"SOURCE( 752 fn f(a : i32) { 753 const a = 0; 754 } 755 )SOURCE", 1, ".tmp_source.zig:3:5: error: redeclaration of variable 'a'"); 756 757 add_compile_fail_case("variable has wrong type", R"SOURCE( 758 fn f() -> i32 { 759 const a = c"a"; 760 a 761 } 762 )SOURCE", 1, ".tmp_source.zig:4:5: error: expected type 'i32', found '&const u8'"); 763 764 add_compile_fail_case("if condition is bool, not int", R"SOURCE( 765 fn f() { 766 if (0) {} 767 } 768 )SOURCE", 1, ".tmp_source.zig:3:9: error: integer value 0 cannot be implicitly casted to type 'bool'"); 769 770 add_compile_fail_case("assign unreachable", R"SOURCE( 771 fn f() { 772 const a = return; 773 } 774 )SOURCE", 1, ".tmp_source.zig:3:5: error: unreachable code"); 775 776 add_compile_fail_case("unreachable variable", R"SOURCE( 777 fn f() { 778 const a : unreachable = {}; 779 } 780 )SOURCE", 1, ".tmp_source.zig:3:15: error: variable of type 'unreachable' not allowed"); 781 782 add_compile_fail_case("unreachable parameter", R"SOURCE( 783 fn f(a : unreachable) {} 784 )SOURCE", 1, ".tmp_source.zig:2:10: error: parameter of type 'unreachable' not allowed"); 785 786 add_compile_fail_case("bad assignment target", R"SOURCE( 787 fn f() { 788 3 = 3; 789 } 790 )SOURCE", 1, ".tmp_source.zig:3:7: error: cannot assign to constant"); 791 792 add_compile_fail_case("assign to constant variable", R"SOURCE( 793 fn f() { 794 const a = 3; 795 a = 4; 796 } 797 )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant"); 798 799 add_compile_fail_case("use of undeclared identifier", R"SOURCE( 800 fn f() { 801 b = 3; 802 } 803 )SOURCE", 1, ".tmp_source.zig:3:5: error: use of undeclared identifier 'b'"); 804 805 add_compile_fail_case("const is a statement, not an expression", R"SOURCE( 806 fn f() { 807 (const a = 0); 808 } 809 )SOURCE", 1, ".tmp_source.zig:3:6: error: invalid token: 'const'"); 810 811 add_compile_fail_case("array access of undeclared identifier", R"SOURCE( 812 fn f() { 813 i[i] = i[i]; 814 } 815 )SOURCE", 2, ".tmp_source.zig:3:5: error: use of undeclared identifier 'i'", 816 ".tmp_source.zig:3:12: error: use of undeclared identifier 'i'"); 817 818 add_compile_fail_case("array access of non array", R"SOURCE( 819 fn f() { 820 var bad : bool = undefined; 821 bad[bad] = bad[bad]; 822 } 823 )SOURCE", 2, ".tmp_source.zig:4:8: error: array access of non-array type 'bool'", 824 ".tmp_source.zig:4:19: error: array access of non-array type 'bool'"); 825 826 add_compile_fail_case("array access with non integer index", R"SOURCE( 827 fn f() { 828 var array = "aoeu"; 829 var bad = false; 830 array[bad] = array[bad]; 831 } 832 )SOURCE", 2, ".tmp_source.zig:5:11: error: expected type 'usize', found 'bool'", 833 ".tmp_source.zig:5:24: error: expected type 'usize', found 'bool'"); 834 835 add_compile_fail_case("write to const global variable", R"SOURCE( 836 const x : i32 = 99; 837 fn f() { 838 x = 1; 839 } 840 )SOURCE", 1, ".tmp_source.zig:4:7: error: cannot assign to constant"); 841 842 843 add_compile_fail_case("missing else clause", R"SOURCE( 844 fn f(b: bool) { 845 const x : i32 = if (b) { 1 }; 846 const y = if (b) { i32(1) }; 847 } 848 )SOURCE", 2, ".tmp_source.zig:3:30: error: integer value 1 cannot be implicitly casted to type 'void'", 849 ".tmp_source.zig:4:15: error: incompatible types: 'i32' and 'void'"); 850 851 add_compile_fail_case("direct struct loop", R"SOURCE( 852 const A = struct { a : A, }; 853 )SOURCE", 1, ".tmp_source.zig:2:11: error: struct 'A' contains itself"); 854 855 add_compile_fail_case("indirect struct loop", R"SOURCE( 856 const A = struct { b : B, }; 857 const B = struct { c : C, }; 858 const C = struct { a : A, }; 859 )SOURCE", 1, ".tmp_source.zig:2:11: error: struct 'A' contains itself"); 860 861 add_compile_fail_case("invalid struct field", R"SOURCE( 862 const A = struct { x : i32, }; 863 fn f() { 864 var a : A = undefined; 865 a.foo = 1; 866 const y = a.bar; 867 } 868 )SOURCE", 2, 869 ".tmp_source.zig:5:6: error: no member named 'foo' in 'A'", 870 ".tmp_source.zig:6:16: error: no member named 'bar' in 'A'"); 871 872 add_compile_fail_case("redefinition of struct", R"SOURCE( 873 const A = struct { x : i32, }; 874 const A = struct { y : i32, }; 875 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'"); 876 877 add_compile_fail_case("redefinition of enums", R"SOURCE( 878 const A = enum {}; 879 const A = enum {}; 880 )SOURCE", 1, ".tmp_source.zig:3:1: error: redefinition of 'A'"); 881 882 add_compile_fail_case("redefinition of global variables", R"SOURCE( 883 var a : i32 = 1; 884 var a : i32 = 2; 885 )SOURCE", 1, ".tmp_source.zig:3:1: error: redeclaration of variable 'a'"); 886 887 add_compile_fail_case("byvalue struct parameter in exported function", R"SOURCE( 888 const A = struct { x : i32, }; 889 export fn f(a : A) {} 890 )SOURCE", 1, ".tmp_source.zig:3:13: error: byvalue types not yet supported on extern function parameters"); 891 892 add_compile_fail_case("byvalue struct return value in exported function", R"SOURCE( 893 const A = struct { x: i32, }; 894 export fn f() -> A { 895 A {.x = 1234 } 896 } 897 )SOURCE", 1, ".tmp_source.zig:3:18: error: byvalue types not yet supported on extern function return values"); 898 899 add_compile_fail_case("duplicate field in struct value expression", R"SOURCE( 900 const A = struct { 901 x : i32, 902 y : i32, 903 z : i32, 904 }; 905 fn f() { 906 const a = A { 907 .z = 1, 908 .y = 2, 909 .x = 3, 910 .z = 4, 911 }; 912 } 913 )SOURCE", 1, ".tmp_source.zig:12:9: error: duplicate field"); 914 915 add_compile_fail_case("missing field in struct value expression", R"SOURCE( 916 const A = struct { 917 x : i32, 918 y : i32, 919 z : i32, 920 }; 921 fn f() { 922 // we want the error on the '{' not the 'A' because 923 // the A could be a complicated expression 924 const a = A { 925 .z = 4, 926 .y = 2, 927 }; 928 } 929 )SOURCE", 1, ".tmp_source.zig:10:17: error: missing field: 'x'"); 930 931 add_compile_fail_case("invalid field in struct value expression", R"SOURCE( 932 const A = struct { 933 x : i32, 934 y : i32, 935 z : i32, 936 }; 937 fn f() { 938 const a = A { 939 .z = 4, 940 .y = 2, 941 .foo = 42, 942 }; 943 } 944 )SOURCE", 1, ".tmp_source.zig:11:9: error: no member named 'foo' in 'A'"); 945 946 add_compile_fail_case("invalid break expression", R"SOURCE( 947 fn f() { 948 break; 949 } 950 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'break' expression outside loop"); 951 952 add_compile_fail_case("invalid continue expression", R"SOURCE( 953 fn f() { 954 continue; 955 } 956 )SOURCE", 1, ".tmp_source.zig:3:5: error: 'continue' expression outside loop"); 957 958 add_compile_fail_case("invalid maybe type", R"SOURCE( 959 fn f() { 960 if (const x ?= true) { } 961 } 962 )SOURCE", 1, ".tmp_source.zig:3:20: error: expected nullable type, found 'bool'"); 963 964 add_compile_fail_case("cast unreachable", R"SOURCE( 965 fn f() -> i32 { 966 i32(return 1) 967 } 968 )SOURCE", 1, ".tmp_source.zig:3:8: error: unreachable code"); 969 970 add_compile_fail_case("invalid builtin fn", R"SOURCE( 971 fn f() -> @bogus(foo) { 972 } 973 )SOURCE", 1, ".tmp_source.zig:2:11: error: invalid builtin function: 'bogus'"); 974 975 add_compile_fail_case("top level decl dependency loop", R"SOURCE( 976 const a : @typeOf(b) = 0; 977 const b : @typeOf(a) = 0; 978 )SOURCE", 1, ".tmp_source.zig:2:1: error: 'a' depends on itself"); 979 980 add_compile_fail_case("noalias on non pointer param", R"SOURCE( 981 fn f(noalias x: i32) {} 982 )SOURCE", 1, ".tmp_source.zig:2:6: error: noalias on non-pointer parameter"); 983 984 add_compile_fail_case("struct init syntax for array", R"SOURCE( 985 const foo = []u16{.x = 1024,}; 986 )SOURCE", 1, ".tmp_source.zig:2:18: error: type '[]u16' does not support struct initialization syntax"); 987 988 add_compile_fail_case("type variables must be constant", R"SOURCE( 989 var foo = u8; 990 )SOURCE", 1, ".tmp_source.zig:2:1: error: variable of type 'type' must be constant"); 991 992 add_compile_fail_case("variables shadowing types", R"SOURCE( 993 const Foo = struct {}; 994 const Bar = struct {}; 995 996 fn f(Foo: i32) { 997 var Bar : i32 = undefined; 998 } 999 )SOURCE", 4, 1000 ".tmp_source.zig:5:6: error: redeclaration of variable 'Foo'", 1001 ".tmp_source.zig:2:1: note: previous declaration is here", 1002 ".tmp_source.zig:6:5: error: redeclaration of variable 'Bar'", 1003 ".tmp_source.zig:3:1: note: previous declaration is here"); 1004 1005 add_compile_fail_case("multiple else prongs in a switch", R"SOURCE( 1006 fn f(x: u32) { 1007 const value: bool = switch (x) { 1008 1234 => false, 1009 else => true, 1010 else => true, 1011 }; 1012 } 1013 )SOURCE", 1, ".tmp_source.zig:6:9: error: multiple else prongs in switch expression"); 1014 1015 add_compile_fail_case("global variable initializer must be constant expression", R"SOURCE( 1016 extern fn foo() -> i32; 1017 const x = foo(); 1018 )SOURCE", 1, ".tmp_source.zig:3:11: error: unable to evaluate constant expression"); 1019 1020 add_compile_fail_case("array concatenation with wrong type", R"SOURCE( 1021 const src = "aoeu"; 1022 const a = src[0...] ++ "foo"; 1023 )SOURCE", 1, ".tmp_source.zig:3:14: error: expected array or C string literal, found '[]u8'"); 1024 1025 add_compile_fail_case("non compile time array concatenation", R"SOURCE( 1026 fn f(s: [10]u8) -> []u8 { 1027 s ++ "foo" 1028 } 1029 )SOURCE", 1, ".tmp_source.zig:3:5: error: unable to evaluate constant expression"); 1030 1031 add_compile_fail_case("@cImport with bogus include", R"SOURCE( 1032 const c = @cImport(@cInclude("bogus.h")); 1033 )SOURCE", 2, ".tmp_source.zig:2:11: error: C import failed", 1034 ".h:1:10: note: 'bogus.h' file not found"); 1035 1036 add_compile_fail_case("address of number literal", R"SOURCE( 1037 const x = 3; 1038 const y = &x; 1039 fn foo() -> &const i32 { y } 1040 )SOURCE", 1, ".tmp_source.zig:4:26: error: expected type '&const i32', found '&const (integer literal)'"); 1041 1042 add_compile_fail_case("integer overflow error", R"SOURCE( 1043 const x : u8 = 300; 1044 )SOURCE", 1, ".tmp_source.zig:2:16: error: integer value 300 cannot be implicitly casted to type 'u8'"); 1045 1046 add_compile_fail_case("incompatible number literals", R"SOURCE( 1047 const x = 2 == 2.0; 1048 )SOURCE", 1, ".tmp_source.zig:2:11: error: integer value 2 cannot be implicitly casted to type '(float literal)'"); 1049 1050 add_compile_fail_case("missing function call param", R"SOURCE( 1051 const Foo = struct { 1052 a: i32, 1053 b: i32, 1054 1055 fn member_a(foo: Foo) -> i32 { 1056 return foo.a; 1057 } 1058 fn member_b(foo: Foo) -> i32 { 1059 return foo.b; 1060 } 1061 }; 1062 1063 const member_fn_type = @typeOf(Foo.member_a); 1064 const members = []member_fn_type { 1065 Foo.member_a, 1066 Foo.member_b, 1067 }; 1068 1069 fn f(foo: Foo, index: usize) { 1070 const result = members[index](); 1071 } 1072 )SOURCE", 1, ".tmp_source.zig:21:34: error: expected 1 arguments, found 0"); 1073 1074 add_compile_fail_case("missing function name and param name", R"SOURCE( 1075 fn () {} 1076 fn f(i32) {} 1077 )SOURCE", 2, 1078 ".tmp_source.zig:2:1: error: missing function name", 1079 ".tmp_source.zig:3:6: error: missing parameter name"); 1080 1081 add_compile_fail_case("wrong function type", R"SOURCE( 1082 const fns = []fn(){ a, b, c }; 1083 fn a() -> i32 {0} 1084 fn b() -> i32 {1} 1085 fn c() -> i32 {2} 1086 )SOURCE", 1, ".tmp_source.zig:2:21: error: expected type 'fn()', found 'fn() -> i32'"); 1087 1088 add_compile_fail_case("extern function pointer mismatch", R"SOURCE( 1089 const fns = [](fn(i32)->i32){ a, b, c }; 1090 pub fn a(x: i32) -> i32 {x + 0} 1091 pub fn b(x: i32) -> i32 {x + 1} 1092 export fn c(x: i32) -> i32 {x + 2} 1093 )SOURCE", 1, ".tmp_source.zig:2:37: error: expected type 'fn(i32) -> i32', found 'extern fn(i32) -> i32'"); 1094 1095 1096 add_compile_fail_case("implicit cast from f64 to f32", R"SOURCE( 1097 const x : f64 = 1.0; 1098 const y : f32 = x; 1099 )SOURCE", 1, ".tmp_source.zig:3:17: error: expected type 'f32', found 'f64'"); 1100 1101 1102 add_compile_fail_case("colliding invalid top level functions", R"SOURCE( 1103 fn func() -> bogus {} 1104 fn func() -> bogus {} 1105 )SOURCE", 2, 1106 ".tmp_source.zig:3:1: error: redefinition of 'func'", 1107 ".tmp_source.zig:2:14: error: use of undeclared identifier 'bogus'"); 1108 1109 1110 add_compile_fail_case("bogus compile var", R"SOURCE( 1111 const x = @compileVar("bogus"); 1112 )SOURCE", 1, ".tmp_source.zig:2:23: error: unrecognized compile variable: 'bogus'"); 1113 1114 1115 add_compile_fail_case("non constant expression in array size outside function", R"SOURCE( 1116 const Foo = struct { 1117 y: [get()]u8, 1118 }; 1119 var global_var: usize = 1; 1120 fn get() -> usize { global_var } 1121 )SOURCE", 3, 1122 ".tmp_source.zig:6:21: error: unable to evaluate constant expression", 1123 ".tmp_source.zig:3:12: note: called from here", 1124 ".tmp_source.zig:3:8: note: called from here"); 1125 1126 1127 add_compile_fail_case("unnecessary if statement", R"SOURCE( 1128 fn f() { 1129 if (true) { } 1130 } 1131 )SOURCE", 1, ".tmp_source.zig:3:9: error: condition is always true; unnecessary if statement"); 1132 1133 1134 add_compile_fail_case("addition with non numbers", R"SOURCE( 1135 const Foo = struct { 1136 field: i32, 1137 }; 1138 const x = Foo {.field = 1} + Foo {.field = 2}; 1139 )SOURCE", 1, ".tmp_source.zig:5:28: error: invalid operands to binary expression: 'Foo' and 'Foo'"); 1140 1141 1142 add_compile_fail_case("division by zero", R"SOURCE( 1143 const lit_int_x = 1 / 0; 1144 const lit_float_x = 1.0 / 0.0; 1145 const int_x = i32(1) / i32(0); 1146 const float_x = f32(1.0) / f32(0.0); 1147 )SOURCE", 4, 1148 ".tmp_source.zig:2:21: error: division by zero is undefined", 1149 ".tmp_source.zig:3:25: error: division by zero is undefined", 1150 ".tmp_source.zig:4:22: error: division by zero is undefined", 1151 ".tmp_source.zig:5:26: error: division by zero is undefined"); 1152 1153 1154 add_compile_fail_case("missing switch prong", R"SOURCE( 1155 const Number = enum { 1156 One, 1157 Two, 1158 Three, 1159 Four, 1160 }; 1161 fn f(n: Number) -> i32 { 1162 switch (n) { 1163 Number.One => 1, 1164 Number.Two => 2, 1165 Number.Three => i32(3), 1166 } 1167 } 1168 )SOURCE", 1, ".tmp_source.zig:9:5: error: enumeration value 'Number.Four' not handled in switch"); 1169 1170 add_compile_fail_case("import inside function body", R"SOURCE( 1171 fn f() { 1172 const std = @import("std"); 1173 } 1174 )SOURCE", 1, ".tmp_source.zig:3:17: error: import valid only at global scope"); 1175 1176 1177 add_compile_fail_case("normal string with newline", R"SOURCE( 1178 const foo = "a 1179 b"; 1180 )SOURCE", 1, ".tmp_source.zig:2:13: error: newline not allowed in string literal"); 1181 1182 add_compile_fail_case("invalid comparison for function pointers", R"SOURCE( 1183 fn foo() {} 1184 const invalid = foo > foo; 1185 )SOURCE", 1, ".tmp_source.zig:3:21: error: operator not allowed for type 'fn()'"); 1186 1187 add_compile_fail_case("generic function instance with non-constant expression", R"SOURCE( 1188 fn foo(comptime x: i32, y: i32) -> i32 { return x + y; } 1189 fn test1(a: i32, b: i32) -> i32 { 1190 return foo(a, b); 1191 } 1192 )SOURCE", 1, ".tmp_source.zig:4:16: error: unable to evaluate constant expression"); 1193 1194 add_compile_fail_case("goto jumping into block", R"SOURCE( 1195 fn f() { 1196 { 1197 a_label: 1198 } 1199 goto a_label; 1200 } 1201 )SOURCE", 1, ".tmp_source.zig:6:5: error: no label in scope named 'a_label'"); 1202 1203 add_compile_fail_case("goto jumping past a defer", R"SOURCE( 1204 fn f(b: bool) { 1205 if (b) goto label; 1206 defer derp(); 1207 label: 1208 } 1209 fn derp(){} 1210 )SOURCE", 1, ".tmp_source.zig:3:12: error: no label in scope named 'label'"); 1211 1212 add_compile_fail_case("assign null to non-nullable pointer", R"SOURCE( 1213 const a: &u8 = null; 1214 )SOURCE", 1, ".tmp_source.zig:2:16: error: expected type '&u8', found '(null)'"); 1215 1216 add_compile_fail_case("indexing an array of size zero", R"SOURCE( 1217 const array = []u8{}; 1218 fn foo() { 1219 const pointer = &array[0]; 1220 } 1221 )SOURCE", 1, ".tmp_source.zig:4:27: error: index 0 outside array of size 0"); 1222 1223 add_compile_fail_case("compile time division by zero", R"SOURCE( 1224 const y = foo(0); 1225 fn foo(x: i32) -> i32 { 1226 1 / x 1227 } 1228 )SOURCE", 2, 1229 ".tmp_source.zig:4:7: error: division by zero is undefined", 1230 ".tmp_source.zig:2:14: note: called from here"); 1231 1232 add_compile_fail_case("branch on undefined value", R"SOURCE( 1233 const x = if (undefined) true else false; 1234 )SOURCE", 1, ".tmp_source.zig:2:15: error: use of undefined value"); 1235 1236 1237 add_compile_fail_case("endless loop in function evaluation", R"SOURCE( 1238 const seventh_fib_number = fibbonaci(7); 1239 fn fibbonaci(x: i32) -> i32 { 1240 return fibbonaci(x - 1) + fibbonaci(x - 2); 1241 } 1242 )SOURCE", 2, 1243 ".tmp_source.zig:4:21: error: evaluation exceeded 1000 backwards branches", 1244 ".tmp_source.zig:4:21: note: called from here"); 1245 1246 add_compile_fail_case("@embedFile with bogus file", R"SOURCE( 1247 const resource = @embedFile("bogus.txt"); 1248 )SOURCE", 1, ".tmp_source.zig:2:29: error: unable to find './bogus.txt'"); 1249 1250 1251 add_compile_fail_case("non-const expression in struct literal outside function", R"SOURCE( 1252 const Foo = struct { 1253 x: i32, 1254 }; 1255 const a = Foo {.x = get_it()}; 1256 extern fn get_it() -> i32; 1257 )SOURCE", 1, ".tmp_source.zig:5:21: error: unable to evaluate constant expression"); 1258 1259 add_compile_fail_case("non-const expression function call with struct return value outside function", R"SOURCE( 1260 const Foo = struct { 1261 x: i32, 1262 }; 1263 const a = get_it(); 1264 fn get_it() -> Foo { 1265 global_side_effect = true; 1266 Foo {.x = 13} 1267 } 1268 var global_side_effect = false; 1269 1270 )SOURCE", 2, 1271 ".tmp_source.zig:7:24: error: unable to evaluate constant expression", 1272 ".tmp_source.zig:5:17: note: called from here"); 1273 1274 add_compile_fail_case("undeclared identifier error should mark fn as impure", R"SOURCE( 1275 fn foo() { 1276 test_a_thing(); 1277 } 1278 fn test_a_thing() { 1279 bad_fn_call(); 1280 } 1281 )SOURCE", 1, ".tmp_source.zig:6:5: error: use of undeclared identifier 'bad_fn_call'"); 1282 1283 add_compile_fail_case("illegal comparison of types", R"SOURCE( 1284 fn bad_eql_1(a: []u8, b: []u8) -> bool { 1285 a == b 1286 } 1287 const EnumWithData = enum { 1288 One, 1289 Two: i32, 1290 }; 1291 fn bad_eql_2(a: EnumWithData, b: EnumWithData) -> bool { 1292 a == b 1293 } 1294 )SOURCE", 2, 1295 ".tmp_source.zig:3:7: error: operator not allowed for type '[]u8'", 1296 ".tmp_source.zig:10:7: error: operator not allowed for type 'EnumWithData'"); 1297 1298 add_compile_fail_case("non-const switch number literal", R"SOURCE( 1299 fn foo() { 1300 const x = switch (bar()) { 1301 1, 2 => 1, 1302 3, 4 => 2, 1303 else => 3, 1304 }; 1305 } 1306 fn bar() -> i32 { 1307 2 1308 } 1309 1310 )SOURCE", 1, ".tmp_source.zig:3:15: error: unable to infer expression type"); 1311 1312 add_compile_fail_case("atomic orderings of cmpxchg - failure stricter than success", R"SOURCE( 1313 fn f() { 1314 var x: i32 = 1234; 1315 while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Monotonic, AtomicOrder.SeqCst)) {} 1316 } 1317 )SOURCE", 1, ".tmp_source.zig:4:72: error: failure atomic ordering must be no stricter than success"); 1318 1319 add_compile_fail_case("atomic orderings of cmpxchg - success Monotonic or stricter", R"SOURCE( 1320 fn f() { 1321 var x: i32 = 1234; 1322 while (!@cmpxchg(&x, 1234, 5678, AtomicOrder.Unordered, AtomicOrder.Unordered)) {} 1323 } 1324 )SOURCE", 1, ".tmp_source.zig:4:49: error: success atomic ordering must be Monotonic or stricter"); 1325 1326 add_compile_fail_case("negation overflow in function evaluation", R"SOURCE( 1327 const y = neg(-128); 1328 fn neg(x: i8) -> i8 { 1329 -x 1330 } 1331 )SOURCE", 2, 1332 ".tmp_source.zig:4:5: error: negation caused overflow", 1333 ".tmp_source.zig:2:14: note: called from here"); 1334 1335 add_compile_fail_case("add overflow in function evaluation", R"SOURCE( 1336 const y = add(65530, 10); 1337 fn add(a: u16, b: u16) -> u16 { 1338 a + b 1339 } 1340 )SOURCE", 2, 1341 ".tmp_source.zig:4:7: error: operation caused overflow", 1342 ".tmp_source.zig:2:14: note: called from here"); 1343 1344 1345 add_compile_fail_case("sub overflow in function evaluation", R"SOURCE( 1346 const y = sub(10, 20); 1347 fn sub(a: u16, b: u16) -> u16 { 1348 a - b 1349 } 1350 )SOURCE", 2, 1351 ".tmp_source.zig:4:7: error: operation caused overflow", 1352 ".tmp_source.zig:2:14: note: called from here"); 1353 1354 add_compile_fail_case("mul overflow in function evaluation", R"SOURCE( 1355 const y = mul(300, 6000); 1356 fn mul(a: u16, b: u16) -> u16 { 1357 a * b 1358 } 1359 )SOURCE", 2, 1360 ".tmp_source.zig:4:7: error: operation caused overflow", 1361 ".tmp_source.zig:2:14: note: called from here"); 1362 1363 add_compile_fail_case("truncate sign mismatch", R"SOURCE( 1364 fn f() -> i8 { 1365 const x: u32 = 10; 1366 @truncate(i8, x) 1367 } 1368 )SOURCE", 1, ".tmp_source.zig:4:19: error: expected signed integer type, found 'u32'"); 1369 1370 add_compile_fail_case("truncate same bit count", R"SOURCE( 1371 fn f() -> i8 { 1372 const x: i8 = 10; 1373 @truncate(i8, x) 1374 } 1375 )SOURCE", 1, ".tmp_source.zig:4:19: error: type 'i8' has same or fewer bits than destination type 'i8'"); 1376 1377 add_compile_fail_case("%return in function with non error return type", R"SOURCE( 1378 fn f() { 1379 %return something(); 1380 } 1381 fn something() -> %void { } 1382 )SOURCE", 1, 1383 ".tmp_source.zig:3:5: error: expected type 'void', found 'error'"); 1384 1385 add_compile_fail_case("wrong return type for main", R"SOURCE( 1386 pub fn main(args: [][]u8) { } 1387 )SOURCE", 1, ".tmp_source.zig:2:27: error: expected return type of main to be '%void', instead is 'void'"); 1388 1389 1390 add_compile_fail_case("invalid pointer for var type", R"SOURCE( 1391 extern fn ext() -> usize; 1392 var bytes: [ext()]u8 = undefined; 1393 fn f() { 1394 for (bytes) |*b, i| { 1395 *b = u8(i); 1396 } 1397 } 1398 )SOURCE", 1, ".tmp_source.zig:3:13: error: unable to evaluate constant expression"); 1399 1400 add_compile_fail_case("export function with comptime parameter", R"SOURCE( 1401 export fn foo(comptime x: i32, y: i32) -> i32{ 1402 x + y 1403 } 1404 )SOURCE", 1, ".tmp_source.zig:2:15: error: comptime parameter not allowed in extern function"); 1405 1406 add_compile_fail_case("extern function with comptime parameter", R"SOURCE( 1407 extern fn foo(comptime x: i32, y: i32) -> i32; 1408 fn f() -> i32 { 1409 foo(1, 2) 1410 } 1411 )SOURCE", 1, ".tmp_source.zig:2:15: error: comptime parameter not allowed in extern function"); 1412 1413 add_compile_fail_case("convert fixed size array to slice with invalid size", R"SOURCE( 1414 fn f() { 1415 var array: [5]u8 = undefined; 1416 var foo = ([]u32)(array)[0]; 1417 } 1418 )SOURCE", 1, ".tmp_source.zig:4:22: error: unable to convert [5]u8 to []u32: size mismatch"); 1419 1420 add_compile_fail_case("non-pure function returns type", R"SOURCE( 1421 var a: u32 = 0; 1422 pub fn List(comptime T: type) -> type { 1423 a += 1; 1424 SmallList(T, 8) 1425 } 1426 1427 pub fn SmallList(comptime T: type, comptime STATIC_SIZE: usize) -> type { 1428 struct { 1429 items: []T, 1430 length: usize, 1431 prealloc_items: [STATIC_SIZE]T, 1432 } 1433 } 1434 1435 fn function_with_return_type_type() { 1436 var list: List(i32) = undefined; 1437 list.length = 10; 1438 } 1439 1440 )SOURCE", 2, 1441 ".tmp_source.zig:4:7: error: unable to evaluate constant expression", 1442 ".tmp_source.zig:17:19: note: called from here"); 1443 1444 add_compile_fail_case("bogus method call on slice", R"SOURCE( 1445 var self = "aoeu"; 1446 fn f(m: []const u8) { 1447 m.copy(u8, self[0...], m); 1448 } 1449 )SOURCE", 1, ".tmp_source.zig:4:6: error: no member named 'copy' in '[]const u8'"); 1450 1451 add_compile_fail_case("wrong number of arguments for method fn call", R"SOURCE( 1452 const Foo = struct { 1453 fn method(self: &const Foo, a: i32) {} 1454 }; 1455 fn f(foo: &const Foo) { 1456 1457 foo.method(1, 2); 1458 } 1459 )SOURCE", 1, ".tmp_source.zig:7:15: error: expected 2 arguments, found 3"); 1460 1461 add_compile_fail_case("assign through constant pointer", R"SOURCE( 1462 fn f() { 1463 var cstr = c"Hat"; 1464 cstr[0] = 'W'; 1465 } 1466 )SOURCE", 1, ".tmp_source.zig:4:11: error: cannot assign to constant"); 1467 1468 add_compile_fail_case("assign through constant slice", R"SOURCE( 1469 pub fn f() { 1470 var cstr: []const u8 = "Hat"; 1471 cstr[0] = 'W'; 1472 } 1473 )SOURCE", 1, ".tmp_source.zig:4:11: error: cannot assign to constant"); 1474 1475 add_compile_fail_case("main function with bogus args type", R"SOURCE( 1476 pub fn main(args: [][]bogus) -> %void {} 1477 )SOURCE", 1, ".tmp_source.zig:2:23: error: use of undeclared identifier 'bogus'"); 1478 1479 add_compile_fail_case("for loop missing element param", R"SOURCE( 1480 fn foo(blah: []u8) { 1481 for (blah) { } 1482 } 1483 )SOURCE", 1, ".tmp_source.zig:3:5: error: for loop expression missing element parameter"); 1484 1485 add_compile_fail_case("misspelled type with pointer only reference", R"SOURCE( 1486 const JasonHM = u8; 1487 const JasonList = &JsonNode; 1488 1489 const JsonOA = enum { 1490 JSONArray: JsonList, 1491 JSONObject: JasonHM, 1492 }; 1493 1494 const JsonType = enum { 1495 JSONNull: void, 1496 JSONInteger: isize, 1497 JSONDouble: f64, 1498 JSONBool: bool, 1499 JSONString: []u8, 1500 JSONArray, 1501 JSONObject, 1502 }; 1503 1504 pub const JsonNode = struct { 1505 kind: JsonType, 1506 jobject: ?JsonOA, 1507 }; 1508 1509 fn foo() { 1510 var jll: JasonList = undefined; 1511 jll.init(1234); 1512 var jd = JsonNode {.kind = JsonType.JSONArray , .jobject = JsonOA.JSONArray {jll} }; 1513 } 1514 )SOURCE", 1, ".tmp_source.zig:6:16: error: use of undeclared identifier 'JsonList'"); 1515 1516 add_compile_fail_case("method call with first arg type primitive", R"SOURCE( 1517 const Foo = struct { 1518 x: i32, 1519 1520 fn init(x: i32) -> Foo { 1521 Foo { 1522 .x = x, 1523 } 1524 } 1525 }; 1526 1527 fn f() { 1528 const derp = Foo.init(3); 1529 1530 derp.init(); 1531 } 1532 )SOURCE", 1, ".tmp_source.zig:15:5: error: expected type 'i32', found '&const Foo'"); 1533 1534 add_compile_fail_case("method call with first arg type wrong container", R"SOURCE( 1535 pub const List = struct { 1536 len: usize, 1537 allocator: &Allocator, 1538 1539 pub fn init(allocator: &Allocator) -> List { 1540 List { 1541 .len = 0, 1542 .allocator = allocator, 1543 } 1544 } 1545 }; 1546 1547 pub var global_allocator = Allocator { 1548 .field = 1234, 1549 }; 1550 1551 pub const Allocator = struct { 1552 field: i32, 1553 }; 1554 1555 fn foo() { 1556 var x = List.init(&global_allocator); 1557 x.init(); 1558 } 1559 )SOURCE", 1, ".tmp_source.zig:24:5: error: expected type '&Allocator', found '&List'"); 1560 1561 add_compile_fail_case("binary not on number literal", R"SOURCE( 1562 const TINY_QUANTUM_SHIFT = 4; 1563 const TINY_QUANTUM_SIZE = 1 << TINY_QUANTUM_SHIFT; 1564 var block_aligned_stuff: usize = (4 + TINY_QUANTUM_SIZE) & ~(TINY_QUANTUM_SIZE - 1); 1565 )SOURCE", 1, ".tmp_source.zig:4:60: error: unable to perform binary not operation on type '(integer literal)'"); 1566 1567 { 1568 TestCase *tc = add_compile_fail_case("multiple files with private function error", R"SOURCE( 1569 const foo = @import("foo.zig"); 1570 1571 fn callPrivFunction() { 1572 foo.privateFunction(); 1573 } 1574 )SOURCE", 2, 1575 ".tmp_source.zig:5:8: error: 'privateFunction' is private", 1576 "foo.zig:2:1: note: declared here"); 1577 1578 add_source_file(tc, "foo.zig", R"SOURCE( 1579 fn privateFunction() { } 1580 )SOURCE"); 1581 } 1582 1583 add_compile_fail_case("container init with non-type", R"SOURCE( 1584 const zero: i32 = 0; 1585 const a = zero{1}; 1586 )SOURCE", 1, ".tmp_source.zig:3:11: error: expected type, found 'i32'"); 1587 1588 add_compile_fail_case("assign to constant field", R"SOURCE( 1589 const Foo = struct { 1590 field: i32, 1591 }; 1592 fn derp() { 1593 const f = Foo {.field = 1234,}; 1594 f.field = 0; 1595 } 1596 )SOURCE", 1, ".tmp_source.zig:7:13: error: cannot assign to constant"); 1597 1598 add_compile_fail_case("compare void with void is compile time known", R"SOURCE( 1599 const Foo = struct { 1600 a: void, 1601 b: i32, 1602 c: void, 1603 }; 1604 1605 fn f() { 1606 const foo = Foo { 1607 .a = {}, 1608 .b = 1, 1609 .c = {}, 1610 }; 1611 if (foo.a != {}) { 1612 @unreachable(); 1613 } 1614 } 1615 )SOURCE", 1, ".tmp_source.zig:14:15: error: condition is always false; unnecessary if statement"); 1616 1617 add_compile_fail_case("return from defer expression", R"SOURCE( 1618 pub fn testTrickyDefer() -> %void { 1619 defer canFail() %% {}; 1620 1621 defer %return canFail(); 1622 1623 const a = maybeInt() ?? return; 1624 } 1625 1626 fn canFail() -> %void { } 1627 1628 pub fn maybeInt() -> ?i32 { 1629 return 0; 1630 } 1631 )SOURCE", 1, ".tmp_source.zig:5:11: error: cannot return from defer expression"); 1632 1633 add_compile_fail_case("attempt to access var args out of bounds", R"SOURCE( 1634 fn add(args: ...) -> i32 { 1635 args[0] + args[1] 1636 } 1637 1638 fn foo() -> i32 { 1639 add(i32(1234)) 1640 } 1641 )SOURCE", 2, 1642 ".tmp_source.zig:3:19: error: index 1 outside argument list of size 1", 1643 ".tmp_source.zig:7:8: note: called from here"); 1644 1645 add_compile_fail_case("pass integer literal to var args", R"SOURCE( 1646 fn add(args: ...) -> i32 { 1647 var sum = i32(0); 1648 {comptime var i: usize = 0; inline while (i < args.len; i += 1) { 1649 sum += args[i]; 1650 }} 1651 return sum; 1652 } 1653 1654 fn bar() -> i32 { 1655 add(1, 2, 3, 4) 1656 } 1657 )SOURCE", 1, ".tmp_source.zig:11:9: error: parameter of type '(integer literal)' requires comptime"); 1658 1659 } 1660 1661 ////////////////////////////////////////////////////////////////////////////// 1662 1663 static void add_debug_safety_test_cases(void) { 1664 add_debug_safety_case("out of bounds slice access", R"SOURCE( 1665 pub fn main(args: [][]u8) -> %void { 1666 const a = []i32{1, 2, 3, 4}; 1667 baz(bar(a)); 1668 } 1669 fn bar(a: []i32) -> i32 { 1670 a[4] 1671 } 1672 fn baz(a: i32) { } 1673 )SOURCE"); 1674 1675 add_debug_safety_case("integer addition overflow", R"SOURCE( 1676 error Whatever; 1677 pub fn main(args: [][]u8) -> %void { 1678 const x = add(65530, 10); 1679 if (x == 0) return error.Whatever; 1680 } 1681 fn add(a: u16, b: u16) -> u16 { 1682 a + b 1683 } 1684 )SOURCE"); 1685 1686 add_debug_safety_case("integer subtraction overflow", R"SOURCE( 1687 error Whatever; 1688 pub fn main(args: [][]u8) -> %void { 1689 const x = sub(10, 20); 1690 if (x == 0) return error.Whatever; 1691 } 1692 fn sub(a: u16, b: u16) -> u16 { 1693 a - b 1694 } 1695 )SOURCE"); 1696 1697 add_debug_safety_case("integer multiplication overflow", R"SOURCE( 1698 error Whatever; 1699 pub fn main(args: [][]u8) -> %void { 1700 const x = mul(300, 6000); 1701 if (x == 0) return error.Whatever; 1702 } 1703 fn mul(a: u16, b: u16) -> u16 { 1704 a * b 1705 } 1706 )SOURCE"); 1707 1708 add_debug_safety_case("integer negation overflow", R"SOURCE( 1709 error Whatever; 1710 pub fn main(args: [][]u8) -> %void { 1711 const x = neg(-32768); 1712 if (x == 0) return error.Whatever; 1713 } 1714 fn neg(a: i16) -> i16 { 1715 -a 1716 } 1717 )SOURCE"); 1718 1719 add_debug_safety_case("signed shift left overflow", R"SOURCE( 1720 error Whatever; 1721 pub fn main(args: [][]u8) -> %void { 1722 const x = shl(-16385, 1); 1723 if (x == 0) return error.Whatever; 1724 } 1725 fn shl(a: i16, b: i16) -> i16 { 1726 a << b 1727 } 1728 )SOURCE"); 1729 1730 add_debug_safety_case("unsigned shift left overflow", R"SOURCE( 1731 error Whatever; 1732 pub fn main(args: [][]u8) -> %void { 1733 const x = shl(0b0010111111111111, 3); 1734 if (x == 0) return error.Whatever; 1735 } 1736 fn shl(a: u16, b: u16) -> u16 { 1737 a << b 1738 } 1739 )SOURCE"); 1740 1741 add_debug_safety_case("integer division by zero", R"SOURCE( 1742 error Whatever; 1743 pub fn main(args: [][]u8) -> %void { 1744 const x = div0(999, 0); 1745 } 1746 fn div0(a: i32, b: i32) -> i32 { 1747 a / b 1748 } 1749 )SOURCE"); 1750 1751 add_debug_safety_case("exact division failure", R"SOURCE( 1752 error Whatever; 1753 pub fn main(args: [][]u8) -> %void { 1754 const x = divExact(10, 3); 1755 if (x == 0) return error.Whatever; 1756 } 1757 fn divExact(a: i32, b: i32) -> i32 { 1758 @divExact(a, b) 1759 } 1760 )SOURCE"); 1761 1762 add_debug_safety_case("cast []u8 to bigger slice of wrong size", R"SOURCE( 1763 error Whatever; 1764 pub fn main(args: [][]u8) -> %void { 1765 const x = widenSlice([]u8{1, 2, 3, 4, 5}); 1766 if (x.len == 0) return error.Whatever; 1767 } 1768 fn widenSlice(slice: []u8) -> []i32 { 1769 ([]i32)(slice) 1770 } 1771 )SOURCE"); 1772 1773 add_debug_safety_case("value does not fit in shortening cast", R"SOURCE( 1774 error Whatever; 1775 pub fn main(args: [][]u8) -> %void { 1776 const x = shorten_cast(200); 1777 if (x == 0) return error.Whatever; 1778 } 1779 fn shorten_cast(x: i32) -> i8 { 1780 i8(x) 1781 } 1782 )SOURCE"); 1783 1784 add_debug_safety_case("signed integer not fitting in cast to unsigned integer", R"SOURCE( 1785 error Whatever; 1786 pub fn main(args: [][]u8) -> %void { 1787 const x = unsigned_cast(-10); 1788 if (x == 0) return error.Whatever; 1789 } 1790 fn unsigned_cast(x: i32) -> u32 { 1791 u32(x) 1792 } 1793 )SOURCE"); 1794 1795 } 1796 1797 ////////////////////////////////////////////////////////////////////////////// 1798 1799 static void add_parseh_test_cases(void) { 1800 add_parseh_case("simple data types", AllowWarningsYes, R"SOURCE( 1801 #include <stdint.h> 1802 int foo(char a, unsigned char b, signed char c); 1803 int foo(char a, unsigned char b, signed char c); // test a duplicate prototype 1804 void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); 1805 void baz(int8_t a, int16_t b, int32_t c, int64_t d); 1806 )SOURCE", 3, 1807 "pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;", 1808 "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);", 1809 "pub extern fn baz(a: i8, b: i16, c: i32, d: i64);"); 1810 1811 add_parseh_case("noreturn attribute", AllowWarningsNo, R"SOURCE( 1812 void foo(void) __attribute__((noreturn)); 1813 )SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); 1814 1815 add_parseh_case("enums", AllowWarningsNo, R"SOURCE( 1816 enum Foo { 1817 FooA, 1818 FooB, 1819 Foo1, 1820 }; 1821 )SOURCE", 5, R"(pub const enum_Foo = extern enum { 1822 A, 1823 B, 1824 @"1", 1825 };)", 1826 R"(pub const FooA = 0;)", 1827 R"(pub const FooB = 1;)", 1828 R"(pub const Foo1 = 2;)", 1829 R"(pub const Foo = enum_Foo;)"); 1830 1831 add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE( 1832 void foo(void *restrict bar, void *restrict); 1833 )SOURCE", 1, R"OUTPUT(pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT"); 1834 1835 add_parseh_case("simple struct", AllowWarningsNo, R"SOURCE( 1836 struct Foo { 1837 int x; 1838 char *y; 1839 }; 1840 )SOURCE", 2, 1841 R"OUTPUT(const struct_Foo = extern struct { 1842 x: c_int, 1843 y: ?&u8, 1844 };)OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); 1845 1846 add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE( 1847 struct Foo { 1848 int x; 1849 int y; 1850 }; 1851 enum Bar { 1852 BarA, 1853 BarB, 1854 }; 1855 void func(struct Foo *a, enum Bar **b); 1856 )SOURCE", 7, R"OUTPUT(pub const struct_Foo = extern struct { 1857 x: c_int, 1858 y: c_int, 1859 };)OUTPUT", R"OUTPUT(pub const enum_Bar = extern enum { 1860 A, 1861 B, 1862 };)OUTPUT", 1863 R"OUTPUT(pub const BarA = 0;)OUTPUT", 1864 R"OUTPUT(pub const BarB = 1;)OUTPUT", 1865 "pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);", 1866 R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT", 1867 R"OUTPUT(pub const Bar = enum_Bar;)OUTPUT"); 1868 1869 add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE( 1870 void func(int array[20]); 1871 )SOURCE", 1, "pub extern fn func(array: ?&c_int);"); 1872 1873 1874 add_parseh_case("self referential struct with function pointer", 1875 AllowWarningsNo, R"SOURCE( 1876 struct Foo { 1877 void (*derp)(struct Foo *foo); 1878 }; 1879 )SOURCE", 2, R"OUTPUT(pub const struct_Foo = extern struct { 1880 derp: ?extern fn(?&struct_Foo), 1881 };)OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); 1882 1883 1884 add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE( 1885 struct Foo; 1886 struct Foo *some_func(struct Foo *foo, int x); 1887 )SOURCE", 3, R"OUTPUT(pub type struct_Foo = u8;)OUTPUT", 1888 R"OUTPUT(pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", 1889 R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); 1890 1891 1892 add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE( 1893 #define A_CHAR 'a' 1894 )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 97;)OUTPUT"); 1895 1896 1897 add_parseh_case("#define an unsigned integer literal", AllowWarningsNo, 1898 R"SOURCE( 1899 #define CHANNEL_COUNT 24 1900 )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT"); 1901 1902 1903 add_parseh_case("#define referencing another #define", AllowWarningsNo, 1904 R"SOURCE( 1905 #define THING2 THING1 1906 #define THING1 1234 1907 )SOURCE", 2, 1908 "pub const THING1 = 1234;", 1909 "pub const THING2 = THING1;"); 1910 1911 1912 add_parseh_case("variables", AllowWarningsNo, R"SOURCE( 1913 extern int extern_var; 1914 static const int int_var = 13; 1915 )SOURCE", 2, 1916 "pub extern var extern_var: c_int;", 1917 "pub const int_var: c_int = 13;"); 1918 1919 1920 add_parseh_case("circular struct definitions", AllowWarningsNo, R"SOURCE( 1921 struct Bar; 1922 1923 struct Foo { 1924 struct Bar *next; 1925 }; 1926 1927 struct Bar { 1928 struct Foo *next; 1929 }; 1930 )SOURCE", 2, 1931 R"SOURCE(pub const struct_Bar = extern struct { 1932 next: ?&struct_Foo, 1933 };)SOURCE", 1934 R"SOURCE(pub const struct_Foo = extern struct { 1935 next: ?&struct_Bar, 1936 };)SOURCE"); 1937 1938 1939 add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( 1940 typedef void Foo; 1941 Foo fun(Foo *a); 1942 )SOURCE", 2, 1943 "pub const Foo = c_void;", 1944 "pub extern fn fun(a: ?&c_void);"); 1945 1946 add_parseh_case("generate inline func for #define global extern fn", AllowWarningsNo, 1947 R"SOURCE( 1948 extern void (*fn_ptr)(void); 1949 #define foo fn_ptr 1950 1951 extern char (*fn_ptr2)(int, float); 1952 #define bar fn_ptr2 1953 )SOURCE", 4, 1954 "pub extern var fn_ptr: ?extern fn();", 1955 "pub fn foo();", 1956 "pub extern var fn_ptr2: ?extern fn(c_int, f32) -> u8;", 1957 "pub fn bar(arg0: c_int, arg1: f32) -> u8;"); 1958 1959 1960 add_parseh_case("#define string", AllowWarningsNo, R"SOURCE( 1961 #define foo "a string" 1962 )SOURCE", 1, "pub const foo: &const u8 = &(c str lit);"); 1963 1964 add_parseh_case("__cdecl doesn't mess up function pointers", AllowWarningsNo, R"SOURCE( 1965 void foo(void (__cdecl *fn_ptr)(void)); 1966 )SOURCE", 1, "pub extern fn foo(fn_ptr: ?extern fn());"); 1967 1968 add_parseh_case("comment after integer literal", AllowWarningsNo, R"SOURCE( 1969 #define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ 1970 )SOURCE", 1, "pub const SDL_INIT_VIDEO = 32;"); 1971 1972 add_parseh_case("zig keywords in C code", AllowWarningsNo, R"SOURCE( 1973 struct type { 1974 int defer; 1975 }; 1976 )SOURCE", 2, R"(pub const struct_type = extern struct { 1977 @"defer": c_int, 1978 };)", R"(pub const @"type" = struct_type;)"); 1979 1980 add_parseh_case("macro defines string literal with octal", AllowWarningsNo, R"SOURCE( 1981 #define FOO "aoeu\023 derp" 1982 #define FOO2 "aoeu\0234 derp" 1983 #define FOO_CHAR '\077' 1984 )SOURCE", 3, 1985 R"(pub const FOO: &const u8 = &(c str lit);)", 1986 R"(pub const FOO2: &const u8 = &(c str lit);)", 1987 R"(pub const FOO_CHAR = 63;)"); 1988 } 1989 1990 static void run_self_hosted_test(bool is_release_mode) { 1991 Buf self_hosted_tests_file = BUF_INIT; 1992 os_path_join(buf_create_from_str(ZIG_TEST_DIR), 1993 buf_create_from_str("self_hosted.zig"), &self_hosted_tests_file); 1994 1995 Buf zig_stderr = BUF_INIT; 1996 Buf zig_stdout = BUF_INIT; 1997 ZigList<const char *> args = {0}; 1998 args.append("test"); 1999 args.append(buf_ptr(&self_hosted_tests_file)); 2000 if (is_release_mode) { 2001 args.append("--release"); 2002 } 2003 Termination term; 2004 os_exec_process(zig_exe, args, &term, &zig_stderr, &zig_stdout); 2005 2006 if (term.how != TerminationIdClean || term.code != 0) { 2007 printf("\nSelf-hosted tests failed:\n"); 2008 printf("./zig"); 2009 for (size_t i = 0; i < args.length; i += 1) { 2010 printf(" %s", args.at(i)); 2011 } 2012 printf("\n%s\n", buf_ptr(&zig_stderr)); 2013 exit(1); 2014 } 2015 } 2016 2017 static void add_self_hosted_tests(void) { 2018 { 2019 TestCase *test_case = allocate<TestCase>(1); 2020 test_case->case_name = "self hosted tests (debug)"; 2021 test_case->is_self_hosted = true; 2022 test_case->is_release_mode = false; 2023 test_cases.append(test_case); 2024 } 2025 { 2026 TestCase *test_case = allocate<TestCase>(1); 2027 test_case->case_name = "self hosted tests (release)"; 2028 test_case->is_self_hosted = true; 2029 test_case->is_release_mode = true; 2030 test_cases.append(test_case); 2031 } 2032 } 2033 2034 static void print_compiler_invocation(TestCase *test_case) { 2035 printf("%s", zig_exe); 2036 for (size_t i = 0; i < test_case->compiler_args.length; i += 1) { 2037 printf(" %s", test_case->compiler_args.at(i)); 2038 } 2039 printf("\n"); 2040 } 2041 2042 static void print_exe_invocation(TestCase *test_case) { 2043 printf("%s", tmp_exe_path); 2044 for (size_t i = 0; i < test_case->program_args.length; i += 1) { 2045 printf(" %s", test_case->program_args.at(i)); 2046 } 2047 printf("\n"); 2048 } 2049 2050 static void run_test(TestCase *test_case) { 2051 if (test_case->is_self_hosted) { 2052 return run_self_hosted_test(test_case->is_release_mode); 2053 } 2054 2055 for (size_t i = 0; i < test_case->source_files.length; i += 1) { 2056 TestSourceFile *test_source = &test_case->source_files.at(i); 2057 os_write_file( 2058 buf_create_from_str(test_source->relative_path), 2059 buf_create_from_str(test_source->source_code)); 2060 } 2061 2062 Buf zig_stderr = BUF_INIT; 2063 Buf zig_stdout = BUF_INIT; 2064 int err; 2065 Termination term; 2066 if ((err = os_exec_process(zig_exe, test_case->compiler_args, &term, &zig_stderr, &zig_stdout))) { 2067 fprintf(stderr, "Unable to exec %s: %s\n", zig_exe, err_str(err)); 2068 } 2069 2070 if (!test_case->is_parseh && test_case->compile_errors.length) { 2071 if (term.how != TerminationIdClean || term.code != 0) { 2072 for (size_t i = 0; i < test_case->compile_errors.length; i += 1) { 2073 const char *err_text = test_case->compile_errors.at(i); 2074 if (!strstr(buf_ptr(&zig_stderr), err_text)) { 2075 printf("\n"); 2076 printf("========= Expected this compile error: =========\n"); 2077 printf("%s\n", err_text); 2078 printf("================================================\n"); 2079 print_compiler_invocation(test_case); 2080 printf("%s\n", buf_ptr(&zig_stderr)); 2081 exit(1); 2082 } 2083 } 2084 return; // success 2085 } else { 2086 printf("\nCompile failed with return code 0 (Expected failure):\n"); 2087 print_compiler_invocation(test_case); 2088 printf("%s\n", buf_ptr(&zig_stderr)); 2089 exit(1); 2090 } 2091 } 2092 2093 if (term.how != TerminationIdClean || term.code != 0) { 2094 printf("\nCompile failed:\n"); 2095 print_compiler_invocation(test_case); 2096 printf("%s\n", buf_ptr(&zig_stderr)); 2097 exit(1); 2098 } 2099 2100 if (test_case->is_parseh) { 2101 if (buf_len(&zig_stderr) > 0) { 2102 printf("\nparseh emitted warnings:\n"); 2103 printf("------------------------------\n"); 2104 print_compiler_invocation(test_case); 2105 printf("%s\n", buf_ptr(&zig_stderr)); 2106 printf("------------------------------\n"); 2107 if (test_case->allow_warnings == AllowWarningsNo) { 2108 exit(1); 2109 } 2110 } 2111 2112 for (size_t i = 0; i < test_case->compile_errors.length; i += 1) { 2113 const char *output = test_case->compile_errors.at(i); 2114 2115 if (!strstr(buf_ptr(&zig_stdout), output)) { 2116 printf("\n"); 2117 printf("========= Expected this output: =========\n"); 2118 printf("%s\n", output); 2119 printf("================================================\n"); 2120 print_compiler_invocation(test_case); 2121 printf("%s\n", buf_ptr(&zig_stdout)); 2122 exit(1); 2123 } 2124 } 2125 } else { 2126 Buf program_stderr = BUF_INIT; 2127 Buf program_stdout = BUF_INIT; 2128 os_exec_process(tmp_exe_path, test_case->program_args, &term, &program_stderr, &program_stdout); 2129 2130 if (test_case->is_debug_safety) { 2131 int debug_trap_signal = 5; 2132 if (term.how != TerminationIdSignaled || term.code != debug_trap_signal) { 2133 if (term.how == TerminationIdClean) { 2134 printf("\nProgram expected to hit debug trap (signal %d) but exited with return code %d\n", 2135 debug_trap_signal, term.code); 2136 } else if (term.how == TerminationIdSignaled) { 2137 printf("\nProgram expected to hit debug trap (signal %d) but signaled with code %d\n", 2138 debug_trap_signal, term.code); 2139 } else { 2140 printf("\nProgram expected to hit debug trap (signal %d) exited in an unexpected way\n", 2141 debug_trap_signal); 2142 } 2143 print_compiler_invocation(test_case); 2144 print_exe_invocation(test_case); 2145 exit(1); 2146 } 2147 } else { 2148 if (term.how != TerminationIdClean || term.code != 0) { 2149 printf("\nProgram exited with error\n"); 2150 print_compiler_invocation(test_case); 2151 print_exe_invocation(test_case); 2152 printf("%s\n", buf_ptr(&program_stderr)); 2153 exit(1); 2154 } 2155 2156 if (!buf_eql_str(&program_stdout, test_case->output)) { 2157 printf("\n"); 2158 print_compiler_invocation(test_case); 2159 print_exe_invocation(test_case); 2160 printf("==== Test failed. Expected output: ====\n"); 2161 printf("%s\n", test_case->output); 2162 printf("========= Actual output: ==============\n"); 2163 printf("%s\n", buf_ptr(&program_stdout)); 2164 printf("=======================================\n"); 2165 exit(1); 2166 } 2167 } 2168 } 2169 2170 for (size_t i = 0; i < test_case->source_files.length; i += 1) { 2171 TestSourceFile *test_source = &test_case->source_files.at(i); 2172 remove(test_source->relative_path); 2173 } 2174 } 2175 2176 static void run_all_tests(bool reverse) { 2177 if (reverse) { 2178 for (size_t i = test_cases.length;;) { 2179 TestCase *test_case = test_cases.at(i); 2180 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name); 2181 run_test(test_case); 2182 printf("OK\n"); 2183 if (i == 0) break; 2184 i -= 1; 2185 } 2186 } else { 2187 for (size_t i = 0; i < test_cases.length; i += 1) { 2188 TestCase *test_case = test_cases.at(i); 2189 printf("Test %zu/%zu %s...", i + 1, test_cases.length, test_case->case_name); 2190 run_test(test_case); 2191 printf("OK\n"); 2192 } 2193 } 2194 printf("%zu tests passed.\n", test_cases.length); 2195 } 2196 2197 static void cleanup(void) { 2198 remove(tmp_source_path); 2199 remove(tmp_h_path); 2200 remove(tmp_exe_path); 2201 } 2202 2203 static int usage(const char *arg0) { 2204 fprintf(stderr, "Usage: %s [--reverse]\n", arg0); 2205 return 1; 2206 } 2207 2208 int main(int argc, char **argv) { 2209 bool reverse = false; 2210 for (int i = 1; i < argc; i += 1) { 2211 if (strcmp(argv[i], "--reverse") == 0) { 2212 reverse = true; 2213 } else { 2214 return usage(argv[0]); 2215 } 2216 } 2217 add_compiling_test_cases(); 2218 add_debug_safety_test_cases(); 2219 add_compile_failure_test_cases(); 2220 add_parseh_test_cases(); 2221 add_self_hosted_tests(); 2222 run_all_tests(reverse); 2223 cleanup(); 2224 }