authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 11:54:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-28 11:54:34-07:00
logf1c5d3d3a1ffd479acecd32bbd0496824316c6a6
treefb591620102897312e116c3af62dc4cefcc4ab93
parent474340a0031c9b3c8ce0d97c2cc36d5327c4e304

add parseh tests


4 files changed, 148 insertions(+), 28 deletions(-)

doc/targets.md+3
......@@ -14,3 +14,6 @@ Update the C integer types to be the correct size for the target.
1414
1515Add the conditional compilation code for the page size global. It is hardcoded
1616for each target.
17
18Make sure that parseh sends the correct command line parameters to libclang for
19the given target.
src/ast_render.cpp+1-1
......@@ -672,7 +672,7 @@ static void render_node(AstRender *ar, AstNode *node) {
672672 }
673673
674674 ar->indent -= ar->indent_size;
675 fprintf(ar->f, "}\n");
675 fprintf(ar->f, "}");
676676 break;
677677 }
678678 case NodeTypeStructField:
src/parseh.cpp+44-1
......@@ -397,6 +397,9 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
397397 if (!enum_def) {
398398 // this is a type that we can point to but that's it, same as `struct Foo;`.
399399 add_typedef_node(c, type_name, create_symbol_node(c, "u8"));
400 AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name),
401 create_symbol_node(c, buf_ptr(type_name)));
402 c->aliases.append(alias_node);
400403 return;
401404 }
402405
......@@ -404,7 +407,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
404407 buf_init_from_buf(&node->data.struct_decl.name, type_name);
405408
406409 node->data.struct_decl.kind = ContainerKindEnum;
407 node->data.struct_decl.visib_mod = c->visib_mod;
410 node->data.struct_decl.visib_mod = VisibModExport;
408411 node->data.struct_decl.directives = create_empty_directives(c);
409412
410413 ZigList<AstNode *> var_decls = {0};
......@@ -465,6 +468,43 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
465468
466469}
467470
471static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
472 Buf bare_name = BUF_INIT;
473 buf_init_from_str(&bare_name, decl_name(record_decl));
474
475 Buf *type_name = buf_alloc();
476 buf_appendf(type_name, "struct_%s", buf_ptr(&bare_name));
477
478 if (c->type_table.maybe_get(type_name)) {
479 // we've already seen it
480 return;
481 }
482
483 RecordDecl *record_def = record_decl->getDefinition();
484 if (!record_def) {
485 // this is a type that we can point to but that's it, such as `struct Foo;`.
486 add_typedef_node(c, type_name, create_symbol_node(c, "u8"));
487 AstNode *alias_node = create_var_decl_node(c, buf_ptr(&bare_name),
488 create_symbol_node(c, buf_ptr(type_name)));
489 c->aliases.append(alias_node);
490 return;
491 }
492
493 emit_warning(c, record_decl, "skipping record %s, TODO", buf_ptr(&bare_name));
494
495 /*
496 AstNode *node = create_node(c, NodeTypeStructDecl);
497 buf_init_from_buf(&node->data.struct_decl.name, type_name);
498
499 node->data.struct_decl.kind = ContainerKindStruct;
500 node->data.struct_decl.visib_mod = VisibModExport;
501 node->data.struct_decl.directives = create_empty_directives(c);
502
503 normalize_parent_ptrs(node);
504 c->root->data.root.top_level_decls.append(node);
505 */
506}
507
468508static bool decl_visitor(void *context, const Decl *decl) {
469509 Context *c = (Context*)context;
470510
......@@ -478,6 +518,9 @@ static bool decl_visitor(void *context, const Decl *decl) {
478518 case Decl::Enum:
479519 visit_enum_decl(c, static_cast<const EnumDecl *>(decl));
480520 break;
521 case Decl::Record:
522 visit_record_decl(c, static_cast<const RecordDecl *>(decl));
523 break;
481524 default:
482525 emit_warning(c, decl, "ignoring %s decl\n", decl->getDeclKindName());
483526 }
test/run_tests.cpp+100-26
......@@ -24,10 +24,12 @@ struct TestCase {
2424 ZigList<const char *> compile_errors;
2525 ZigList<const char *> compiler_args;
2626 ZigList<const char *> program_args;
27 bool is_parseh;
2728};
2829
2930static ZigList<TestCase*> test_cases = {0};
3031static const char *tmp_source_path = ".tmp_source.zig";
32static const char *tmp_h_path = ".tmp_header.h";
3133static const char *tmp_exe_path = "./.tmp_exe";
3234static const char *zig_exe = "./zig";
3335
......@@ -94,6 +96,24 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
9496 return test_case;
9597}
9698
99static TestCase *add_parseh_case(const char *case_name, const char *source, const char *output) {
100 TestCase *test_case = allocate<TestCase>(1);
101 test_case->case_name = case_name;
102 test_case->output = output;
103 test_case->is_parseh = true;
104
105 test_case->source_files.resize(1);
106 test_case->source_files.at(0).relative_path = tmp_h_path;
107 test_case->source_files.at(0).source_code = source;
108
109 test_case->compiler_args.append("parseh");
110 test_case->compiler_args.append(tmp_h_path);
111 test_case->compiler_args.append("--c-import-warnings");
112
113 test_cases.append(test_case);
114 return test_case;
115}
116
97117static void add_compiling_test_cases(void) {
98118 add_simple_case("hello world with libc", R"SOURCE(
99119#link("c")
......@@ -1771,6 +1791,39 @@ const x = 2 == 2.0;
17711791
17721792}
17731793
1794//////////////////////////////////////////////////////////////////////////////
1795
1796static void add_parseh_test_cases(void) {
1797 add_parseh_case("simple data types", R"SOURCE(
1798#include <stdint.h>
1799int foo(char a, unsigned char b, signed char c);
1800void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d);
1801void baz(int8_t a, int16_t b, int32_t c, int64_t d);
1802 )SOURCE", R"OUTPUT(pub extern fn foo(a: u8, b: u8, c: i8) -> c_int;
1803pub extern fn bar(a: u8, b: u16, c: u32, d: u64);
1804pub extern fn baz(a: i8, b: i16, c: i32, d: i64);)OUTPUT");
1805
1806 add_parseh_case("noreturn attribute", R"SOURCE(
1807void foo(void) __attribute__((noreturn));
1808 )SOURCE", R"OUTPUT(pub extern fn foo() -> unreachable;)OUTPUT");
1809
1810 add_parseh_case("enums", R"SOURCE(
1811enum Foo {
1812 FooA,
1813 FooB,
1814 Foo1,
1815};
1816 )SOURCE", R"OUTPUT(export enum enum_Foo {
1817 A,
1818 B,
1819 _1,
1820}
1821pub const FooA = enum_Foo.A;
1822pub const FooB = enum_Foo.B;
1823pub const Foo1 = enum_Foo._1;
1824pub const Foo = enum_Foo;)OUTPUT");
1825}
1826
17741827static void print_compiler_invocation(TestCase *test_case) {
17751828 printf("%s", zig_exe);
17761829 for (int i = 0; i < test_case->compiler_args.length; i += 1) {
......@@ -1822,36 +1875,55 @@ static void run_test(TestCase *test_case) {
18221875 exit(1);
18231876 }
18241877
1825 Buf program_stderr = BUF_INIT;
1826 Buf program_stdout = BUF_INIT;
1827 os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout);
1878 if (test_case->is_parseh) {
1879 if (buf_len(&zig_stderr) > 0) {
1880 printf("\nparseh emitted warnings:\n");
1881 print_compiler_invocation(test_case);
1882 printf("%s\n", buf_ptr(&zig_stderr));
1883 exit(1);
1884 }
18281885
1829 if (return_code != 0) {
1830 printf("\nProgram exited with return code %d:\n", return_code);
1831 print_compiler_invocation(test_case);
1832 printf("%s", tmp_exe_path);
1833 for (int i = 0; i < test_case->program_args.length; i += 1) {
1834 printf(" %s", test_case->program_args.at(i));
1886 if (!strstr(buf_ptr(&zig_stdout), test_case->output)) {
1887 printf("\n");
1888 printf("========= Expected this output: =========\n");
1889 printf("%s\n", test_case->output);
1890 printf("================================================\n");
1891 print_compiler_invocation(test_case);
1892 printf("%s\n", buf_ptr(&zig_stdout));
1893 exit(1);
18351894 }
1836 printf("\n");
1837 printf("%s\n", buf_ptr(&program_stderr));
1838 exit(1);
1839 }
1895 } else {
1896 Buf program_stderr = BUF_INIT;
1897 Buf program_stdout = BUF_INIT;
1898 os_exec_process(tmp_exe_path, test_case->program_args, &return_code, &program_stderr, &program_stdout);
18401899
1841 if (!buf_eql_str(&program_stdout, test_case->output)) {
1842 printf("\n");
1843 print_compiler_invocation(test_case);
1844 printf("%s", tmp_exe_path);
1845 for (int i = 0; i < test_case->program_args.length; i += 1) {
1846 printf(" %s", test_case->program_args.at(i));
1900 if (return_code != 0) {
1901 printf("\nProgram exited with return code %d:\n", return_code);
1902 print_compiler_invocation(test_case);
1903 printf("%s", tmp_exe_path);
1904 for (int i = 0; i < test_case->program_args.length; i += 1) {
1905 printf(" %s", test_case->program_args.at(i));
1906 }
1907 printf("\n");
1908 printf("%s\n", buf_ptr(&program_stderr));
1909 exit(1);
1910 }
1911
1912 if (!buf_eql_str(&program_stdout, test_case->output)) {
1913 printf("\n");
1914 print_compiler_invocation(test_case);
1915 printf("%s", tmp_exe_path);
1916 for (int i = 0; i < test_case->program_args.length; i += 1) {
1917 printf(" %s", test_case->program_args.at(i));
1918 }
1919 printf("\n");
1920 printf("==== Test failed. Expected output: ====\n");
1921 printf("%s\n", test_case->output);
1922 printf("========= Actual output: ==============\n");
1923 printf("%s\n", buf_ptr(&program_stdout));
1924 printf("=======================================\n");
1925 exit(1);
18471926 }
1848 printf("\n");
1849 printf("==== Test failed. Expected output: ====\n");
1850 printf("%s\n", test_case->output);
1851 printf("========= Actual output: ==============\n");
1852 printf("%s\n", buf_ptr(&program_stdout));
1853 printf("=======================================\n");
1854 exit(1);
18551927 }
18561928
18571929 for (int i = 0; i < test_case->source_files.length; i += 1) {
......@@ -1881,6 +1953,7 @@ static void run_all_tests(bool reverse) {
18811953
18821954static void cleanup(void) {
18831955 remove(tmp_source_path);
1956 remove(tmp_h_path);
18841957 remove(tmp_exe_path);
18851958}
18861959
......@@ -1900,6 +1973,7 @@ int main(int argc, char **argv) {
19001973 }
19011974 add_compiling_test_cases();
19021975 add_compile_failure_test_cases();
1976 add_parseh_test_cases();
19031977 run_all_tests(reverse);
19041978 cleanup();
19051979}