| ... | ... | @@ -96,21 +96,30 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source |
| 96 | 96 | return test_case; |
| 97 | 97 | } |
| 98 | 98 | |
| 99 | | static TestCase *add_parseh_case(const char *case_name, const char *source, const char *output) { |
| 99 | static TestCase *add_parseh_case(const char *case_name, const char *source, int count, ...) { |
| 100 | va_list ap; |
| 101 | va_start(ap, count); |
| 102 | |
| 100 | 103 | TestCase *test_case = allocate<TestCase>(1); |
| 101 | 104 | test_case->case_name = case_name; |
| 102 | | test_case->output = output; |
| 103 | 105 | test_case->is_parseh = true; |
| 104 | 106 | |
| 105 | 107 | test_case->source_files.resize(1); |
| 106 | 108 | test_case->source_files.at(0).relative_path = tmp_h_path; |
| 107 | 109 | test_case->source_files.at(0).source_code = source; |
| 108 | 110 | |
| 111 | for (int i = 0; i < count; i += 1) { |
| 112 | const char *arg = va_arg(ap, const char *); |
| 113 | test_case->compile_errors.append(arg); |
| 114 | } |
| 115 | |
| 109 | 116 | test_case->compiler_args.append("parseh"); |
| 110 | 117 | test_case->compiler_args.append(tmp_h_path); |
| 111 | 118 | test_case->compiler_args.append("--c-import-warnings"); |
| 112 | 119 | |
| 113 | 120 | test_cases.append(test_case); |
| 121 | |
| 122 | va_end(ap); |
| 114 | 123 | return test_case; |
| 115 | 124 | } |
| 116 | 125 | |
| ... | ... | @@ -1894,13 +1903,13 @@ int foo(char a, unsigned char b, signed char c); |
| 1894 | 1903 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype |
| 1895 | 1904 | void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); |
| 1896 | 1905 | void baz(int8_t a, int16_t b, int32_t c, int64_t d); |
| 1897 | | )SOURCE", R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; |
| 1906 | )SOURCE", 1, R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; |
| 1898 | 1907 | pub extern fn bar(a: u8, b: u16, c: u32, d: u64); |
| 1899 | 1908 | pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT"); |
| 1900 | 1909 | |
| 1901 | 1910 | add_parseh_case("noreturn attribute", R"SOURCE( |
| 1902 | 1911 | void foo(void) __attribute__((noreturn)); |
| 1903 | | )SOURCE", R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); |
| 1912 | )SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); |
| 1904 | 1913 | |
| 1905 | 1914 | add_parseh_case("enums", R"SOURCE( |
| 1906 | 1915 | enum Foo { |
| ... | ... | @@ -1908,19 +1917,19 @@ enum Foo { |
| 1908 | 1917 | FooB, |
| 1909 | 1918 | Foo1, |
| 1910 | 1919 | }; |
| 1911 | | )SOURCE", R"OUTPUT(export enum enum_Foo { |
| 1920 | )SOURCE", 1, R"OUTPUT(export enum enum_Foo { |
| 1912 | 1921 | A, |
| 1913 | 1922 | B, |
| 1914 | 1923 | _1, |
| 1915 | 1924 | } |
| 1916 | 1925 | pub const FooA = enum_Foo.A; |
| 1917 | 1926 | pub const FooB = enum_Foo.B; |
| 1918 | | pub const Foo1 = enum_Foo._1; |
| 1919 | | pub const Foo = enum_Foo;)OUTPUT"); |
| 1927 | pub const Foo1 = enum_Foo._1;)OUTPUT", |
| 1928 | R"OUTPUT(pub const Foo = enum_Foo;)OUTPUT"); |
| 1920 | 1929 | |
| 1921 | 1930 | add_parseh_case("restrict -> noalias", R"SOURCE( |
| 1922 | 1931 | void foo(void *restrict bar, void *restrict); |
| 1923 | | )SOURCE", R"OUTPUT(pub const c_void = u8; |
| 1932 | )SOURCE", 1, R"OUTPUT(pub const c_void = u8; |
| 1924 | 1933 | pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT"); |
| 1925 | 1934 | |
| 1926 | 1935 | add_parseh_case("simple struct", R"SOURCE( |
| ... | ... | @@ -1928,11 +1937,11 @@ struct Foo { |
| 1928 | 1937 | int x; |
| 1929 | 1938 | char *y; |
| 1930 | 1939 | }; |
| 1931 | | )SOURCE", R"OUTPUT(export struct struct_Foo { |
| 1940 | )SOURCE", 2, |
| 1941 | R"OUTPUT(export struct struct_Foo { |
| 1932 | 1942 | x: c_int, |
| 1933 | 1943 | y: ?&u8, |
| 1934 | | } |
| 1935 | | pub const Foo = struct_Foo;)OUTPUT"); |
| 1944 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1936 | 1945 | |
| 1937 | 1946 | add_parseh_case("qualified struct and enum", R"SOURCE( |
| 1938 | 1947 | struct Foo { |
| ... | ... | @@ -1944,7 +1953,7 @@ enum Bar { |
| 1944 | 1953 | BarB, |
| 1945 | 1954 | }; |
| 1946 | 1955 | void func(struct Foo *a, enum Bar **b); |
| 1947 | | )SOURCE", R"OUTPUT(export struct struct_Foo { |
| 1956 | )SOURCE", 2, R"OUTPUT(export struct struct_Foo { |
| 1948 | 1957 | x: c_int, |
| 1949 | 1958 | y: c_int, |
| 1950 | 1959 | } |
| ... | ... | @@ -1954,36 +1963,45 @@ export enum enum_Bar { |
| 1954 | 1963 | } |
| 1955 | 1964 | pub const BarA = enum_Bar.A; |
| 1956 | 1965 | pub const BarB = enum_Bar.B; |
| 1957 | | pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar); |
| 1958 | | pub const Foo = struct_Foo; |
| 1966 | pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);)OUTPUT", |
| 1967 | R"OUTPUT(pub const Foo = struct_Foo; |
| 1959 | 1968 | pub const Bar = enum_Bar;)OUTPUT"); |
| 1960 | 1969 | |
| 1961 | 1970 | add_parseh_case("constant size array", R"SOURCE( |
| 1962 | 1971 | void func(int array[20]); |
| 1963 | | )SOURCE", R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT"); |
| 1972 | )SOURCE", 1, R"OUTPUT(pub extern fn func(array: [20]c_int);)OUTPUT"); |
| 1964 | 1973 | |
| 1965 | 1974 | |
| 1966 | 1975 | add_parseh_case("self referential struct with function pointer", R"SOURCE( |
| 1967 | 1976 | struct Foo { |
| 1968 | 1977 | void (*derp)(struct Foo *foo); |
| 1969 | 1978 | }; |
| 1970 | | )SOURCE", R"OUTPUT(export struct struct_Foo { |
| 1979 | )SOURCE", 2, R"OUTPUT(export struct struct_Foo { |
| 1971 | 1980 | derp: ?extern fn (?&struct_Foo), |
| 1972 | | } |
| 1973 | | pub const Foo = struct_Foo;)OUTPUT"); |
| 1981 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1974 | 1982 | |
| 1975 | 1983 | |
| 1976 | 1984 | add_parseh_case("struct prototype used in func", R"SOURCE( |
| 1977 | 1985 | struct Foo; |
| 1978 | 1986 | struct Foo *some_func(struct Foo *foo, int x); |
| 1979 | | )SOURCE", R"OUTPUT(pub const struct_Foo = u8; |
| 1980 | | pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo; |
| 1981 | | pub const Foo = struct_Foo;)OUTPUT"); |
| 1987 | )SOURCE", 2, R"OUTPUT(pub const struct_Foo = u8; |
| 1988 | pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1989 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1982 | 1990 | |
| 1983 | 1991 | |
| 1984 | 1992 | add_parseh_case("#define a char literal", R"SOURCE( |
| 1985 | 1993 | #define A_CHAR 'a' |
| 1986 | | )SOURCE", R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); |
| 1994 | )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); |
| 1995 | |
| 1996 | |
| 1997 | add_parseh_case("#define an unsigned integer literal", R"SOURCE( |
| 1998 | #define CHANNEL_COUNT 24 |
| 1999 | )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT"); |
| 2000 | |
| 2001 | add_parseh_case("overide previous #define", R"SOURCE( |
| 2002 | #define A_CHAR 'a' |
| 2003 | #define A_CHAR 'b' |
| 2004 | )SOURCE", 1, "pub const A_CHAR = 'b';"); |
| 1987 | 2005 | } |
| 1988 | 2006 | |
| 1989 | 2007 | static void print_compiler_invocation(TestCase *test_case) { |
| ... | ... | @@ -2007,7 +2025,7 @@ static void run_test(TestCase *test_case) { |
| 2007 | 2025 | int return_code; |
| 2008 | 2026 | os_exec_process(zig_exe, test_case->compiler_args, &return_code, &zig_stderr, &zig_stdout); |
| 2009 | 2027 | |
| 2010 | | if (test_case->compile_errors.length) { |
| 2028 | if (!test_case->is_parseh && test_case->compile_errors.length) { |
| 2011 | 2029 | if (return_code) { |
| 2012 | 2030 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { |
| 2013 | 2031 | const char *err_text = test_case->compile_errors.at(i); |
| ... | ... | @@ -2045,14 +2063,18 @@ static void run_test(TestCase *test_case) { |
| 2045 | 2063 | exit(1); |
| 2046 | 2064 | } |
| 2047 | 2065 | |
| 2048 | | if (!strstr(buf_ptr(&zig_stdout), test_case->output)) { |
| 2049 | | printf("\n"); |
| 2050 | | printf("========= Expected this output: =========\n"); |
| 2051 | | printf("%s\n", test_case->output); |
| 2052 | | printf("================================================\n"); |
| 2053 | | print_compiler_invocation(test_case); |
| 2054 | | printf("%s\n", buf_ptr(&zig_stdout)); |
| 2055 | | exit(1); |
| 2066 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { |
| 2067 | const char *output = test_case->compile_errors.at(i); |
| 2068 | |
| 2069 | if (!strstr(buf_ptr(&zig_stdout), output)) { |
| 2070 | printf("\n"); |
| 2071 | printf("========= Expected this output: =========\n"); |
| 2072 | printf("%s\n", output); |
| 2073 | printf("================================================\n"); |
| 2074 | print_compiler_invocation(test_case); |
| 2075 | printf("%s\n", buf_ptr(&zig_stdout)); |
| 2076 | exit(1); |
| 2077 | } |
| 2056 | 2078 | } |
| 2057 | 2079 | } else { |
| 2058 | 2080 | Buf program_stderr = BUF_INIT; |