| ... | @@ -18,6 +18,11 @@ struct TestSourceFile { | ... | @@ -18,6 +18,11 @@ struct TestSourceFile { |
| 18 | const char *source_code; | 18 | const char *source_code; |
| 19 | }; | 19 | }; |
| 20 | | 20 | |
| | 21 | enum AllowWarnings { |
| | 22 | AllowWarningsNo, |
| | 23 | AllowWarningsYes, |
| | 24 | }; |
| | 25 | |
| 21 | struct TestCase { | 26 | struct TestCase { |
| 22 | const char *case_name; | 27 | const char *case_name; |
| 23 | const char *output; | 28 | const char *output; |
| ... | @@ -29,6 +34,7 @@ struct TestCase { | ... | @@ -29,6 +34,7 @@ struct TestCase { |
| 29 | bool is_self_hosted; | 34 | bool is_self_hosted; |
| 30 | bool is_release_mode; | 35 | bool is_release_mode; |
| 31 | bool is_debug_safety; | 36 | bool is_debug_safety; |
| | 37 | AllowWarnings allow_warnings; |
| 32 | }; | 38 | }; |
| 33 | | 39 | |
| 34 | static ZigList<TestCase*> test_cases = {0}; | 40 | static ZigList<TestCase*> test_cases = {0}; |
| ... | @@ -173,13 +179,16 @@ static void add_debug_safety_case(const char *case_name, const char *source) { | ... | @@ -173,13 +179,16 @@ static void add_debug_safety_case(const char *case_name, const char *source) { |
| 173 | } | 179 | } |
| 174 | } | 180 | } |
| 175 | | 181 | |
| 176 | static TestCase *add_parseh_case(const char *case_name, const char *source, int count, ...) { | 182 | static TestCase *add_parseh_case(const char *case_name, AllowWarnings allow_warnings, |
| | 183 | const char *source, int count, ...) |
| | 184 | { |
| 177 | va_list ap; | 185 | va_list ap; |
| 178 | va_start(ap, count); | 186 | va_start(ap, count); |
| 179 | | 187 | |
| 180 | TestCase *test_case = allocate<TestCase>(1); | 188 | TestCase *test_case = allocate<TestCase>(1); |
| 181 | test_case->case_name = case_name; | 189 | test_case->case_name = case_name; |
| 182 | test_case->is_parseh = true; | 190 | test_case->is_parseh = true; |
| | 191 | test_case->allow_warnings = allow_warnings; |
| 183 | | 192 | |
| 184 | test_case->source_files.resize(1); | 193 | test_case->source_files.resize(1); |
| 185 | test_case->source_files.at(0).relative_path = tmp_h_path; | 194 | test_case->source_files.at(0).relative_path = tmp_h_path; |
| ... | @@ -1635,7 +1644,7 @@ fn unsigned_cast(x: i32) -> u32 { | ... | @@ -1635,7 +1644,7 @@ fn unsigned_cast(x: i32) -> u32 { |
| 1635 | ////////////////////////////////////////////////////////////////////////////// | 1644 | ////////////////////////////////////////////////////////////////////////////// |
| 1636 | | 1645 | |
| 1637 | static void add_parseh_test_cases(void) { | 1646 | static void add_parseh_test_cases(void) { |
| 1638 | add_parseh_case("simple data types", R"SOURCE( | 1647 | add_parseh_case("simple data types", AllowWarningsYes, R"SOURCE( |
| 1639 | #include <stdint.h> | 1648 | #include <stdint.h> |
| 1640 | int foo(char a, unsigned char b, signed char c); | 1649 | int foo(char a, unsigned char b, signed char c); |
| 1641 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype | 1650 | int foo(char a, unsigned char b, signed char c); // test a duplicate prototype |
| ... | @@ -1646,11 +1655,11 @@ void baz(int8_t a, int16_t b, int32_t c, int64_t d); | ... | @@ -1646,11 +1655,11 @@ void baz(int8_t a, int16_t b, int32_t c, int64_t d); |
| 1646 | "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);", | 1655 | "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);", |
| 1647 | "pub extern fn baz(a: i8, b: i16, c: i32, d: i64);"); | 1656 | "pub extern fn baz(a: i8, b: i16, c: i32, d: i64);"); |
| 1648 | | 1657 | |
| 1649 | add_parseh_case("noreturn attribute", R"SOURCE( | 1658 | add_parseh_case("noreturn attribute", AllowWarningsNo, R"SOURCE( |
| 1650 | void foo(void) __attribute__((noreturn)); | 1659 | void foo(void) __attribute__((noreturn)); |
| 1651 | )SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); | 1660 | )SOURCE", 1, R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT"); |
| 1652 | | 1661 | |
| 1653 | add_parseh_case("enums", R"SOURCE( | 1662 | add_parseh_case("enums", AllowWarningsNo, R"SOURCE( |
| 1654 | enum Foo { | 1663 | enum Foo { |
| 1655 | FooA, | 1664 | FooA, |
| 1656 | FooB, | 1665 | FooB, |
| ... | @@ -1665,11 +1674,11 @@ pub const FooB = enum_Foo.B; | ... | @@ -1665,11 +1674,11 @@ pub const FooB = enum_Foo.B; |
| 1665 | pub const Foo1 = enum_Foo.@"1";)", | 1674 | pub const Foo1 = enum_Foo.@"1";)", |
| 1666 | R"(pub const Foo = enum_Foo;)"); | 1675 | R"(pub const Foo = enum_Foo;)"); |
| 1667 | | 1676 | |
| 1668 | add_parseh_case("restrict -> noalias", R"SOURCE( | 1677 | add_parseh_case("restrict -> noalias", AllowWarningsNo, R"SOURCE( |
| 1669 | void foo(void *restrict bar, void *restrict); | 1678 | void foo(void *restrict bar, void *restrict); |
| 1670 | )SOURCE", 1, R"OUTPUT(pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT"); | 1679 | )SOURCE", 1, R"OUTPUT(pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void);)OUTPUT"); |
| 1671 | | 1680 | |
| 1672 | add_parseh_case("simple struct", R"SOURCE( | 1681 | add_parseh_case("simple struct", AllowWarningsNo, R"SOURCE( |
| 1673 | struct Foo { | 1682 | struct Foo { |
| 1674 | int x; | 1683 | int x; |
| 1675 | char *y; | 1684 | char *y; |
| ... | @@ -1680,7 +1689,7 @@ struct Foo { | ... | @@ -1680,7 +1689,7 @@ struct Foo { |
| 1680 | y: ?&u8, | 1689 | y: ?&u8, |
| 1681 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | 1690 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1682 | | 1691 | |
| 1683 | add_parseh_case("qualified struct and enum", R"SOURCE( | 1692 | add_parseh_case("qualified struct and enum", AllowWarningsNo, R"SOURCE( |
| 1684 | struct Foo { | 1693 | struct Foo { |
| 1685 | int x; | 1694 | int x; |
| 1686 | int y; | 1695 | int y; |
| ... | @@ -1703,12 +1712,13 @@ pub const BarB = enum_Bar.B;)OUTPUT", | ... | @@ -1703,12 +1712,13 @@ pub const BarB = enum_Bar.B;)OUTPUT", |
| 1703 | R"OUTPUT(pub const Foo = struct_Foo; | 1712 | R"OUTPUT(pub const Foo = struct_Foo; |
| 1704 | pub const Bar = enum_Bar;)OUTPUT"); | 1713 | pub const Bar = enum_Bar;)OUTPUT"); |
| 1705 | | 1714 | |
| 1706 | add_parseh_case("constant size array", R"SOURCE( | 1715 | add_parseh_case("constant size array", AllowWarningsNo, R"SOURCE( |
| 1707 | void func(int array[20]); | 1716 | void func(int array[20]); |
| 1708 | )SOURCE", 1, "pub extern fn func(array: ?&c_int);"); | 1717 | )SOURCE", 1, "pub extern fn func(array: ?&c_int);"); |
| 1709 | | 1718 | |
| 1710 | | 1719 | |
| 1711 | add_parseh_case("self referential struct with function pointer", R"SOURCE( | 1720 | add_parseh_case("self referential struct with function pointer", |
| | 1721 | AllowWarningsNo, R"SOURCE( |
| 1712 | struct Foo { | 1722 | struct Foo { |
| 1713 | void (*derp)(struct Foo *foo); | 1723 | void (*derp)(struct Foo *foo); |
| 1714 | }; | 1724 | }; |
| ... | @@ -1717,7 +1727,7 @@ struct Foo { | ... | @@ -1717,7 +1727,7 @@ struct Foo { |
| 1717 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | 1727 | })OUTPUT", R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1718 | | 1728 | |
| 1719 | | 1729 | |
| 1720 | add_parseh_case("struct prototype used in func", R"SOURCE( | 1730 | add_parseh_case("struct prototype used in func", AllowWarningsNo, R"SOURCE( |
| 1721 | struct Foo; | 1731 | struct Foo; |
| 1722 | struct Foo *some_func(struct Foo *foo, int x); | 1732 | struct Foo *some_func(struct Foo *foo, int x); |
| 1723 | )SOURCE", 2, R"OUTPUT(pub type struct_Foo = u8; | 1733 | )SOURCE", 2, R"OUTPUT(pub type struct_Foo = u8; |
| ... | @@ -1725,17 +1735,19 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", | ... | @@ -1725,17 +1735,19 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1725 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); | 1735 | R"OUTPUT(pub const Foo = struct_Foo;)OUTPUT"); |
| 1726 | | 1736 | |
| 1727 | | 1737 | |
| 1728 | add_parseh_case("#define a char literal", R"SOURCE( | 1738 | add_parseh_case("#define a char literal", AllowWarningsNo, R"SOURCE( |
| 1729 | #define A_CHAR 'a' | 1739 | #define A_CHAR 'a' |
| 1730 | )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); | 1740 | )SOURCE", 1, R"OUTPUT(pub const A_CHAR = 'a';)OUTPUT"); |
| 1731 | | 1741 | |
| 1732 | | 1742 | |
| 1733 | add_parseh_case("#define an unsigned integer literal", R"SOURCE( | 1743 | add_parseh_case("#define an unsigned integer literal", AllowWarningsNo, |
| | 1744 | R"SOURCE( |
| 1734 | #define CHANNEL_COUNT 24 | 1745 | #define CHANNEL_COUNT 24 |
| 1735 | )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT"); | 1746 | )SOURCE", 1, R"OUTPUT(pub const CHANNEL_COUNT = 24;)OUTPUT"); |
| 1736 | | 1747 | |
| 1737 | | 1748 | |
| 1738 | add_parseh_case("#define referencing another #define", R"SOURCE( | 1749 | add_parseh_case("#define referencing another #define", AllowWarningsNo, |
| | 1750 | R"SOURCE( |
| 1739 | #define THING2 THING1 | 1751 | #define THING2 THING1 |
| 1740 | #define THING1 1234 | 1752 | #define THING1 1234 |
| 1741 | )SOURCE", 2, | 1753 | )SOURCE", 2, |
| ... | @@ -1743,7 +1755,7 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", | ... | @@ -1743,7 +1755,7 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1743 | "pub const THING2 = THING1;"); | 1755 | "pub const THING2 = THING1;"); |
| 1744 | | 1756 | |
| 1745 | | 1757 | |
| 1746 | add_parseh_case("variables", R"SOURCE( | 1758 | add_parseh_case("variables", AllowWarningsNo, R"SOURCE( |
| 1747 | extern int extern_var; | 1759 | extern int extern_var; |
| 1748 | static const int int_var = 13; | 1760 | static const int int_var = 13; |
| 1749 | )SOURCE", 2, | 1761 | )SOURCE", 2, |
| ... | @@ -1751,7 +1763,7 @@ static const int int_var = 13; | ... | @@ -1751,7 +1763,7 @@ static const int int_var = 13; |
| 1751 | "pub const int_var: c_int = 13;"); | 1763 | "pub const int_var: c_int = 13;"); |
| 1752 | | 1764 | |
| 1753 | | 1765 | |
| 1754 | add_parseh_case("circular struct definitions", R"SOURCE( | 1766 | add_parseh_case("circular struct definitions", AllowWarningsNo, R"SOURCE( |
| 1755 | struct Bar; | 1767 | struct Bar; |
| 1756 | | 1768 | |
| 1757 | struct Foo { | 1769 | struct Foo { |
| ... | @@ -1770,14 +1782,15 @@ struct Bar { | ... | @@ -1770,14 +1782,15 @@ struct Bar { |
| 1770 | })SOURCE"); | 1782 | })SOURCE"); |
| 1771 | | 1783 | |
| 1772 | | 1784 | |
| 1773 | add_parseh_case("typedef void", R"SOURCE( | 1785 | add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( |
| 1774 | typedef void Foo; | 1786 | typedef void Foo; |
| 1775 | Foo fun(Foo *a); | 1787 | Foo fun(Foo *a); |
| 1776 | )SOURCE", 2, | 1788 | )SOURCE", 2, |
| 1777 | "pub const Foo = c_void;", | 1789 | "pub const Foo = c_void;", |
| 1778 | "pub extern fn fun(a: ?&c_void);"); | 1790 | "pub extern fn fun(a: ?&c_void);"); |
| 1779 | | 1791 | |
| 1780 | add_parseh_case("generate inline func for #define global extern fn", R"SOURCE( | 1792 | add_parseh_case("generate inline func for #define global extern fn", AllowWarningsNo, |
| | 1793 | R"SOURCE( |
| 1781 | extern void (*fn_ptr)(void); | 1794 | extern void (*fn_ptr)(void); |
| 1782 | #define foo fn_ptr | 1795 | #define foo fn_ptr |
| 1783 | )SOURCE", 2, | 1796 | )SOURCE", 2, |
| ... | @@ -1787,19 +1800,19 @@ extern void (*fn_ptr)(void); | ... | @@ -1787,19 +1800,19 @@ extern void (*fn_ptr)(void); |
| 1787 | })SOURCE"); | 1800 | })SOURCE"); |
| 1788 | | 1801 | |
| 1789 | | 1802 | |
| 1790 | add_parseh_case("#define string", R"SOURCE( | 1803 | add_parseh_case("#define string", AllowWarningsNo, R"SOURCE( |
| 1791 | #define foo "a string" | 1804 | #define foo "a string" |
| 1792 | )SOURCE", 1, "pub const foo = c\"a string\";"); | 1805 | )SOURCE", 1, "pub const foo = c\"a string\";"); |
| 1793 | | 1806 | |
| 1794 | add_parseh_case("__cdecl doesn't mess up function pointers", R"SOURCE( | 1807 | add_parseh_case("__cdecl doesn't mess up function pointers", AllowWarningsNo, R"SOURCE( |
| 1795 | void foo(void (__cdecl *fn_ptr)(void)); | 1808 | void foo(void (__cdecl *fn_ptr)(void)); |
| 1796 | )SOURCE", 1, "pub extern fn foo(fn_ptr: ?extern fn());"); | 1809 | )SOURCE", 1, "pub extern fn foo(fn_ptr: ?extern fn());"); |
| 1797 | | 1810 | |
| 1798 | add_parseh_case("comment after integer literal", R"SOURCE( | 1811 | add_parseh_case("comment after integer literal", AllowWarningsNo, R"SOURCE( |
| 1799 | #define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | 1812 | #define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ |
| 1800 | )SOURCE", 1, "pub const SDL_INIT_VIDEO = 32;"); | 1813 | )SOURCE", 1, "pub const SDL_INIT_VIDEO = 32;"); |
| 1801 | | 1814 | |
| 1802 | add_parseh_case("zig keywords in C code", R"SOURCE( | 1815 | add_parseh_case("zig keywords in C code", AllowWarningsNo, R"SOURCE( |
| 1803 | struct type { | 1816 | struct type { |
| 1804 | int defer; | 1817 | int defer; |
| 1805 | }; | 1818 | }; |
| ... | @@ -1807,7 +1820,7 @@ struct type { | ... | @@ -1807,7 +1820,7 @@ struct type { |
| 1807 | @"defer": c_int, | 1820 | @"defer": c_int, |
| 1808 | })", R"(pub const @"type" = struct_type;)"); | 1821 | })", R"(pub const @"type" = struct_type;)"); |
| 1809 | | 1822 | |
| 1810 | add_parseh_case("macro defines string literal with octal", R"SOURCE( | 1823 | add_parseh_case("macro defines string literal with octal", AllowWarningsNo, R"SOURCE( |
| 1811 | #define FOO "aoeu\023 derp" | 1824 | #define FOO "aoeu\023 derp" |
| 1812 | #define FOO2 "aoeu\0234 derp" | 1825 | #define FOO2 "aoeu\0234 derp" |
| 1813 | #define FOO_CHAR '\077' | 1826 | #define FOO_CHAR '\077' |
| ... | @@ -1925,10 +1938,14 @@ static void run_test(TestCase *test_case) { | ... | @@ -1925,10 +1938,14 @@ static void run_test(TestCase *test_case) { |
| 1925 | | 1938 | |
| 1926 | if (test_case->is_parseh) { | 1939 | if (test_case->is_parseh) { |
| 1927 | if (buf_len(&zig_stderr) > 0) { | 1940 | if (buf_len(&zig_stderr) > 0) { |
| 1928 | printf("\n!!!!! parseh emitted warnings:\n"); | 1941 | printf("\nparseh emitted warnings:\n"); |
| | 1942 | printf("------------------------------\n"); |
| 1929 | print_compiler_invocation(test_case); | 1943 | print_compiler_invocation(test_case); |
| 1930 | printf("%s\n", buf_ptr(&zig_stderr)); | 1944 | printf("%s\n", buf_ptr(&zig_stderr)); |
| 1931 | // exit(1); | 1945 | printf("------------------------------\n"); |
| | 1946 | if (test_case->allow_warnings == AllowWarningsNo) { |
| | 1947 | exit(1); |
| | 1948 | } |
| 1932 | } | 1949 | } |
| 1933 | | 1950 | |
| 1934 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { | 1951 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { |