| ... | ... | @@ -18,6 +18,11 @@ struct TestSourceFile { |
| 18 | 18 | const char *source_code; |
| 19 | 19 | }; |
| 20 | 20 | |
| 21 | enum AllowWarnings { |
| 22 | AllowWarningsNo, |
| 23 | AllowWarningsYes, |
| 24 | }; |
| 25 | |
| 21 | 26 | struct TestCase { |
| 22 | 27 | const char *case_name; |
| 23 | 28 | const char *output; |
| ... | ... | @@ -29,6 +34,7 @@ struct TestCase { |
| 29 | 34 | bool is_self_hosted; |
| 30 | 35 | bool is_release_mode; |
| 31 | 36 | bool is_debug_safety; |
| 37 | AllowWarnings allow_warnings; |
| 32 | 38 | }; |
| 33 | 39 | |
| 34 | 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 | 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 | 185 | va_list ap; |
| 178 | 186 | va_start(ap, count); |
| 179 | 187 | |
| 180 | 188 | TestCase *test_case = allocate<TestCase>(1); |
| 181 | 189 | test_case->case_name = case_name; |
| 182 | 190 | test_case->is_parseh = true; |
| 191 | test_case->allow_warnings = allow_warnings; |
| 183 | 192 | |
| 184 | 193 | test_case->source_files.resize(1); |
| 185 | 194 | test_case->source_files.at(0).relative_path = tmp_h_path; |
| ... | ... | @@ -1635,7 +1644,7 @@ fn unsigned_cast(x: i32) -> u32 { |
| 1635 | 1644 | ////////////////////////////////////////////////////////////////////////////// |
| 1636 | 1645 | |
| 1637 | 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 | 1648 | #include <stdint.h> |
| 1640 | 1649 | int foo(char a, unsigned char b, signed char c); |
| 1641 | 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 | 1655 | "pub extern fn bar(a: u8, b: u16, c: u32, d: u64);", |
| 1647 | 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 | 1659 | void foo(void) __attribute__((noreturn)); |
| 1651 | 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 | 1663 | enum Foo { |
| 1655 | 1664 | FooA, |
| 1656 | 1665 | FooB, |
| ... | ... | @@ -1665,11 +1674,11 @@ pub const FooB = enum_Foo.B; |
| 1665 | 1674 | pub const Foo1 = enum_Foo.@"1";)", |
| 1666 | 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 | 1678 | void foo(void *restrict bar, void *restrict); |
| 1670 | 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 | 1682 | struct Foo { |
| 1674 | 1683 | int x; |
| 1675 | 1684 | char *y; |
| ... | ... | @@ -1680,7 +1689,7 @@ struct Foo { |
| 1680 | 1689 | y: ?&u8, |
| 1681 | 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 | 1693 | struct Foo { |
| 1685 | 1694 | int x; |
| 1686 | 1695 | int y; |
| ... | ... | @@ -1703,12 +1712,13 @@ pub const BarB = enum_Bar.B;)OUTPUT", |
| 1703 | 1712 | R"OUTPUT(pub const Foo = struct_Foo; |
| 1704 | 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 | 1716 | void func(int array[20]); |
| 1708 | 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 | 1722 | struct Foo { |
| 1713 | 1723 | void (*derp)(struct Foo *foo); |
| 1714 | 1724 | }; |
| ... | ... | @@ -1717,7 +1727,7 @@ struct Foo { |
| 1717 | 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 | 1731 | struct Foo; |
| 1722 | 1732 | struct Foo *some_func(struct Foo *foo, int x); |
| 1723 | 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 | 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 | 1739 | #define A_CHAR 'a' |
| 1730 | 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 | 1745 | #define CHANNEL_COUNT 24 |
| 1735 | 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 | 1751 | #define THING2 THING1 |
| 1740 | 1752 | #define THING1 1234 |
| 1741 | 1753 | )SOURCE", 2, |
| ... | ... | @@ -1743,7 +1755,7 @@ pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo;)OUTPUT", |
| 1743 | 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 | 1759 | extern int extern_var; |
| 1748 | 1760 | static const int int_var = 13; |
| 1749 | 1761 | )SOURCE", 2, |
| ... | ... | @@ -1751,7 +1763,7 @@ static const int int_var = 13; |
| 1751 | 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 | 1767 | struct Bar; |
| 1756 | 1768 | |
| 1757 | 1769 | struct Foo { |
| ... | ... | @@ -1770,14 +1782,15 @@ struct Bar { |
| 1770 | 1782 | })SOURCE"); |
| 1771 | 1783 | |
| 1772 | 1784 | |
| 1773 | | add_parseh_case("typedef void", R"SOURCE( |
| 1785 | add_parseh_case("typedef void", AllowWarningsNo, R"SOURCE( |
| 1774 | 1786 | typedef void Foo; |
| 1775 | 1787 | Foo fun(Foo *a); |
| 1776 | 1788 | )SOURCE", 2, |
| 1777 | 1789 | "pub const Foo = c_void;", |
| 1778 | 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 | 1794 | extern void (*fn_ptr)(void); |
| 1782 | 1795 | #define foo fn_ptr |
| 1783 | 1796 | )SOURCE", 2, |
| ... | ... | @@ -1787,19 +1800,19 @@ extern void (*fn_ptr)(void); |
| 1787 | 1800 | })SOURCE"); |
| 1788 | 1801 | |
| 1789 | 1802 | |
| 1790 | | add_parseh_case("#define string", R"SOURCE( |
| 1803 | add_parseh_case("#define string", AllowWarningsNo, R"SOURCE( |
| 1791 | 1804 | #define foo "a string" |
| 1792 | 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 | 1808 | void foo(void (__cdecl *fn_ptr)(void)); |
| 1796 | 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 | 1812 | #define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ |
| 1800 | 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 | 1816 | struct type { |
| 1804 | 1817 | int defer; |
| 1805 | 1818 | }; |
| ... | ... | @@ -1807,7 +1820,7 @@ struct type { |
| 1807 | 1820 | @"defer": c_int, |
| 1808 | 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 | 1824 | #define FOO "aoeu\023 derp" |
| 1812 | 1825 | #define FOO2 "aoeu\0234 derp" |
| 1813 | 1826 | #define FOO_CHAR '\077' |
| ... | ... | @@ -1925,10 +1938,14 @@ static void run_test(TestCase *test_case) { |
| 1925 | 1938 | |
| 1926 | 1939 | if (test_case->is_parseh) { |
| 1927 | 1940 | if (buf_len(&zig_stderr) > 0) { |
| 1928 | | printf("\n!!!!! parseh emitted warnings:\n"); |
| 1941 | printf("\nparseh emitted warnings:\n"); |
| 1942 | printf("------------------------------\n"); |
| 1929 | 1943 | print_compiler_invocation(test_case); |
| 1930 | 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 | 1951 | for (int i = 0; i < test_case->compile_errors.length; i += 1) { |