zig

fork of https://codeberg.org/ziglang/zig
Log | Tree | Refs | README | LICENSE

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 }