| author | |
| committer | |
| log | 2c9bdad3462f356f4c2ed2442f2cd6de80b9805b |
| tree | 4bd725e4f8e4ef33121c91ff114057bbd9f277c6 |
| parent | 48c44615a4f03c105a8053db552320d26482436a |
15 files changed, 2752 insertions(+), 2757 deletions(-)
CMakeLists.txt+1-1| ... | @@ -193,7 +193,7 @@ set(ZIG_SOURCES | ... | @@ -193,7 +193,7 @@ set(ZIG_SOURCES |
| 193 | "${CMAKE_SOURCE_DIR}/src/target.cpp" | 193 | "${CMAKE_SOURCE_DIR}/src/target.cpp" |
| 194 | "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" | 194 | "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp" |
| 195 | "${CMAKE_SOURCE_DIR}/src/util.cpp" | 195 | "${CMAKE_SOURCE_DIR}/src/util.cpp" |
| 196 | "${CMAKE_SOURCE_DIR}/src/parseh.cpp" | 196 | "${CMAKE_SOURCE_DIR}/src/parsec.cpp" |
| 197 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" | 197 | "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp" |
| 198 | ) | 198 | ) |
| 199 | 199 |
build.zig+1-1| ... | @@ -19,5 +19,5 @@ pub fn build(b: &Builder) { | ... | @@ -19,5 +19,5 @@ pub fn build(b: &Builder) { |
| 19 | test_step.dependOn(tests.addCompileErrorTests(b, test_filter)); | 19 | test_step.dependOn(tests.addCompileErrorTests(b, test_filter)); |
| 20 | test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter)); | 20 | test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter)); |
| 21 | test_step.dependOn(tests.addDebugSafetyTests(b, test_filter)); | 21 | test_step.dependOn(tests.addDebugSafetyTests(b, test_filter)); |
| 22 | test_step.dependOn(tests.addParseHTests(b, test_filter)); | 22 | test_step.dependOn(tests.addParseCTests(b, test_filter)); |
| 23 | } | 23 | } |
ci/travis_linux_script+1-1| ... | @@ -15,4 +15,4 @@ make install | ... | @@ -15,4 +15,4 @@ make install |
| 15 | # we have to skip cross compiling OSX tests because apt.llvm.org has an old version | 15 | # we have to skip cross compiling OSX tests because apt.llvm.org has an old version |
| 16 | # of llvm for the version of ubuntu that travis is running on. | 16 | # of llvm for the version of ubuntu that travis is running on. |
| 17 | ./zig build --build-file ../build.zig test-behavior test-std test-compiler-rt -Dtest-filter=linux | 17 | ./zig build --build-file ../build.zig test-behavior test-std test-compiler-rt -Dtest-filter=linux |
| 18 | ./zig build --build-file ../build.zig test-compare-output test-build-examples test-compile-errors test-asm-link test-debug-safety test-parseh | 18 | ./zig build --build-file ../build.zig test-compare-output test-build-examples test-compile-errors test-asm-link test-debug-safety test-parsec |
src/analyze.cpp+2-7| ... | @@ -26,7 +26,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type); | ... | @@ -26,7 +26,7 @@ static void resolve_enum_zero_bits(CodeGen *g, TypeTableEntry *enum_type); |
| 26 | static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type); | 26 | static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type); |
| 27 | 27 | ||
| 28 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { | 28 | ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 29 | // if this assert fails, then parseh generated code that | 29 | // if this assert fails, then parsec generated code that |
| 30 | // failed semantic analysis, which isn't supposed to happen | 30 | // failed semantic analysis, which isn't supposed to happen |
| 31 | assert(!node->owner->c_import_node); | 31 | assert(!node->owner->c_import_node); |
| 32 | 32 | ||
| ... | @@ -38,7 +38,7 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { | ... | @@ -38,7 +38,7 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) { |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) { | 40 | ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) { |
| 41 | // if this assert fails, then parseh generated code that | 41 | // if this assert fails, then parsec generated code that |
| 42 | // failed semantic analysis, which isn't supposed to happen | 42 | // failed semantic analysis, which isn't supposed to happen |
| 43 | assert(!node->owner->c_import_node); | 43 | assert(!node->owner->c_import_node); |
| 44 | 44 | ||
| ... | @@ -1265,7 +1265,6 @@ TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, Type | ... | @@ -1265,7 +1265,6 @@ TypeTableEntry *create_enum_tag_type(CodeGen *g, TypeTableEntry *enum_type, Type |
| 1265 | } | 1265 | } |
| 1266 | 1266 | ||
| 1267 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { | 1267 | static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) { |
| 1268 | // if you change this logic you likely must also change similar logic in parseh.cpp | ||
| 1269 | assert(enum_type->id == TypeTableEntryIdEnum); | 1268 | assert(enum_type->id == TypeTableEntryIdEnum); |
| 1270 | 1269 | ||
| 1271 | if (enum_type->data.enumeration.complete) | 1270 | if (enum_type->data.enumeration.complete) |
| ... | @@ -1578,8 +1577,6 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f | ... | @@ -1578,8 +1577,6 @@ TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *f |
| 1578 | } | 1577 | } |
| 1579 | 1578 | ||
| 1580 | static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { | 1579 | static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { |
| 1581 | // if you change the logic of this function likely you must make a similar change in | ||
| 1582 | // parseh.cpp | ||
| 1583 | assert(struct_type->id == TypeTableEntryIdStruct); | 1580 | assert(struct_type->id == TypeTableEntryIdStruct); |
| 1584 | 1581 | ||
| 1585 | if (struct_type->data.structure.complete) | 1582 | if (struct_type->data.structure.complete) |
| ... | @@ -3079,8 +3076,6 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * | ... | @@ -3079,8 +3076,6 @@ static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode * |
| 3079 | continue; | 3076 | continue; |
| 3080 | } | 3077 | } |
| 3081 | 3078 | ||
| 3082 | // Note: target_tld->name is not necessarily equal to entry->key because | ||
| 3083 | // of aliases that parseh uses. | ||
| 3084 | Buf *target_tld_name = entry->key; | 3079 | Buf *target_tld_name = entry->key; |
| 3085 | 3080 | ||
| 3086 | auto existing_entry = dst_use_node->owner->decls_scope->decl_table.put_unique(target_tld_name, target_tld); | 3081 | auto existing_entry = dst_use_node->owner->decls_scope->decl_table.put_unique(target_tld_name, target_tld); |
src/codegen.cpp+2-2| ... | @@ -15,7 +15,7 @@ | ... | @@ -15,7 +15,7 @@ |
| 15 | #include "ir.hpp" | 15 | #include "ir.hpp" |
| 16 | #include "link.hpp" | 16 | #include "link.hpp" |
| 17 | #include "os.hpp" | 17 | #include "os.hpp" |
| 18 | #include "parseh.hpp" | 18 | #include "parsec.hpp" |
| 19 | #include "target.hpp" | 19 | #include "target.hpp" |
| 20 | #include "zig_llvm.hpp" | 20 | #include "zig_llvm.hpp" |
| 21 | 21 | ||
| ... | @@ -5001,7 +5001,7 @@ static void init(CodeGen *g) { | ... | @@ -5001,7 +5001,7 @@ static void init(CodeGen *g) { |
| 5001 | define_builtin_compile_vars(g); | 5001 | define_builtin_compile_vars(g); |
| 5002 | } | 5002 | } |
| 5003 | 5003 | ||
| 5004 | void codegen_parseh(CodeGen *g, Buf *full_path) { | 5004 | void codegen_parsec(CodeGen *g, Buf *full_path) { |
| 5005 | find_libc_include_path(g); | 5005 | find_libc_include_path(g); |
| 5006 | 5006 | ||
| 5007 | Buf *src_basename = buf_alloc(); | 5007 | Buf *src_basename = buf_alloc(); |
src/codegen.hpp+1-1| ... | @@ -54,7 +54,7 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, | ... | @@ -54,7 +54,7 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir, |
| 54 | void codegen_add_assembly(CodeGen *g, Buf *path); | 54 | void codegen_add_assembly(CodeGen *g, Buf *path); |
| 55 | void codegen_add_object(CodeGen *g, Buf *object_path); | 55 | void codegen_add_object(CodeGen *g, Buf *object_path); |
| 56 | 56 | ||
| 57 | void codegen_parseh(CodeGen *g, Buf *path); | 57 | void codegen_parsec(CodeGen *g, Buf *path); |
| 58 | 58 | ||
| 59 | 59 | ||
| 60 | #endif | 60 | #endif |
src/ir.cpp+1-1| ... | @@ -11,7 +11,7 @@ | ... | @@ -11,7 +11,7 @@ |
| 11 | #include "ir.hpp" | 11 | #include "ir.hpp" |
| 12 | #include "ir_print.hpp" | 12 | #include "ir_print.hpp" |
| 13 | #include "os.hpp" | 13 | #include "os.hpp" |
| 14 | #include "parseh.hpp" | 14 | #include "parsec.hpp" |
| 15 | #include "quadmath.hpp" | 15 | #include "quadmath.hpp" |
| 16 | #include "range_set.hpp" | 16 | #include "range_set.hpp" |
| 17 | 17 |
src/main.cpp+11-11| ... | @@ -23,7 +23,7 @@ static int usage(const char *arg0) { | ... | @@ -23,7 +23,7 @@ static int usage(const char *arg0) { |
| 23 | " build_exe [source] create executable from source or object files\n" | 23 | " build_exe [source] create executable from source or object files\n" |
| 24 | " build_lib [source] create library from source or object files\n" | 24 | " build_lib [source] create library from source or object files\n" |
| 25 | " build_obj [source] create object from source or assembly\n" | 25 | " build_obj [source] create object from source or assembly\n" |
| 26 | " parseh [source] convert a c header file to zig extern declarations\n" | 26 | " parsec [source] convert c code to zig code\n" |
| 27 | " targets list available compilation targets\n" | 27 | " targets list available compilation targets\n" |
| 28 | " test [source] create and run a test build\n" | 28 | " test [source] create and run a test build\n" |
| 29 | " version print version number and exit\n" | 29 | " version print version number and exit\n" |
| ... | @@ -132,7 +132,7 @@ enum Cmd { | ... | @@ -132,7 +132,7 @@ enum Cmd { |
| 132 | CmdTest, | 132 | CmdTest, |
| 133 | CmdVersion, | 133 | CmdVersion, |
| 134 | CmdZen, | 134 | CmdZen, |
| 135 | CmdParseH, | 135 | CmdParseC, |
| 136 | CmdTargets, | 136 | CmdTargets, |
| 137 | }; | 137 | }; |
| 138 | 138 | ||
| ... | @@ -470,8 +470,8 @@ int main(int argc, char **argv) { | ... | @@ -470,8 +470,8 @@ int main(int argc, char **argv) { |
| 470 | cmd = CmdVersion; | 470 | cmd = CmdVersion; |
| 471 | } else if (strcmp(arg, "zen") == 0) { | 471 | } else if (strcmp(arg, "zen") == 0) { |
| 472 | cmd = CmdZen; | 472 | cmd = CmdZen; |
| 473 | } else if (strcmp(arg, "parseh") == 0) { | 473 | } else if (strcmp(arg, "parsec") == 0) { |
| 474 | cmd = CmdParseH; | 474 | cmd = CmdParseC; |
| 475 | } else if (strcmp(arg, "test") == 0) { | 475 | } else if (strcmp(arg, "test") == 0) { |
| 476 | cmd = CmdTest; | 476 | cmd = CmdTest; |
| 477 | out_type = OutTypeExe; | 477 | out_type = OutTypeExe; |
| ... | @@ -484,7 +484,7 @@ int main(int argc, char **argv) { | ... | @@ -484,7 +484,7 @@ int main(int argc, char **argv) { |
| 484 | } else { | 484 | } else { |
| 485 | switch (cmd) { | 485 | switch (cmd) { |
| 486 | case CmdBuild: | 486 | case CmdBuild: |
| 487 | case CmdParseH: | 487 | case CmdParseC: |
| 488 | case CmdTest: | 488 | case CmdTest: |
| 489 | if (!in_file) { | 489 | if (!in_file) { |
| 490 | in_file = arg; | 490 | in_file = arg; |
| ... | @@ -541,13 +541,13 @@ int main(int argc, char **argv) { | ... | @@ -541,13 +541,13 @@ int main(int argc, char **argv) { |
| 541 | 541 | ||
| 542 | switch (cmd) { | 542 | switch (cmd) { |
| 543 | case CmdBuild: | 543 | case CmdBuild: |
| 544 | case CmdParseH: | 544 | case CmdParseC: |
| 545 | case CmdTest: | 545 | case CmdTest: |
| 546 | { | 546 | { |
| 547 | if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) { | 547 | if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) { |
| 548 | fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n"); | 548 | fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n"); |
| 549 | return usage(arg0); | 549 | return usage(arg0); |
| 550 | } else if ((cmd == CmdParseH || cmd == CmdTest) && !in_file) { | 550 | } else if ((cmd == CmdParseC || cmd == CmdTest) && !in_file) { |
| 551 | fprintf(stderr, "Expected source file argument.\n"); | 551 | fprintf(stderr, "Expected source file argument.\n"); |
| 552 | return usage(arg0); | 552 | return usage(arg0); |
| 553 | } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) { | 553 | } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) { |
| ... | @@ -557,7 +557,7 @@ int main(int argc, char **argv) { | ... | @@ -557,7 +557,7 @@ int main(int argc, char **argv) { |
| 557 | 557 | ||
| 558 | assert(cmd != CmdBuild || out_type != OutTypeUnknown); | 558 | assert(cmd != CmdBuild || out_type != OutTypeUnknown); |
| 559 | 559 | ||
| 560 | bool need_name = (cmd == CmdBuild || cmd == CmdParseH); | 560 | bool need_name = (cmd == CmdBuild || cmd == CmdParseC); |
| 561 | 561 | ||
| 562 | Buf *in_file_buf = nullptr; | 562 | Buf *in_file_buf = nullptr; |
| 563 | 563 | ||
| ... | @@ -580,7 +580,7 @@ int main(int argc, char **argv) { | ... | @@ -580,7 +580,7 @@ int main(int argc, char **argv) { |
| 580 | return usage(arg0); | 580 | return usage(arg0); |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | Buf *zig_root_source_file = (cmd == CmdParseH) ? nullptr : in_file_buf; | 583 | Buf *zig_root_source_file = (cmd == CmdParseC) ? nullptr : in_file_buf; |
| 584 | 584 | ||
| 585 | Buf *full_cache_dir = buf_alloc(); | 585 | Buf *full_cache_dir = buf_alloc(); |
| 586 | os_path_resolve(buf_create_from_str("."), | 586 | os_path_resolve(buf_create_from_str("."), |
| ... | @@ -668,8 +668,8 @@ int main(int argc, char **argv) { | ... | @@ -668,8 +668,8 @@ int main(int argc, char **argv) { |
| 668 | if (timing_info) | 668 | if (timing_info) |
| 669 | codegen_print_timing_report(g, stdout); | 669 | codegen_print_timing_report(g, stdout); |
| 670 | return EXIT_SUCCESS; | 670 | return EXIT_SUCCESS; |
| 671 | } else if (cmd == CmdParseH) { | 671 | } else if (cmd == CmdParseC) { |
| 672 | codegen_parseh(g, in_file_buf); | 672 | codegen_parsec(g, in_file_buf); |
| 673 | ast_render(g, stdout, g->root_import->root, 4); | 673 | ast_render(g, stdout, g->root_import->root, 4); |
| 674 | if (timing_info) | 674 | if (timing_info) |
| 675 | codegen_print_timing_report(g, stdout); | 675 | codegen_print_timing_report(g, stdout); |
src/parsec.cpp created+2389| ... | @@ -0,0 +1,2389 @@ | ||
| 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 "all_types.hpp" | ||
| 9 | #include "analyze.hpp" | ||
| 10 | #include "c_tokenizer.hpp" | ||
| 11 | #include "config.h" | ||
| 12 | #include "error.hpp" | ||
| 13 | #include "ir.hpp" | ||
| 14 | #include "os.hpp" | ||
| 15 | #include "parsec.hpp" | ||
| 16 | #include "parser.hpp" | ||
| 17 | |||
| 18 | |||
| 19 | #include <clang/Frontend/ASTUnit.h> | ||
| 20 | #include <clang/Frontend/CompilerInstance.h> | ||
| 21 | #include <clang/AST/Expr.h> | ||
| 22 | |||
| 23 | #include <string.h> | ||
| 24 | |||
| 25 | using namespace clang; | ||
| 26 | |||
| 27 | struct MacroSymbol { | ||
| 28 | Buf *name; | ||
| 29 | Buf *value; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct Alias { | ||
| 33 | Buf *new_name; | ||
| 34 | Buf *canon_name; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct Context { | ||
| 38 | ImportTableEntry *import; | ||
| 39 | ZigList<ErrorMsg *> *errors; | ||
| 40 | bool warnings_on; | ||
| 41 | VisibMod visib_mod; | ||
| 42 | AstNode *root; | ||
| 43 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; | ||
| 44 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; | ||
| 45 | SourceManager *source_manager; | ||
| 46 | ZigList<Alias> aliases; | ||
| 47 | ZigList<MacroSymbol> macro_symbols; | ||
| 48 | AstNode *source_node; | ||
| 49 | |||
| 50 | CodeGen *codegen; | ||
| 51 | ASTContext *ctx; | ||
| 52 | }; | ||
| 53 | |||
| 54 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); | ||
| 55 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); | ||
| 56 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl); | ||
| 57 | static AstNode *trans_qual_type_with_table(Context *c, QualType qt, const SourceLocation &source_loc); | ||
| 58 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | ||
| 59 | |||
| 60 | |||
| 61 | __attribute__ ((format (printf, 3, 4))) | ||
| 62 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { | ||
| 63 | if (!c->warnings_on) { | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | |||
| 67 | va_list ap; | ||
| 68 | va_start(ap, format); | ||
| 69 | Buf *msg = buf_vprintf(format, ap); | ||
| 70 | va_end(ap); | ||
| 71 | |||
| 72 | StringRef filename = c->source_manager->getFilename(sl); | ||
| 73 | const char *filename_bytes = (const char *)filename.bytes_begin(); | ||
| 74 | Buf *path; | ||
| 75 | if (filename_bytes) { | ||
| 76 | path = buf_create_from_str(filename_bytes); | ||
| 77 | } else { | ||
| 78 | path = buf_sprintf("(no file)"); | ||
| 79 | } | ||
| 80 | unsigned line = c->source_manager->getSpellingLineNumber(sl); | ||
| 81 | unsigned column = c->source_manager->getSpellingColumnNumber(sl); | ||
| 82 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) { | ||
| 86 | Alias *alias = c->aliases.add_one(); | ||
| 87 | alias->new_name = new_name; | ||
| 88 | alias->canon_name = canon_name; | ||
| 89 | } | ||
| 90 | |||
| 91 | static AstNode * trans_create_node(Context *c, NodeType id) { | ||
| 92 | AstNode *node = allocate<AstNode>(1); | ||
| 93 | node->type = id; | ||
| 94 | node->owner = c->import; | ||
| 95 | // TODO line/column. mapping to C file?? | ||
| 96 | return node; | ||
| 97 | } | ||
| 98 | |||
| 99 | static AstNode *trans_create_node_float_lit(Context *c, double value) { | ||
| 100 | AstNode *node = trans_create_node(c, NodeTypeFloatLiteral); | ||
| 101 | node->data.float_literal.bigfloat = allocate<BigFloat>(1); | ||
| 102 | bigfloat_init_64(node->data.float_literal.bigfloat, value); | ||
| 103 | return node; | ||
| 104 | } | ||
| 105 | |||
| 106 | static AstNode *trans_create_node_symbol(Context *c, Buf *name) { | ||
| 107 | AstNode *node = trans_create_node(c, NodeTypeSymbol); | ||
| 108 | node->data.symbol_expr.symbol = name; | ||
| 109 | return node; | ||
| 110 | } | ||
| 111 | |||
| 112 | static AstNode *trans_create_node_symbol_str(Context *c, const char *name) { | ||
| 113 | return trans_create_node_symbol(c, buf_create_from_str(name)); | ||
| 114 | } | ||
| 115 | |||
| 116 | static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) { | ||
| 117 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); | ||
| 118 | node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name); | ||
| 119 | node->data.fn_call_expr.is_builtin = true; | ||
| 120 | return node; | ||
| 121 | } | ||
| 122 | |||
| 123 | static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *name) { | ||
| 124 | return trans_create_node_builtin_fn_call(c, buf_create_from_str(name)); | ||
| 125 | } | ||
| 126 | |||
| 127 | static AstNode *trans_create_node_opaque(Context *c) { | ||
| 128 | return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); | ||
| 129 | } | ||
| 130 | |||
| 131 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { | ||
| 132 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); | ||
| 133 | node->data.field_access_expr.struct_expr = container; | ||
| 134 | node->data.field_access_expr.field_name = field_name; | ||
| 135 | return node; | ||
| 136 | } | ||
| 137 | |||
| 138 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { | ||
| 139 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | ||
| 140 | node->data.prefix_op_expr.prefix_op = op; | ||
| 141 | node->data.prefix_op_expr.primary_expr = child_node; | ||
| 142 | return node; | ||
| 143 | } | ||
| 144 | |||
| 145 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { | ||
| 146 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); | ||
| 147 | node->data.addr_of_expr.is_const = is_const; | ||
| 148 | node->data.addr_of_expr.is_volatile = is_volatile; | ||
| 149 | node->data.addr_of_expr.op_expr = child_node; | ||
| 150 | return node; | ||
| 151 | } | ||
| 152 | |||
| 153 | static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { | ||
| 154 | AstNode *node = trans_create_node(c, NodeTypeStringLiteral); | ||
| 155 | node->data.string_literal.buf = buf; | ||
| 156 | node->data.string_literal.c = true; | ||
| 157 | return node; | ||
| 158 | } | ||
| 159 | |||
| 160 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { | ||
| 161 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); | ||
| 162 | node->data.int_literal.bigint = allocate<BigInt>(1); | ||
| 163 | bigint_init_data(node->data.int_literal.bigint, &x, 1, is_negative); | ||
| 164 | return node; | ||
| 165 | } | ||
| 166 | |||
| 167 | static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) { | ||
| 168 | return trans_create_node_unsigned_negative(c, x, false); | ||
| 169 | } | ||
| 170 | |||
| 171 | static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) { | ||
| 172 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); | ||
| 173 | node->data.fn_call_expr.fn_ref_expr = dest; | ||
| 174 | node->data.fn_call_expr.params.resize(1); | ||
| 175 | node->data.fn_call_expr.params.items[0] = src; | ||
| 176 | return node; | ||
| 177 | } | ||
| 178 | |||
| 179 | static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative, | ||
| 180 | const char *type_name) | ||
| 181 | { | ||
| 182 | AstNode *lit_node = trans_create_node_unsigned_negative(c, x, is_negative); | ||
| 183 | return trans_create_node_cast(c, trans_create_node_symbol_str(c, type_name), lit_node); | ||
| 184 | } | ||
| 185 | |||
| 186 | static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, AstNode *child_type_node) { | ||
| 187 | AstNode *node = trans_create_node(c, NodeTypeArrayType); | ||
| 188 | node->data.array_type.size = size_node; | ||
| 189 | node->data.array_type.child_type = child_type_node; | ||
| 190 | return node; | ||
| 191 | } | ||
| 192 | |||
| 193 | static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_name, AstNode *type_node, | ||
| 194 | AstNode *init_node) | ||
| 195 | { | ||
| 196 | AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration); | ||
| 197 | node->data.variable_declaration.visib_mod = c->visib_mod; | ||
| 198 | node->data.variable_declaration.symbol = var_name; | ||
| 199 | node->data.variable_declaration.is_const = is_const; | ||
| 200 | node->data.variable_declaration.type = type_node; | ||
| 201 | node->data.variable_declaration.expr = init_node; | ||
| 202 | return node; | ||
| 203 | } | ||
| 204 | |||
| 205 | |||
| 206 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { | ||
| 207 | AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); | ||
| 208 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); | ||
| 209 | fn_proto->data.fn_proto.visib_mod = c->visib_mod; | ||
| 210 | fn_proto->data.fn_proto.name = fn_name; | ||
| 211 | fn_proto->data.fn_proto.is_inline = true; | ||
| 212 | fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? | ||
| 213 | |||
| 214 | fn_def->data.fn_def.fn_proto = fn_proto; | ||
| 215 | fn_proto->data.fn_proto.fn_def_node = fn_def; | ||
| 216 | |||
| 217 | AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, trans_create_node_symbol(c, var_name)); | ||
| 218 | AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr); | ||
| 219 | fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; | ||
| 220 | |||
| 221 | for (size_t i = 0; i < src_proto_node->data.fn_proto.params.length; i += 1) { | ||
| 222 | AstNode *src_param_node = src_proto_node->data.fn_proto.params.at(i); | ||
| 223 | Buf *param_name = src_param_node->data.param_decl.name; | ||
| 224 | if (!param_name) param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i); | ||
| 225 | |||
| 226 | AstNode *dest_param_node = trans_create_node(c, NodeTypeParamDecl); | ||
| 227 | dest_param_node->data.param_decl.name = param_name; | ||
| 228 | dest_param_node->data.param_decl.type = src_param_node->data.param_decl.type; | ||
| 229 | dest_param_node->data.param_decl.is_noalias = src_param_node->data.param_decl.is_noalias; | ||
| 230 | fn_proto->data.fn_proto.params.append(dest_param_node); | ||
| 231 | |||
| 232 | fn_call_node->data.fn_call_expr.params.append(trans_create_node_symbol(c, param_name)); | ||
| 233 | |||
| 234 | } | ||
| 235 | |||
| 236 | AstNode *block = trans_create_node(c, NodeTypeBlock); | ||
| 237 | block->data.block.statements.resize(1); | ||
| 238 | block->data.block.statements.items[0] = fn_call_node; | ||
| 239 | block->data.block.last_statement_is_result_expression = true; | ||
| 240 | |||
| 241 | fn_def->data.fn_def.body = block; | ||
| 242 | return fn_def; | ||
| 243 | } | ||
| 244 | |||
| 245 | static AstNode *get_global(Context *c, Buf *name) { | ||
| 246 | for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) { | ||
| 247 | AstNode *decl_node = c->root->data.root.top_level_decls.items[i]; | ||
| 248 | if (decl_node->type == NodeTypeVariableDeclaration) { | ||
| 249 | if (buf_eql_buf(decl_node->data.variable_declaration.symbol, name)) { | ||
| 250 | return decl_node; | ||
| 251 | } | ||
| 252 | } else if (decl_node->type == NodeTypeFnDef) { | ||
| 253 | if (buf_eql_buf(decl_node->data.fn_def.fn_proto->data.fn_proto.name, name)) { | ||
| 254 | return decl_node; | ||
| 255 | } | ||
| 256 | } else if (decl_node->type == NodeTypeFnProto) { | ||
| 257 | if (buf_eql_buf(decl_node->data.fn_proto.name, name)) { | ||
| 258 | return decl_node; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | { | ||
| 263 | auto entry = c->macro_table.maybe_get(name); | ||
| 264 | if (entry) | ||
| 265 | return entry->value; | ||
| 266 | } | ||
| 267 | return nullptr; | ||
| 268 | } | ||
| 269 | |||
| 270 | static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) { | ||
| 271 | bool is_const = true; | ||
| 272 | AstNode *type_node = nullptr; | ||
| 273 | AstNode *node = trans_create_node_var_decl(c, is_const, var_name, type_node, value_node); | ||
| 274 | c->root->data.root.top_level_decls.append(node); | ||
| 275 | return node; | ||
| 276 | } | ||
| 277 | |||
| 278 | static const char *decl_name(const Decl *decl) { | ||
| 279 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); | ||
| 280 | return (const char *)named_decl->getName().bytes_begin(); | ||
| 281 | } | ||
| 282 | |||
| 283 | static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { | ||
| 284 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); | ||
| 285 | node->data.int_literal.bigint = allocate<BigInt>(1); | ||
| 286 | bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative()); | ||
| 287 | return node; | ||
| 288 | |||
| 289 | } | ||
| 290 | |||
| 291 | static bool is_c_void_type(AstNode *node) { | ||
| 292 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); | ||
| 293 | } | ||
| 294 | |||
| 295 | static bool qual_type_child_is_fn_proto(const QualType &qt) { | ||
| 296 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { | ||
| 297 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); | ||
| 298 | if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) { | ||
| 299 | return true; | ||
| 300 | } | ||
| 301 | } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) { | ||
| 302 | const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr()); | ||
| 303 | return qual_type_child_is_fn_proto(attr_type->getEquivalentType()); | ||
| 304 | } | ||
| 305 | return false; | ||
| 306 | } | ||
| 307 | |||
| 308 | static bool c_is_signed_integer(Context *c, QualType qt) { | ||
| 309 | const Type *c_type = qt.getTypePtr(); | ||
| 310 | if (c_type->getTypeClass() != Type::Builtin) | ||
| 311 | return false; | ||
| 312 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | ||
| 313 | switch (builtin_ty->getKind()) { | ||
| 314 | case BuiltinType::SChar: | ||
| 315 | case BuiltinType::Short: | ||
| 316 | case BuiltinType::Int: | ||
| 317 | case BuiltinType::Long: | ||
| 318 | case BuiltinType::LongLong: | ||
| 319 | case BuiltinType::Int128: | ||
| 320 | case BuiltinType::WChar_S: | ||
| 321 | return true; | ||
| 322 | default: | ||
| 323 | return false; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | static bool c_is_unsigned_integer(Context *c, QualType qt) { | ||
| 328 | const Type *c_type = qt.getTypePtr(); | ||
| 329 | if (c_type->getTypeClass() != Type::Builtin) | ||
| 330 | return false; | ||
| 331 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | ||
| 332 | switch (builtin_ty->getKind()) { | ||
| 333 | case BuiltinType::Char_U: | ||
| 334 | case BuiltinType::UChar: | ||
| 335 | case BuiltinType::Char_S: | ||
| 336 | case BuiltinType::UShort: | ||
| 337 | case BuiltinType::UInt: | ||
| 338 | case BuiltinType::ULong: | ||
| 339 | case BuiltinType::ULongLong: | ||
| 340 | case BuiltinType::UInt128: | ||
| 341 | case BuiltinType::WChar_U: | ||
| 342 | return true; | ||
| 343 | default: | ||
| 344 | return false; | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | static bool c_is_float(Context *c, QualType qt) { | ||
| 349 | const Type *c_type = qt.getTypePtr(); | ||
| 350 | if (c_type->getTypeClass() != Type::Builtin) | ||
| 351 | return false; | ||
| 352 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | ||
| 353 | switch (builtin_ty->getKind()) { | ||
| 354 | case BuiltinType::Half: | ||
| 355 | case BuiltinType::Float: | ||
| 356 | case BuiltinType::Double: | ||
| 357 | case BuiltinType::Float128: | ||
| 358 | case BuiltinType::LongDouble: | ||
| 359 | return true; | ||
| 360 | default: | ||
| 361 | return false; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | static AstNode * trans_stmt(Context *c, AstNode *block, Stmt *stmt); | ||
| 366 | static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | ||
| 367 | |||
| 368 | static AstNode * trans_expr(Context *c, AstNode *block, Expr *expr) { | ||
| 369 | return trans_stmt(c, block, expr); | ||
| 370 | } | ||
| 371 | |||
| 372 | static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLocation &source_loc) { | ||
| 373 | switch (ty->getTypeClass()) { | ||
| 374 | case Type::Builtin: | ||
| 375 | { | ||
| 376 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | ||
| 377 | switch (builtin_ty->getKind()) { | ||
| 378 | case BuiltinType::Void: | ||
| 379 | return trans_create_node_symbol_str(c, "c_void"); | ||
| 380 | case BuiltinType::Bool: | ||
| 381 | return trans_create_node_symbol_str(c, "bool"); | ||
| 382 | case BuiltinType::Char_U: | ||
| 383 | case BuiltinType::UChar: | ||
| 384 | case BuiltinType::Char_S: | ||
| 385 | return trans_create_node_symbol_str(c, "u8"); | ||
| 386 | case BuiltinType::SChar: | ||
| 387 | return trans_create_node_symbol_str(c, "i8"); | ||
| 388 | case BuiltinType::UShort: | ||
| 389 | return trans_create_node_symbol_str(c, "c_ushort"); | ||
| 390 | case BuiltinType::UInt: | ||
| 391 | return trans_create_node_symbol_str(c, "c_uint"); | ||
| 392 | case BuiltinType::ULong: | ||
| 393 | return trans_create_node_symbol_str(c, "c_ulong"); | ||
| 394 | case BuiltinType::ULongLong: | ||
| 395 | return trans_create_node_symbol_str(c, "c_ulonglong"); | ||
| 396 | case BuiltinType::Short: | ||
| 397 | return trans_create_node_symbol_str(c, "c_short"); | ||
| 398 | case BuiltinType::Int: | ||
| 399 | return trans_create_node_symbol_str(c, "c_int"); | ||
| 400 | case BuiltinType::Long: | ||
| 401 | return trans_create_node_symbol_str(c, "c_long"); | ||
| 402 | case BuiltinType::LongLong: | ||
| 403 | return trans_create_node_symbol_str(c, "c_longlong"); | ||
| 404 | case BuiltinType::UInt128: | ||
| 405 | return trans_create_node_symbol_str(c, "u128"); | ||
| 406 | case BuiltinType::Int128: | ||
| 407 | return trans_create_node_symbol_str(c, "i128"); | ||
| 408 | case BuiltinType::Float: | ||
| 409 | return trans_create_node_symbol_str(c, "f32"); | ||
| 410 | case BuiltinType::Double: | ||
| 411 | return trans_create_node_symbol_str(c, "f64"); | ||
| 412 | case BuiltinType::Float128: | ||
| 413 | return trans_create_node_symbol_str(c, "f128"); | ||
| 414 | case BuiltinType::LongDouble: | ||
| 415 | return trans_create_node_symbol_str(c, "c_longdouble"); | ||
| 416 | case BuiltinType::WChar_U: | ||
| 417 | case BuiltinType::Char16: | ||
| 418 | case BuiltinType::Char32: | ||
| 419 | case BuiltinType::WChar_S: | ||
| 420 | case BuiltinType::Half: | ||
| 421 | case BuiltinType::NullPtr: | ||
| 422 | case BuiltinType::ObjCId: | ||
| 423 | case BuiltinType::ObjCClass: | ||
| 424 | case BuiltinType::ObjCSel: | ||
| 425 | case BuiltinType::OMPArraySection: | ||
| 426 | case BuiltinType::Dependent: | ||
| 427 | case BuiltinType::Overload: | ||
| 428 | case BuiltinType::BoundMember: | ||
| 429 | case BuiltinType::PseudoObject: | ||
| 430 | case BuiltinType::UnknownAny: | ||
| 431 | case BuiltinType::BuiltinFn: | ||
| 432 | case BuiltinType::ARCUnbridgedCast: | ||
| 433 | |||
| 434 | case BuiltinType::OCLImage1dRO: | ||
| 435 | case BuiltinType::OCLImage1dArrayRO: | ||
| 436 | case BuiltinType::OCLImage1dBufferRO: | ||
| 437 | case BuiltinType::OCLImage2dRO: | ||
| 438 | case BuiltinType::OCLImage2dArrayRO: | ||
| 439 | case BuiltinType::OCLImage2dDepthRO: | ||
| 440 | case BuiltinType::OCLImage2dArrayDepthRO: | ||
| 441 | case BuiltinType::OCLImage2dMSAARO: | ||
| 442 | case BuiltinType::OCLImage2dArrayMSAARO: | ||
| 443 | case BuiltinType::OCLImage2dMSAADepthRO: | ||
| 444 | case BuiltinType::OCLImage2dArrayMSAADepthRO: | ||
| 445 | case BuiltinType::OCLImage3dRO: | ||
| 446 | case BuiltinType::OCLImage1dWO: | ||
| 447 | case BuiltinType::OCLImage1dArrayWO: | ||
| 448 | case BuiltinType::OCLImage1dBufferWO: | ||
| 449 | case BuiltinType::OCLImage2dWO: | ||
| 450 | case BuiltinType::OCLImage2dArrayWO: | ||
| 451 | case BuiltinType::OCLImage2dDepthWO: | ||
| 452 | case BuiltinType::OCLImage2dArrayDepthWO: | ||
| 453 | case BuiltinType::OCLImage2dMSAAWO: | ||
| 454 | case BuiltinType::OCLImage2dArrayMSAAWO: | ||
| 455 | case BuiltinType::OCLImage2dMSAADepthWO: | ||
| 456 | case BuiltinType::OCLImage2dArrayMSAADepthWO: | ||
| 457 | case BuiltinType::OCLImage3dWO: | ||
| 458 | case BuiltinType::OCLImage1dRW: | ||
| 459 | case BuiltinType::OCLImage1dArrayRW: | ||
| 460 | case BuiltinType::OCLImage1dBufferRW: | ||
| 461 | case BuiltinType::OCLImage2dRW: | ||
| 462 | case BuiltinType::OCLImage2dArrayRW: | ||
| 463 | case BuiltinType::OCLImage2dDepthRW: | ||
| 464 | case BuiltinType::OCLImage2dArrayDepthRW: | ||
| 465 | case BuiltinType::OCLImage2dMSAARW: | ||
| 466 | case BuiltinType::OCLImage2dArrayMSAARW: | ||
| 467 | case BuiltinType::OCLImage2dMSAADepthRW: | ||
| 468 | case BuiltinType::OCLImage2dArrayMSAADepthRW: | ||
| 469 | case BuiltinType::OCLImage3dRW: | ||
| 470 | case BuiltinType::OCLSampler: | ||
| 471 | case BuiltinType::OCLEvent: | ||
| 472 | case BuiltinType::OCLClkEvent: | ||
| 473 | case BuiltinType::OCLQueue: | ||
| 474 | case BuiltinType::OCLReserveID: | ||
| 475 | emit_warning(c, source_loc, "unsupported builtin type"); | ||
| 476 | return nullptr; | ||
| 477 | } | ||
| 478 | break; | ||
| 479 | } | ||
| 480 | case Type::Pointer: | ||
| 481 | { | ||
| 482 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | ||
| 483 | QualType child_qt = pointer_ty->getPointeeType(); | ||
| 484 | AstNode *child_node = trans_qual_type(c, child_qt, source_loc); | ||
| 485 | if (child_node == nullptr) { | ||
| 486 | emit_warning(c, source_loc, "pointer to unsupported type"); | ||
| 487 | return nullptr; | ||
| 488 | } | ||
| 489 | |||
| 490 | if (qual_type_child_is_fn_proto(child_qt)) { | ||
| 491 | return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node); | ||
| 492 | } | ||
| 493 | |||
| 494 | AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(), | ||
| 495 | child_qt.isVolatileQualified(), child_node); | ||
| 496 | return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node); | ||
| 497 | } | ||
| 498 | case Type::Typedef: | ||
| 499 | { | ||
| 500 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | ||
| 501 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | ||
| 502 | return resolve_typedef_decl(c, typedef_decl); | ||
| 503 | } | ||
| 504 | case Type::Elaborated: | ||
| 505 | { | ||
| 506 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | ||
| 507 | switch (elaborated_ty->getKeyword()) { | ||
| 508 | case ETK_Struct: | ||
| 509 | return trans_qual_type_with_table(c, elaborated_ty->getNamedType(), source_loc); | ||
| 510 | case ETK_Enum: | ||
| 511 | return trans_qual_type_with_table(c, elaborated_ty->getNamedType(), source_loc); | ||
| 512 | case ETK_Interface: | ||
| 513 | case ETK_Union: | ||
| 514 | case ETK_Class: | ||
| 515 | case ETK_Typename: | ||
| 516 | case ETK_None: | ||
| 517 | emit_warning(c, source_loc, "unsupported elaborated type"); | ||
| 518 | return nullptr; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | case Type::FunctionProto: | ||
| 522 | { | ||
| 523 | const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty); | ||
| 524 | |||
| 525 | AstNode *proto_node = trans_create_node(c, NodeTypeFnProto); | ||
| 526 | switch (fn_proto_ty->getCallConv()) { | ||
| 527 | case CC_C: // __attribute__((cdecl)) | ||
| 528 | proto_node->data.fn_proto.cc = CallingConventionC; | ||
| 529 | proto_node->data.fn_proto.is_extern = true; | ||
| 530 | break; | ||
| 531 | case CC_X86StdCall: // __attribute__((stdcall)) | ||
| 532 | proto_node->data.fn_proto.cc = CallingConventionStdcall; | ||
| 533 | break; | ||
| 534 | case CC_X86FastCall: // __attribute__((fastcall)) | ||
| 535 | emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall"); | ||
| 536 | return nullptr; | ||
| 537 | case CC_X86ThisCall: // __attribute__((thiscall)) | ||
| 538 | emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall"); | ||
| 539 | return nullptr; | ||
| 540 | case CC_X86VectorCall: // __attribute__((vectorcall)) | ||
| 541 | emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall"); | ||
| 542 | return nullptr; | ||
| 543 | case CC_X86Pascal: // __attribute__((pascal)) | ||
| 544 | emit_warning(c, source_loc, "unsupported calling convention: x86 pascal"); | ||
| 545 | return nullptr; | ||
| 546 | case CC_Win64: // __attribute__((ms_abi)) | ||
| 547 | emit_warning(c, source_loc, "unsupported calling convention: win64"); | ||
| 548 | return nullptr; | ||
| 549 | case CC_X86_64SysV: // __attribute__((sysv_abi)) | ||
| 550 | emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv"); | ||
| 551 | return nullptr; | ||
| 552 | case CC_X86RegCall: | ||
| 553 | emit_warning(c, source_loc, "unsupported calling convention: x86 reg"); | ||
| 554 | return nullptr; | ||
| 555 | case CC_AAPCS: // __attribute__((pcs("aapcs"))) | ||
| 556 | emit_warning(c, source_loc, "unsupported calling convention: aapcs"); | ||
| 557 | return nullptr; | ||
| 558 | case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) | ||
| 559 | emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp"); | ||
| 560 | return nullptr; | ||
| 561 | case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) | ||
| 562 | emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc"); | ||
| 563 | return nullptr; | ||
| 564 | case CC_SpirFunction: // default for OpenCL functions on SPIR target | ||
| 565 | emit_warning(c, source_loc, "unsupported calling convention: SPIR function"); | ||
| 566 | return nullptr; | ||
| 567 | case CC_OpenCLKernel: | ||
| 568 | emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel"); | ||
| 569 | return nullptr; | ||
| 570 | case CC_Swift: | ||
| 571 | emit_warning(c, source_loc, "unsupported calling convention: Swift"); | ||
| 572 | return nullptr; | ||
| 573 | case CC_PreserveMost: | ||
| 574 | emit_warning(c, source_loc, "unsupported calling convention: PreserveMost"); | ||
| 575 | return nullptr; | ||
| 576 | case CC_PreserveAll: | ||
| 577 | emit_warning(c, source_loc, "unsupported calling convention: PreserveAll"); | ||
| 578 | return nullptr; | ||
| 579 | } | ||
| 580 | |||
| 581 | proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic(); | ||
| 582 | size_t param_count = fn_proto_ty->getNumParams(); | ||
| 583 | |||
| 584 | if (fn_proto_ty->getNoReturnAttr()) { | ||
| 585 | proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn"); | ||
| 586 | } else { | ||
| 587 | proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(), | ||
| 588 | source_loc); | ||
| 589 | if (proto_node->data.fn_proto.return_type == nullptr) { | ||
| 590 | emit_warning(c, source_loc, "unsupported function proto return type"); | ||
| 591 | return nullptr; | ||
| 592 | } | ||
| 593 | // convert c_void to actual void (only for return type) | ||
| 594 | if (is_c_void_type(proto_node->data.fn_proto.return_type)) { | ||
| 595 | proto_node->data.fn_proto.return_type = nullptr; | ||
| 596 | } | ||
| 597 | } | ||
| 598 | |||
| 599 | //emit_warning(c, source_loc, "TODO figure out fn prototype fn name"); | ||
| 600 | const char *fn_name = nullptr; | ||
| 601 | if (fn_name != nullptr) { | ||
| 602 | proto_node->data.fn_proto.name = buf_create_from_str(fn_name); | ||
| 603 | } | ||
| 604 | |||
| 605 | for (size_t i = 0; i < param_count; i += 1) { | ||
| 606 | QualType qt = fn_proto_ty->getParamType(i); | ||
| 607 | AstNode *param_type_node = trans_qual_type(c, qt, source_loc); | ||
| 608 | |||
| 609 | if (param_type_node == nullptr) { | ||
| 610 | emit_warning(c, source_loc, "unresolved function proto parameter type"); | ||
| 611 | return nullptr; | ||
| 612 | } | ||
| 613 | |||
| 614 | AstNode *param_node = trans_create_node(c, NodeTypeParamDecl); | ||
| 615 | //emit_warning(c, source_loc, "TODO figure out fn prototype param name"); | ||
| 616 | const char *param_name = nullptr; | ||
| 617 | if (param_name != nullptr) { | ||
| 618 | param_node->data.param_decl.name = buf_create_from_str(param_name); | ||
| 619 | } | ||
| 620 | param_node->data.param_decl.is_noalias = qt.isRestrictQualified(); | ||
| 621 | param_node->data.param_decl.type = param_type_node; | ||
| 622 | proto_node->data.fn_proto.params.append(param_node); | ||
| 623 | } | ||
| 624 | // TODO check for always_inline attribute | ||
| 625 | // TODO check for align attribute | ||
| 626 | |||
| 627 | return proto_node; | ||
| 628 | } | ||
| 629 | case Type::Record: | ||
| 630 | { | ||
| 631 | const RecordType *record_ty = static_cast<const RecordType*>(ty); | ||
| 632 | return resolve_record_decl(c, record_ty->getDecl()); | ||
| 633 | } | ||
| 634 | case Type::Enum: | ||
| 635 | { | ||
| 636 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); | ||
| 637 | return resolve_enum_decl(c, enum_ty->getDecl()); | ||
| 638 | } | ||
| 639 | case Type::ConstantArray: | ||
| 640 | { | ||
| 641 | const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty); | ||
| 642 | AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc); | ||
| 643 | if (child_type_node == nullptr) { | ||
| 644 | emit_warning(c, source_loc, "unresolved array element type"); | ||
| 645 | return nullptr; | ||
| 646 | } | ||
| 647 | uint64_t size = const_arr_ty->getSize().getLimitedValue(); | ||
| 648 | AstNode *size_node = trans_create_node_unsigned(c, size); | ||
| 649 | return trans_create_node_array_type(c, size_node, child_type_node); | ||
| 650 | } | ||
| 651 | case Type::Paren: | ||
| 652 | { | ||
| 653 | const ParenType *paren_ty = static_cast<const ParenType *>(ty); | ||
| 654 | return trans_qual_type(c, paren_ty->getInnerType(), source_loc); | ||
| 655 | } | ||
| 656 | case Type::Decayed: | ||
| 657 | { | ||
| 658 | const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty); | ||
| 659 | return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc); | ||
| 660 | } | ||
| 661 | case Type::Attributed: | ||
| 662 | { | ||
| 663 | const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty); | ||
| 664 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); | ||
| 665 | } | ||
| 666 | case Type::BlockPointer: | ||
| 667 | case Type::LValueReference: | ||
| 668 | case Type::RValueReference: | ||
| 669 | case Type::MemberPointer: | ||
| 670 | case Type::IncompleteArray: | ||
| 671 | case Type::VariableArray: | ||
| 672 | case Type::DependentSizedArray: | ||
| 673 | case Type::DependentSizedExtVector: | ||
| 674 | case Type::Vector: | ||
| 675 | case Type::ExtVector: | ||
| 676 | case Type::FunctionNoProto: | ||
| 677 | case Type::UnresolvedUsing: | ||
| 678 | case Type::Adjusted: | ||
| 679 | case Type::TypeOfExpr: | ||
| 680 | case Type::TypeOf: | ||
| 681 | case Type::Decltype: | ||
| 682 | case Type::UnaryTransform: | ||
| 683 | case Type::TemplateTypeParm: | ||
| 684 | case Type::SubstTemplateTypeParm: | ||
| 685 | case Type::SubstTemplateTypeParmPack: | ||
| 686 | case Type::TemplateSpecialization: | ||
| 687 | case Type::Auto: | ||
| 688 | case Type::InjectedClassName: | ||
| 689 | case Type::DependentName: | ||
| 690 | case Type::DependentTemplateSpecialization: | ||
| 691 | case Type::PackExpansion: | ||
| 692 | case Type::ObjCObject: | ||
| 693 | case Type::ObjCInterface: | ||
| 694 | case Type::Complex: | ||
| 695 | case Type::ObjCObjectPointer: | ||
| 696 | case Type::Atomic: | ||
| 697 | case Type::Pipe: | ||
| 698 | case Type::ObjCTypeParam: | ||
| 699 | case Type::DeducedTemplateSpecialization: | ||
| 700 | emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName()); | ||
| 701 | return nullptr; | ||
| 702 | } | ||
| 703 | zig_unreachable(); | ||
| 704 | } | ||
| 705 | |||
| 706 | static AstNode * trans_qual_type_with_table(Context *c, QualType qt, const SourceLocation &source_loc) { | ||
| 707 | return trans_type_with_table(c, qt.getTypePtr(), source_loc); | ||
| 708 | } | ||
| 709 | |||
| 710 | static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) { | ||
| 711 | return trans_qual_type_with_table(c, qt, source_loc); | ||
| 712 | } | ||
| 713 | |||
| 714 | static AstNode * trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { | ||
| 715 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | ||
| 716 | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | ||
| 717 | AstNode *child_node = trans_stmt(c, child_block, *it); | ||
| 718 | if (child_node != nullptr) | ||
| 719 | child_block->data.block.statements.append(child_node); | ||
| 720 | } | ||
| 721 | return child_block; | ||
| 722 | } | ||
| 723 | |||
| 724 | static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) { | ||
| 725 | Expr *value_expr = stmt->getRetValue(); | ||
| 726 | if (value_expr == nullptr) { | ||
| 727 | zig_panic("TODO handle C return void"); | ||
| 728 | } else { | ||
| 729 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); | ||
| 730 | return_node->data.return_expr.expr = trans_expr(c, block, value_expr); | ||
| 731 | return return_node; | ||
| 732 | } | ||
| 733 | } | ||
| 734 | |||
| 735 | static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { | ||
| 736 | llvm::APSInt result; | ||
| 737 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { | ||
| 738 | zig_panic("TODO handle libclang unable to evaluate C integer literal"); | ||
| 739 | } | ||
| 740 | return trans_create_node_apint(c, result); | ||
| 741 | } | ||
| 742 | |||
| 743 | static AstNode *trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) { | ||
| 744 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); | ||
| 745 | |||
| 746 | Expr *cond_expr = stmt->getCond(); | ||
| 747 | Expr *true_expr = stmt->getTrueExpr(); | ||
| 748 | Expr *false_expr = stmt->getFalseExpr(); | ||
| 749 | |||
| 750 | node->data.if_bool_expr.condition = trans_expr(c, block, cond_expr); | ||
| 751 | node->data.if_bool_expr.then_block = trans_expr(c, block, true_expr); | ||
| 752 | node->data.if_bool_expr.else_node = trans_expr(c, block, false_expr); | ||
| 753 | |||
| 754 | return node; | ||
| 755 | } | ||
| 756 | |||
| 757 | static AstNode * trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) { | ||
| 758 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | ||
| 759 | node->data.bin_op_expr.bin_op = bin_op; | ||
| 760 | node->data.bin_op_expr.op1 = trans_expr(c, block, lhs); | ||
| 761 | node->data.bin_op_expr.op2 = trans_expr(c, block, rhs); | ||
| 762 | return node; | ||
| 763 | } | ||
| 764 | |||
| 765 | static AstNode * trans_binary_operator(Context *c, AstNode *block, BinaryOperator *stmt) { | ||
| 766 | switch (stmt->getOpcode()) { | ||
| 767 | case BO_PtrMemD: | ||
| 768 | zig_panic("TODO handle more C binary operators: BO_PtrMemD"); | ||
| 769 | case BO_PtrMemI: | ||
| 770 | zig_panic("TODO handle more C binary operators: BO_PtrMemI"); | ||
| 771 | case BO_Mul: | ||
| 772 | zig_panic("TODO handle more C binary operators: BO_Mul"); | ||
| 773 | case BO_Div: | ||
| 774 | zig_panic("TODO handle more C binary operators: BO_Div"); | ||
| 775 | case BO_Rem: | ||
| 776 | zig_panic("TODO handle more C binary operators: BO_Rem"); | ||
| 777 | case BO_Add: | ||
| 778 | zig_panic("TODO handle more C binary operators: BO_Add"); | ||
| 779 | case BO_Sub: | ||
| 780 | zig_panic("TODO handle more C binary operators: BO_Sub"); | ||
| 781 | case BO_Shl: | ||
| 782 | zig_panic("TODO handle more C binary operators: BO_Shl"); | ||
| 783 | case BO_Shr: | ||
| 784 | zig_panic("TODO handle more C binary operators: BO_Shr"); | ||
| 785 | case BO_LT: | ||
| 786 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); | ||
| 787 | case BO_GT: | ||
| 788 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); | ||
| 789 | case BO_LE: | ||
| 790 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); | ||
| 791 | case BO_GE: | ||
| 792 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); | ||
| 793 | case BO_EQ: | ||
| 794 | zig_panic("TODO handle more C binary operators: BO_EQ"); | ||
| 795 | case BO_NE: | ||
| 796 | zig_panic("TODO handle more C binary operators: BO_NE"); | ||
| 797 | case BO_And: | ||
| 798 | zig_panic("TODO handle more C binary operators: BO_And"); | ||
| 799 | case BO_Xor: | ||
| 800 | zig_panic("TODO handle more C binary operators: BO_Xor"); | ||
| 801 | case BO_Or: | ||
| 802 | zig_panic("TODO handle more C binary operators: BO_Or"); | ||
| 803 | case BO_LAnd: | ||
| 804 | zig_panic("TODO handle more C binary operators: BO_LAnd"); | ||
| 805 | case BO_LOr: | ||
| 806 | zig_panic("TODO handle more C binary operators: BO_LOr"); | ||
| 807 | case BO_Assign: | ||
| 808 | zig_panic("TODO handle more C binary operators: BO_Assign"); | ||
| 809 | case BO_MulAssign: | ||
| 810 | zig_panic("TODO handle more C binary operators: BO_MulAssign"); | ||
| 811 | case BO_DivAssign: | ||
| 812 | zig_panic("TODO handle more C binary operators: BO_DivAssign"); | ||
| 813 | case BO_RemAssign: | ||
| 814 | zig_panic("TODO handle more C binary operators: BO_RemAssign"); | ||
| 815 | case BO_AddAssign: | ||
| 816 | zig_panic("TODO handle more C binary operators: BO_AddAssign"); | ||
| 817 | case BO_SubAssign: | ||
| 818 | zig_panic("TODO handle more C binary operators: BO_SubAssign"); | ||
| 819 | case BO_ShlAssign: | ||
| 820 | zig_panic("TODO handle more C binary operators: BO_ShlAssign"); | ||
| 821 | case BO_ShrAssign: | ||
| 822 | zig_panic("TODO handle more C binary operators: BO_ShrAssign"); | ||
| 823 | case BO_AndAssign: | ||
| 824 | zig_panic("TODO handle more C binary operators: BO_AndAssign"); | ||
| 825 | case BO_XorAssign: | ||
| 826 | zig_panic("TODO handle more C binary operators: BO_XorAssign"); | ||
| 827 | case BO_OrAssign: | ||
| 828 | zig_panic("TODO handle more C binary operators: BO_OrAssign"); | ||
| 829 | case BO_Comma: | ||
| 830 | zig_panic("TODO handle more C binary operators: BO_Comma"); | ||
| 831 | } | ||
| 832 | |||
| 833 | zig_unreachable(); | ||
| 834 | } | ||
| 835 | |||
| 836 | static AstNode * trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { | ||
| 837 | switch (stmt->getCastKind()) { | ||
| 838 | case CK_LValueToRValue: | ||
| 839 | return trans_expr(c, block, stmt->getSubExpr()); | ||
| 840 | case CK_IntegralCast: | ||
| 841 | { | ||
| 842 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast"); | ||
| 843 | node->data.fn_call_expr.params.append(trans_qual_type(c, stmt->getType(), stmt->getExprLoc())); | ||
| 844 | node->data.fn_call_expr.params.append(trans_expr(c, block, stmt->getSubExpr())); | ||
| 845 | return node; | ||
| 846 | } | ||
| 847 | case CK_Dependent: | ||
| 848 | zig_panic("TODO handle C translation cast CK_Dependent"); | ||
| 849 | case CK_BitCast: | ||
| 850 | zig_panic("TODO handle C translation cast CK_BitCast"); | ||
| 851 | case CK_LValueBitCast: | ||
| 852 | zig_panic("TODO handle C translation cast CK_LValueBitCast"); | ||
| 853 | case CK_NoOp: | ||
| 854 | zig_panic("TODO handle C translation cast CK_NoOp"); | ||
| 855 | case CK_BaseToDerived: | ||
| 856 | zig_panic("TODO handle C translation cast CK_BaseToDerived"); | ||
| 857 | case CK_DerivedToBase: | ||
| 858 | zig_panic("TODO handle C translation cast CK_DerivedToBase"); | ||
| 859 | case CK_UncheckedDerivedToBase: | ||
| 860 | zig_panic("TODO handle C translation cast CK_UncheckedDerivedToBase"); | ||
| 861 | case CK_Dynamic: | ||
| 862 | zig_panic("TODO handle C translation cast CK_Dynamic"); | ||
| 863 | case CK_ToUnion: | ||
| 864 | zig_panic("TODO handle C translation cast CK_ToUnion"); | ||
| 865 | case CK_ArrayToPointerDecay: | ||
| 866 | zig_panic("TODO handle C translation cast CK_ArrayToPointerDecay"); | ||
| 867 | case CK_FunctionToPointerDecay: | ||
| 868 | zig_panic("TODO handle C translation cast CK_FunctionToPointerDecay"); | ||
| 869 | case CK_NullToPointer: | ||
| 870 | zig_panic("TODO handle C translation cast CK_NullToPointer"); | ||
| 871 | case CK_NullToMemberPointer: | ||
| 872 | zig_panic("TODO handle C translation cast CK_NullToMemberPointer"); | ||
| 873 | case CK_BaseToDerivedMemberPointer: | ||
| 874 | zig_panic("TODO handle C translation cast CK_BaseToDerivedMemberPointer"); | ||
| 875 | case CK_DerivedToBaseMemberPointer: | ||
| 876 | zig_panic("TODO handle C translation cast CK_DerivedToBaseMemberPointer"); | ||
| 877 | case CK_MemberPointerToBoolean: | ||
| 878 | zig_panic("TODO handle C translation cast CK_MemberPointerToBoolean"); | ||
| 879 | case CK_ReinterpretMemberPointer: | ||
| 880 | zig_panic("TODO handle C translation cast CK_ReinterpretMemberPointer"); | ||
| 881 | case CK_UserDefinedConversion: | ||
| 882 | zig_panic("TODO handle C translation cast CK_UserDefinedConversion"); | ||
| 883 | case CK_ConstructorConversion: | ||
| 884 | zig_panic("TODO handle C translation cast CK_ConstructorConversion"); | ||
| 885 | case CK_IntegralToPointer: | ||
| 886 | zig_panic("TODO handle C translation cast CK_IntegralToPointer"); | ||
| 887 | case CK_PointerToIntegral: | ||
| 888 | zig_panic("TODO handle C translation cast CK_PointerToIntegral"); | ||
| 889 | case CK_PointerToBoolean: | ||
| 890 | zig_panic("TODO handle C translation cast CK_PointerToBoolean"); | ||
| 891 | case CK_ToVoid: | ||
| 892 | zig_panic("TODO handle C translation cast CK_ToVoid"); | ||
| 893 | case CK_VectorSplat: | ||
| 894 | zig_panic("TODO handle C translation cast CK_VectorSplat"); | ||
| 895 | case CK_IntegralToBoolean: | ||
| 896 | zig_panic("TODO handle C translation cast CK_IntegralToBoolean"); | ||
| 897 | case CK_IntegralToFloating: | ||
| 898 | zig_panic("TODO handle C translation cast CK_IntegralToFloating"); | ||
| 899 | case CK_FloatingToIntegral: | ||
| 900 | zig_panic("TODO handle C translation cast CK_FloatingToIntegral"); | ||
| 901 | case CK_FloatingToBoolean: | ||
| 902 | zig_panic("TODO handle C translation cast CK_FloatingToBoolean"); | ||
| 903 | case CK_BooleanToSignedIntegral: | ||
| 904 | zig_panic("TODO handle C translation cast CK_BooleanToSignedIntegral"); | ||
| 905 | case CK_FloatingCast: | ||
| 906 | zig_panic("TODO handle C translation cast CK_FloatingCast"); | ||
| 907 | case CK_CPointerToObjCPointerCast: | ||
| 908 | zig_panic("TODO handle C translation cast CK_CPointerToObjCPointerCast"); | ||
| 909 | case CK_BlockPointerToObjCPointerCast: | ||
| 910 | zig_panic("TODO handle C translation cast CK_BlockPointerToObjCPointerCast"); | ||
| 911 | case CK_AnyPointerToBlockPointerCast: | ||
| 912 | zig_panic("TODO handle C translation cast CK_AnyPointerToBlockPointerCast"); | ||
| 913 | case CK_ObjCObjectLValueCast: | ||
| 914 | zig_panic("TODO handle C translation cast CK_ObjCObjectLValueCast"); | ||
| 915 | case CK_FloatingRealToComplex: | ||
| 916 | zig_panic("TODO handle C translation cast CK_FloatingRealToComplex"); | ||
| 917 | case CK_FloatingComplexToReal: | ||
| 918 | zig_panic("TODO handle C translation cast CK_FloatingComplexToReal"); | ||
| 919 | case CK_FloatingComplexToBoolean: | ||
| 920 | zig_panic("TODO handle C translation cast CK_FloatingComplexToBoolean"); | ||
| 921 | case CK_FloatingComplexCast: | ||
| 922 | zig_panic("TODO handle C translation cast CK_FloatingComplexCast"); | ||
| 923 | case CK_FloatingComplexToIntegralComplex: | ||
| 924 | zig_panic("TODO handle C translation cast CK_FloatingComplexToIntegralComplex"); | ||
| 925 | case CK_IntegralRealToComplex: | ||
| 926 | zig_panic("TODO handle C translation cast CK_IntegralRealToComplex"); | ||
| 927 | case CK_IntegralComplexToReal: | ||
| 928 | zig_panic("TODO handle C translation cast CK_IntegralComplexToReal"); | ||
| 929 | case CK_IntegralComplexToBoolean: | ||
| 930 | zig_panic("TODO handle C translation cast CK_IntegralComplexToBoolean"); | ||
| 931 | case CK_IntegralComplexCast: | ||
| 932 | zig_panic("TODO handle C translation cast CK_IntegralComplexCast"); | ||
| 933 | case CK_IntegralComplexToFloatingComplex: | ||
| 934 | zig_panic("TODO handle C translation cast CK_IntegralComplexToFloatingComplex"); | ||
| 935 | case CK_ARCProduceObject: | ||
| 936 | zig_panic("TODO handle C translation cast CK_ARCProduceObject"); | ||
| 937 | case CK_ARCConsumeObject: | ||
| 938 | zig_panic("TODO handle C translation cast CK_ARCConsumeObject"); | ||
| 939 | case CK_ARCReclaimReturnedObject: | ||
| 940 | zig_panic("TODO handle C translation cast CK_ARCReclaimReturnedObject"); | ||
| 941 | case CK_ARCExtendBlockObject: | ||
| 942 | zig_panic("TODO handle C translation cast CK_ARCExtendBlockObject"); | ||
| 943 | case CK_AtomicToNonAtomic: | ||
| 944 | zig_panic("TODO handle C translation cast CK_AtomicToNonAtomic"); | ||
| 945 | case CK_NonAtomicToAtomic: | ||
| 946 | zig_panic("TODO handle C translation cast CK_NonAtomicToAtomic"); | ||
| 947 | case CK_CopyAndAutoreleaseBlockObject: | ||
| 948 | zig_panic("TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject"); | ||
| 949 | case CK_BuiltinFnToFnPtr: | ||
| 950 | zig_panic("TODO handle C translation cast CK_BuiltinFnToFnPtr"); | ||
| 951 | case CK_ZeroToOCLEvent: | ||
| 952 | zig_panic("TODO handle C translation cast CK_ZeroToOCLEvent"); | ||
| 953 | case CK_ZeroToOCLQueue: | ||
| 954 | zig_panic("TODO handle C translation cast CK_ZeroToOCLQueue"); | ||
| 955 | case CK_AddressSpaceConversion: | ||
| 956 | zig_panic("TODO handle C translation cast CK_AddressSpaceConversion"); | ||
| 957 | case CK_IntToOCLSampler: | ||
| 958 | zig_panic("TODO handle C translation cast CK_IntToOCLSampler"); | ||
| 959 | } | ||
| 960 | zig_unreachable(); | ||
| 961 | } | ||
| 962 | |||
| 963 | static AstNode * trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) { | ||
| 964 | ValueDecl *value_decl = stmt->getDecl(); | ||
| 965 | const char *name = decl_name(value_decl); | ||
| 966 | |||
| 967 | AstNode *node = trans_create_node(c, NodeTypeSymbol); | ||
| 968 | node->data.symbol_expr.symbol = buf_create_from_str(name); | ||
| 969 | return node; | ||
| 970 | } | ||
| 971 | |||
| 972 | static AstNode * trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) { | ||
| 973 | switch (stmt->getOpcode()) { | ||
| 974 | case UO_PostInc: | ||
| 975 | zig_panic("TODO handle C translation UO_PostInc"); | ||
| 976 | case UO_PostDec: | ||
| 977 | zig_panic("TODO handle C translation UO_PostDec"); | ||
| 978 | case UO_PreInc: | ||
| 979 | zig_panic("TODO handle C translation UO_PreInc"); | ||
| 980 | case UO_PreDec: | ||
| 981 | zig_panic("TODO handle C translation UO_PreDec"); | ||
| 982 | case UO_AddrOf: | ||
| 983 | zig_panic("TODO handle C translation UO_AddrOf"); | ||
| 984 | case UO_Deref: | ||
| 985 | zig_panic("TODO handle C translation UO_Deref"); | ||
| 986 | case UO_Plus: | ||
| 987 | zig_panic("TODO handle C translation UO_Plus"); | ||
| 988 | case UO_Minus: | ||
| 989 | { | ||
| 990 | Expr *op_expr = stmt->getSubExpr(); | ||
| 991 | if (c_is_signed_integer(c, op_expr->getType()) || c_is_float(c, op_expr->getType())) { | ||
| 992 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | ||
| 993 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; | ||
| 994 | node->data.prefix_op_expr.primary_expr = trans_expr(c, block, op_expr); | ||
| 995 | return node; | ||
| 996 | } else if (c_is_unsigned_integer(c, op_expr->getType())) { | ||
| 997 | // we gotta emit 0 -% x | ||
| 998 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | ||
| 999 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); | ||
| 1000 | node->data.bin_op_expr.op2 = trans_expr(c, block, op_expr); | ||
| 1001 | node->data.bin_op_expr.bin_op = BinOpTypeSubWrap; | ||
| 1002 | return node; | ||
| 1003 | } else { | ||
| 1004 | zig_panic("TODO translate C negation with non float non integer"); | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | case UO_Not: | ||
| 1008 | zig_panic("TODO handle C translation UO_Not"); | ||
| 1009 | case UO_LNot: | ||
| 1010 | zig_panic("TODO handle C translation UO_LNot"); | ||
| 1011 | case UO_Real: | ||
| 1012 | zig_panic("TODO handle C translation UO_Real"); | ||
| 1013 | case UO_Imag: | ||
| 1014 | zig_panic("TODO handle C translation UO_Imag"); | ||
| 1015 | case UO_Extension: | ||
| 1016 | zig_panic("TODO handle C translation UO_Extension"); | ||
| 1017 | case UO_Coawait: | ||
| 1018 | zig_panic("TODO handle C translation UO_Coawait"); | ||
| 1019 | } | ||
| 1020 | zig_unreachable(); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | static AstNode * trans_local_declaration(Context *c, AstNode *block, DeclStmt *stmt) { | ||
| 1024 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { | ||
| 1025 | Decl *decl = *iter; | ||
| 1026 | switch (decl->getKind()) { | ||
| 1027 | case Decl::Var: { | ||
| 1028 | VarDecl *var_decl = (VarDecl *)decl; | ||
| 1029 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); | ||
| 1030 | AstNode *init_node = var_decl->hasInit() ? trans_expr(c, block, var_decl->getInit()) : nullptr; | ||
| 1031 | AstNode *type_node = trans_qual_type(c, qual_type, stmt->getStartLoc()); | ||
| 1032 | AstNode *node = trans_create_node_var_decl(c, qual_type.isConstQualified(), | ||
| 1033 | buf_create_from_str(decl_name(var_decl)), type_node, init_node); | ||
| 1034 | block->data.block.statements.append(node); | ||
| 1035 | continue; | ||
| 1036 | } | ||
| 1037 | case Decl::AccessSpec: | ||
| 1038 | zig_panic("TODO handle decl kind AccessSpec"); | ||
| 1039 | case Decl::Block: | ||
| 1040 | zig_panic("TODO handle decl kind Block"); | ||
| 1041 | case Decl::Captured: | ||
| 1042 | zig_panic("TODO handle decl kind Captured"); | ||
| 1043 | case Decl::ClassScopeFunctionSpecialization: | ||
| 1044 | zig_panic("TODO handle decl kind ClassScopeFunctionSpecialization"); | ||
| 1045 | case Decl::Empty: | ||
| 1046 | zig_panic("TODO handle decl kind Empty"); | ||
| 1047 | case Decl::Export: | ||
| 1048 | zig_panic("TODO handle decl kind Export"); | ||
| 1049 | case Decl::ExternCContext: | ||
| 1050 | zig_panic("TODO handle decl kind ExternCContext"); | ||
| 1051 | case Decl::FileScopeAsm: | ||
| 1052 | zig_panic("TODO handle decl kind FileScopeAsm"); | ||
| 1053 | case Decl::Friend: | ||
| 1054 | zig_panic("TODO handle decl kind Friend"); | ||
| 1055 | case Decl::FriendTemplate: | ||
| 1056 | zig_panic("TODO handle decl kind FriendTemplate"); | ||
| 1057 | case Decl::Import: | ||
| 1058 | zig_panic("TODO handle decl kind Import"); | ||
| 1059 | case Decl::LinkageSpec: | ||
| 1060 | zig_panic("TODO handle decl kind LinkageSpec"); | ||
| 1061 | case Decl::Label: | ||
| 1062 | zig_panic("TODO handle decl kind Label"); | ||
| 1063 | case Decl::Namespace: | ||
| 1064 | zig_panic("TODO handle decl kind Namespace"); | ||
| 1065 | case Decl::NamespaceAlias: | ||
| 1066 | zig_panic("TODO handle decl kind NamespaceAlias"); | ||
| 1067 | case Decl::ObjCCompatibleAlias: | ||
| 1068 | zig_panic("TODO handle decl kind ObjCCompatibleAlias"); | ||
| 1069 | case Decl::ObjCCategory: | ||
| 1070 | zig_panic("TODO handle decl kind ObjCCategory"); | ||
| 1071 | case Decl::ObjCCategoryImpl: | ||
| 1072 | zig_panic("TODO handle decl kind ObjCCategoryImpl"); | ||
| 1073 | case Decl::ObjCImplementation: | ||
| 1074 | zig_panic("TODO handle decl kind ObjCImplementation"); | ||
| 1075 | case Decl::ObjCInterface: | ||
| 1076 | zig_panic("TODO handle decl kind ObjCInterface"); | ||
| 1077 | case Decl::ObjCProtocol: | ||
| 1078 | zig_panic("TODO handle decl kind ObjCProtocol"); | ||
| 1079 | case Decl::ObjCMethod: | ||
| 1080 | zig_panic("TODO handle decl kind ObjCMethod"); | ||
| 1081 | case Decl::ObjCProperty: | ||
| 1082 | zig_panic("TODO handle decl kind ObjCProperty"); | ||
| 1083 | case Decl::BuiltinTemplate: | ||
| 1084 | zig_panic("TODO handle decl kind BuiltinTemplate"); | ||
| 1085 | case Decl::ClassTemplate: | ||
| 1086 | zig_panic("TODO handle decl kind ClassTemplate"); | ||
| 1087 | case Decl::FunctionTemplate: | ||
| 1088 | zig_panic("TODO handle decl kind FunctionTemplate"); | ||
| 1089 | case Decl::TypeAliasTemplate: | ||
| 1090 | zig_panic("TODO handle decl kind TypeAliasTemplate"); | ||
| 1091 | case Decl::VarTemplate: | ||
| 1092 | zig_panic("TODO handle decl kind VarTemplate"); | ||
| 1093 | case Decl::TemplateTemplateParm: | ||
| 1094 | zig_panic("TODO handle decl kind TemplateTemplateParm"); | ||
| 1095 | case Decl::Enum: | ||
| 1096 | zig_panic("TODO handle decl kind Enum"); | ||
| 1097 | case Decl::Record: | ||
| 1098 | zig_panic("TODO handle decl kind Record"); | ||
| 1099 | case Decl::CXXRecord: | ||
| 1100 | zig_panic("TODO handle decl kind CXXRecord"); | ||
| 1101 | case Decl::ClassTemplateSpecialization: | ||
| 1102 | zig_panic("TODO handle decl kind ClassTemplateSpecialization"); | ||
| 1103 | case Decl::ClassTemplatePartialSpecialization: | ||
| 1104 | zig_panic("TODO handle decl kind ClassTemplatePartialSpecialization"); | ||
| 1105 | case Decl::TemplateTypeParm: | ||
| 1106 | zig_panic("TODO handle decl kind TemplateTypeParm"); | ||
| 1107 | case Decl::ObjCTypeParam: | ||
| 1108 | zig_panic("TODO handle decl kind ObjCTypeParam"); | ||
| 1109 | case Decl::TypeAlias: | ||
| 1110 | zig_panic("TODO handle decl kind TypeAlias"); | ||
| 1111 | case Decl::Typedef: | ||
| 1112 | zig_panic("TODO handle decl kind Typedef"); | ||
| 1113 | case Decl::UnresolvedUsingTypename: | ||
| 1114 | zig_panic("TODO handle decl kind UnresolvedUsingTypename"); | ||
| 1115 | case Decl::Using: | ||
| 1116 | zig_panic("TODO handle decl kind Using"); | ||
| 1117 | case Decl::UsingDirective: | ||
| 1118 | zig_panic("TODO handle decl kind UsingDirective"); | ||
| 1119 | case Decl::UsingPack: | ||
| 1120 | zig_panic("TODO handle decl kind UsingPack"); | ||
| 1121 | case Decl::UsingShadow: | ||
| 1122 | zig_panic("TODO handle decl kind UsingShadow"); | ||
| 1123 | case Decl::ConstructorUsingShadow: | ||
| 1124 | zig_panic("TODO handle decl kind ConstructorUsingShadow"); | ||
| 1125 | case Decl::Binding: | ||
| 1126 | zig_panic("TODO handle decl kind Binding"); | ||
| 1127 | case Decl::Field: | ||
| 1128 | zig_panic("TODO handle decl kind Field"); | ||
| 1129 | case Decl::ObjCAtDefsField: | ||
| 1130 | zig_panic("TODO handle decl kind ObjCAtDefsField"); | ||
| 1131 | case Decl::ObjCIvar: | ||
| 1132 | zig_panic("TODO handle decl kind ObjCIvar"); | ||
| 1133 | case Decl::Function: | ||
| 1134 | zig_panic("TODO handle decl kind Function"); | ||
| 1135 | case Decl::CXXDeductionGuide: | ||
| 1136 | zig_panic("TODO handle decl kind CXXDeductionGuide"); | ||
| 1137 | case Decl::CXXMethod: | ||
| 1138 | zig_panic("TODO handle decl kind CXXMethod"); | ||
| 1139 | case Decl::CXXConstructor: | ||
| 1140 | zig_panic("TODO handle decl kind CXXConstructor"); | ||
| 1141 | case Decl::CXXConversion: | ||
| 1142 | zig_panic("TODO handle decl kind CXXConversion"); | ||
| 1143 | case Decl::CXXDestructor: | ||
| 1144 | zig_panic("TODO handle decl kind CXXDestructor"); | ||
| 1145 | case Decl::MSProperty: | ||
| 1146 | zig_panic("TODO handle decl kind MSProperty"); | ||
| 1147 | case Decl::NonTypeTemplateParm: | ||
| 1148 | zig_panic("TODO handle decl kind NonTypeTemplateParm"); | ||
| 1149 | case Decl::Decomposition: | ||
| 1150 | zig_panic("TODO handle decl kind Decomposition"); | ||
| 1151 | case Decl::ImplicitParam: | ||
| 1152 | zig_panic("TODO handle decl kind ImplicitParam"); | ||
| 1153 | case Decl::OMPCapturedExpr: | ||
| 1154 | zig_panic("TODO handle decl kind OMPCapturedExpr"); | ||
| 1155 | case Decl::ParmVar: | ||
| 1156 | zig_panic("TODO handle decl kind ParmVar"); | ||
| 1157 | case Decl::VarTemplateSpecialization: | ||
| 1158 | zig_panic("TODO handle decl kind VarTemplateSpecialization"); | ||
| 1159 | case Decl::VarTemplatePartialSpecialization: | ||
| 1160 | zig_panic("TODO handle decl kind VarTemplatePartialSpecialization"); | ||
| 1161 | case Decl::EnumConstant: | ||
| 1162 | zig_panic("TODO handle decl kind EnumConstant"); | ||
| 1163 | case Decl::IndirectField: | ||
| 1164 | zig_panic("TODO handle decl kind IndirectField"); | ||
| 1165 | case Decl::OMPDeclareReduction: | ||
| 1166 | zig_panic("TODO handle decl kind OMPDeclareReduction"); | ||
| 1167 | case Decl::UnresolvedUsingValue: | ||
| 1168 | zig_panic("TODO handle decl kind UnresolvedUsingValue"); | ||
| 1169 | case Decl::OMPThreadPrivate: | ||
| 1170 | zig_panic("TODO handle decl kind OMPThreadPrivate"); | ||
| 1171 | case Decl::ObjCPropertyImpl: | ||
| 1172 | zig_panic("TODO handle decl kind ObjCPropertyImpl"); | ||
| 1173 | case Decl::PragmaComment: | ||
| 1174 | zig_panic("TODO handle decl kind PragmaComment"); | ||
| 1175 | case Decl::PragmaDetectMismatch: | ||
| 1176 | zig_panic("TODO handle decl kind PragmaDetectMismatch"); | ||
| 1177 | case Decl::StaticAssert: | ||
| 1178 | zig_panic("TODO handle decl kind StaticAssert"); | ||
| 1179 | case Decl::TranslationUnit: | ||
| 1180 | zig_panic("TODO handle decl kind TranslationUnit"); | ||
| 1181 | } | ||
| 1182 | zig_unreachable(); | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | // declarations were already added | ||
| 1186 | return nullptr; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { | ||
| 1190 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); | ||
| 1191 | while_node->data.while_expr.condition = trans_expr(c, block, stmt->getCond()); | ||
| 1192 | while_node->data.while_expr.body = trans_stmt(c, block, stmt->getBody()); | ||
| 1193 | return while_node; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ||
| 1197 | Stmt::StmtClass sc = stmt->getStmtClass(); | ||
| 1198 | switch (sc) { | ||
| 1199 | case Stmt::ReturnStmtClass: | ||
| 1200 | return trans_return_stmt(c, block, (ReturnStmt *)stmt); | ||
| 1201 | case Stmt::CompoundStmtClass: | ||
| 1202 | return trans_compound_stmt(c, block, (CompoundStmt *)stmt); | ||
| 1203 | case Stmt::IntegerLiteralClass: | ||
| 1204 | return trans_integer_literal(c, (IntegerLiteral *)stmt); | ||
| 1205 | case Stmt::ConditionalOperatorClass: | ||
| 1206 | return trans_conditional_operator(c, block, (ConditionalOperator *)stmt); | ||
| 1207 | case Stmt::BinaryOperatorClass: | ||
| 1208 | return trans_binary_operator(c, block, (BinaryOperator *)stmt); | ||
| 1209 | case Stmt::ImplicitCastExprClass: | ||
| 1210 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); | ||
| 1211 | case Stmt::DeclRefExprClass: | ||
| 1212 | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt); | ||
| 1213 | case Stmt::UnaryOperatorClass: | ||
| 1214 | return trans_unary_operator(c, block, (UnaryOperator *)stmt); | ||
| 1215 | case Stmt::DeclStmtClass: | ||
| 1216 | return trans_local_declaration(c, block, (DeclStmt *)stmt); | ||
| 1217 | case Stmt::WhileStmtClass: | ||
| 1218 | return trans_while_loop(c, block, (WhileStmt *)stmt); | ||
| 1219 | case Stmt::CaseStmtClass: | ||
| 1220 | zig_panic("TODO handle C CaseStmtClass"); | ||
| 1221 | case Stmt::DefaultStmtClass: | ||
| 1222 | zig_panic("TODO handle C DefaultStmtClass"); | ||
| 1223 | case Stmt::SwitchStmtClass: | ||
| 1224 | zig_panic("TODO handle C SwitchStmtClass"); | ||
| 1225 | case Stmt::NoStmtClass: | ||
| 1226 | zig_panic("TODO handle C NoStmtClass"); | ||
| 1227 | case Stmt::GCCAsmStmtClass: | ||
| 1228 | zig_panic("TODO handle C GCCAsmStmtClass"); | ||
| 1229 | case Stmt::MSAsmStmtClass: | ||
| 1230 | zig_panic("TODO handle C MSAsmStmtClass"); | ||
| 1231 | case Stmt::AttributedStmtClass: | ||
| 1232 | zig_panic("TODO handle C AttributedStmtClass"); | ||
| 1233 | case Stmt::BreakStmtClass: | ||
| 1234 | zig_panic("TODO handle C BreakStmtClass"); | ||
| 1235 | case Stmt::CXXCatchStmtClass: | ||
| 1236 | zig_panic("TODO handle C CXXCatchStmtClass"); | ||
| 1237 | case Stmt::CXXForRangeStmtClass: | ||
| 1238 | zig_panic("TODO handle C CXXForRangeStmtClass"); | ||
| 1239 | case Stmt::CXXTryStmtClass: | ||
| 1240 | zig_panic("TODO handle C CXXTryStmtClass"); | ||
| 1241 | case Stmt::CapturedStmtClass: | ||
| 1242 | zig_panic("TODO handle C CapturedStmtClass"); | ||
| 1243 | case Stmt::ContinueStmtClass: | ||
| 1244 | zig_panic("TODO handle C ContinueStmtClass"); | ||
| 1245 | case Stmt::CoreturnStmtClass: | ||
| 1246 | zig_panic("TODO handle C CoreturnStmtClass"); | ||
| 1247 | case Stmt::CoroutineBodyStmtClass: | ||
| 1248 | zig_panic("TODO handle C CoroutineBodyStmtClass"); | ||
| 1249 | case Stmt::DoStmtClass: | ||
| 1250 | zig_panic("TODO handle C DoStmtClass"); | ||
| 1251 | case Stmt::BinaryConditionalOperatorClass: | ||
| 1252 | zig_panic("TODO handle C BinaryConditionalOperatorClass"); | ||
| 1253 | case Stmt::AddrLabelExprClass: | ||
| 1254 | zig_panic("TODO handle C AddrLabelExprClass"); | ||
| 1255 | case Stmt::ArrayInitIndexExprClass: | ||
| 1256 | zig_panic("TODO handle C ArrayInitIndexExprClass"); | ||
| 1257 | case Stmt::ArrayInitLoopExprClass: | ||
| 1258 | zig_panic("TODO handle C ArrayInitLoopExprClass"); | ||
| 1259 | case Stmt::ArraySubscriptExprClass: | ||
| 1260 | zig_panic("TODO handle C ArraySubscriptExprClass"); | ||
| 1261 | case Stmt::ArrayTypeTraitExprClass: | ||
| 1262 | zig_panic("TODO handle C ArrayTypeTraitExprClass"); | ||
| 1263 | case Stmt::AsTypeExprClass: | ||
| 1264 | zig_panic("TODO handle C AsTypeExprClass"); | ||
| 1265 | case Stmt::AtomicExprClass: | ||
| 1266 | zig_panic("TODO handle C AtomicExprClass"); | ||
| 1267 | case Stmt::CompoundAssignOperatorClass: | ||
| 1268 | zig_panic("TODO handle C CompoundAssignOperatorClass"); | ||
| 1269 | case Stmt::BlockExprClass: | ||
| 1270 | zig_panic("TODO handle C BlockExprClass"); | ||
| 1271 | case Stmt::CXXBindTemporaryExprClass: | ||
| 1272 | zig_panic("TODO handle C CXXBindTemporaryExprClass"); | ||
| 1273 | case Stmt::CXXBoolLiteralExprClass: | ||
| 1274 | zig_panic("TODO handle C CXXBoolLiteralExprClass"); | ||
| 1275 | case Stmt::CXXConstructExprClass: | ||
| 1276 | zig_panic("TODO handle C CXXConstructExprClass"); | ||
| 1277 | case Stmt::CXXTemporaryObjectExprClass: | ||
| 1278 | zig_panic("TODO handle C CXXTemporaryObjectExprClass"); | ||
| 1279 | case Stmt::CXXDefaultArgExprClass: | ||
| 1280 | zig_panic("TODO handle C CXXDefaultArgExprClass"); | ||
| 1281 | case Stmt::CXXDefaultInitExprClass: | ||
| 1282 | zig_panic("TODO handle C CXXDefaultInitExprClass"); | ||
| 1283 | case Stmt::CXXDeleteExprClass: | ||
| 1284 | zig_panic("TODO handle C CXXDeleteExprClass"); | ||
| 1285 | case Stmt::CXXDependentScopeMemberExprClass: | ||
| 1286 | zig_panic("TODO handle C CXXDependentScopeMemberExprClass"); | ||
| 1287 | case Stmt::CXXFoldExprClass: | ||
| 1288 | zig_panic("TODO handle C CXXFoldExprClass"); | ||
| 1289 | case Stmt::CXXInheritedCtorInitExprClass: | ||
| 1290 | zig_panic("TODO handle C CXXInheritedCtorInitExprClass"); | ||
| 1291 | case Stmt::CXXNewExprClass: | ||
| 1292 | zig_panic("TODO handle C CXXNewExprClass"); | ||
| 1293 | case Stmt::CXXNoexceptExprClass: | ||
| 1294 | zig_panic("TODO handle C CXXNoexceptExprClass"); | ||
| 1295 | case Stmt::CXXNullPtrLiteralExprClass: | ||
| 1296 | zig_panic("TODO handle C CXXNullPtrLiteralExprClass"); | ||
| 1297 | case Stmt::CXXPseudoDestructorExprClass: | ||
| 1298 | zig_panic("TODO handle C CXXPseudoDestructorExprClass"); | ||
| 1299 | case Stmt::CXXScalarValueInitExprClass: | ||
| 1300 | zig_panic("TODO handle C CXXScalarValueInitExprClass"); | ||
| 1301 | case Stmt::CXXStdInitializerListExprClass: | ||
| 1302 | zig_panic("TODO handle C CXXStdInitializerListExprClass"); | ||
| 1303 | case Stmt::CXXThisExprClass: | ||
| 1304 | zig_panic("TODO handle C CXXThisExprClass"); | ||
| 1305 | case Stmt::CXXThrowExprClass: | ||
| 1306 | zig_panic("TODO handle C CXXThrowExprClass"); | ||
| 1307 | case Stmt::CXXTypeidExprClass: | ||
| 1308 | zig_panic("TODO handle C CXXTypeidExprClass"); | ||
| 1309 | case Stmt::CXXUnresolvedConstructExprClass: | ||
| 1310 | zig_panic("TODO handle C CXXUnresolvedConstructExprClass"); | ||
| 1311 | case Stmt::CXXUuidofExprClass: | ||
| 1312 | zig_panic("TODO handle C CXXUuidofExprClass"); | ||
| 1313 | case Stmt::CallExprClass: | ||
| 1314 | zig_panic("TODO handle C CallExprClass"); | ||
| 1315 | case Stmt::CUDAKernelCallExprClass: | ||
| 1316 | zig_panic("TODO handle C CUDAKernelCallExprClass"); | ||
| 1317 | case Stmt::CXXMemberCallExprClass: | ||
| 1318 | zig_panic("TODO handle C CXXMemberCallExprClass"); | ||
| 1319 | case Stmt::CXXOperatorCallExprClass: | ||
| 1320 | zig_panic("TODO handle C CXXOperatorCallExprClass"); | ||
| 1321 | case Stmt::UserDefinedLiteralClass: | ||
| 1322 | zig_panic("TODO handle C UserDefinedLiteralClass"); | ||
| 1323 | case Stmt::CStyleCastExprClass: | ||
| 1324 | zig_panic("TODO handle C CStyleCastExprClass"); | ||
| 1325 | case Stmt::CXXFunctionalCastExprClass: | ||
| 1326 | zig_panic("TODO handle C CXXFunctionalCastExprClass"); | ||
| 1327 | case Stmt::CXXConstCastExprClass: | ||
| 1328 | zig_panic("TODO handle C CXXConstCastExprClass"); | ||
| 1329 | case Stmt::CXXDynamicCastExprClass: | ||
| 1330 | zig_panic("TODO handle C CXXDynamicCastExprClass"); | ||
| 1331 | case Stmt::CXXReinterpretCastExprClass: | ||
| 1332 | zig_panic("TODO handle C CXXReinterpretCastExprClass"); | ||
| 1333 | case Stmt::CXXStaticCastExprClass: | ||
| 1334 | zig_panic("TODO handle C CXXStaticCastExprClass"); | ||
| 1335 | case Stmt::ObjCBridgedCastExprClass: | ||
| 1336 | zig_panic("TODO handle C ObjCBridgedCastExprClass"); | ||
| 1337 | case Stmt::CharacterLiteralClass: | ||
| 1338 | zig_panic("TODO handle C CharacterLiteralClass"); | ||
| 1339 | case Stmt::ChooseExprClass: | ||
| 1340 | zig_panic("TODO handle C ChooseExprClass"); | ||
| 1341 | case Stmt::CompoundLiteralExprClass: | ||
| 1342 | zig_panic("TODO handle C CompoundLiteralExprClass"); | ||
| 1343 | case Stmt::ConvertVectorExprClass: | ||
| 1344 | zig_panic("TODO handle C ConvertVectorExprClass"); | ||
| 1345 | case Stmt::CoawaitExprClass: | ||
| 1346 | zig_panic("TODO handle C CoawaitExprClass"); | ||
| 1347 | case Stmt::CoyieldExprClass: | ||
| 1348 | zig_panic("TODO handle C CoyieldExprClass"); | ||
| 1349 | case Stmt::DependentCoawaitExprClass: | ||
| 1350 | zig_panic("TODO handle C DependentCoawaitExprClass"); | ||
| 1351 | case Stmt::DependentScopeDeclRefExprClass: | ||
| 1352 | zig_panic("TODO handle C DependentScopeDeclRefExprClass"); | ||
| 1353 | case Stmt::DesignatedInitExprClass: | ||
| 1354 | zig_panic("TODO handle C DesignatedInitExprClass"); | ||
| 1355 | case Stmt::DesignatedInitUpdateExprClass: | ||
| 1356 | zig_panic("TODO handle C DesignatedInitUpdateExprClass"); | ||
| 1357 | case Stmt::ExprWithCleanupsClass: | ||
| 1358 | zig_panic("TODO handle C ExprWithCleanupsClass"); | ||
| 1359 | case Stmt::ExpressionTraitExprClass: | ||
| 1360 | zig_panic("TODO handle C ExpressionTraitExprClass"); | ||
| 1361 | case Stmt::ExtVectorElementExprClass: | ||
| 1362 | zig_panic("TODO handle C ExtVectorElementExprClass"); | ||
| 1363 | case Stmt::FloatingLiteralClass: | ||
| 1364 | zig_panic("TODO handle C FloatingLiteralClass"); | ||
| 1365 | case Stmt::FunctionParmPackExprClass: | ||
| 1366 | zig_panic("TODO handle C FunctionParmPackExprClass"); | ||
| 1367 | case Stmt::GNUNullExprClass: | ||
| 1368 | zig_panic("TODO handle C GNUNullExprClass"); | ||
| 1369 | case Stmt::GenericSelectionExprClass: | ||
| 1370 | zig_panic("TODO handle C GenericSelectionExprClass"); | ||
| 1371 | case Stmt::ImaginaryLiteralClass: | ||
| 1372 | zig_panic("TODO handle C ImaginaryLiteralClass"); | ||
| 1373 | case Stmt::ImplicitValueInitExprClass: | ||
| 1374 | zig_panic("TODO handle C ImplicitValueInitExprClass"); | ||
| 1375 | case Stmt::InitListExprClass: | ||
| 1376 | zig_panic("TODO handle C InitListExprClass"); | ||
| 1377 | case Stmt::LambdaExprClass: | ||
| 1378 | zig_panic("TODO handle C LambdaExprClass"); | ||
| 1379 | case Stmt::MSPropertyRefExprClass: | ||
| 1380 | zig_panic("TODO handle C MSPropertyRefExprClass"); | ||
| 1381 | case Stmt::MSPropertySubscriptExprClass: | ||
| 1382 | zig_panic("TODO handle C MSPropertySubscriptExprClass"); | ||
| 1383 | case Stmt::MaterializeTemporaryExprClass: | ||
| 1384 | zig_panic("TODO handle C MaterializeTemporaryExprClass"); | ||
| 1385 | case Stmt::MemberExprClass: | ||
| 1386 | zig_panic("TODO handle C MemberExprClass"); | ||
| 1387 | case Stmt::NoInitExprClass: | ||
| 1388 | zig_panic("TODO handle C NoInitExprClass"); | ||
| 1389 | case Stmt::OMPArraySectionExprClass: | ||
| 1390 | zig_panic("TODO handle C OMPArraySectionExprClass"); | ||
| 1391 | case Stmt::ObjCArrayLiteralClass: | ||
| 1392 | zig_panic("TODO handle C ObjCArrayLiteralClass"); | ||
| 1393 | case Stmt::ObjCAvailabilityCheckExprClass: | ||
| 1394 | zig_panic("TODO handle C ObjCAvailabilityCheckExprClass"); | ||
| 1395 | case Stmt::ObjCBoolLiteralExprClass: | ||
| 1396 | zig_panic("TODO handle C ObjCBoolLiteralExprClass"); | ||
| 1397 | case Stmt::ObjCBoxedExprClass: | ||
| 1398 | zig_panic("TODO handle C ObjCBoxedExprClass"); | ||
| 1399 | case Stmt::ObjCDictionaryLiteralClass: | ||
| 1400 | zig_panic("TODO handle C ObjCDictionaryLiteralClass"); | ||
| 1401 | case Stmt::ObjCEncodeExprClass: | ||
| 1402 | zig_panic("TODO handle C ObjCEncodeExprClass"); | ||
| 1403 | case Stmt::ObjCIndirectCopyRestoreExprClass: | ||
| 1404 | zig_panic("TODO handle C ObjCIndirectCopyRestoreExprClass"); | ||
| 1405 | case Stmt::ObjCIsaExprClass: | ||
| 1406 | zig_panic("TODO handle C ObjCIsaExprClass"); | ||
| 1407 | case Stmt::ObjCIvarRefExprClass: | ||
| 1408 | zig_panic("TODO handle C ObjCIvarRefExprClass"); | ||
| 1409 | case Stmt::ObjCMessageExprClass: | ||
| 1410 | zig_panic("TODO handle C ObjCMessageExprClass"); | ||
| 1411 | case Stmt::ObjCPropertyRefExprClass: | ||
| 1412 | zig_panic("TODO handle C ObjCPropertyRefExprClass"); | ||
| 1413 | case Stmt::ObjCProtocolExprClass: | ||
| 1414 | zig_panic("TODO handle C ObjCProtocolExprClass"); | ||
| 1415 | case Stmt::ObjCSelectorExprClass: | ||
| 1416 | zig_panic("TODO handle C ObjCSelectorExprClass"); | ||
| 1417 | case Stmt::ObjCStringLiteralClass: | ||
| 1418 | zig_panic("TODO handle C ObjCStringLiteralClass"); | ||
| 1419 | case Stmt::ObjCSubscriptRefExprClass: | ||
| 1420 | zig_panic("TODO handle C ObjCSubscriptRefExprClass"); | ||
| 1421 | case Stmt::OffsetOfExprClass: | ||
| 1422 | zig_panic("TODO handle C OffsetOfExprClass"); | ||
| 1423 | case Stmt::OpaqueValueExprClass: | ||
| 1424 | zig_panic("TODO handle C OpaqueValueExprClass"); | ||
| 1425 | case Stmt::UnresolvedLookupExprClass: | ||
| 1426 | zig_panic("TODO handle C UnresolvedLookupExprClass"); | ||
| 1427 | case Stmt::UnresolvedMemberExprClass: | ||
| 1428 | zig_panic("TODO handle C UnresolvedMemberExprClass"); | ||
| 1429 | case Stmt::PackExpansionExprClass: | ||
| 1430 | zig_panic("TODO handle C PackExpansionExprClass"); | ||
| 1431 | case Stmt::ParenExprClass: | ||
| 1432 | zig_panic("TODO handle C ParenExprClass"); | ||
| 1433 | case Stmt::ParenListExprClass: | ||
| 1434 | zig_panic("TODO handle C ParenListExprClass"); | ||
| 1435 | case Stmt::PredefinedExprClass: | ||
| 1436 | zig_panic("TODO handle C PredefinedExprClass"); | ||
| 1437 | case Stmt::PseudoObjectExprClass: | ||
| 1438 | zig_panic("TODO handle C PseudoObjectExprClass"); | ||
| 1439 | case Stmt::ShuffleVectorExprClass: | ||
| 1440 | zig_panic("TODO handle C ShuffleVectorExprClass"); | ||
| 1441 | case Stmt::SizeOfPackExprClass: | ||
| 1442 | zig_panic("TODO handle C SizeOfPackExprClass"); | ||
| 1443 | case Stmt::StmtExprClass: | ||
| 1444 | zig_panic("TODO handle C StmtExprClass"); | ||
| 1445 | case Stmt::StringLiteralClass: | ||
| 1446 | zig_panic("TODO handle C StringLiteralClass"); | ||
| 1447 | case Stmt::SubstNonTypeTemplateParmExprClass: | ||
| 1448 | zig_panic("TODO handle C SubstNonTypeTemplateParmExprClass"); | ||
| 1449 | case Stmt::SubstNonTypeTemplateParmPackExprClass: | ||
| 1450 | zig_panic("TODO handle C SubstNonTypeTemplateParmPackExprClass"); | ||
| 1451 | case Stmt::TypeTraitExprClass: | ||
| 1452 | zig_panic("TODO handle C TypeTraitExprClass"); | ||
| 1453 | case Stmt::TypoExprClass: | ||
| 1454 | zig_panic("TODO handle C TypoExprClass"); | ||
| 1455 | case Stmt::UnaryExprOrTypeTraitExprClass: | ||
| 1456 | zig_panic("TODO handle C UnaryExprOrTypeTraitExprClass"); | ||
| 1457 | case Stmt::VAArgExprClass: | ||
| 1458 | zig_panic("TODO handle C VAArgExprClass"); | ||
| 1459 | case Stmt::ForStmtClass: | ||
| 1460 | zig_panic("TODO handle C ForStmtClass"); | ||
| 1461 | case Stmt::GotoStmtClass: | ||
| 1462 | zig_panic("TODO handle C GotoStmtClass"); | ||
| 1463 | case Stmt::IfStmtClass: | ||
| 1464 | zig_panic("TODO handle C IfStmtClass"); | ||
| 1465 | case Stmt::IndirectGotoStmtClass: | ||
| 1466 | zig_panic("TODO handle C IndirectGotoStmtClass"); | ||
| 1467 | case Stmt::LabelStmtClass: | ||
| 1468 | zig_panic("TODO handle C LabelStmtClass"); | ||
| 1469 | case Stmt::MSDependentExistsStmtClass: | ||
| 1470 | zig_panic("TODO handle C MSDependentExistsStmtClass"); | ||
| 1471 | case Stmt::NullStmtClass: | ||
| 1472 | zig_panic("TODO handle C NullStmtClass"); | ||
| 1473 | case Stmt::OMPAtomicDirectiveClass: | ||
| 1474 | zig_panic("TODO handle C OMPAtomicDirectiveClass"); | ||
| 1475 | case Stmt::OMPBarrierDirectiveClass: | ||
| 1476 | zig_panic("TODO handle C OMPBarrierDirectiveClass"); | ||
| 1477 | case Stmt::OMPCancelDirectiveClass: | ||
| 1478 | zig_panic("TODO handle C OMPCancelDirectiveClass"); | ||
| 1479 | case Stmt::OMPCancellationPointDirectiveClass: | ||
| 1480 | zig_panic("TODO handle C OMPCancellationPointDirectiveClass"); | ||
| 1481 | case Stmt::OMPCriticalDirectiveClass: | ||
| 1482 | zig_panic("TODO handle C OMPCriticalDirectiveClass"); | ||
| 1483 | case Stmt::OMPFlushDirectiveClass: | ||
| 1484 | zig_panic("TODO handle C OMPFlushDirectiveClass"); | ||
| 1485 | case Stmt::OMPDistributeDirectiveClass: | ||
| 1486 | zig_panic("TODO handle C OMPDistributeDirectiveClass"); | ||
| 1487 | case Stmt::OMPDistributeParallelForDirectiveClass: | ||
| 1488 | zig_panic("TODO handle C OMPDistributeParallelForDirectiveClass"); | ||
| 1489 | case Stmt::OMPDistributeParallelForSimdDirectiveClass: | ||
| 1490 | zig_panic("TODO handle C OMPDistributeParallelForSimdDirectiveClass"); | ||
| 1491 | case Stmt::OMPDistributeSimdDirectiveClass: | ||
| 1492 | zig_panic("TODO handle C OMPDistributeSimdDirectiveClass"); | ||
| 1493 | case Stmt::OMPForDirectiveClass: | ||
| 1494 | zig_panic("TODO handle C OMPForDirectiveClass"); | ||
| 1495 | case Stmt::OMPForSimdDirectiveClass: | ||
| 1496 | zig_panic("TODO handle C OMPForSimdDirectiveClass"); | ||
| 1497 | case Stmt::OMPParallelForDirectiveClass: | ||
| 1498 | zig_panic("TODO handle C OMPParallelForDirectiveClass"); | ||
| 1499 | case Stmt::OMPParallelForSimdDirectiveClass: | ||
| 1500 | zig_panic("TODO handle C OMPParallelForSimdDirectiveClass"); | ||
| 1501 | case Stmt::OMPSimdDirectiveClass: | ||
| 1502 | zig_panic("TODO handle C OMPSimdDirectiveClass"); | ||
| 1503 | case Stmt::OMPTargetParallelForSimdDirectiveClass: | ||
| 1504 | zig_panic("TODO handle C OMPTargetParallelForSimdDirectiveClass"); | ||
| 1505 | case Stmt::OMPTargetSimdDirectiveClass: | ||
| 1506 | zig_panic("TODO handle C OMPTargetSimdDirectiveClass"); | ||
| 1507 | case Stmt::OMPTargetTeamsDistributeDirectiveClass: | ||
| 1508 | zig_panic("TODO handle C OMPTargetTeamsDistributeDirectiveClass"); | ||
| 1509 | case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: | ||
| 1510 | zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); | ||
| 1511 | case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: | ||
| 1512 | zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); | ||
| 1513 | case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: | ||
| 1514 | zig_panic("TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); | ||
| 1515 | case Stmt::OMPTaskLoopDirectiveClass: | ||
| 1516 | zig_panic("TODO handle C OMPTaskLoopDirectiveClass"); | ||
| 1517 | case Stmt::OMPTaskLoopSimdDirectiveClass: | ||
| 1518 | zig_panic("TODO handle C OMPTaskLoopSimdDirectiveClass"); | ||
| 1519 | case Stmt::OMPTeamsDistributeDirectiveClass: | ||
| 1520 | zig_panic("TODO handle C OMPTeamsDistributeDirectiveClass"); | ||
| 1521 | case Stmt::OMPTeamsDistributeParallelForDirectiveClass: | ||
| 1522 | zig_panic("TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); | ||
| 1523 | case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: | ||
| 1524 | zig_panic("TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); | ||
| 1525 | case Stmt::OMPTeamsDistributeSimdDirectiveClass: | ||
| 1526 | zig_panic("TODO handle C OMPTeamsDistributeSimdDirectiveClass"); | ||
| 1527 | case Stmt::OMPMasterDirectiveClass: | ||
| 1528 | zig_panic("TODO handle C OMPMasterDirectiveClass"); | ||
| 1529 | case Stmt::OMPOrderedDirectiveClass: | ||
| 1530 | zig_panic("TODO handle C OMPOrderedDirectiveClass"); | ||
| 1531 | case Stmt::OMPParallelDirectiveClass: | ||
| 1532 | zig_panic("TODO handle C OMPParallelDirectiveClass"); | ||
| 1533 | case Stmt::OMPParallelSectionsDirectiveClass: | ||
| 1534 | zig_panic("TODO handle C OMPParallelSectionsDirectiveClass"); | ||
| 1535 | case Stmt::OMPSectionDirectiveClass: | ||
| 1536 | zig_panic("TODO handle C OMPSectionDirectiveClass"); | ||
| 1537 | case Stmt::OMPSectionsDirectiveClass: | ||
| 1538 | zig_panic("TODO handle C OMPSectionsDirectiveClass"); | ||
| 1539 | case Stmt::OMPSingleDirectiveClass: | ||
| 1540 | zig_panic("TODO handle C OMPSingleDirectiveClass"); | ||
| 1541 | case Stmt::OMPTargetDataDirectiveClass: | ||
| 1542 | zig_panic("TODO handle C OMPTargetDataDirectiveClass"); | ||
| 1543 | case Stmt::OMPTargetDirectiveClass: | ||
| 1544 | zig_panic("TODO handle C OMPTargetDirectiveClass"); | ||
| 1545 | case Stmt::OMPTargetEnterDataDirectiveClass: | ||
| 1546 | zig_panic("TODO handle C OMPTargetEnterDataDirectiveClass"); | ||
| 1547 | case Stmt::OMPTargetExitDataDirectiveClass: | ||
| 1548 | zig_panic("TODO handle C OMPTargetExitDataDirectiveClass"); | ||
| 1549 | case Stmt::OMPTargetParallelDirectiveClass: | ||
| 1550 | zig_panic("TODO handle C OMPTargetParallelDirectiveClass"); | ||
| 1551 | case Stmt::OMPTargetParallelForDirectiveClass: | ||
| 1552 | zig_panic("TODO handle C OMPTargetParallelForDirectiveClass"); | ||
| 1553 | case Stmt::OMPTargetTeamsDirectiveClass: | ||
| 1554 | zig_panic("TODO handle C OMPTargetTeamsDirectiveClass"); | ||
| 1555 | case Stmt::OMPTargetUpdateDirectiveClass: | ||
| 1556 | zig_panic("TODO handle C OMPTargetUpdateDirectiveClass"); | ||
| 1557 | case Stmt::OMPTaskDirectiveClass: | ||
| 1558 | zig_panic("TODO handle C OMPTaskDirectiveClass"); | ||
| 1559 | case Stmt::OMPTaskgroupDirectiveClass: | ||
| 1560 | zig_panic("TODO handle C OMPTaskgroupDirectiveClass"); | ||
| 1561 | case Stmt::OMPTaskwaitDirectiveClass: | ||
| 1562 | zig_panic("TODO handle C OMPTaskwaitDirectiveClass"); | ||
| 1563 | case Stmt::OMPTaskyieldDirectiveClass: | ||
| 1564 | zig_panic("TODO handle C OMPTaskyieldDirectiveClass"); | ||
| 1565 | case Stmt::OMPTeamsDirectiveClass: | ||
| 1566 | zig_panic("TODO handle C OMPTeamsDirectiveClass"); | ||
| 1567 | case Stmt::ObjCAtCatchStmtClass: | ||
| 1568 | zig_panic("TODO handle C ObjCAtCatchStmtClass"); | ||
| 1569 | case Stmt::ObjCAtFinallyStmtClass: | ||
| 1570 | zig_panic("TODO handle C ObjCAtFinallyStmtClass"); | ||
| 1571 | case Stmt::ObjCAtSynchronizedStmtClass: | ||
| 1572 | zig_panic("TODO handle C ObjCAtSynchronizedStmtClass"); | ||
| 1573 | case Stmt::ObjCAtThrowStmtClass: | ||
| 1574 | zig_panic("TODO handle C ObjCAtThrowStmtClass"); | ||
| 1575 | case Stmt::ObjCAtTryStmtClass: | ||
| 1576 | zig_panic("TODO handle C ObjCAtTryStmtClass"); | ||
| 1577 | case Stmt::ObjCAutoreleasePoolStmtClass: | ||
| 1578 | zig_panic("TODO handle C ObjCAutoreleasePoolStmtClass"); | ||
| 1579 | case Stmt::ObjCForCollectionStmtClass: | ||
| 1580 | zig_panic("TODO handle C ObjCForCollectionStmtClass"); | ||
| 1581 | case Stmt::SEHExceptStmtClass: | ||
| 1582 | zig_panic("TODO handle C SEHExceptStmtClass"); | ||
| 1583 | case Stmt::SEHFinallyStmtClass: | ||
| 1584 | zig_panic("TODO handle C SEHFinallyStmtClass"); | ||
| 1585 | case Stmt::SEHLeaveStmtClass: | ||
| 1586 | zig_panic("TODO handle C SEHLeaveStmtClass"); | ||
| 1587 | case Stmt::SEHTryStmtClass: | ||
| 1588 | zig_panic("TODO handle C SEHTryStmtClass"); | ||
| 1589 | } | ||
| 1590 | zig_unreachable(); | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ||
| 1594 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); | ||
| 1595 | |||
| 1596 | if (get_global(c, fn_name)) { | ||
| 1597 | // we already saw this function | ||
| 1598 | return; | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation()); | ||
| 1602 | if (proto_node == nullptr) { | ||
| 1603 | emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name)); | ||
| 1604 | return; | ||
| 1605 | } | ||
| 1606 | |||
| 1607 | proto_node->data.fn_proto.name = fn_name; | ||
| 1608 | proto_node->data.fn_proto.is_extern = !fn_decl->hasBody(); | ||
| 1609 | |||
| 1610 | StorageClass sc = fn_decl->getStorageClass(); | ||
| 1611 | if (sc == SC_None) { | ||
| 1612 | proto_node->data.fn_proto.visib_mod = fn_decl->hasBody() ? VisibModExport : c->visib_mod; | ||
| 1613 | } else if (sc == SC_Extern || sc == SC_Static) { | ||
| 1614 | proto_node->data.fn_proto.visib_mod = c->visib_mod; | ||
| 1615 | } else if (sc == SC_PrivateExtern) { | ||
| 1616 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); | ||
| 1617 | return; | ||
| 1618 | } else { | ||
| 1619 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown"); | ||
| 1620 | return; | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { | ||
| 1624 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); | ||
| 1625 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | ||
| 1626 | const char *name = decl_name(param); | ||
| 1627 | if (strlen(name) == 0) { | ||
| 1628 | Buf *proto_param_name = param_node->data.param_decl.name; | ||
| 1629 | if (proto_param_name == nullptr) { | ||
| 1630 | param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i); | ||
| 1631 | } else { | ||
| 1632 | param_node->data.param_decl.name = proto_param_name; | ||
| 1633 | } | ||
| 1634 | } else { | ||
| 1635 | param_node->data.param_decl.name = buf_create_from_str(name); | ||
| 1636 | } | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | if (fn_decl->hasBody()) { | ||
| 1640 | Stmt *body = fn_decl->getBody(); | ||
| 1641 | |||
| 1642 | AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef); | ||
| 1643 | fn_def_node->data.fn_def.fn_proto = proto_node; | ||
| 1644 | fn_def_node->data.fn_def.body = trans_stmt(c, nullptr, body); | ||
| 1645 | |||
| 1646 | proto_node->data.fn_proto.fn_def_node = fn_def_node; | ||
| 1647 | c->root->data.root.top_level_decls.append(fn_def_node); | ||
| 1648 | return; | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | c->root->data.root.top_level_decls.append(proto_node); | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) { | ||
| 1655 | AstNode *node = trans_create_node_symbol_str(c, primitive_name); | ||
| 1656 | c->decl_table.put(typedef_decl, node); | ||
| 1657 | return node; | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) { | ||
| 1661 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl); | ||
| 1662 | if (existing_entry) { | ||
| 1663 | return existing_entry->value; | ||
| 1664 | } | ||
| 1665 | |||
| 1666 | QualType child_qt = typedef_decl->getUnderlyingType(); | ||
| 1667 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); | ||
| 1668 | |||
| 1669 | if (buf_eql_str(type_name, "uint8_t")) { | ||
| 1670 | return resolve_typdef_as_builtin(c, typedef_decl, "u8"); | ||
| 1671 | } else if (buf_eql_str(type_name, "int8_t")) { | ||
| 1672 | return resolve_typdef_as_builtin(c, typedef_decl, "i8"); | ||
| 1673 | } else if (buf_eql_str(type_name, "uint16_t")) { | ||
| 1674 | return resolve_typdef_as_builtin(c, typedef_decl, "u16"); | ||
| 1675 | } else if (buf_eql_str(type_name, "int16_t")) { | ||
| 1676 | return resolve_typdef_as_builtin(c, typedef_decl, "i16"); | ||
| 1677 | } else if (buf_eql_str(type_name, "uint32_t")) { | ||
| 1678 | return resolve_typdef_as_builtin(c, typedef_decl, "u32"); | ||
| 1679 | } else if (buf_eql_str(type_name, "int32_t")) { | ||
| 1680 | return resolve_typdef_as_builtin(c, typedef_decl, "i32"); | ||
| 1681 | } else if (buf_eql_str(type_name, "uint64_t")) { | ||
| 1682 | return resolve_typdef_as_builtin(c, typedef_decl, "u64"); | ||
| 1683 | } else if (buf_eql_str(type_name, "int64_t")) { | ||
| 1684 | return resolve_typdef_as_builtin(c, typedef_decl, "i64"); | ||
| 1685 | } else if (buf_eql_str(type_name, "intptr_t")) { | ||
| 1686 | return resolve_typdef_as_builtin(c, typedef_decl, "isize"); | ||
| 1687 | } else if (buf_eql_str(type_name, "uintptr_t")) { | ||
| 1688 | return resolve_typdef_as_builtin(c, typedef_decl, "usize"); | ||
| 1689 | } else if (buf_eql_str(type_name, "ssize_t")) { | ||
| 1690 | return resolve_typdef_as_builtin(c, typedef_decl, "isize"); | ||
| 1691 | } else if (buf_eql_str(type_name, "size_t")) { | ||
| 1692 | return resolve_typdef_as_builtin(c, typedef_decl, "usize"); | ||
| 1693 | } | ||
| 1694 | |||
| 1695 | // if the underlying type is anonymous, we can special case it to just | ||
| 1696 | // use the name of this typedef | ||
| 1697 | // TODO | ||
| 1698 | |||
| 1699 | AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation()); | ||
| 1700 | if (type_node == nullptr) { | ||
| 1701 | emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name)); | ||
| 1702 | c->decl_table.put(typedef_decl, nullptr); | ||
| 1703 | return nullptr; | ||
| 1704 | } | ||
| 1705 | add_global_var(c, type_name, type_node); | ||
| 1706 | |||
| 1707 | AstNode *symbol_node = trans_create_node_symbol(c, type_name); | ||
| 1708 | c->decl_table.put(typedef_decl, symbol_node); | ||
| 1709 | return symbol_node; | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl, | ||
| 1713 | Buf *full_type_name, Buf *bare_name) | ||
| 1714 | { | ||
| 1715 | AstNode *opaque_node = trans_create_node_opaque(c); | ||
| 1716 | if (full_type_name == nullptr) { | ||
| 1717 | c->decl_table.put(enum_decl->getCanonicalDecl(), opaque_node); | ||
| 1718 | return opaque_node; | ||
| 1719 | } | ||
| 1720 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1721 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1722 | add_global_var(c, full_type_name, opaque_node); | ||
| 1723 | c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node); | ||
| 1724 | return symbol_node; | ||
| 1725 | } | ||
| 1726 | |||
| 1727 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ||
| 1728 | auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl()); | ||
| 1729 | if (existing_entry) { | ||
| 1730 | return existing_entry->value; | ||
| 1731 | } | ||
| 1732 | |||
| 1733 | const char *raw_name = decl_name(enum_decl); | ||
| 1734 | bool is_anonymous = (raw_name[0] == 0); | ||
| 1735 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); | ||
| 1736 | Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); | ||
| 1737 | |||
| 1738 | const EnumDecl *enum_def = enum_decl->getDefinition(); | ||
| 1739 | if (!enum_def) { | ||
| 1740 | return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name); | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | bool pure_enum = true; | ||
| 1744 | uint32_t field_count = 0; | ||
| 1745 | for (auto it = enum_def->enumerator_begin(), | ||
| 1746 | it_end = enum_def->enumerator_end(); | ||
| 1747 | it != it_end; ++it, field_count += 1) | ||
| 1748 | { | ||
| 1749 | const EnumConstantDecl *enum_const = *it; | ||
| 1750 | if (enum_const->getInitExpr()) { | ||
| 1751 | pure_enum = false; | ||
| 1752 | } | ||
| 1753 | } | ||
| 1754 | |||
| 1755 | AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation()); | ||
| 1756 | assert(tag_int_type); | ||
| 1757 | |||
| 1758 | if (pure_enum) { | ||
| 1759 | AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl); | ||
| 1760 | enum_node->data.container_decl.kind = ContainerKindEnum; | ||
| 1761 | enum_node->data.container_decl.layout = ContainerLayoutExtern; | ||
| 1762 | enum_node->data.container_decl.init_arg_expr = tag_int_type; | ||
| 1763 | |||
| 1764 | enum_node->data.container_decl.fields.resize(field_count); | ||
| 1765 | uint32_t i = 0; | ||
| 1766 | for (auto it = enum_def->enumerator_begin(), | ||
| 1767 | it_end = enum_def->enumerator_end(); | ||
| 1768 | it != it_end; ++it, i += 1) | ||
| 1769 | { | ||
| 1770 | const EnumConstantDecl *enum_const = *it; | ||
| 1771 | |||
| 1772 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); | ||
| 1773 | Buf *field_name; | ||
| 1774 | if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) { | ||
| 1775 | field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name)); | ||
| 1776 | } else { | ||
| 1777 | field_name = enum_val_name; | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); | ||
| 1781 | field_node->data.struct_field.name = field_name; | ||
| 1782 | field_node->data.struct_field.type = nullptr; | ||
| 1783 | enum_node->data.container_decl.fields.items[i] = field_node; | ||
| 1784 | |||
| 1785 | // in C each enum value is in the global namespace. so we put them there too. | ||
| 1786 | // at this point we can rely on the enum emitting successfully | ||
| 1787 | AstNode *field_access_node = trans_create_node_field_access(c, | ||
| 1788 | trans_create_node_symbol(c, full_type_name), field_name); | ||
| 1789 | add_global_var(c, enum_val_name, field_access_node); | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | if (is_anonymous) { | ||
| 1793 | c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node); | ||
| 1794 | return enum_node; | ||
| 1795 | } else { | ||
| 1796 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1797 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1798 | add_global_var(c, full_type_name, enum_node); | ||
| 1799 | c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node); | ||
| 1800 | return enum_node; | ||
| 1801 | } | ||
| 1802 | } | ||
| 1803 | |||
| 1804 | // TODO after issue #305 is solved, make this be an enum with tag_int_type | ||
| 1805 | // as the integer type and set the custom enum values | ||
| 1806 | AstNode *enum_node = tag_int_type; | ||
| 1807 | |||
| 1808 | |||
| 1809 | // add variables for all the values with enum_node | ||
| 1810 | for (auto it = enum_def->enumerator_begin(), | ||
| 1811 | it_end = enum_def->enumerator_end(); | ||
| 1812 | it != it_end; ++it) | ||
| 1813 | { | ||
| 1814 | const EnumConstantDecl *enum_const = *it; | ||
| 1815 | |||
| 1816 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); | ||
| 1817 | AstNode *int_node = trans_create_node_apint(c, enum_const->getInitVal()); | ||
| 1818 | AstNode *var_node = add_global_var(c, enum_val_name, int_node); | ||
| 1819 | var_node->data.variable_declaration.type = tag_int_type; | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | if (is_anonymous) { | ||
| 1823 | c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node); | ||
| 1824 | return enum_node; | ||
| 1825 | } else { | ||
| 1826 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1827 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1828 | add_global_var(c, full_type_name, enum_node); | ||
| 1829 | return symbol_node; | ||
| 1830 | } | ||
| 1831 | } | ||
| 1832 | |||
| 1833 | static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl, | ||
| 1834 | Buf *full_type_name, Buf *bare_name) | ||
| 1835 | { | ||
| 1836 | AstNode *opaque_node = trans_create_node_opaque(c); | ||
| 1837 | if (full_type_name == nullptr) { | ||
| 1838 | c->decl_table.put(record_decl->getCanonicalDecl(), opaque_node); | ||
| 1839 | return opaque_node; | ||
| 1840 | } | ||
| 1841 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1842 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1843 | add_global_var(c, full_type_name, opaque_node); | ||
| 1844 | c->decl_table.put(record_decl->getCanonicalDecl(), symbol_node); | ||
| 1845 | return symbol_node; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | ||
| 1849 | auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl()); | ||
| 1850 | if (existing_entry) { | ||
| 1851 | return existing_entry->value; | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | const char *raw_name = decl_name(record_decl); | ||
| 1855 | |||
| 1856 | if (!record_decl->isStruct()) { | ||
| 1857 | emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct", raw_name); | ||
| 1858 | c->decl_table.put(record_decl->getCanonicalDecl(), nullptr); | ||
| 1859 | return nullptr; | ||
| 1860 | } | ||
| 1861 | |||
| 1862 | bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0; | ||
| 1863 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); | ||
| 1864 | Buf *full_type_name = (bare_name == nullptr) ? nullptr : buf_sprintf("struct_%s", buf_ptr(bare_name)); | ||
| 1865 | |||
| 1866 | RecordDecl *record_def = record_decl->getDefinition(); | ||
| 1867 | if (record_def == nullptr) { | ||
| 1868 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); | ||
| 1869 | } | ||
| 1870 | |||
| 1871 | // count fields and validate | ||
| 1872 | uint32_t field_count = 0; | ||
| 1873 | for (auto it = record_def->field_begin(), | ||
| 1874 | it_end = record_def->field_end(); | ||
| 1875 | it != it_end; ++it, field_count += 1) | ||
| 1876 | { | ||
| 1877 | const FieldDecl *field_decl = *it; | ||
| 1878 | |||
| 1879 | if (field_decl->isBitField()) { | ||
| 1880 | emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield", | ||
| 1881 | is_anonymous ? "(anon)" : buf_ptr(bare_name)); | ||
| 1882 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); | ||
| 1883 | } | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl); | ||
| 1887 | struct_node->data.container_decl.kind = ContainerKindStruct; | ||
| 1888 | struct_node->data.container_decl.layout = ContainerLayoutExtern; | ||
| 1889 | |||
| 1890 | // TODO handle attribute packed | ||
| 1891 | |||
| 1892 | struct_node->data.container_decl.fields.resize(field_count); | ||
| 1893 | |||
| 1894 | // must be before fields in case a circular reference happens | ||
| 1895 | if (is_anonymous) { | ||
| 1896 | c->decl_table.put(record_decl->getCanonicalDecl(), struct_node); | ||
| 1897 | } else { | ||
| 1898 | c->decl_table.put(record_decl->getCanonicalDecl(), trans_create_node_symbol(c, full_type_name)); | ||
| 1899 | } | ||
| 1900 | |||
| 1901 | uint32_t i = 0; | ||
| 1902 | for (auto it = record_def->field_begin(), | ||
| 1903 | it_end = record_def->field_end(); | ||
| 1904 | it != it_end; ++it, i += 1) | ||
| 1905 | { | ||
| 1906 | const FieldDecl *field_decl = *it; | ||
| 1907 | |||
| 1908 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); | ||
| 1909 | field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); | ||
| 1910 | field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation()); | ||
| 1911 | |||
| 1912 | if (field_node->data.struct_field.type == nullptr) { | ||
| 1913 | emit_warning(c, field_decl->getLocation(), | ||
| 1914 | "struct %s demoted to opaque type - unresolved type", | ||
| 1915 | is_anonymous ? "(anon)" : buf_ptr(bare_name)); | ||
| 1916 | |||
| 1917 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); | ||
| 1918 | } | ||
| 1919 | |||
| 1920 | struct_node->data.container_decl.fields.items[i] = field_node; | ||
| 1921 | } | ||
| 1922 | |||
| 1923 | if (is_anonymous) { | ||
| 1924 | return struct_node; | ||
| 1925 | } else { | ||
| 1926 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1927 | add_global_var(c, full_type_name, struct_node); | ||
| 1928 | return trans_create_node_symbol(c, full_type_name); | ||
| 1929 | } | ||
| 1930 | } | ||
| 1931 | |||
| 1932 | static void visit_var_decl(Context *c, const VarDecl *var_decl) { | ||
| 1933 | Buf *name = buf_create_from_str(decl_name(var_decl)); | ||
| 1934 | |||
| 1935 | switch (var_decl->getTLSKind()) { | ||
| 1936 | case VarDecl::TLS_None: | ||
| 1937 | break; | ||
| 1938 | case VarDecl::TLS_Static: | ||
| 1939 | emit_warning(c, var_decl->getLocation(), | ||
| 1940 | "ignoring variable '%s' - static thread local storage", buf_ptr(name)); | ||
| 1941 | return; | ||
| 1942 | case VarDecl::TLS_Dynamic: | ||
| 1943 | emit_warning(c, var_decl->getLocation(), | ||
| 1944 | "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); | ||
| 1945 | return; | ||
| 1946 | } | ||
| 1947 | |||
| 1948 | QualType qt = var_decl->getType(); | ||
| 1949 | AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); | ||
| 1950 | if (var_type == nullptr) { | ||
| 1951 | emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name)); | ||
| 1952 | return; | ||
| 1953 | } | ||
| 1954 | |||
| 1955 | bool is_extern = var_decl->hasExternalStorage(); | ||
| 1956 | bool is_static = var_decl->isFileVarDecl(); | ||
| 1957 | bool is_const = qt.isConstQualified(); | ||
| 1958 | |||
| 1959 | if (is_static && !is_extern) { | ||
| 1960 | AstNode *init_node; | ||
| 1961 | if (var_decl->hasInit()) { | ||
| 1962 | APValue *ap_value = var_decl->evaluateValue(); | ||
| 1963 | if (ap_value == nullptr) { | ||
| 1964 | emit_warning(c, var_decl->getLocation(), | ||
| 1965 | "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); | ||
| 1966 | return; | ||
| 1967 | } | ||
| 1968 | switch (ap_value->getKind()) { | ||
| 1969 | case APValue::Int: | ||
| 1970 | init_node = trans_create_node_apint(c, ap_value->getInt()); | ||
| 1971 | break; | ||
| 1972 | case APValue::Uninitialized: | ||
| 1973 | init_node = trans_create_node_symbol_str(c, "undefined"); | ||
| 1974 | break; | ||
| 1975 | case APValue::Float: | ||
| 1976 | case APValue::ComplexInt: | ||
| 1977 | case APValue::ComplexFloat: | ||
| 1978 | case APValue::LValue: | ||
| 1979 | case APValue::Vector: | ||
| 1980 | case APValue::Array: | ||
| 1981 | case APValue::Struct: | ||
| 1982 | case APValue::Union: | ||
| 1983 | case APValue::MemberPointer: | ||
| 1984 | case APValue::AddrLabelDiff: | ||
| 1985 | emit_warning(c, var_decl->getLocation(), | ||
| 1986 | "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name)); | ||
| 1987 | return; | ||
| 1988 | } | ||
| 1989 | } else { | ||
| 1990 | init_node = trans_create_node_symbol_str(c, "undefined"); | ||
| 1991 | } | ||
| 1992 | |||
| 1993 | AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, init_node); | ||
| 1994 | c->root->data.root.top_level_decls.append(var_node); | ||
| 1995 | return; | ||
| 1996 | } | ||
| 1997 | |||
| 1998 | if (is_extern) { | ||
| 1999 | AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, nullptr); | ||
| 2000 | var_node->data.variable_declaration.is_extern = true; | ||
| 2001 | c->root->data.root.top_level_decls.append(var_node); | ||
| 2002 | return; | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | emit_warning(c, var_decl->getLocation(), | ||
| 2006 | "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name)); | ||
| 2007 | return; | ||
| 2008 | } | ||
| 2009 | |||
| 2010 | static bool decl_visitor(void *context, const Decl *decl) { | ||
| 2011 | Context *c = (Context*)context; | ||
| 2012 | |||
| 2013 | switch (decl->getKind()) { | ||
| 2014 | case Decl::Function: | ||
| 2015 | visit_fn_decl(c, static_cast<const FunctionDecl*>(decl)); | ||
| 2016 | break; | ||
| 2017 | case Decl::Typedef: | ||
| 2018 | resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); | ||
| 2019 | break; | ||
| 2020 | case Decl::Enum: | ||
| 2021 | resolve_enum_decl(c, static_cast<const EnumDecl *>(decl)); | ||
| 2022 | break; | ||
| 2023 | case Decl::Record: | ||
| 2024 | resolve_record_decl(c, static_cast<const RecordDecl *>(decl)); | ||
| 2025 | break; | ||
| 2026 | case Decl::Var: | ||
| 2027 | visit_var_decl(c, static_cast<const VarDecl *>(decl)); | ||
| 2028 | break; | ||
| 2029 | default: | ||
| 2030 | emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName()); | ||
| 2031 | } | ||
| 2032 | |||
| 2033 | return true; | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | static bool name_exists(Context *c, Buf *name) { | ||
| 2037 | return get_global(c, name) != nullptr; | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | static void render_aliases(Context *c) { | ||
| 2041 | for (size_t i = 0; i < c->aliases.length; i += 1) { | ||
| 2042 | Alias *alias = &c->aliases.at(i); | ||
| 2043 | if (name_exists(c, alias->new_name)) | ||
| 2044 | continue; | ||
| 2045 | |||
| 2046 | add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name)); | ||
| 2047 | } | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | static void render_macros(Context *c) { | ||
| 2051 | auto it = c->macro_table.entry_iterator(); | ||
| 2052 | for (;;) { | ||
| 2053 | auto *entry = it.next(); | ||
| 2054 | if (!entry) | ||
| 2055 | break; | ||
| 2056 | |||
| 2057 | AstNode *value_node = entry->value; | ||
| 2058 | if (value_node->type == NodeTypeFnDef) { | ||
| 2059 | c->root->data.root.top_level_decls.append(value_node); | ||
| 2060 | } else { | ||
| 2061 | add_global_var(c, entry->key, value_node); | ||
| 2062 | } | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) { | ||
| 2067 | tokenize_c_macro(ctok, (const uint8_t *)char_ptr); | ||
| 2068 | |||
| 2069 | if (ctok->error) { | ||
| 2070 | return; | ||
| 2071 | } | ||
| 2072 | |||
| 2073 | bool negate = false; | ||
| 2074 | for (size_t i = 0; i < ctok->tokens.length; i += 1) { | ||
| 2075 | bool is_first = (i == 0); | ||
| 2076 | bool is_last = (i == ctok->tokens.length - 1); | ||
| 2077 | CTok *tok = &ctok->tokens.at(i); | ||
| 2078 | switch (tok->id) { | ||
| 2079 | case CTokIdCharLit: | ||
| 2080 | if (is_last && is_first) { | ||
| 2081 | AstNode *node = trans_create_node_unsigned(c, tok->data.char_lit); | ||
| 2082 | c->macro_table.put(name, node); | ||
| 2083 | } | ||
| 2084 | return; | ||
| 2085 | case CTokIdStrLit: | ||
| 2086 | if (is_last && is_first) { | ||
| 2087 | AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit)); | ||
| 2088 | c->macro_table.put(name, node); | ||
| 2089 | } | ||
| 2090 | return; | ||
| 2091 | case CTokIdNumLitInt: | ||
| 2092 | if (is_last) { | ||
| 2093 | AstNode *node; | ||
| 2094 | switch (tok->data.num_lit_int.suffix) { | ||
| 2095 | case CNumLitSuffixNone: | ||
| 2096 | node = trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate); | ||
| 2097 | break; | ||
| 2098 | case CNumLitSuffixL: | ||
| 2099 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2100 | "c_long"); | ||
| 2101 | break; | ||
| 2102 | case CNumLitSuffixU: | ||
| 2103 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2104 | "c_uint"); | ||
| 2105 | break; | ||
| 2106 | case CNumLitSuffixLU: | ||
| 2107 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2108 | "c_ulong"); | ||
| 2109 | break; | ||
| 2110 | case CNumLitSuffixLL: | ||
| 2111 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2112 | "c_longlong"); | ||
| 2113 | break; | ||
| 2114 | case CNumLitSuffixLLU: | ||
| 2115 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2116 | "c_ulonglong"); | ||
| 2117 | break; | ||
| 2118 | } | ||
| 2119 | c->macro_table.put(name, node); | ||
| 2120 | } | ||
| 2121 | return; | ||
| 2122 | case CTokIdNumLitFloat: | ||
| 2123 | if (is_last) { | ||
| 2124 | double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float; | ||
| 2125 | AstNode *node = trans_create_node_float_lit(c, value); | ||
| 2126 | c->macro_table.put(name, node); | ||
| 2127 | } | ||
| 2128 | return; | ||
| 2129 | case CTokIdSymbol: | ||
| 2130 | if (is_last && is_first) { | ||
| 2131 | // if it equals itself, ignore. for example, from stdio.h: | ||
| 2132 | // #define stdin stdin | ||
| 2133 | Buf *symbol_name = buf_create_from_buf(&tok->data.symbol); | ||
| 2134 | if (buf_eql_buf(name, symbol_name)) { | ||
| 2135 | return; | ||
| 2136 | } | ||
| 2137 | c->macro_symbols.append({name, symbol_name}); | ||
| 2138 | return; | ||
| 2139 | } | ||
| 2140 | case CTokIdMinus: | ||
| 2141 | if (is_first) { | ||
| 2142 | negate = true; | ||
| 2143 | break; | ||
| 2144 | } else { | ||
| 2145 | return; | ||
| 2146 | } | ||
| 2147 | } | ||
| 2148 | } | ||
| 2149 | } | ||
| 2150 | |||
| 2151 | static void process_symbol_macros(Context *c) { | ||
| 2152 | for (size_t i = 0; i < c->macro_symbols.length; i += 1) { | ||
| 2153 | MacroSymbol ms = c->macro_symbols.at(i); | ||
| 2154 | |||
| 2155 | // Check if this macro aliases another top level declaration | ||
| 2156 | AstNode *existing_node = get_global(c, ms.value); | ||
| 2157 | if (!existing_node || name_exists(c, ms.name)) | ||
| 2158 | continue; | ||
| 2159 | |||
| 2160 | // If a macro aliases a global variable which is a function pointer, we conclude that | ||
| 2161 | // the macro is intended to represent a function that assumes the function pointer | ||
| 2162 | // variable is non-null and calls it. | ||
| 2163 | if (existing_node->type == NodeTypeVariableDeclaration) { | ||
| 2164 | AstNode *var_type = existing_node->data.variable_declaration.type; | ||
| 2165 | if (var_type != nullptr && var_type->type == NodeTypePrefixOpExpr && | ||
| 2166 | var_type->data.prefix_op_expr.prefix_op == PrefixOpMaybe) | ||
| 2167 | { | ||
| 2168 | AstNode *fn_proto_node = var_type->data.prefix_op_expr.primary_expr; | ||
| 2169 | if (fn_proto_node->type == NodeTypeFnProto) { | ||
| 2170 | AstNode *inline_fn_node = trans_create_node_inline_fn(c, ms.name, ms.value, fn_proto_node); | ||
| 2171 | c->macro_table.put(ms.name, inline_fn_node); | ||
| 2172 | continue; | ||
| 2173 | } | ||
| 2174 | } | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | add_global_var(c, ms.name, trans_create_node_symbol(c, ms.value)); | ||
| 2178 | } | ||
| 2179 | } | ||
| 2180 | |||
| 2181 | static void process_preprocessor_entities(Context *c, ASTUnit &unit) { | ||
| 2182 | CTokenize ctok = {{0}}; | ||
| 2183 | |||
| 2184 | // TODO if we see #undef, delete it from the table | ||
| 2185 | |||
| 2186 | for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) { | ||
| 2187 | switch (entity->getKind()) { | ||
| 2188 | case PreprocessedEntity::InvalidKind: | ||
| 2189 | case PreprocessedEntity::InclusionDirectiveKind: | ||
| 2190 | case PreprocessedEntity::MacroExpansionKind: | ||
| 2191 | continue; | ||
| 2192 | case PreprocessedEntity::MacroDefinitionKind: | ||
| 2193 | { | ||
| 2194 | MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity); | ||
| 2195 | const char *raw_name = macro->getName()->getNameStart(); | ||
| 2196 | SourceRange range = macro->getSourceRange(); | ||
| 2197 | SourceLocation begin_loc = range.getBegin(); | ||
| 2198 | SourceLocation end_loc = range.getEnd(); | ||
| 2199 | |||
| 2200 | if (begin_loc == end_loc) { | ||
| 2201 | // this means it is a macro without a value | ||
| 2202 | // we don't care about such things | ||
| 2203 | continue; | ||
| 2204 | } | ||
| 2205 | Buf *name = buf_create_from_str(raw_name); | ||
| 2206 | if (name_exists(c, name)) { | ||
| 2207 | continue; | ||
| 2208 | } | ||
| 2209 | |||
| 2210 | const char *end_c = c->source_manager->getCharacterData(end_loc); | ||
| 2211 | process_macro(c, &ctok, name, end_c); | ||
| 2212 | } | ||
| 2213 | } | ||
| 2214 | } | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source, | ||
| 2218 | CodeGen *codegen, AstNode *source_node) | ||
| 2219 | { | ||
| 2220 | int err; | ||
| 2221 | Buf tmp_file_path = BUF_INIT; | ||
| 2222 | if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) { | ||
| 2223 | return err; | ||
| 2224 | } | ||
| 2225 | |||
| 2226 | err = parse_h_file(import, errors, buf_ptr(&tmp_file_path), codegen, source_node); | ||
| 2227 | |||
| 2228 | os_delete_file(&tmp_file_path); | ||
| 2229 | |||
| 2230 | return err; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file, | ||
| 2234 | CodeGen *codegen, AstNode *source_node) | ||
| 2235 | { | ||
| 2236 | Context context = {0}; | ||
| 2237 | Context *c = &context; | ||
| 2238 | c->warnings_on = codegen->verbose; | ||
| 2239 | c->import = import; | ||
| 2240 | c->errors = errors; | ||
| 2241 | c->visib_mod = VisibModPub; | ||
| 2242 | c->decl_table.init(8); | ||
| 2243 | c->macro_table.init(8); | ||
| 2244 | c->codegen = codegen; | ||
| 2245 | c->source_node = source_node; | ||
| 2246 | |||
| 2247 | ZigList<const char *> clang_argv = {0}; | ||
| 2248 | |||
| 2249 | clang_argv.append("-x"); | ||
| 2250 | clang_argv.append("c"); | ||
| 2251 | |||
| 2252 | if (c->codegen->is_native_target) { | ||
| 2253 | char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS"); | ||
| 2254 | if (ZIG_PARSEC_CFLAGS) { | ||
| 2255 | Buf tmp_buf = BUF_INIT; | ||
| 2256 | char *start = ZIG_PARSEC_CFLAGS; | ||
| 2257 | char *space = strstr(start, " "); | ||
| 2258 | while (space) { | ||
| 2259 | if (space - start > 0) { | ||
| 2260 | buf_init_from_mem(&tmp_buf, start, space - start); | ||
| 2261 | clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf))); | ||
| 2262 | } | ||
| 2263 | start = space + 1; | ||
| 2264 | space = strstr(start, " "); | ||
| 2265 | } | ||
| 2266 | buf_init_from_str(&tmp_buf, start); | ||
| 2267 | clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf))); | ||
| 2268 | } | ||
| 2269 | } | ||
| 2270 | |||
| 2271 | clang_argv.append("-isystem"); | ||
| 2272 | clang_argv.append(ZIG_HEADERS_DIR); | ||
| 2273 | |||
| 2274 | clang_argv.append("-isystem"); | ||
| 2275 | clang_argv.append(buf_ptr(codegen->libc_include_dir)); | ||
| 2276 | |||
| 2277 | for (size_t i = 0; i < codegen->clang_argv_len; i += 1) { | ||
| 2278 | clang_argv.append(codegen->clang_argv[i]); | ||
| 2279 | } | ||
| 2280 | |||
| 2281 | // we don't need spell checking and it slows things down | ||
| 2282 | clang_argv.append("-fno-spell-checking"); | ||
| 2283 | |||
| 2284 | // this gives us access to preprocessing entities, presumably at | ||
| 2285 | // the cost of performance | ||
| 2286 | clang_argv.append("-Xclang"); | ||
| 2287 | clang_argv.append("-detailed-preprocessing-record"); | ||
| 2288 | |||
| 2289 | if (!c->codegen->is_native_target) { | ||
| 2290 | clang_argv.append("-target"); | ||
| 2291 | clang_argv.append(buf_ptr(&c->codegen->triple_str)); | ||
| 2292 | } | ||
| 2293 | |||
| 2294 | clang_argv.append(target_file); | ||
| 2295 | |||
| 2296 | // to make the [start...end] argument work | ||
| 2297 | clang_argv.append(nullptr); | ||
| 2298 | |||
| 2299 | IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); | ||
| 2300 | |||
| 2301 | std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>(); | ||
| 2302 | |||
| 2303 | bool skip_function_bodies = false; | ||
| 2304 | bool only_local_decls = true; | ||
| 2305 | bool capture_diagnostics = true; | ||
| 2306 | bool user_files_are_volatile = true; | ||
| 2307 | bool allow_pch_with_compiler_errors = false; | ||
| 2308 | bool single_file_parse = false; | ||
| 2309 | bool for_serialization = false; | ||
| 2310 | const char *resources_path = ZIG_HEADERS_DIR; | ||
| 2311 | std::unique_ptr<ASTUnit> err_unit; | ||
| 2312 | std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine( | ||
| 2313 | &clang_argv.at(0), &clang_argv.last(), | ||
| 2314 | pch_container_ops, diags, resources_path, | ||
| 2315 | only_local_decls, capture_diagnostics, None, true, 0, TU_Complete, | ||
| 2316 | false, false, allow_pch_with_compiler_errors, skip_function_bodies, | ||
| 2317 | single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit, | ||
| 2318 | nullptr)); | ||
| 2319 | |||
| 2320 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. | ||
| 2321 | if (!ast_unit && !err_unit) { | ||
| 2322 | return ErrorFileSystem; | ||
| 2323 | } | ||
| 2324 | |||
| 2325 | if (diags->getClient()->getNumErrors() > 0) { | ||
| 2326 | if (ast_unit) { | ||
| 2327 | err_unit = std::move(ast_unit); | ||
| 2328 | } | ||
| 2329 | |||
| 2330 | for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | ||
| 2331 | it_end = err_unit->stored_diag_end(); | ||
| 2332 | it != it_end; ++it) | ||
| 2333 | { | ||
| 2334 | switch (it->getLevel()) { | ||
| 2335 | case DiagnosticsEngine::Ignored: | ||
| 2336 | case DiagnosticsEngine::Note: | ||
| 2337 | case DiagnosticsEngine::Remark: | ||
| 2338 | case DiagnosticsEngine::Warning: | ||
| 2339 | continue; | ||
| 2340 | case DiagnosticsEngine::Error: | ||
| 2341 | case DiagnosticsEngine::Fatal: | ||
| 2342 | break; | ||
| 2343 | } | ||
| 2344 | StringRef msg_str_ref = it->getMessage(); | ||
| 2345 | Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin()); | ||
| 2346 | FullSourceLoc fsl = it->getLocation(); | ||
| 2347 | if (fsl.hasManager()) { | ||
| 2348 | FileID file_id = fsl.getFileID(); | ||
| 2349 | StringRef filename = fsl.getManager().getFilename(fsl); | ||
| 2350 | unsigned line = fsl.getSpellingLineNumber() - 1; | ||
| 2351 | unsigned column = fsl.getSpellingColumnNumber() - 1; | ||
| 2352 | unsigned offset = fsl.getManager().getFileOffset(fsl); | ||
| 2353 | const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); | ||
| 2354 | Buf *path; | ||
| 2355 | if (filename.empty()) { | ||
| 2356 | path = buf_alloc(); | ||
| 2357 | } else { | ||
| 2358 | path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size()); | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); | ||
| 2362 | |||
| 2363 | c->errors->append(err_msg); | ||
| 2364 | } else { | ||
| 2365 | // NOTE the only known way this gets triggered right now is if you have a lot of errors | ||
| 2366 | // clang emits "too many errors emitted, stopping now" | ||
| 2367 | fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg)); | ||
| 2368 | } | ||
| 2369 | } | ||
| 2370 | |||
| 2371 | return 0; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | c->ctx = &ast_unit->getASTContext(); | ||
| 2375 | c->source_manager = &ast_unit->getSourceManager(); | ||
| 2376 | c->root = trans_create_node(c, NodeTypeRoot); | ||
| 2377 | |||
| 2378 | ast_unit->visitLocalTopLevelDecls(c, decl_visitor); | ||
| 2379 | |||
| 2380 | process_preprocessor_entities(c, *ast_unit); | ||
| 2381 | |||
| 2382 | process_symbol_macros(c); | ||
| 2383 | render_macros(c); | ||
| 2384 | render_aliases(c); | ||
| 2385 | |||
| 2386 | import->root = c->root; | ||
| 2387 | |||
| 2388 | return 0; | ||
| 2389 | } | ||
src/parsec.hpp created+20| ... | @@ -0,0 +1,20 @@ | ||
| 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 | |||
| 9 | #ifndef ZIG_PARSEC_HPP | ||
| 10 | #define ZIG_PARSEC_HPP | ||
| 11 | |||
| 12 | #include "all_types.hpp" | ||
| 13 | |||
| 14 | int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file, | ||
| 15 | CodeGen *codegen, AstNode *source_node); | ||
| 16 | |||
| 17 | int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source, | ||
| 18 | CodeGen *codegen, AstNode *source_node); | ||
| 19 | |||
| 20 | #endif | ||
src/parseh.cpp deleted-2389| ... | @@ -1,2389 +0,0 @@ | ||
| 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 "all_types.hpp" | ||
| 9 | #include "analyze.hpp" | ||
| 10 | #include "c_tokenizer.hpp" | ||
| 11 | #include "config.h" | ||
| 12 | #include "error.hpp" | ||
| 13 | #include "ir.hpp" | ||
| 14 | #include "os.hpp" | ||
| 15 | #include "parseh.hpp" | ||
| 16 | #include "parser.hpp" | ||
| 17 | |||
| 18 | |||
| 19 | #include <clang/Frontend/ASTUnit.h> | ||
| 20 | #include <clang/Frontend/CompilerInstance.h> | ||
| 21 | #include <clang/AST/Expr.h> | ||
| 22 | |||
| 23 | #include <string.h> | ||
| 24 | |||
| 25 | using namespace clang; | ||
| 26 | |||
| 27 | struct MacroSymbol { | ||
| 28 | Buf *name; | ||
| 29 | Buf *value; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct Alias { | ||
| 33 | Buf *new_name; | ||
| 34 | Buf *canon_name; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct Context { | ||
| 38 | ImportTableEntry *import; | ||
| 39 | ZigList<ErrorMsg *> *errors; | ||
| 40 | bool warnings_on; | ||
| 41 | VisibMod visib_mod; | ||
| 42 | AstNode *root; | ||
| 43 | HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table; | ||
| 44 | HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table; | ||
| 45 | SourceManager *source_manager; | ||
| 46 | ZigList<Alias> aliases; | ||
| 47 | ZigList<MacroSymbol> macro_symbols; | ||
| 48 | AstNode *source_node; | ||
| 49 | |||
| 50 | CodeGen *codegen; | ||
| 51 | ASTContext *ctx; | ||
| 52 | }; | ||
| 53 | |||
| 54 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl); | ||
| 55 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl); | ||
| 56 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl); | ||
| 57 | static AstNode *trans_qual_type_with_table(Context *c, QualType qt, const SourceLocation &source_loc); | ||
| 58 | static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | ||
| 59 | |||
| 60 | |||
| 61 | __attribute__ ((format (printf, 3, 4))) | ||
| 62 | static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) { | ||
| 63 | if (!c->warnings_on) { | ||
| 64 | return; | ||
| 65 | } | ||
| 66 | |||
| 67 | va_list ap; | ||
| 68 | va_start(ap, format); | ||
| 69 | Buf *msg = buf_vprintf(format, ap); | ||
| 70 | va_end(ap); | ||
| 71 | |||
| 72 | StringRef filename = c->source_manager->getFilename(sl); | ||
| 73 | const char *filename_bytes = (const char *)filename.bytes_begin(); | ||
| 74 | Buf *path; | ||
| 75 | if (filename_bytes) { | ||
| 76 | path = buf_create_from_str(filename_bytes); | ||
| 77 | } else { | ||
| 78 | path = buf_sprintf("(no file)"); | ||
| 79 | } | ||
| 80 | unsigned line = c->source_manager->getSpellingLineNumber(sl); | ||
| 81 | unsigned column = c->source_manager->getSpellingColumnNumber(sl); | ||
| 82 | fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg)); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) { | ||
| 86 | Alias *alias = c->aliases.add_one(); | ||
| 87 | alias->new_name = new_name; | ||
| 88 | alias->canon_name = canon_name; | ||
| 89 | } | ||
| 90 | |||
| 91 | static AstNode * trans_create_node(Context *c, NodeType id) { | ||
| 92 | AstNode *node = allocate<AstNode>(1); | ||
| 93 | node->type = id; | ||
| 94 | node->owner = c->import; | ||
| 95 | // TODO line/column. mapping to C file?? | ||
| 96 | return node; | ||
| 97 | } | ||
| 98 | |||
| 99 | static AstNode *trans_create_node_float_lit(Context *c, double value) { | ||
| 100 | AstNode *node = trans_create_node(c, NodeTypeFloatLiteral); | ||
| 101 | node->data.float_literal.bigfloat = allocate<BigFloat>(1); | ||
| 102 | bigfloat_init_64(node->data.float_literal.bigfloat, value); | ||
| 103 | return node; | ||
| 104 | } | ||
| 105 | |||
| 106 | static AstNode *trans_create_node_symbol(Context *c, Buf *name) { | ||
| 107 | AstNode *node = trans_create_node(c, NodeTypeSymbol); | ||
| 108 | node->data.symbol_expr.symbol = name; | ||
| 109 | return node; | ||
| 110 | } | ||
| 111 | |||
| 112 | static AstNode *trans_create_node_symbol_str(Context *c, const char *name) { | ||
| 113 | return trans_create_node_symbol(c, buf_create_from_str(name)); | ||
| 114 | } | ||
| 115 | |||
| 116 | static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) { | ||
| 117 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); | ||
| 118 | node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name); | ||
| 119 | node->data.fn_call_expr.is_builtin = true; | ||
| 120 | return node; | ||
| 121 | } | ||
| 122 | |||
| 123 | static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *name) { | ||
| 124 | return trans_create_node_builtin_fn_call(c, buf_create_from_str(name)); | ||
| 125 | } | ||
| 126 | |||
| 127 | static AstNode *trans_create_node_opaque(Context *c) { | ||
| 128 | return trans_create_node_builtin_fn_call_str(c, "OpaqueType"); | ||
| 129 | } | ||
| 130 | |||
| 131 | static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) { | ||
| 132 | AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr); | ||
| 133 | node->data.field_access_expr.struct_expr = container; | ||
| 134 | node->data.field_access_expr.field_name = field_name; | ||
| 135 | return node; | ||
| 136 | } | ||
| 137 | |||
| 138 | static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) { | ||
| 139 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | ||
| 140 | node->data.prefix_op_expr.prefix_op = op; | ||
| 141 | node->data.prefix_op_expr.primary_expr = child_node; | ||
| 142 | return node; | ||
| 143 | } | ||
| 144 | |||
| 145 | static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) { | ||
| 146 | AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr); | ||
| 147 | node->data.addr_of_expr.is_const = is_const; | ||
| 148 | node->data.addr_of_expr.is_volatile = is_volatile; | ||
| 149 | node->data.addr_of_expr.op_expr = child_node; | ||
| 150 | return node; | ||
| 151 | } | ||
| 152 | |||
| 153 | static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { | ||
| 154 | AstNode *node = trans_create_node(c, NodeTypeStringLiteral); | ||
| 155 | node->data.string_literal.buf = buf; | ||
| 156 | node->data.string_literal.c = true; | ||
| 157 | return node; | ||
| 158 | } | ||
| 159 | |||
| 160 | static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) { | ||
| 161 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); | ||
| 162 | node->data.int_literal.bigint = allocate<BigInt>(1); | ||
| 163 | bigint_init_data(node->data.int_literal.bigint, &x, 1, is_negative); | ||
| 164 | return node; | ||
| 165 | } | ||
| 166 | |||
| 167 | static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) { | ||
| 168 | return trans_create_node_unsigned_negative(c, x, false); | ||
| 169 | } | ||
| 170 | |||
| 171 | static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) { | ||
| 172 | AstNode *node = trans_create_node(c, NodeTypeFnCallExpr); | ||
| 173 | node->data.fn_call_expr.fn_ref_expr = dest; | ||
| 174 | node->data.fn_call_expr.params.resize(1); | ||
| 175 | node->data.fn_call_expr.params.items[0] = src; | ||
| 176 | return node; | ||
| 177 | } | ||
| 178 | |||
| 179 | static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative, | ||
| 180 | const char *type_name) | ||
| 181 | { | ||
| 182 | AstNode *lit_node = trans_create_node_unsigned_negative(c, x, is_negative); | ||
| 183 | return trans_create_node_cast(c, trans_create_node_symbol_str(c, type_name), lit_node); | ||
| 184 | } | ||
| 185 | |||
| 186 | static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, AstNode *child_type_node) { | ||
| 187 | AstNode *node = trans_create_node(c, NodeTypeArrayType); | ||
| 188 | node->data.array_type.size = size_node; | ||
| 189 | node->data.array_type.child_type = child_type_node; | ||
| 190 | return node; | ||
| 191 | } | ||
| 192 | |||
| 193 | static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_name, AstNode *type_node, | ||
| 194 | AstNode *init_node) | ||
| 195 | { | ||
| 196 | AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration); | ||
| 197 | node->data.variable_declaration.visib_mod = c->visib_mod; | ||
| 198 | node->data.variable_declaration.symbol = var_name; | ||
| 199 | node->data.variable_declaration.is_const = is_const; | ||
| 200 | node->data.variable_declaration.type = type_node; | ||
| 201 | node->data.variable_declaration.expr = init_node; | ||
| 202 | return node; | ||
| 203 | } | ||
| 204 | |||
| 205 | |||
| 206 | static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) { | ||
| 207 | AstNode *fn_def = trans_create_node(c, NodeTypeFnDef); | ||
| 208 | AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto); | ||
| 209 | fn_proto->data.fn_proto.visib_mod = c->visib_mod; | ||
| 210 | fn_proto->data.fn_proto.name = fn_name; | ||
| 211 | fn_proto->data.fn_proto.is_inline = true; | ||
| 212 | fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias? | ||
| 213 | |||
| 214 | fn_def->data.fn_def.fn_proto = fn_proto; | ||
| 215 | fn_proto->data.fn_proto.fn_def_node = fn_def; | ||
| 216 | |||
| 217 | AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, trans_create_node_symbol(c, var_name)); | ||
| 218 | AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr); | ||
| 219 | fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node; | ||
| 220 | |||
| 221 | for (size_t i = 0; i < src_proto_node->data.fn_proto.params.length; i += 1) { | ||
| 222 | AstNode *src_param_node = src_proto_node->data.fn_proto.params.at(i); | ||
| 223 | Buf *param_name = src_param_node->data.param_decl.name; | ||
| 224 | if (!param_name) param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i); | ||
| 225 | |||
| 226 | AstNode *dest_param_node = trans_create_node(c, NodeTypeParamDecl); | ||
| 227 | dest_param_node->data.param_decl.name = param_name; | ||
| 228 | dest_param_node->data.param_decl.type = src_param_node->data.param_decl.type; | ||
| 229 | dest_param_node->data.param_decl.is_noalias = src_param_node->data.param_decl.is_noalias; | ||
| 230 | fn_proto->data.fn_proto.params.append(dest_param_node); | ||
| 231 | |||
| 232 | fn_call_node->data.fn_call_expr.params.append(trans_create_node_symbol(c, param_name)); | ||
| 233 | |||
| 234 | } | ||
| 235 | |||
| 236 | AstNode *block = trans_create_node(c, NodeTypeBlock); | ||
| 237 | block->data.block.statements.resize(1); | ||
| 238 | block->data.block.statements.items[0] = fn_call_node; | ||
| 239 | block->data.block.last_statement_is_result_expression = true; | ||
| 240 | |||
| 241 | fn_def->data.fn_def.body = block; | ||
| 242 | return fn_def; | ||
| 243 | } | ||
| 244 | |||
| 245 | static AstNode *get_global(Context *c, Buf *name) { | ||
| 246 | for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) { | ||
| 247 | AstNode *decl_node = c->root->data.root.top_level_decls.items[i]; | ||
| 248 | if (decl_node->type == NodeTypeVariableDeclaration) { | ||
| 249 | if (buf_eql_buf(decl_node->data.variable_declaration.symbol, name)) { | ||
| 250 | return decl_node; | ||
| 251 | } | ||
| 252 | } else if (decl_node->type == NodeTypeFnDef) { | ||
| 253 | if (buf_eql_buf(decl_node->data.fn_def.fn_proto->data.fn_proto.name, name)) { | ||
| 254 | return decl_node; | ||
| 255 | } | ||
| 256 | } else if (decl_node->type == NodeTypeFnProto) { | ||
| 257 | if (buf_eql_buf(decl_node->data.fn_proto.name, name)) { | ||
| 258 | return decl_node; | ||
| 259 | } | ||
| 260 | } | ||
| 261 | } | ||
| 262 | { | ||
| 263 | auto entry = c->macro_table.maybe_get(name); | ||
| 264 | if (entry) | ||
| 265 | return entry->value; | ||
| 266 | } | ||
| 267 | return nullptr; | ||
| 268 | } | ||
| 269 | |||
| 270 | static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) { | ||
| 271 | bool is_const = true; | ||
| 272 | AstNode *type_node = nullptr; | ||
| 273 | AstNode *node = trans_create_node_var_decl(c, is_const, var_name, type_node, value_node); | ||
| 274 | c->root->data.root.top_level_decls.append(node); | ||
| 275 | return node; | ||
| 276 | } | ||
| 277 | |||
| 278 | static const char *decl_name(const Decl *decl) { | ||
| 279 | const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl); | ||
| 280 | return (const char *)named_decl->getName().bytes_begin(); | ||
| 281 | } | ||
| 282 | |||
| 283 | static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) { | ||
| 284 | AstNode *node = trans_create_node(c, NodeTypeIntLiteral); | ||
| 285 | node->data.int_literal.bigint = allocate<BigInt>(1); | ||
| 286 | bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative()); | ||
| 287 | return node; | ||
| 288 | |||
| 289 | } | ||
| 290 | |||
| 291 | static bool is_c_void_type(AstNode *node) { | ||
| 292 | return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void")); | ||
| 293 | } | ||
| 294 | |||
| 295 | static bool qual_type_child_is_fn_proto(const QualType &qt) { | ||
| 296 | if (qt.getTypePtr()->getTypeClass() == Type::Paren) { | ||
| 297 | const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr()); | ||
| 298 | if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) { | ||
| 299 | return true; | ||
| 300 | } | ||
| 301 | } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) { | ||
| 302 | const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr()); | ||
| 303 | return qual_type_child_is_fn_proto(attr_type->getEquivalentType()); | ||
| 304 | } | ||
| 305 | return false; | ||
| 306 | } | ||
| 307 | |||
| 308 | static bool c_is_signed_integer(Context *c, QualType qt) { | ||
| 309 | const Type *c_type = qt.getTypePtr(); | ||
| 310 | if (c_type->getTypeClass() != Type::Builtin) | ||
| 311 | return false; | ||
| 312 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | ||
| 313 | switch (builtin_ty->getKind()) { | ||
| 314 | case BuiltinType::SChar: | ||
| 315 | case BuiltinType::Short: | ||
| 316 | case BuiltinType::Int: | ||
| 317 | case BuiltinType::Long: | ||
| 318 | case BuiltinType::LongLong: | ||
| 319 | case BuiltinType::Int128: | ||
| 320 | case BuiltinType::WChar_S: | ||
| 321 | return true; | ||
| 322 | default: | ||
| 323 | return false; | ||
| 324 | } | ||
| 325 | } | ||
| 326 | |||
| 327 | static bool c_is_unsigned_integer(Context *c, QualType qt) { | ||
| 328 | const Type *c_type = qt.getTypePtr(); | ||
| 329 | if (c_type->getTypeClass() != Type::Builtin) | ||
| 330 | return false; | ||
| 331 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | ||
| 332 | switch (builtin_ty->getKind()) { | ||
| 333 | case BuiltinType::Char_U: | ||
| 334 | case BuiltinType::UChar: | ||
| 335 | case BuiltinType::Char_S: | ||
| 336 | case BuiltinType::UShort: | ||
| 337 | case BuiltinType::UInt: | ||
| 338 | case BuiltinType::ULong: | ||
| 339 | case BuiltinType::ULongLong: | ||
| 340 | case BuiltinType::UInt128: | ||
| 341 | case BuiltinType::WChar_U: | ||
| 342 | return true; | ||
| 343 | default: | ||
| 344 | return false; | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | static bool c_is_float(Context *c, QualType qt) { | ||
| 349 | const Type *c_type = qt.getTypePtr(); | ||
| 350 | if (c_type->getTypeClass() != Type::Builtin) | ||
| 351 | return false; | ||
| 352 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type); | ||
| 353 | switch (builtin_ty->getKind()) { | ||
| 354 | case BuiltinType::Half: | ||
| 355 | case BuiltinType::Float: | ||
| 356 | case BuiltinType::Double: | ||
| 357 | case BuiltinType::Float128: | ||
| 358 | case BuiltinType::LongDouble: | ||
| 359 | return true; | ||
| 360 | default: | ||
| 361 | return false; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | static AstNode * trans_stmt(Context *c, AstNode *block, Stmt *stmt); | ||
| 366 | static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc); | ||
| 367 | |||
| 368 | static AstNode * trans_expr(Context *c, AstNode *block, Expr *expr) { | ||
| 369 | return trans_stmt(c, block, expr); | ||
| 370 | } | ||
| 371 | |||
| 372 | static AstNode *trans_type_with_table(Context *c, const Type *ty, const SourceLocation &source_loc) { | ||
| 373 | switch (ty->getTypeClass()) { | ||
| 374 | case Type::Builtin: | ||
| 375 | { | ||
| 376 | const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty); | ||
| 377 | switch (builtin_ty->getKind()) { | ||
| 378 | case BuiltinType::Void: | ||
| 379 | return trans_create_node_symbol_str(c, "c_void"); | ||
| 380 | case BuiltinType::Bool: | ||
| 381 | return trans_create_node_symbol_str(c, "bool"); | ||
| 382 | case BuiltinType::Char_U: | ||
| 383 | case BuiltinType::UChar: | ||
| 384 | case BuiltinType::Char_S: | ||
| 385 | return trans_create_node_symbol_str(c, "u8"); | ||
| 386 | case BuiltinType::SChar: | ||
| 387 | return trans_create_node_symbol_str(c, "i8"); | ||
| 388 | case BuiltinType::UShort: | ||
| 389 | return trans_create_node_symbol_str(c, "c_ushort"); | ||
| 390 | case BuiltinType::UInt: | ||
| 391 | return trans_create_node_symbol_str(c, "c_uint"); | ||
| 392 | case BuiltinType::ULong: | ||
| 393 | return trans_create_node_symbol_str(c, "c_ulong"); | ||
| 394 | case BuiltinType::ULongLong: | ||
| 395 | return trans_create_node_symbol_str(c, "c_ulonglong"); | ||
| 396 | case BuiltinType::Short: | ||
| 397 | return trans_create_node_symbol_str(c, "c_short"); | ||
| 398 | case BuiltinType::Int: | ||
| 399 | return trans_create_node_symbol_str(c, "c_int"); | ||
| 400 | case BuiltinType::Long: | ||
| 401 | return trans_create_node_symbol_str(c, "c_long"); | ||
| 402 | case BuiltinType::LongLong: | ||
| 403 | return trans_create_node_symbol_str(c, "c_longlong"); | ||
| 404 | case BuiltinType::UInt128: | ||
| 405 | return trans_create_node_symbol_str(c, "u128"); | ||
| 406 | case BuiltinType::Int128: | ||
| 407 | return trans_create_node_symbol_str(c, "i128"); | ||
| 408 | case BuiltinType::Float: | ||
| 409 | return trans_create_node_symbol_str(c, "f32"); | ||
| 410 | case BuiltinType::Double: | ||
| 411 | return trans_create_node_symbol_str(c, "f64"); | ||
| 412 | case BuiltinType::Float128: | ||
| 413 | return trans_create_node_symbol_str(c, "f128"); | ||
| 414 | case BuiltinType::LongDouble: | ||
| 415 | return trans_create_node_symbol_str(c, "c_longdouble"); | ||
| 416 | case BuiltinType::WChar_U: | ||
| 417 | case BuiltinType::Char16: | ||
| 418 | case BuiltinType::Char32: | ||
| 419 | case BuiltinType::WChar_S: | ||
| 420 | case BuiltinType::Half: | ||
| 421 | case BuiltinType::NullPtr: | ||
| 422 | case BuiltinType::ObjCId: | ||
| 423 | case BuiltinType::ObjCClass: | ||
| 424 | case BuiltinType::ObjCSel: | ||
| 425 | case BuiltinType::OMPArraySection: | ||
| 426 | case BuiltinType::Dependent: | ||
| 427 | case BuiltinType::Overload: | ||
| 428 | case BuiltinType::BoundMember: | ||
| 429 | case BuiltinType::PseudoObject: | ||
| 430 | case BuiltinType::UnknownAny: | ||
| 431 | case BuiltinType::BuiltinFn: | ||
| 432 | case BuiltinType::ARCUnbridgedCast: | ||
| 433 | |||
| 434 | case BuiltinType::OCLImage1dRO: | ||
| 435 | case BuiltinType::OCLImage1dArrayRO: | ||
| 436 | case BuiltinType::OCLImage1dBufferRO: | ||
| 437 | case BuiltinType::OCLImage2dRO: | ||
| 438 | case BuiltinType::OCLImage2dArrayRO: | ||
| 439 | case BuiltinType::OCLImage2dDepthRO: | ||
| 440 | case BuiltinType::OCLImage2dArrayDepthRO: | ||
| 441 | case BuiltinType::OCLImage2dMSAARO: | ||
| 442 | case BuiltinType::OCLImage2dArrayMSAARO: | ||
| 443 | case BuiltinType::OCLImage2dMSAADepthRO: | ||
| 444 | case BuiltinType::OCLImage2dArrayMSAADepthRO: | ||
| 445 | case BuiltinType::OCLImage3dRO: | ||
| 446 | case BuiltinType::OCLImage1dWO: | ||
| 447 | case BuiltinType::OCLImage1dArrayWO: | ||
| 448 | case BuiltinType::OCLImage1dBufferWO: | ||
| 449 | case BuiltinType::OCLImage2dWO: | ||
| 450 | case BuiltinType::OCLImage2dArrayWO: | ||
| 451 | case BuiltinType::OCLImage2dDepthWO: | ||
| 452 | case BuiltinType::OCLImage2dArrayDepthWO: | ||
| 453 | case BuiltinType::OCLImage2dMSAAWO: | ||
| 454 | case BuiltinType::OCLImage2dArrayMSAAWO: | ||
| 455 | case BuiltinType::OCLImage2dMSAADepthWO: | ||
| 456 | case BuiltinType::OCLImage2dArrayMSAADepthWO: | ||
| 457 | case BuiltinType::OCLImage3dWO: | ||
| 458 | case BuiltinType::OCLImage1dRW: | ||
| 459 | case BuiltinType::OCLImage1dArrayRW: | ||
| 460 | case BuiltinType::OCLImage1dBufferRW: | ||
| 461 | case BuiltinType::OCLImage2dRW: | ||
| 462 | case BuiltinType::OCLImage2dArrayRW: | ||
| 463 | case BuiltinType::OCLImage2dDepthRW: | ||
| 464 | case BuiltinType::OCLImage2dArrayDepthRW: | ||
| 465 | case BuiltinType::OCLImage2dMSAARW: | ||
| 466 | case BuiltinType::OCLImage2dArrayMSAARW: | ||
| 467 | case BuiltinType::OCLImage2dMSAADepthRW: | ||
| 468 | case BuiltinType::OCLImage2dArrayMSAADepthRW: | ||
| 469 | case BuiltinType::OCLImage3dRW: | ||
| 470 | case BuiltinType::OCLSampler: | ||
| 471 | case BuiltinType::OCLEvent: | ||
| 472 | case BuiltinType::OCLClkEvent: | ||
| 473 | case BuiltinType::OCLQueue: | ||
| 474 | case BuiltinType::OCLReserveID: | ||
| 475 | emit_warning(c, source_loc, "unsupported builtin type"); | ||
| 476 | return nullptr; | ||
| 477 | } | ||
| 478 | break; | ||
| 479 | } | ||
| 480 | case Type::Pointer: | ||
| 481 | { | ||
| 482 | const PointerType *pointer_ty = static_cast<const PointerType*>(ty); | ||
| 483 | QualType child_qt = pointer_ty->getPointeeType(); | ||
| 484 | AstNode *child_node = trans_qual_type(c, child_qt, source_loc); | ||
| 485 | if (child_node == nullptr) { | ||
| 486 | emit_warning(c, source_loc, "pointer to unsupported type"); | ||
| 487 | return nullptr; | ||
| 488 | } | ||
| 489 | |||
| 490 | if (qual_type_child_is_fn_proto(child_qt)) { | ||
| 491 | return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node); | ||
| 492 | } | ||
| 493 | |||
| 494 | AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(), | ||
| 495 | child_qt.isVolatileQualified(), child_node); | ||
| 496 | return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node); | ||
| 497 | } | ||
| 498 | case Type::Typedef: | ||
| 499 | { | ||
| 500 | const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty); | ||
| 501 | const TypedefNameDecl *typedef_decl = typedef_ty->getDecl(); | ||
| 502 | return resolve_typedef_decl(c, typedef_decl); | ||
| 503 | } | ||
| 504 | case Type::Elaborated: | ||
| 505 | { | ||
| 506 | const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty); | ||
| 507 | switch (elaborated_ty->getKeyword()) { | ||
| 508 | case ETK_Struct: | ||
| 509 | return trans_qual_type_with_table(c, elaborated_ty->getNamedType(), source_loc); | ||
| 510 | case ETK_Enum: | ||
| 511 | return trans_qual_type_with_table(c, elaborated_ty->getNamedType(), source_loc); | ||
| 512 | case ETK_Interface: | ||
| 513 | case ETK_Union: | ||
| 514 | case ETK_Class: | ||
| 515 | case ETK_Typename: | ||
| 516 | case ETK_None: | ||
| 517 | emit_warning(c, source_loc, "unsupported elaborated type"); | ||
| 518 | return nullptr; | ||
| 519 | } | ||
| 520 | } | ||
| 521 | case Type::FunctionProto: | ||
| 522 | { | ||
| 523 | const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty); | ||
| 524 | |||
| 525 | AstNode *proto_node = trans_create_node(c, NodeTypeFnProto); | ||
| 526 | switch (fn_proto_ty->getCallConv()) { | ||
| 527 | case CC_C: // __attribute__((cdecl)) | ||
| 528 | proto_node->data.fn_proto.cc = CallingConventionC; | ||
| 529 | proto_node->data.fn_proto.is_extern = true; | ||
| 530 | break; | ||
| 531 | case CC_X86StdCall: // __attribute__((stdcall)) | ||
| 532 | proto_node->data.fn_proto.cc = CallingConventionStdcall; | ||
| 533 | break; | ||
| 534 | case CC_X86FastCall: // __attribute__((fastcall)) | ||
| 535 | emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall"); | ||
| 536 | return nullptr; | ||
| 537 | case CC_X86ThisCall: // __attribute__((thiscall)) | ||
| 538 | emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall"); | ||
| 539 | return nullptr; | ||
| 540 | case CC_X86VectorCall: // __attribute__((vectorcall)) | ||
| 541 | emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall"); | ||
| 542 | return nullptr; | ||
| 543 | case CC_X86Pascal: // __attribute__((pascal)) | ||
| 544 | emit_warning(c, source_loc, "unsupported calling convention: x86 pascal"); | ||
| 545 | return nullptr; | ||
| 546 | case CC_Win64: // __attribute__((ms_abi)) | ||
| 547 | emit_warning(c, source_loc, "unsupported calling convention: win64"); | ||
| 548 | return nullptr; | ||
| 549 | case CC_X86_64SysV: // __attribute__((sysv_abi)) | ||
| 550 | emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv"); | ||
| 551 | return nullptr; | ||
| 552 | case CC_X86RegCall: | ||
| 553 | emit_warning(c, source_loc, "unsupported calling convention: x86 reg"); | ||
| 554 | return nullptr; | ||
| 555 | case CC_AAPCS: // __attribute__((pcs("aapcs"))) | ||
| 556 | emit_warning(c, source_loc, "unsupported calling convention: aapcs"); | ||
| 557 | return nullptr; | ||
| 558 | case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp"))) | ||
| 559 | emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp"); | ||
| 560 | return nullptr; | ||
| 561 | case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc)) | ||
| 562 | emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc"); | ||
| 563 | return nullptr; | ||
| 564 | case CC_SpirFunction: // default for OpenCL functions on SPIR target | ||
| 565 | emit_warning(c, source_loc, "unsupported calling convention: SPIR function"); | ||
| 566 | return nullptr; | ||
| 567 | case CC_OpenCLKernel: | ||
| 568 | emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel"); | ||
| 569 | return nullptr; | ||
| 570 | case CC_Swift: | ||
| 571 | emit_warning(c, source_loc, "unsupported calling convention: Swift"); | ||
| 572 | return nullptr; | ||
| 573 | case CC_PreserveMost: | ||
| 574 | emit_warning(c, source_loc, "unsupported calling convention: PreserveMost"); | ||
| 575 | return nullptr; | ||
| 576 | case CC_PreserveAll: | ||
| 577 | emit_warning(c, source_loc, "unsupported calling convention: PreserveAll"); | ||
| 578 | return nullptr; | ||
| 579 | } | ||
| 580 | |||
| 581 | proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic(); | ||
| 582 | size_t param_count = fn_proto_ty->getNumParams(); | ||
| 583 | |||
| 584 | if (fn_proto_ty->getNoReturnAttr()) { | ||
| 585 | proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn"); | ||
| 586 | } else { | ||
| 587 | proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(), | ||
| 588 | source_loc); | ||
| 589 | if (proto_node->data.fn_proto.return_type == nullptr) { | ||
| 590 | emit_warning(c, source_loc, "unsupported function proto return type"); | ||
| 591 | return nullptr; | ||
| 592 | } | ||
| 593 | // convert c_void to actual void (only for return type) | ||
| 594 | if (is_c_void_type(proto_node->data.fn_proto.return_type)) { | ||
| 595 | proto_node->data.fn_proto.return_type = nullptr; | ||
| 596 | } | ||
| 597 | } | ||
| 598 | |||
| 599 | //emit_warning(c, source_loc, "TODO figure out fn prototype fn name"); | ||
| 600 | const char *fn_name = nullptr; | ||
| 601 | if (fn_name != nullptr) { | ||
| 602 | proto_node->data.fn_proto.name = buf_create_from_str(fn_name); | ||
| 603 | } | ||
| 604 | |||
| 605 | for (size_t i = 0; i < param_count; i += 1) { | ||
| 606 | QualType qt = fn_proto_ty->getParamType(i); | ||
| 607 | AstNode *param_type_node = trans_qual_type(c, qt, source_loc); | ||
| 608 | |||
| 609 | if (param_type_node == nullptr) { | ||
| 610 | emit_warning(c, source_loc, "unresolved function proto parameter type"); | ||
| 611 | return nullptr; | ||
| 612 | } | ||
| 613 | |||
| 614 | AstNode *param_node = trans_create_node(c, NodeTypeParamDecl); | ||
| 615 | //emit_warning(c, source_loc, "TODO figure out fn prototype param name"); | ||
| 616 | const char *param_name = nullptr; | ||
| 617 | if (param_name != nullptr) { | ||
| 618 | param_node->data.param_decl.name = buf_create_from_str(param_name); | ||
| 619 | } | ||
| 620 | param_node->data.param_decl.is_noalias = qt.isRestrictQualified(); | ||
| 621 | param_node->data.param_decl.type = param_type_node; | ||
| 622 | proto_node->data.fn_proto.params.append(param_node); | ||
| 623 | } | ||
| 624 | // TODO check for always_inline attribute | ||
| 625 | // TODO check for align attribute | ||
| 626 | |||
| 627 | return proto_node; | ||
| 628 | } | ||
| 629 | case Type::Record: | ||
| 630 | { | ||
| 631 | const RecordType *record_ty = static_cast<const RecordType*>(ty); | ||
| 632 | return resolve_record_decl(c, record_ty->getDecl()); | ||
| 633 | } | ||
| 634 | case Type::Enum: | ||
| 635 | { | ||
| 636 | const EnumType *enum_ty = static_cast<const EnumType*>(ty); | ||
| 637 | return resolve_enum_decl(c, enum_ty->getDecl()); | ||
| 638 | } | ||
| 639 | case Type::ConstantArray: | ||
| 640 | { | ||
| 641 | const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty); | ||
| 642 | AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc); | ||
| 643 | if (child_type_node == nullptr) { | ||
| 644 | emit_warning(c, source_loc, "unresolved array element type"); | ||
| 645 | return nullptr; | ||
| 646 | } | ||
| 647 | uint64_t size = const_arr_ty->getSize().getLimitedValue(); | ||
| 648 | AstNode *size_node = trans_create_node_unsigned(c, size); | ||
| 649 | return trans_create_node_array_type(c, size_node, child_type_node); | ||
| 650 | } | ||
| 651 | case Type::Paren: | ||
| 652 | { | ||
| 653 | const ParenType *paren_ty = static_cast<const ParenType *>(ty); | ||
| 654 | return trans_qual_type(c, paren_ty->getInnerType(), source_loc); | ||
| 655 | } | ||
| 656 | case Type::Decayed: | ||
| 657 | { | ||
| 658 | const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty); | ||
| 659 | return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc); | ||
| 660 | } | ||
| 661 | case Type::Attributed: | ||
| 662 | { | ||
| 663 | const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty); | ||
| 664 | return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc); | ||
| 665 | } | ||
| 666 | case Type::BlockPointer: | ||
| 667 | case Type::LValueReference: | ||
| 668 | case Type::RValueReference: | ||
| 669 | case Type::MemberPointer: | ||
| 670 | case Type::IncompleteArray: | ||
| 671 | case Type::VariableArray: | ||
| 672 | case Type::DependentSizedArray: | ||
| 673 | case Type::DependentSizedExtVector: | ||
| 674 | case Type::Vector: | ||
| 675 | case Type::ExtVector: | ||
| 676 | case Type::FunctionNoProto: | ||
| 677 | case Type::UnresolvedUsing: | ||
| 678 | case Type::Adjusted: | ||
| 679 | case Type::TypeOfExpr: | ||
| 680 | case Type::TypeOf: | ||
| 681 | case Type::Decltype: | ||
| 682 | case Type::UnaryTransform: | ||
| 683 | case Type::TemplateTypeParm: | ||
| 684 | case Type::SubstTemplateTypeParm: | ||
| 685 | case Type::SubstTemplateTypeParmPack: | ||
| 686 | case Type::TemplateSpecialization: | ||
| 687 | case Type::Auto: | ||
| 688 | case Type::InjectedClassName: | ||
| 689 | case Type::DependentName: | ||
| 690 | case Type::DependentTemplateSpecialization: | ||
| 691 | case Type::PackExpansion: | ||
| 692 | case Type::ObjCObject: | ||
| 693 | case Type::ObjCInterface: | ||
| 694 | case Type::Complex: | ||
| 695 | case Type::ObjCObjectPointer: | ||
| 696 | case Type::Atomic: | ||
| 697 | case Type::Pipe: | ||
| 698 | case Type::ObjCTypeParam: | ||
| 699 | case Type::DeducedTemplateSpecialization: | ||
| 700 | emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName()); | ||
| 701 | return nullptr; | ||
| 702 | } | ||
| 703 | zig_unreachable(); | ||
| 704 | } | ||
| 705 | |||
| 706 | static AstNode * trans_qual_type_with_table(Context *c, QualType qt, const SourceLocation &source_loc) { | ||
| 707 | return trans_type_with_table(c, qt.getTypePtr(), source_loc); | ||
| 708 | } | ||
| 709 | |||
| 710 | static AstNode * trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) { | ||
| 711 | return trans_qual_type_with_table(c, qt, source_loc); | ||
| 712 | } | ||
| 713 | |||
| 714 | static AstNode * trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) { | ||
| 715 | AstNode *child_block = trans_create_node(c, NodeTypeBlock); | ||
| 716 | for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) { | ||
| 717 | AstNode *child_node = trans_stmt(c, child_block, *it); | ||
| 718 | if (child_node != nullptr) | ||
| 719 | child_block->data.block.statements.append(child_node); | ||
| 720 | } | ||
| 721 | return child_block; | ||
| 722 | } | ||
| 723 | |||
| 724 | static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) { | ||
| 725 | Expr *value_expr = stmt->getRetValue(); | ||
| 726 | if (value_expr == nullptr) { | ||
| 727 | zig_panic("TODO handle C return void"); | ||
| 728 | } else { | ||
| 729 | AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr); | ||
| 730 | return_node->data.return_expr.expr = trans_expr(c, block, value_expr); | ||
| 731 | return return_node; | ||
| 732 | } | ||
| 733 | } | ||
| 734 | |||
| 735 | static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) { | ||
| 736 | llvm::APSInt result; | ||
| 737 | if (!stmt->EvaluateAsInt(result, *c->ctx)) { | ||
| 738 | zig_panic("TODO handle libclang unable to evaluate C integer literal"); | ||
| 739 | } | ||
| 740 | return trans_create_node_apint(c, result); | ||
| 741 | } | ||
| 742 | |||
| 743 | static AstNode *trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) { | ||
| 744 | AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr); | ||
| 745 | |||
| 746 | Expr *cond_expr = stmt->getCond(); | ||
| 747 | Expr *true_expr = stmt->getTrueExpr(); | ||
| 748 | Expr *false_expr = stmt->getFalseExpr(); | ||
| 749 | |||
| 750 | node->data.if_bool_expr.condition = trans_expr(c, block, cond_expr); | ||
| 751 | node->data.if_bool_expr.then_block = trans_expr(c, block, true_expr); | ||
| 752 | node->data.if_bool_expr.else_node = trans_expr(c, block, false_expr); | ||
| 753 | |||
| 754 | return node; | ||
| 755 | } | ||
| 756 | |||
| 757 | static AstNode * trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) { | ||
| 758 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | ||
| 759 | node->data.bin_op_expr.bin_op = bin_op; | ||
| 760 | node->data.bin_op_expr.op1 = trans_expr(c, block, lhs); | ||
| 761 | node->data.bin_op_expr.op2 = trans_expr(c, block, rhs); | ||
| 762 | return node; | ||
| 763 | } | ||
| 764 | |||
| 765 | static AstNode * trans_binary_operator(Context *c, AstNode *block, BinaryOperator *stmt) { | ||
| 766 | switch (stmt->getOpcode()) { | ||
| 767 | case BO_PtrMemD: | ||
| 768 | zig_panic("TODO handle more C binary operators: BO_PtrMemD"); | ||
| 769 | case BO_PtrMemI: | ||
| 770 | zig_panic("TODO handle more C binary operators: BO_PtrMemI"); | ||
| 771 | case BO_Mul: | ||
| 772 | zig_panic("TODO handle more C binary operators: BO_Mul"); | ||
| 773 | case BO_Div: | ||
| 774 | zig_panic("TODO handle more C binary operators: BO_Div"); | ||
| 775 | case BO_Rem: | ||
| 776 | zig_panic("TODO handle more C binary operators: BO_Rem"); | ||
| 777 | case BO_Add: | ||
| 778 | zig_panic("TODO handle more C binary operators: BO_Add"); | ||
| 779 | case BO_Sub: | ||
| 780 | zig_panic("TODO handle more C binary operators: BO_Sub"); | ||
| 781 | case BO_Shl: | ||
| 782 | zig_panic("TODO handle more C binary operators: BO_Shl"); | ||
| 783 | case BO_Shr: | ||
| 784 | zig_panic("TODO handle more C binary operators: BO_Shr"); | ||
| 785 | case BO_LT: | ||
| 786 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); | ||
| 787 | case BO_GT: | ||
| 788 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); | ||
| 789 | case BO_LE: | ||
| 790 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); | ||
| 791 | case BO_GE: | ||
| 792 | return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); | ||
| 793 | case BO_EQ: | ||
| 794 | zig_panic("TODO handle more C binary operators: BO_EQ"); | ||
| 795 | case BO_NE: | ||
| 796 | zig_panic("TODO handle more C binary operators: BO_NE"); | ||
| 797 | case BO_And: | ||
| 798 | zig_panic("TODO handle more C binary operators: BO_And"); | ||
| 799 | case BO_Xor: | ||
| 800 | zig_panic("TODO handle more C binary operators: BO_Xor"); | ||
| 801 | case BO_Or: | ||
| 802 | zig_panic("TODO handle more C binary operators: BO_Or"); | ||
| 803 | case BO_LAnd: | ||
| 804 | zig_panic("TODO handle more C binary operators: BO_LAnd"); | ||
| 805 | case BO_LOr: | ||
| 806 | zig_panic("TODO handle more C binary operators: BO_LOr"); | ||
| 807 | case BO_Assign: | ||
| 808 | zig_panic("TODO handle more C binary operators: BO_Assign"); | ||
| 809 | case BO_MulAssign: | ||
| 810 | zig_panic("TODO handle more C binary operators: BO_MulAssign"); | ||
| 811 | case BO_DivAssign: | ||
| 812 | zig_panic("TODO handle more C binary operators: BO_DivAssign"); | ||
| 813 | case BO_RemAssign: | ||
| 814 | zig_panic("TODO handle more C binary operators: BO_RemAssign"); | ||
| 815 | case BO_AddAssign: | ||
| 816 | zig_panic("TODO handle more C binary operators: BO_AddAssign"); | ||
| 817 | case BO_SubAssign: | ||
| 818 | zig_panic("TODO handle more C binary operators: BO_SubAssign"); | ||
| 819 | case BO_ShlAssign: | ||
| 820 | zig_panic("TODO handle more C binary operators: BO_ShlAssign"); | ||
| 821 | case BO_ShrAssign: | ||
| 822 | zig_panic("TODO handle more C binary operators: BO_ShrAssign"); | ||
| 823 | case BO_AndAssign: | ||
| 824 | zig_panic("TODO handle more C binary operators: BO_AndAssign"); | ||
| 825 | case BO_XorAssign: | ||
| 826 | zig_panic("TODO handle more C binary operators: BO_XorAssign"); | ||
| 827 | case BO_OrAssign: | ||
| 828 | zig_panic("TODO handle more C binary operators: BO_OrAssign"); | ||
| 829 | case BO_Comma: | ||
| 830 | zig_panic("TODO handle more C binary operators: BO_Comma"); | ||
| 831 | } | ||
| 832 | |||
| 833 | zig_unreachable(); | ||
| 834 | } | ||
| 835 | |||
| 836 | static AstNode * trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) { | ||
| 837 | switch (stmt->getCastKind()) { | ||
| 838 | case CK_LValueToRValue: | ||
| 839 | return trans_expr(c, block, stmt->getSubExpr()); | ||
| 840 | case CK_IntegralCast: | ||
| 841 | { | ||
| 842 | AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast"); | ||
| 843 | node->data.fn_call_expr.params.append(trans_qual_type(c, stmt->getType(), stmt->getExprLoc())); | ||
| 844 | node->data.fn_call_expr.params.append(trans_expr(c, block, stmt->getSubExpr())); | ||
| 845 | return node; | ||
| 846 | } | ||
| 847 | case CK_Dependent: | ||
| 848 | zig_panic("TODO handle C translation cast CK_Dependent"); | ||
| 849 | case CK_BitCast: | ||
| 850 | zig_panic("TODO handle C translation cast CK_BitCast"); | ||
| 851 | case CK_LValueBitCast: | ||
| 852 | zig_panic("TODO handle C translation cast CK_LValueBitCast"); | ||
| 853 | case CK_NoOp: | ||
| 854 | zig_panic("TODO handle C translation cast CK_NoOp"); | ||
| 855 | case CK_BaseToDerived: | ||
| 856 | zig_panic("TODO handle C translation cast CK_BaseToDerived"); | ||
| 857 | case CK_DerivedToBase: | ||
| 858 | zig_panic("TODO handle C translation cast CK_DerivedToBase"); | ||
| 859 | case CK_UncheckedDerivedToBase: | ||
| 860 | zig_panic("TODO handle C translation cast CK_UncheckedDerivedToBase"); | ||
| 861 | case CK_Dynamic: | ||
| 862 | zig_panic("TODO handle C translation cast CK_Dynamic"); | ||
| 863 | case CK_ToUnion: | ||
| 864 | zig_panic("TODO handle C translation cast CK_ToUnion"); | ||
| 865 | case CK_ArrayToPointerDecay: | ||
| 866 | zig_panic("TODO handle C translation cast CK_ArrayToPointerDecay"); | ||
| 867 | case CK_FunctionToPointerDecay: | ||
| 868 | zig_panic("TODO handle C translation cast CK_FunctionToPointerDecay"); | ||
| 869 | case CK_NullToPointer: | ||
| 870 | zig_panic("TODO handle C translation cast CK_NullToPointer"); | ||
| 871 | case CK_NullToMemberPointer: | ||
| 872 | zig_panic("TODO handle C translation cast CK_NullToMemberPointer"); | ||
| 873 | case CK_BaseToDerivedMemberPointer: | ||
| 874 | zig_panic("TODO handle C translation cast CK_BaseToDerivedMemberPointer"); | ||
| 875 | case CK_DerivedToBaseMemberPointer: | ||
| 876 | zig_panic("TODO handle C translation cast CK_DerivedToBaseMemberPointer"); | ||
| 877 | case CK_MemberPointerToBoolean: | ||
| 878 | zig_panic("TODO handle C translation cast CK_MemberPointerToBoolean"); | ||
| 879 | case CK_ReinterpretMemberPointer: | ||
| 880 | zig_panic("TODO handle C translation cast CK_ReinterpretMemberPointer"); | ||
| 881 | case CK_UserDefinedConversion: | ||
| 882 | zig_panic("TODO handle C translation cast CK_UserDefinedConversion"); | ||
| 883 | case CK_ConstructorConversion: | ||
| 884 | zig_panic("TODO handle C translation cast CK_ConstructorConversion"); | ||
| 885 | case CK_IntegralToPointer: | ||
| 886 | zig_panic("TODO handle C translation cast CK_IntegralToPointer"); | ||
| 887 | case CK_PointerToIntegral: | ||
| 888 | zig_panic("TODO handle C translation cast CK_PointerToIntegral"); | ||
| 889 | case CK_PointerToBoolean: | ||
| 890 | zig_panic("TODO handle C translation cast CK_PointerToBoolean"); | ||
| 891 | case CK_ToVoid: | ||
| 892 | zig_panic("TODO handle C translation cast CK_ToVoid"); | ||
| 893 | case CK_VectorSplat: | ||
| 894 | zig_panic("TODO handle C translation cast CK_VectorSplat"); | ||
| 895 | case CK_IntegralToBoolean: | ||
| 896 | zig_panic("TODO handle C translation cast CK_IntegralToBoolean"); | ||
| 897 | case CK_IntegralToFloating: | ||
| 898 | zig_panic("TODO handle C translation cast CK_IntegralToFloating"); | ||
| 899 | case CK_FloatingToIntegral: | ||
| 900 | zig_panic("TODO handle C translation cast CK_FloatingToIntegral"); | ||
| 901 | case CK_FloatingToBoolean: | ||
| 902 | zig_panic("TODO handle C translation cast CK_FloatingToBoolean"); | ||
| 903 | case CK_BooleanToSignedIntegral: | ||
| 904 | zig_panic("TODO handle C translation cast CK_BooleanToSignedIntegral"); | ||
| 905 | case CK_FloatingCast: | ||
| 906 | zig_panic("TODO handle C translation cast CK_FloatingCast"); | ||
| 907 | case CK_CPointerToObjCPointerCast: | ||
| 908 | zig_panic("TODO handle C translation cast CK_CPointerToObjCPointerCast"); | ||
| 909 | case CK_BlockPointerToObjCPointerCast: | ||
| 910 | zig_panic("TODO handle C translation cast CK_BlockPointerToObjCPointerCast"); | ||
| 911 | case CK_AnyPointerToBlockPointerCast: | ||
| 912 | zig_panic("TODO handle C translation cast CK_AnyPointerToBlockPointerCast"); | ||
| 913 | case CK_ObjCObjectLValueCast: | ||
| 914 | zig_panic("TODO handle C translation cast CK_ObjCObjectLValueCast"); | ||
| 915 | case CK_FloatingRealToComplex: | ||
| 916 | zig_panic("TODO handle C translation cast CK_FloatingRealToComplex"); | ||
| 917 | case CK_FloatingComplexToReal: | ||
| 918 | zig_panic("TODO handle C translation cast CK_FloatingComplexToReal"); | ||
| 919 | case CK_FloatingComplexToBoolean: | ||
| 920 | zig_panic("TODO handle C translation cast CK_FloatingComplexToBoolean"); | ||
| 921 | case CK_FloatingComplexCast: | ||
| 922 | zig_panic("TODO handle C translation cast CK_FloatingComplexCast"); | ||
| 923 | case CK_FloatingComplexToIntegralComplex: | ||
| 924 | zig_panic("TODO handle C translation cast CK_FloatingComplexToIntegralComplex"); | ||
| 925 | case CK_IntegralRealToComplex: | ||
| 926 | zig_panic("TODO handle C translation cast CK_IntegralRealToComplex"); | ||
| 927 | case CK_IntegralComplexToReal: | ||
| 928 | zig_panic("TODO handle C translation cast CK_IntegralComplexToReal"); | ||
| 929 | case CK_IntegralComplexToBoolean: | ||
| 930 | zig_panic("TODO handle C translation cast CK_IntegralComplexToBoolean"); | ||
| 931 | case CK_IntegralComplexCast: | ||
| 932 | zig_panic("TODO handle C translation cast CK_IntegralComplexCast"); | ||
| 933 | case CK_IntegralComplexToFloatingComplex: | ||
| 934 | zig_panic("TODO handle C translation cast CK_IntegralComplexToFloatingComplex"); | ||
| 935 | case CK_ARCProduceObject: | ||
| 936 | zig_panic("TODO handle C translation cast CK_ARCProduceObject"); | ||
| 937 | case CK_ARCConsumeObject: | ||
| 938 | zig_panic("TODO handle C translation cast CK_ARCConsumeObject"); | ||
| 939 | case CK_ARCReclaimReturnedObject: | ||
| 940 | zig_panic("TODO handle C translation cast CK_ARCReclaimReturnedObject"); | ||
| 941 | case CK_ARCExtendBlockObject: | ||
| 942 | zig_panic("TODO handle C translation cast CK_ARCExtendBlockObject"); | ||
| 943 | case CK_AtomicToNonAtomic: | ||
| 944 | zig_panic("TODO handle C translation cast CK_AtomicToNonAtomic"); | ||
| 945 | case CK_NonAtomicToAtomic: | ||
| 946 | zig_panic("TODO handle C translation cast CK_NonAtomicToAtomic"); | ||
| 947 | case CK_CopyAndAutoreleaseBlockObject: | ||
| 948 | zig_panic("TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject"); | ||
| 949 | case CK_BuiltinFnToFnPtr: | ||
| 950 | zig_panic("TODO handle C translation cast CK_BuiltinFnToFnPtr"); | ||
| 951 | case CK_ZeroToOCLEvent: | ||
| 952 | zig_panic("TODO handle C translation cast CK_ZeroToOCLEvent"); | ||
| 953 | case CK_ZeroToOCLQueue: | ||
| 954 | zig_panic("TODO handle C translation cast CK_ZeroToOCLQueue"); | ||
| 955 | case CK_AddressSpaceConversion: | ||
| 956 | zig_panic("TODO handle C translation cast CK_AddressSpaceConversion"); | ||
| 957 | case CK_IntToOCLSampler: | ||
| 958 | zig_panic("TODO handle C translation cast CK_IntToOCLSampler"); | ||
| 959 | } | ||
| 960 | zig_unreachable(); | ||
| 961 | } | ||
| 962 | |||
| 963 | static AstNode * trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) { | ||
| 964 | ValueDecl *value_decl = stmt->getDecl(); | ||
| 965 | const char *name = decl_name(value_decl); | ||
| 966 | |||
| 967 | AstNode *node = trans_create_node(c, NodeTypeSymbol); | ||
| 968 | node->data.symbol_expr.symbol = buf_create_from_str(name); | ||
| 969 | return node; | ||
| 970 | } | ||
| 971 | |||
| 972 | static AstNode * trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) { | ||
| 973 | switch (stmt->getOpcode()) { | ||
| 974 | case UO_PostInc: | ||
| 975 | zig_panic("TODO handle C translation UO_PostInc"); | ||
| 976 | case UO_PostDec: | ||
| 977 | zig_panic("TODO handle C translation UO_PostDec"); | ||
| 978 | case UO_PreInc: | ||
| 979 | zig_panic("TODO handle C translation UO_PreInc"); | ||
| 980 | case UO_PreDec: | ||
| 981 | zig_panic("TODO handle C translation UO_PreDec"); | ||
| 982 | case UO_AddrOf: | ||
| 983 | zig_panic("TODO handle C translation UO_AddrOf"); | ||
| 984 | case UO_Deref: | ||
| 985 | zig_panic("TODO handle C translation UO_Deref"); | ||
| 986 | case UO_Plus: | ||
| 987 | zig_panic("TODO handle C translation UO_Plus"); | ||
| 988 | case UO_Minus: | ||
| 989 | { | ||
| 990 | Expr *op_expr = stmt->getSubExpr(); | ||
| 991 | if (c_is_signed_integer(c, op_expr->getType()) || c_is_float(c, op_expr->getType())) { | ||
| 992 | AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr); | ||
| 993 | node->data.prefix_op_expr.prefix_op = PrefixOpNegation; | ||
| 994 | node->data.prefix_op_expr.primary_expr = trans_expr(c, block, op_expr); | ||
| 995 | return node; | ||
| 996 | } else if (c_is_unsigned_integer(c, op_expr->getType())) { | ||
| 997 | // we gotta emit 0 -% x | ||
| 998 | AstNode *node = trans_create_node(c, NodeTypeBinOpExpr); | ||
| 999 | node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0); | ||
| 1000 | node->data.bin_op_expr.op2 = trans_expr(c, block, op_expr); | ||
| 1001 | node->data.bin_op_expr.bin_op = BinOpTypeSubWrap; | ||
| 1002 | return node; | ||
| 1003 | } else { | ||
| 1004 | zig_panic("TODO translate C negation with non float non integer"); | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | case UO_Not: | ||
| 1008 | zig_panic("TODO handle C translation UO_Not"); | ||
| 1009 | case UO_LNot: | ||
| 1010 | zig_panic("TODO handle C translation UO_LNot"); | ||
| 1011 | case UO_Real: | ||
| 1012 | zig_panic("TODO handle C translation UO_Real"); | ||
| 1013 | case UO_Imag: | ||
| 1014 | zig_panic("TODO handle C translation UO_Imag"); | ||
| 1015 | case UO_Extension: | ||
| 1016 | zig_panic("TODO handle C translation UO_Extension"); | ||
| 1017 | case UO_Coawait: | ||
| 1018 | zig_panic("TODO handle C translation UO_Coawait"); | ||
| 1019 | } | ||
| 1020 | zig_unreachable(); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | static AstNode * trans_local_declaration(Context *c, AstNode *block, DeclStmt *stmt) { | ||
| 1024 | for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) { | ||
| 1025 | Decl *decl = *iter; | ||
| 1026 | switch (decl->getKind()) { | ||
| 1027 | case Decl::Var: { | ||
| 1028 | VarDecl *var_decl = (VarDecl *)decl; | ||
| 1029 | QualType qual_type = var_decl->getTypeSourceInfo()->getType(); | ||
| 1030 | AstNode *init_node = var_decl->hasInit() ? trans_expr(c, block, var_decl->getInit()) : nullptr; | ||
| 1031 | AstNode *type_node = trans_qual_type(c, qual_type, stmt->getStartLoc()); | ||
| 1032 | AstNode *node = trans_create_node_var_decl(c, qual_type.isConstQualified(), | ||
| 1033 | buf_create_from_str(decl_name(var_decl)), type_node, init_node); | ||
| 1034 | block->data.block.statements.append(node); | ||
| 1035 | continue; | ||
| 1036 | } | ||
| 1037 | case Decl::AccessSpec: | ||
| 1038 | zig_panic("TODO handle decl kind AccessSpec"); | ||
| 1039 | case Decl::Block: | ||
| 1040 | zig_panic("TODO handle decl kind Block"); | ||
| 1041 | case Decl::Captured: | ||
| 1042 | zig_panic("TODO handle decl kind Captured"); | ||
| 1043 | case Decl::ClassScopeFunctionSpecialization: | ||
| 1044 | zig_panic("TODO handle decl kind ClassScopeFunctionSpecialization"); | ||
| 1045 | case Decl::Empty: | ||
| 1046 | zig_panic("TODO handle decl kind Empty"); | ||
| 1047 | case Decl::Export: | ||
| 1048 | zig_panic("TODO handle decl kind Export"); | ||
| 1049 | case Decl::ExternCContext: | ||
| 1050 | zig_panic("TODO handle decl kind ExternCContext"); | ||
| 1051 | case Decl::FileScopeAsm: | ||
| 1052 | zig_panic("TODO handle decl kind FileScopeAsm"); | ||
| 1053 | case Decl::Friend: | ||
| 1054 | zig_panic("TODO handle decl kind Friend"); | ||
| 1055 | case Decl::FriendTemplate: | ||
| 1056 | zig_panic("TODO handle decl kind FriendTemplate"); | ||
| 1057 | case Decl::Import: | ||
| 1058 | zig_panic("TODO handle decl kind Import"); | ||
| 1059 | case Decl::LinkageSpec: | ||
| 1060 | zig_panic("TODO handle decl kind LinkageSpec"); | ||
| 1061 | case Decl::Label: | ||
| 1062 | zig_panic("TODO handle decl kind Label"); | ||
| 1063 | case Decl::Namespace: | ||
| 1064 | zig_panic("TODO handle decl kind Namespace"); | ||
| 1065 | case Decl::NamespaceAlias: | ||
| 1066 | zig_panic("TODO handle decl kind NamespaceAlias"); | ||
| 1067 | case Decl::ObjCCompatibleAlias: | ||
| 1068 | zig_panic("TODO handle decl kind ObjCCompatibleAlias"); | ||
| 1069 | case Decl::ObjCCategory: | ||
| 1070 | zig_panic("TODO handle decl kind ObjCCategory"); | ||
| 1071 | case Decl::ObjCCategoryImpl: | ||
| 1072 | zig_panic("TODO handle decl kind ObjCCategoryImpl"); | ||
| 1073 | case Decl::ObjCImplementation: | ||
| 1074 | zig_panic("TODO handle decl kind ObjCImplementation"); | ||
| 1075 | case Decl::ObjCInterface: | ||
| 1076 | zig_panic("TODO handle decl kind ObjCInterface"); | ||
| 1077 | case Decl::ObjCProtocol: | ||
| 1078 | zig_panic("TODO handle decl kind ObjCProtocol"); | ||
| 1079 | case Decl::ObjCMethod: | ||
| 1080 | zig_panic("TODO handle decl kind ObjCMethod"); | ||
| 1081 | case Decl::ObjCProperty: | ||
| 1082 | zig_panic("TODO handle decl kind ObjCProperty"); | ||
| 1083 | case Decl::BuiltinTemplate: | ||
| 1084 | zig_panic("TODO handle decl kind BuiltinTemplate"); | ||
| 1085 | case Decl::ClassTemplate: | ||
| 1086 | zig_panic("TODO handle decl kind ClassTemplate"); | ||
| 1087 | case Decl::FunctionTemplate: | ||
| 1088 | zig_panic("TODO handle decl kind FunctionTemplate"); | ||
| 1089 | case Decl::TypeAliasTemplate: | ||
| 1090 | zig_panic("TODO handle decl kind TypeAliasTemplate"); | ||
| 1091 | case Decl::VarTemplate: | ||
| 1092 | zig_panic("TODO handle decl kind VarTemplate"); | ||
| 1093 | case Decl::TemplateTemplateParm: | ||
| 1094 | zig_panic("TODO handle decl kind TemplateTemplateParm"); | ||
| 1095 | case Decl::Enum: | ||
| 1096 | zig_panic("TODO handle decl kind Enum"); | ||
| 1097 | case Decl::Record: | ||
| 1098 | zig_panic("TODO handle decl kind Record"); | ||
| 1099 | case Decl::CXXRecord: | ||
| 1100 | zig_panic("TODO handle decl kind CXXRecord"); | ||
| 1101 | case Decl::ClassTemplateSpecialization: | ||
| 1102 | zig_panic("TODO handle decl kind ClassTemplateSpecialization"); | ||
| 1103 | case Decl::ClassTemplatePartialSpecialization: | ||
| 1104 | zig_panic("TODO handle decl kind ClassTemplatePartialSpecialization"); | ||
| 1105 | case Decl::TemplateTypeParm: | ||
| 1106 | zig_panic("TODO handle decl kind TemplateTypeParm"); | ||
| 1107 | case Decl::ObjCTypeParam: | ||
| 1108 | zig_panic("TODO handle decl kind ObjCTypeParam"); | ||
| 1109 | case Decl::TypeAlias: | ||
| 1110 | zig_panic("TODO handle decl kind TypeAlias"); | ||
| 1111 | case Decl::Typedef: | ||
| 1112 | zig_panic("TODO handle decl kind Typedef"); | ||
| 1113 | case Decl::UnresolvedUsingTypename: | ||
| 1114 | zig_panic("TODO handle decl kind UnresolvedUsingTypename"); | ||
| 1115 | case Decl::Using: | ||
| 1116 | zig_panic("TODO handle decl kind Using"); | ||
| 1117 | case Decl::UsingDirective: | ||
| 1118 | zig_panic("TODO handle decl kind UsingDirective"); | ||
| 1119 | case Decl::UsingPack: | ||
| 1120 | zig_panic("TODO handle decl kind UsingPack"); | ||
| 1121 | case Decl::UsingShadow: | ||
| 1122 | zig_panic("TODO handle decl kind UsingShadow"); | ||
| 1123 | case Decl::ConstructorUsingShadow: | ||
| 1124 | zig_panic("TODO handle decl kind ConstructorUsingShadow"); | ||
| 1125 | case Decl::Binding: | ||
| 1126 | zig_panic("TODO handle decl kind Binding"); | ||
| 1127 | case Decl::Field: | ||
| 1128 | zig_panic("TODO handle decl kind Field"); | ||
| 1129 | case Decl::ObjCAtDefsField: | ||
| 1130 | zig_panic("TODO handle decl kind ObjCAtDefsField"); | ||
| 1131 | case Decl::ObjCIvar: | ||
| 1132 | zig_panic("TODO handle decl kind ObjCIvar"); | ||
| 1133 | case Decl::Function: | ||
| 1134 | zig_panic("TODO handle decl kind Function"); | ||
| 1135 | case Decl::CXXDeductionGuide: | ||
| 1136 | zig_panic("TODO handle decl kind CXXDeductionGuide"); | ||
| 1137 | case Decl::CXXMethod: | ||
| 1138 | zig_panic("TODO handle decl kind CXXMethod"); | ||
| 1139 | case Decl::CXXConstructor: | ||
| 1140 | zig_panic("TODO handle decl kind CXXConstructor"); | ||
| 1141 | case Decl::CXXConversion: | ||
| 1142 | zig_panic("TODO handle decl kind CXXConversion"); | ||
| 1143 | case Decl::CXXDestructor: | ||
| 1144 | zig_panic("TODO handle decl kind CXXDestructor"); | ||
| 1145 | case Decl::MSProperty: | ||
| 1146 | zig_panic("TODO handle decl kind MSProperty"); | ||
| 1147 | case Decl::NonTypeTemplateParm: | ||
| 1148 | zig_panic("TODO handle decl kind NonTypeTemplateParm"); | ||
| 1149 | case Decl::Decomposition: | ||
| 1150 | zig_panic("TODO handle decl kind Decomposition"); | ||
| 1151 | case Decl::ImplicitParam: | ||
| 1152 | zig_panic("TODO handle decl kind ImplicitParam"); | ||
| 1153 | case Decl::OMPCapturedExpr: | ||
| 1154 | zig_panic("TODO handle decl kind OMPCapturedExpr"); | ||
| 1155 | case Decl::ParmVar: | ||
| 1156 | zig_panic("TODO handle decl kind ParmVar"); | ||
| 1157 | case Decl::VarTemplateSpecialization: | ||
| 1158 | zig_panic("TODO handle decl kind VarTemplateSpecialization"); | ||
| 1159 | case Decl::VarTemplatePartialSpecialization: | ||
| 1160 | zig_panic("TODO handle decl kind VarTemplatePartialSpecialization"); | ||
| 1161 | case Decl::EnumConstant: | ||
| 1162 | zig_panic("TODO handle decl kind EnumConstant"); | ||
| 1163 | case Decl::IndirectField: | ||
| 1164 | zig_panic("TODO handle decl kind IndirectField"); | ||
| 1165 | case Decl::OMPDeclareReduction: | ||
| 1166 | zig_panic("TODO handle decl kind OMPDeclareReduction"); | ||
| 1167 | case Decl::UnresolvedUsingValue: | ||
| 1168 | zig_panic("TODO handle decl kind UnresolvedUsingValue"); | ||
| 1169 | case Decl::OMPThreadPrivate: | ||
| 1170 | zig_panic("TODO handle decl kind OMPThreadPrivate"); | ||
| 1171 | case Decl::ObjCPropertyImpl: | ||
| 1172 | zig_panic("TODO handle decl kind ObjCPropertyImpl"); | ||
| 1173 | case Decl::PragmaComment: | ||
| 1174 | zig_panic("TODO handle decl kind PragmaComment"); | ||
| 1175 | case Decl::PragmaDetectMismatch: | ||
| 1176 | zig_panic("TODO handle decl kind PragmaDetectMismatch"); | ||
| 1177 | case Decl::StaticAssert: | ||
| 1178 | zig_panic("TODO handle decl kind StaticAssert"); | ||
| 1179 | case Decl::TranslationUnit: | ||
| 1180 | zig_panic("TODO handle decl kind TranslationUnit"); | ||
| 1181 | } | ||
| 1182 | zig_unreachable(); | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | // declarations were already added | ||
| 1186 | return nullptr; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) { | ||
| 1190 | AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr); | ||
| 1191 | while_node->data.while_expr.condition = trans_expr(c, block, stmt->getCond()); | ||
| 1192 | while_node->data.while_expr.body = trans_stmt(c, block, stmt->getBody()); | ||
| 1193 | return while_node; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) { | ||
| 1197 | Stmt::StmtClass sc = stmt->getStmtClass(); | ||
| 1198 | switch (sc) { | ||
| 1199 | case Stmt::ReturnStmtClass: | ||
| 1200 | return trans_return_stmt(c, block, (ReturnStmt *)stmt); | ||
| 1201 | case Stmt::CompoundStmtClass: | ||
| 1202 | return trans_compound_stmt(c, block, (CompoundStmt *)stmt); | ||
| 1203 | case Stmt::IntegerLiteralClass: | ||
| 1204 | return trans_integer_literal(c, (IntegerLiteral *)stmt); | ||
| 1205 | case Stmt::ConditionalOperatorClass: | ||
| 1206 | return trans_conditional_operator(c, block, (ConditionalOperator *)stmt); | ||
| 1207 | case Stmt::BinaryOperatorClass: | ||
| 1208 | return trans_binary_operator(c, block, (BinaryOperator *)stmt); | ||
| 1209 | case Stmt::ImplicitCastExprClass: | ||
| 1210 | return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt); | ||
| 1211 | case Stmt::DeclRefExprClass: | ||
| 1212 | return trans_decl_ref_expr(c, (DeclRefExpr *)stmt); | ||
| 1213 | case Stmt::UnaryOperatorClass: | ||
| 1214 | return trans_unary_operator(c, block, (UnaryOperator *)stmt); | ||
| 1215 | case Stmt::DeclStmtClass: | ||
| 1216 | return trans_local_declaration(c, block, (DeclStmt *)stmt); | ||
| 1217 | case Stmt::WhileStmtClass: | ||
| 1218 | return trans_while_loop(c, block, (WhileStmt *)stmt); | ||
| 1219 | case Stmt::CaseStmtClass: | ||
| 1220 | zig_panic("TODO handle C CaseStmtClass"); | ||
| 1221 | case Stmt::DefaultStmtClass: | ||
| 1222 | zig_panic("TODO handle C DefaultStmtClass"); | ||
| 1223 | case Stmt::SwitchStmtClass: | ||
| 1224 | zig_panic("TODO handle C SwitchStmtClass"); | ||
| 1225 | case Stmt::NoStmtClass: | ||
| 1226 | zig_panic("TODO handle C NoStmtClass"); | ||
| 1227 | case Stmt::GCCAsmStmtClass: | ||
| 1228 | zig_panic("TODO handle C GCCAsmStmtClass"); | ||
| 1229 | case Stmt::MSAsmStmtClass: | ||
| 1230 | zig_panic("TODO handle C MSAsmStmtClass"); | ||
| 1231 | case Stmt::AttributedStmtClass: | ||
| 1232 | zig_panic("TODO handle C AttributedStmtClass"); | ||
| 1233 | case Stmt::BreakStmtClass: | ||
| 1234 | zig_panic("TODO handle C BreakStmtClass"); | ||
| 1235 | case Stmt::CXXCatchStmtClass: | ||
| 1236 | zig_panic("TODO handle C CXXCatchStmtClass"); | ||
| 1237 | case Stmt::CXXForRangeStmtClass: | ||
| 1238 | zig_panic("TODO handle C CXXForRangeStmtClass"); | ||
| 1239 | case Stmt::CXXTryStmtClass: | ||
| 1240 | zig_panic("TODO handle C CXXTryStmtClass"); | ||
| 1241 | case Stmt::CapturedStmtClass: | ||
| 1242 | zig_panic("TODO handle C CapturedStmtClass"); | ||
| 1243 | case Stmt::ContinueStmtClass: | ||
| 1244 | zig_panic("TODO handle C ContinueStmtClass"); | ||
| 1245 | case Stmt::CoreturnStmtClass: | ||
| 1246 | zig_panic("TODO handle C CoreturnStmtClass"); | ||
| 1247 | case Stmt::CoroutineBodyStmtClass: | ||
| 1248 | zig_panic("TODO handle C CoroutineBodyStmtClass"); | ||
| 1249 | case Stmt::DoStmtClass: | ||
| 1250 | zig_panic("TODO handle C DoStmtClass"); | ||
| 1251 | case Stmt::BinaryConditionalOperatorClass: | ||
| 1252 | zig_panic("TODO handle C BinaryConditionalOperatorClass"); | ||
| 1253 | case Stmt::AddrLabelExprClass: | ||
| 1254 | zig_panic("TODO handle C AddrLabelExprClass"); | ||
| 1255 | case Stmt::ArrayInitIndexExprClass: | ||
| 1256 | zig_panic("TODO handle C ArrayInitIndexExprClass"); | ||
| 1257 | case Stmt::ArrayInitLoopExprClass: | ||
| 1258 | zig_panic("TODO handle C ArrayInitLoopExprClass"); | ||
| 1259 | case Stmt::ArraySubscriptExprClass: | ||
| 1260 | zig_panic("TODO handle C ArraySubscriptExprClass"); | ||
| 1261 | case Stmt::ArrayTypeTraitExprClass: | ||
| 1262 | zig_panic("TODO handle C ArrayTypeTraitExprClass"); | ||
| 1263 | case Stmt::AsTypeExprClass: | ||
| 1264 | zig_panic("TODO handle C AsTypeExprClass"); | ||
| 1265 | case Stmt::AtomicExprClass: | ||
| 1266 | zig_panic("TODO handle C AtomicExprClass"); | ||
| 1267 | case Stmt::CompoundAssignOperatorClass: | ||
| 1268 | zig_panic("TODO handle C CompoundAssignOperatorClass"); | ||
| 1269 | case Stmt::BlockExprClass: | ||
| 1270 | zig_panic("TODO handle C BlockExprClass"); | ||
| 1271 | case Stmt::CXXBindTemporaryExprClass: | ||
| 1272 | zig_panic("TODO handle C CXXBindTemporaryExprClass"); | ||
| 1273 | case Stmt::CXXBoolLiteralExprClass: | ||
| 1274 | zig_panic("TODO handle C CXXBoolLiteralExprClass"); | ||
| 1275 | case Stmt::CXXConstructExprClass: | ||
| 1276 | zig_panic("TODO handle C CXXConstructExprClass"); | ||
| 1277 | case Stmt::CXXTemporaryObjectExprClass: | ||
| 1278 | zig_panic("TODO handle C CXXTemporaryObjectExprClass"); | ||
| 1279 | case Stmt::CXXDefaultArgExprClass: | ||
| 1280 | zig_panic("TODO handle C CXXDefaultArgExprClass"); | ||
| 1281 | case Stmt::CXXDefaultInitExprClass: | ||
| 1282 | zig_panic("TODO handle C CXXDefaultInitExprClass"); | ||
| 1283 | case Stmt::CXXDeleteExprClass: | ||
| 1284 | zig_panic("TODO handle C CXXDeleteExprClass"); | ||
| 1285 | case Stmt::CXXDependentScopeMemberExprClass: | ||
| 1286 | zig_panic("TODO handle C CXXDependentScopeMemberExprClass"); | ||
| 1287 | case Stmt::CXXFoldExprClass: | ||
| 1288 | zig_panic("TODO handle C CXXFoldExprClass"); | ||
| 1289 | case Stmt::CXXInheritedCtorInitExprClass: | ||
| 1290 | zig_panic("TODO handle C CXXInheritedCtorInitExprClass"); | ||
| 1291 | case Stmt::CXXNewExprClass: | ||
| 1292 | zig_panic("TODO handle C CXXNewExprClass"); | ||
| 1293 | case Stmt::CXXNoexceptExprClass: | ||
| 1294 | zig_panic("TODO handle C CXXNoexceptExprClass"); | ||
| 1295 | case Stmt::CXXNullPtrLiteralExprClass: | ||
| 1296 | zig_panic("TODO handle C CXXNullPtrLiteralExprClass"); | ||
| 1297 | case Stmt::CXXPseudoDestructorExprClass: | ||
| 1298 | zig_panic("TODO handle C CXXPseudoDestructorExprClass"); | ||
| 1299 | case Stmt::CXXScalarValueInitExprClass: | ||
| 1300 | zig_panic("TODO handle C CXXScalarValueInitExprClass"); | ||
| 1301 | case Stmt::CXXStdInitializerListExprClass: | ||
| 1302 | zig_panic("TODO handle C CXXStdInitializerListExprClass"); | ||
| 1303 | case Stmt::CXXThisExprClass: | ||
| 1304 | zig_panic("TODO handle C CXXThisExprClass"); | ||
| 1305 | case Stmt::CXXThrowExprClass: | ||
| 1306 | zig_panic("TODO handle C CXXThrowExprClass"); | ||
| 1307 | case Stmt::CXXTypeidExprClass: | ||
| 1308 | zig_panic("TODO handle C CXXTypeidExprClass"); | ||
| 1309 | case Stmt::CXXUnresolvedConstructExprClass: | ||
| 1310 | zig_panic("TODO handle C CXXUnresolvedConstructExprClass"); | ||
| 1311 | case Stmt::CXXUuidofExprClass: | ||
| 1312 | zig_panic("TODO handle C CXXUuidofExprClass"); | ||
| 1313 | case Stmt::CallExprClass: | ||
| 1314 | zig_panic("TODO handle C CallExprClass"); | ||
| 1315 | case Stmt::CUDAKernelCallExprClass: | ||
| 1316 | zig_panic("TODO handle C CUDAKernelCallExprClass"); | ||
| 1317 | case Stmt::CXXMemberCallExprClass: | ||
| 1318 | zig_panic("TODO handle C CXXMemberCallExprClass"); | ||
| 1319 | case Stmt::CXXOperatorCallExprClass: | ||
| 1320 | zig_panic("TODO handle C CXXOperatorCallExprClass"); | ||
| 1321 | case Stmt::UserDefinedLiteralClass: | ||
| 1322 | zig_panic("TODO handle C UserDefinedLiteralClass"); | ||
| 1323 | case Stmt::CStyleCastExprClass: | ||
| 1324 | zig_panic("TODO handle C CStyleCastExprClass"); | ||
| 1325 | case Stmt::CXXFunctionalCastExprClass: | ||
| 1326 | zig_panic("TODO handle C CXXFunctionalCastExprClass"); | ||
| 1327 | case Stmt::CXXConstCastExprClass: | ||
| 1328 | zig_panic("TODO handle C CXXConstCastExprClass"); | ||
| 1329 | case Stmt::CXXDynamicCastExprClass: | ||
| 1330 | zig_panic("TODO handle C CXXDynamicCastExprClass"); | ||
| 1331 | case Stmt::CXXReinterpretCastExprClass: | ||
| 1332 | zig_panic("TODO handle C CXXReinterpretCastExprClass"); | ||
| 1333 | case Stmt::CXXStaticCastExprClass: | ||
| 1334 | zig_panic("TODO handle C CXXStaticCastExprClass"); | ||
| 1335 | case Stmt::ObjCBridgedCastExprClass: | ||
| 1336 | zig_panic("TODO handle C ObjCBridgedCastExprClass"); | ||
| 1337 | case Stmt::CharacterLiteralClass: | ||
| 1338 | zig_panic("TODO handle C CharacterLiteralClass"); | ||
| 1339 | case Stmt::ChooseExprClass: | ||
| 1340 | zig_panic("TODO handle C ChooseExprClass"); | ||
| 1341 | case Stmt::CompoundLiteralExprClass: | ||
| 1342 | zig_panic("TODO handle C CompoundLiteralExprClass"); | ||
| 1343 | case Stmt::ConvertVectorExprClass: | ||
| 1344 | zig_panic("TODO handle C ConvertVectorExprClass"); | ||
| 1345 | case Stmt::CoawaitExprClass: | ||
| 1346 | zig_panic("TODO handle C CoawaitExprClass"); | ||
| 1347 | case Stmt::CoyieldExprClass: | ||
| 1348 | zig_panic("TODO handle C CoyieldExprClass"); | ||
| 1349 | case Stmt::DependentCoawaitExprClass: | ||
| 1350 | zig_panic("TODO handle C DependentCoawaitExprClass"); | ||
| 1351 | case Stmt::DependentScopeDeclRefExprClass: | ||
| 1352 | zig_panic("TODO handle C DependentScopeDeclRefExprClass"); | ||
| 1353 | case Stmt::DesignatedInitExprClass: | ||
| 1354 | zig_panic("TODO handle C DesignatedInitExprClass"); | ||
| 1355 | case Stmt::DesignatedInitUpdateExprClass: | ||
| 1356 | zig_panic("TODO handle C DesignatedInitUpdateExprClass"); | ||
| 1357 | case Stmt::ExprWithCleanupsClass: | ||
| 1358 | zig_panic("TODO handle C ExprWithCleanupsClass"); | ||
| 1359 | case Stmt::ExpressionTraitExprClass: | ||
| 1360 | zig_panic("TODO handle C ExpressionTraitExprClass"); | ||
| 1361 | case Stmt::ExtVectorElementExprClass: | ||
| 1362 | zig_panic("TODO handle C ExtVectorElementExprClass"); | ||
| 1363 | case Stmt::FloatingLiteralClass: | ||
| 1364 | zig_panic("TODO handle C FloatingLiteralClass"); | ||
| 1365 | case Stmt::FunctionParmPackExprClass: | ||
| 1366 | zig_panic("TODO handle C FunctionParmPackExprClass"); | ||
| 1367 | case Stmt::GNUNullExprClass: | ||
| 1368 | zig_panic("TODO handle C GNUNullExprClass"); | ||
| 1369 | case Stmt::GenericSelectionExprClass: | ||
| 1370 | zig_panic("TODO handle C GenericSelectionExprClass"); | ||
| 1371 | case Stmt::ImaginaryLiteralClass: | ||
| 1372 | zig_panic("TODO handle C ImaginaryLiteralClass"); | ||
| 1373 | case Stmt::ImplicitValueInitExprClass: | ||
| 1374 | zig_panic("TODO handle C ImplicitValueInitExprClass"); | ||
| 1375 | case Stmt::InitListExprClass: | ||
| 1376 | zig_panic("TODO handle C InitListExprClass"); | ||
| 1377 | case Stmt::LambdaExprClass: | ||
| 1378 | zig_panic("TODO handle C LambdaExprClass"); | ||
| 1379 | case Stmt::MSPropertyRefExprClass: | ||
| 1380 | zig_panic("TODO handle C MSPropertyRefExprClass"); | ||
| 1381 | case Stmt::MSPropertySubscriptExprClass: | ||
| 1382 | zig_panic("TODO handle C MSPropertySubscriptExprClass"); | ||
| 1383 | case Stmt::MaterializeTemporaryExprClass: | ||
| 1384 | zig_panic("TODO handle C MaterializeTemporaryExprClass"); | ||
| 1385 | case Stmt::MemberExprClass: | ||
| 1386 | zig_panic("TODO handle C MemberExprClass"); | ||
| 1387 | case Stmt::NoInitExprClass: | ||
| 1388 | zig_panic("TODO handle C NoInitExprClass"); | ||
| 1389 | case Stmt::OMPArraySectionExprClass: | ||
| 1390 | zig_panic("TODO handle C OMPArraySectionExprClass"); | ||
| 1391 | case Stmt::ObjCArrayLiteralClass: | ||
| 1392 | zig_panic("TODO handle C ObjCArrayLiteralClass"); | ||
| 1393 | case Stmt::ObjCAvailabilityCheckExprClass: | ||
| 1394 | zig_panic("TODO handle C ObjCAvailabilityCheckExprClass"); | ||
| 1395 | case Stmt::ObjCBoolLiteralExprClass: | ||
| 1396 | zig_panic("TODO handle C ObjCBoolLiteralExprClass"); | ||
| 1397 | case Stmt::ObjCBoxedExprClass: | ||
| 1398 | zig_panic("TODO handle C ObjCBoxedExprClass"); | ||
| 1399 | case Stmt::ObjCDictionaryLiteralClass: | ||
| 1400 | zig_panic("TODO handle C ObjCDictionaryLiteralClass"); | ||
| 1401 | case Stmt::ObjCEncodeExprClass: | ||
| 1402 | zig_panic("TODO handle C ObjCEncodeExprClass"); | ||
| 1403 | case Stmt::ObjCIndirectCopyRestoreExprClass: | ||
| 1404 | zig_panic("TODO handle C ObjCIndirectCopyRestoreExprClass"); | ||
| 1405 | case Stmt::ObjCIsaExprClass: | ||
| 1406 | zig_panic("TODO handle C ObjCIsaExprClass"); | ||
| 1407 | case Stmt::ObjCIvarRefExprClass: | ||
| 1408 | zig_panic("TODO handle C ObjCIvarRefExprClass"); | ||
| 1409 | case Stmt::ObjCMessageExprClass: | ||
| 1410 | zig_panic("TODO handle C ObjCMessageExprClass"); | ||
| 1411 | case Stmt::ObjCPropertyRefExprClass: | ||
| 1412 | zig_panic("TODO handle C ObjCPropertyRefExprClass"); | ||
| 1413 | case Stmt::ObjCProtocolExprClass: | ||
| 1414 | zig_panic("TODO handle C ObjCProtocolExprClass"); | ||
| 1415 | case Stmt::ObjCSelectorExprClass: | ||
| 1416 | zig_panic("TODO handle C ObjCSelectorExprClass"); | ||
| 1417 | case Stmt::ObjCStringLiteralClass: | ||
| 1418 | zig_panic("TODO handle C ObjCStringLiteralClass"); | ||
| 1419 | case Stmt::ObjCSubscriptRefExprClass: | ||
| 1420 | zig_panic("TODO handle C ObjCSubscriptRefExprClass"); | ||
| 1421 | case Stmt::OffsetOfExprClass: | ||
| 1422 | zig_panic("TODO handle C OffsetOfExprClass"); | ||
| 1423 | case Stmt::OpaqueValueExprClass: | ||
| 1424 | zig_panic("TODO handle C OpaqueValueExprClass"); | ||
| 1425 | case Stmt::UnresolvedLookupExprClass: | ||
| 1426 | zig_panic("TODO handle C UnresolvedLookupExprClass"); | ||
| 1427 | case Stmt::UnresolvedMemberExprClass: | ||
| 1428 | zig_panic("TODO handle C UnresolvedMemberExprClass"); | ||
| 1429 | case Stmt::PackExpansionExprClass: | ||
| 1430 | zig_panic("TODO handle C PackExpansionExprClass"); | ||
| 1431 | case Stmt::ParenExprClass: | ||
| 1432 | zig_panic("TODO handle C ParenExprClass"); | ||
| 1433 | case Stmt::ParenListExprClass: | ||
| 1434 | zig_panic("TODO handle C ParenListExprClass"); | ||
| 1435 | case Stmt::PredefinedExprClass: | ||
| 1436 | zig_panic("TODO handle C PredefinedExprClass"); | ||
| 1437 | case Stmt::PseudoObjectExprClass: | ||
| 1438 | zig_panic("TODO handle C PseudoObjectExprClass"); | ||
| 1439 | case Stmt::ShuffleVectorExprClass: | ||
| 1440 | zig_panic("TODO handle C ShuffleVectorExprClass"); | ||
| 1441 | case Stmt::SizeOfPackExprClass: | ||
| 1442 | zig_panic("TODO handle C SizeOfPackExprClass"); | ||
| 1443 | case Stmt::StmtExprClass: | ||
| 1444 | zig_panic("TODO handle C StmtExprClass"); | ||
| 1445 | case Stmt::StringLiteralClass: | ||
| 1446 | zig_panic("TODO handle C StringLiteralClass"); | ||
| 1447 | case Stmt::SubstNonTypeTemplateParmExprClass: | ||
| 1448 | zig_panic("TODO handle C SubstNonTypeTemplateParmExprClass"); | ||
| 1449 | case Stmt::SubstNonTypeTemplateParmPackExprClass: | ||
| 1450 | zig_panic("TODO handle C SubstNonTypeTemplateParmPackExprClass"); | ||
| 1451 | case Stmt::TypeTraitExprClass: | ||
| 1452 | zig_panic("TODO handle C TypeTraitExprClass"); | ||
| 1453 | case Stmt::TypoExprClass: | ||
| 1454 | zig_panic("TODO handle C TypoExprClass"); | ||
| 1455 | case Stmt::UnaryExprOrTypeTraitExprClass: | ||
| 1456 | zig_panic("TODO handle C UnaryExprOrTypeTraitExprClass"); | ||
| 1457 | case Stmt::VAArgExprClass: | ||
| 1458 | zig_panic("TODO handle C VAArgExprClass"); | ||
| 1459 | case Stmt::ForStmtClass: | ||
| 1460 | zig_panic("TODO handle C ForStmtClass"); | ||
| 1461 | case Stmt::GotoStmtClass: | ||
| 1462 | zig_panic("TODO handle C GotoStmtClass"); | ||
| 1463 | case Stmt::IfStmtClass: | ||
| 1464 | zig_panic("TODO handle C IfStmtClass"); | ||
| 1465 | case Stmt::IndirectGotoStmtClass: | ||
| 1466 | zig_panic("TODO handle C IndirectGotoStmtClass"); | ||
| 1467 | case Stmt::LabelStmtClass: | ||
| 1468 | zig_panic("TODO handle C LabelStmtClass"); | ||
| 1469 | case Stmt::MSDependentExistsStmtClass: | ||
| 1470 | zig_panic("TODO handle C MSDependentExistsStmtClass"); | ||
| 1471 | case Stmt::NullStmtClass: | ||
| 1472 | zig_panic("TODO handle C NullStmtClass"); | ||
| 1473 | case Stmt::OMPAtomicDirectiveClass: | ||
| 1474 | zig_panic("TODO handle C OMPAtomicDirectiveClass"); | ||
| 1475 | case Stmt::OMPBarrierDirectiveClass: | ||
| 1476 | zig_panic("TODO handle C OMPBarrierDirectiveClass"); | ||
| 1477 | case Stmt::OMPCancelDirectiveClass: | ||
| 1478 | zig_panic("TODO handle C OMPCancelDirectiveClass"); | ||
| 1479 | case Stmt::OMPCancellationPointDirectiveClass: | ||
| 1480 | zig_panic("TODO handle C OMPCancellationPointDirectiveClass"); | ||
| 1481 | case Stmt::OMPCriticalDirectiveClass: | ||
| 1482 | zig_panic("TODO handle C OMPCriticalDirectiveClass"); | ||
| 1483 | case Stmt::OMPFlushDirectiveClass: | ||
| 1484 | zig_panic("TODO handle C OMPFlushDirectiveClass"); | ||
| 1485 | case Stmt::OMPDistributeDirectiveClass: | ||
| 1486 | zig_panic("TODO handle C OMPDistributeDirectiveClass"); | ||
| 1487 | case Stmt::OMPDistributeParallelForDirectiveClass: | ||
| 1488 | zig_panic("TODO handle C OMPDistributeParallelForDirectiveClass"); | ||
| 1489 | case Stmt::OMPDistributeParallelForSimdDirectiveClass: | ||
| 1490 | zig_panic("TODO handle C OMPDistributeParallelForSimdDirectiveClass"); | ||
| 1491 | case Stmt::OMPDistributeSimdDirectiveClass: | ||
| 1492 | zig_panic("TODO handle C OMPDistributeSimdDirectiveClass"); | ||
| 1493 | case Stmt::OMPForDirectiveClass: | ||
| 1494 | zig_panic("TODO handle C OMPForDirectiveClass"); | ||
| 1495 | case Stmt::OMPForSimdDirectiveClass: | ||
| 1496 | zig_panic("TODO handle C OMPForSimdDirectiveClass"); | ||
| 1497 | case Stmt::OMPParallelForDirectiveClass: | ||
| 1498 | zig_panic("TODO handle C OMPParallelForDirectiveClass"); | ||
| 1499 | case Stmt::OMPParallelForSimdDirectiveClass: | ||
| 1500 | zig_panic("TODO handle C OMPParallelForSimdDirectiveClass"); | ||
| 1501 | case Stmt::OMPSimdDirectiveClass: | ||
| 1502 | zig_panic("TODO handle C OMPSimdDirectiveClass"); | ||
| 1503 | case Stmt::OMPTargetParallelForSimdDirectiveClass: | ||
| 1504 | zig_panic("TODO handle C OMPTargetParallelForSimdDirectiveClass"); | ||
| 1505 | case Stmt::OMPTargetSimdDirectiveClass: | ||
| 1506 | zig_panic("TODO handle C OMPTargetSimdDirectiveClass"); | ||
| 1507 | case Stmt::OMPTargetTeamsDistributeDirectiveClass: | ||
| 1508 | zig_panic("TODO handle C OMPTargetTeamsDistributeDirectiveClass"); | ||
| 1509 | case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: | ||
| 1510 | zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass"); | ||
| 1511 | case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: | ||
| 1512 | zig_panic("TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass"); | ||
| 1513 | case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: | ||
| 1514 | zig_panic("TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass"); | ||
| 1515 | case Stmt::OMPTaskLoopDirectiveClass: | ||
| 1516 | zig_panic("TODO handle C OMPTaskLoopDirectiveClass"); | ||
| 1517 | case Stmt::OMPTaskLoopSimdDirectiveClass: | ||
| 1518 | zig_panic("TODO handle C OMPTaskLoopSimdDirectiveClass"); | ||
| 1519 | case Stmt::OMPTeamsDistributeDirectiveClass: | ||
| 1520 | zig_panic("TODO handle C OMPTeamsDistributeDirectiveClass"); | ||
| 1521 | case Stmt::OMPTeamsDistributeParallelForDirectiveClass: | ||
| 1522 | zig_panic("TODO handle C OMPTeamsDistributeParallelForDirectiveClass"); | ||
| 1523 | case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: | ||
| 1524 | zig_panic("TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass"); | ||
| 1525 | case Stmt::OMPTeamsDistributeSimdDirectiveClass: | ||
| 1526 | zig_panic("TODO handle C OMPTeamsDistributeSimdDirectiveClass"); | ||
| 1527 | case Stmt::OMPMasterDirectiveClass: | ||
| 1528 | zig_panic("TODO handle C OMPMasterDirectiveClass"); | ||
| 1529 | case Stmt::OMPOrderedDirectiveClass: | ||
| 1530 | zig_panic("TODO handle C OMPOrderedDirectiveClass"); | ||
| 1531 | case Stmt::OMPParallelDirectiveClass: | ||
| 1532 | zig_panic("TODO handle C OMPParallelDirectiveClass"); | ||
| 1533 | case Stmt::OMPParallelSectionsDirectiveClass: | ||
| 1534 | zig_panic("TODO handle C OMPParallelSectionsDirectiveClass"); | ||
| 1535 | case Stmt::OMPSectionDirectiveClass: | ||
| 1536 | zig_panic("TODO handle C OMPSectionDirectiveClass"); | ||
| 1537 | case Stmt::OMPSectionsDirectiveClass: | ||
| 1538 | zig_panic("TODO handle C OMPSectionsDirectiveClass"); | ||
| 1539 | case Stmt::OMPSingleDirectiveClass: | ||
| 1540 | zig_panic("TODO handle C OMPSingleDirectiveClass"); | ||
| 1541 | case Stmt::OMPTargetDataDirectiveClass: | ||
| 1542 | zig_panic("TODO handle C OMPTargetDataDirectiveClass"); | ||
| 1543 | case Stmt::OMPTargetDirectiveClass: | ||
| 1544 | zig_panic("TODO handle C OMPTargetDirectiveClass"); | ||
| 1545 | case Stmt::OMPTargetEnterDataDirectiveClass: | ||
| 1546 | zig_panic("TODO handle C OMPTargetEnterDataDirectiveClass"); | ||
| 1547 | case Stmt::OMPTargetExitDataDirectiveClass: | ||
| 1548 | zig_panic("TODO handle C OMPTargetExitDataDirectiveClass"); | ||
| 1549 | case Stmt::OMPTargetParallelDirectiveClass: | ||
| 1550 | zig_panic("TODO handle C OMPTargetParallelDirectiveClass"); | ||
| 1551 | case Stmt::OMPTargetParallelForDirectiveClass: | ||
| 1552 | zig_panic("TODO handle C OMPTargetParallelForDirectiveClass"); | ||
| 1553 | case Stmt::OMPTargetTeamsDirectiveClass: | ||
| 1554 | zig_panic("TODO handle C OMPTargetTeamsDirectiveClass"); | ||
| 1555 | case Stmt::OMPTargetUpdateDirectiveClass: | ||
| 1556 | zig_panic("TODO handle C OMPTargetUpdateDirectiveClass"); | ||
| 1557 | case Stmt::OMPTaskDirectiveClass: | ||
| 1558 | zig_panic("TODO handle C OMPTaskDirectiveClass"); | ||
| 1559 | case Stmt::OMPTaskgroupDirectiveClass: | ||
| 1560 | zig_panic("TODO handle C OMPTaskgroupDirectiveClass"); | ||
| 1561 | case Stmt::OMPTaskwaitDirectiveClass: | ||
| 1562 | zig_panic("TODO handle C OMPTaskwaitDirectiveClass"); | ||
| 1563 | case Stmt::OMPTaskyieldDirectiveClass: | ||
| 1564 | zig_panic("TODO handle C OMPTaskyieldDirectiveClass"); | ||
| 1565 | case Stmt::OMPTeamsDirectiveClass: | ||
| 1566 | zig_panic("TODO handle C OMPTeamsDirectiveClass"); | ||
| 1567 | case Stmt::ObjCAtCatchStmtClass: | ||
| 1568 | zig_panic("TODO handle C ObjCAtCatchStmtClass"); | ||
| 1569 | case Stmt::ObjCAtFinallyStmtClass: | ||
| 1570 | zig_panic("TODO handle C ObjCAtFinallyStmtClass"); | ||
| 1571 | case Stmt::ObjCAtSynchronizedStmtClass: | ||
| 1572 | zig_panic("TODO handle C ObjCAtSynchronizedStmtClass"); | ||
| 1573 | case Stmt::ObjCAtThrowStmtClass: | ||
| 1574 | zig_panic("TODO handle C ObjCAtThrowStmtClass"); | ||
| 1575 | case Stmt::ObjCAtTryStmtClass: | ||
| 1576 | zig_panic("TODO handle C ObjCAtTryStmtClass"); | ||
| 1577 | case Stmt::ObjCAutoreleasePoolStmtClass: | ||
| 1578 | zig_panic("TODO handle C ObjCAutoreleasePoolStmtClass"); | ||
| 1579 | case Stmt::ObjCForCollectionStmtClass: | ||
| 1580 | zig_panic("TODO handle C ObjCForCollectionStmtClass"); | ||
| 1581 | case Stmt::SEHExceptStmtClass: | ||
| 1582 | zig_panic("TODO handle C SEHExceptStmtClass"); | ||
| 1583 | case Stmt::SEHFinallyStmtClass: | ||
| 1584 | zig_panic("TODO handle C SEHFinallyStmtClass"); | ||
| 1585 | case Stmt::SEHLeaveStmtClass: | ||
| 1586 | zig_panic("TODO handle C SEHLeaveStmtClass"); | ||
| 1587 | case Stmt::SEHTryStmtClass: | ||
| 1588 | zig_panic("TODO handle C SEHTryStmtClass"); | ||
| 1589 | } | ||
| 1590 | zig_unreachable(); | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) { | ||
| 1594 | Buf *fn_name = buf_create_from_str(decl_name(fn_decl)); | ||
| 1595 | |||
| 1596 | if (get_global(c, fn_name)) { | ||
| 1597 | // we already saw this function | ||
| 1598 | return; | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation()); | ||
| 1602 | if (proto_node == nullptr) { | ||
| 1603 | emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name)); | ||
| 1604 | return; | ||
| 1605 | } | ||
| 1606 | |||
| 1607 | proto_node->data.fn_proto.name = fn_name; | ||
| 1608 | proto_node->data.fn_proto.is_extern = !fn_decl->hasBody(); | ||
| 1609 | |||
| 1610 | StorageClass sc = fn_decl->getStorageClass(); | ||
| 1611 | if (sc == SC_None) { | ||
| 1612 | proto_node->data.fn_proto.visib_mod = fn_decl->hasBody() ? VisibModExport : c->visib_mod; | ||
| 1613 | } else if (sc == SC_Extern || sc == SC_Static) { | ||
| 1614 | proto_node->data.fn_proto.visib_mod = c->visib_mod; | ||
| 1615 | } else if (sc == SC_PrivateExtern) { | ||
| 1616 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern"); | ||
| 1617 | return; | ||
| 1618 | } else { | ||
| 1619 | emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown"); | ||
| 1620 | return; | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) { | ||
| 1624 | AstNode *param_node = proto_node->data.fn_proto.params.at(i); | ||
| 1625 | const ParmVarDecl *param = fn_decl->getParamDecl(i); | ||
| 1626 | const char *name = decl_name(param); | ||
| 1627 | if (strlen(name) == 0) { | ||
| 1628 | Buf *proto_param_name = param_node->data.param_decl.name; | ||
| 1629 | if (proto_param_name == nullptr) { | ||
| 1630 | param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i); | ||
| 1631 | } else { | ||
| 1632 | param_node->data.param_decl.name = proto_param_name; | ||
| 1633 | } | ||
| 1634 | } else { | ||
| 1635 | param_node->data.param_decl.name = buf_create_from_str(name); | ||
| 1636 | } | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | if (fn_decl->hasBody()) { | ||
| 1640 | Stmt *body = fn_decl->getBody(); | ||
| 1641 | |||
| 1642 | AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef); | ||
| 1643 | fn_def_node->data.fn_def.fn_proto = proto_node; | ||
| 1644 | fn_def_node->data.fn_def.body = trans_stmt(c, nullptr, body); | ||
| 1645 | |||
| 1646 | proto_node->data.fn_proto.fn_def_node = fn_def_node; | ||
| 1647 | c->root->data.root.top_level_decls.append(fn_def_node); | ||
| 1648 | return; | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | c->root->data.root.top_level_decls.append(proto_node); | ||
| 1652 | } | ||
| 1653 | |||
| 1654 | static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) { | ||
| 1655 | AstNode *node = trans_create_node_symbol_str(c, primitive_name); | ||
| 1656 | c->decl_table.put(typedef_decl, node); | ||
| 1657 | return node; | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) { | ||
| 1661 | auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl); | ||
| 1662 | if (existing_entry) { | ||
| 1663 | return existing_entry->value; | ||
| 1664 | } | ||
| 1665 | |||
| 1666 | QualType child_qt = typedef_decl->getUnderlyingType(); | ||
| 1667 | Buf *type_name = buf_create_from_str(decl_name(typedef_decl)); | ||
| 1668 | |||
| 1669 | if (buf_eql_str(type_name, "uint8_t")) { | ||
| 1670 | return resolve_typdef_as_builtin(c, typedef_decl, "u8"); | ||
| 1671 | } else if (buf_eql_str(type_name, "int8_t")) { | ||
| 1672 | return resolve_typdef_as_builtin(c, typedef_decl, "i8"); | ||
| 1673 | } else if (buf_eql_str(type_name, "uint16_t")) { | ||
| 1674 | return resolve_typdef_as_builtin(c, typedef_decl, "u16"); | ||
| 1675 | } else if (buf_eql_str(type_name, "int16_t")) { | ||
| 1676 | return resolve_typdef_as_builtin(c, typedef_decl, "i16"); | ||
| 1677 | } else if (buf_eql_str(type_name, "uint32_t")) { | ||
| 1678 | return resolve_typdef_as_builtin(c, typedef_decl, "u32"); | ||
| 1679 | } else if (buf_eql_str(type_name, "int32_t")) { | ||
| 1680 | return resolve_typdef_as_builtin(c, typedef_decl, "i32"); | ||
| 1681 | } else if (buf_eql_str(type_name, "uint64_t")) { | ||
| 1682 | return resolve_typdef_as_builtin(c, typedef_decl, "u64"); | ||
| 1683 | } else if (buf_eql_str(type_name, "int64_t")) { | ||
| 1684 | return resolve_typdef_as_builtin(c, typedef_decl, "i64"); | ||
| 1685 | } else if (buf_eql_str(type_name, "intptr_t")) { | ||
| 1686 | return resolve_typdef_as_builtin(c, typedef_decl, "isize"); | ||
| 1687 | } else if (buf_eql_str(type_name, "uintptr_t")) { | ||
| 1688 | return resolve_typdef_as_builtin(c, typedef_decl, "usize"); | ||
| 1689 | } else if (buf_eql_str(type_name, "ssize_t")) { | ||
| 1690 | return resolve_typdef_as_builtin(c, typedef_decl, "isize"); | ||
| 1691 | } else if (buf_eql_str(type_name, "size_t")) { | ||
| 1692 | return resolve_typdef_as_builtin(c, typedef_decl, "usize"); | ||
| 1693 | } | ||
| 1694 | |||
| 1695 | // if the underlying type is anonymous, we can special case it to just | ||
| 1696 | // use the name of this typedef | ||
| 1697 | // TODO | ||
| 1698 | |||
| 1699 | AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation()); | ||
| 1700 | if (type_node == nullptr) { | ||
| 1701 | emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name)); | ||
| 1702 | c->decl_table.put(typedef_decl, nullptr); | ||
| 1703 | return nullptr; | ||
| 1704 | } | ||
| 1705 | add_global_var(c, type_name, type_node); | ||
| 1706 | |||
| 1707 | AstNode *symbol_node = trans_create_node_symbol(c, type_name); | ||
| 1708 | c->decl_table.put(typedef_decl, symbol_node); | ||
| 1709 | return symbol_node; | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl, | ||
| 1713 | Buf *full_type_name, Buf *bare_name) | ||
| 1714 | { | ||
| 1715 | AstNode *opaque_node = trans_create_node_opaque(c); | ||
| 1716 | if (full_type_name == nullptr) { | ||
| 1717 | c->decl_table.put(enum_decl->getCanonicalDecl(), opaque_node); | ||
| 1718 | return opaque_node; | ||
| 1719 | } | ||
| 1720 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1721 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1722 | add_global_var(c, full_type_name, opaque_node); | ||
| 1723 | c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node); | ||
| 1724 | return symbol_node; | ||
| 1725 | } | ||
| 1726 | |||
| 1727 | static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) { | ||
| 1728 | auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl()); | ||
| 1729 | if (existing_entry) { | ||
| 1730 | return existing_entry->value; | ||
| 1731 | } | ||
| 1732 | |||
| 1733 | const char *raw_name = decl_name(enum_decl); | ||
| 1734 | bool is_anonymous = (raw_name[0] == 0); | ||
| 1735 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); | ||
| 1736 | Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name)); | ||
| 1737 | |||
| 1738 | const EnumDecl *enum_def = enum_decl->getDefinition(); | ||
| 1739 | if (!enum_def) { | ||
| 1740 | return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name); | ||
| 1741 | } | ||
| 1742 | |||
| 1743 | bool pure_enum = true; | ||
| 1744 | uint32_t field_count = 0; | ||
| 1745 | for (auto it = enum_def->enumerator_begin(), | ||
| 1746 | it_end = enum_def->enumerator_end(); | ||
| 1747 | it != it_end; ++it, field_count += 1) | ||
| 1748 | { | ||
| 1749 | const EnumConstantDecl *enum_const = *it; | ||
| 1750 | if (enum_const->getInitExpr()) { | ||
| 1751 | pure_enum = false; | ||
| 1752 | } | ||
| 1753 | } | ||
| 1754 | |||
| 1755 | AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation()); | ||
| 1756 | assert(tag_int_type); | ||
| 1757 | |||
| 1758 | if (pure_enum) { | ||
| 1759 | AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl); | ||
| 1760 | enum_node->data.container_decl.kind = ContainerKindEnum; | ||
| 1761 | enum_node->data.container_decl.layout = ContainerLayoutExtern; | ||
| 1762 | enum_node->data.container_decl.init_arg_expr = tag_int_type; | ||
| 1763 | |||
| 1764 | enum_node->data.container_decl.fields.resize(field_count); | ||
| 1765 | uint32_t i = 0; | ||
| 1766 | for (auto it = enum_def->enumerator_begin(), | ||
| 1767 | it_end = enum_def->enumerator_end(); | ||
| 1768 | it != it_end; ++it, i += 1) | ||
| 1769 | { | ||
| 1770 | const EnumConstantDecl *enum_const = *it; | ||
| 1771 | |||
| 1772 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); | ||
| 1773 | Buf *field_name; | ||
| 1774 | if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) { | ||
| 1775 | field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name)); | ||
| 1776 | } else { | ||
| 1777 | field_name = enum_val_name; | ||
| 1778 | } | ||
| 1779 | |||
| 1780 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); | ||
| 1781 | field_node->data.struct_field.name = field_name; | ||
| 1782 | field_node->data.struct_field.type = nullptr; | ||
| 1783 | enum_node->data.container_decl.fields.items[i] = field_node; | ||
| 1784 | |||
| 1785 | // in C each enum value is in the global namespace. so we put them there too. | ||
| 1786 | // at this point we can rely on the enum emitting successfully | ||
| 1787 | AstNode *field_access_node = trans_create_node_field_access(c, | ||
| 1788 | trans_create_node_symbol(c, full_type_name), field_name); | ||
| 1789 | add_global_var(c, enum_val_name, field_access_node); | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | if (is_anonymous) { | ||
| 1793 | c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node); | ||
| 1794 | return enum_node; | ||
| 1795 | } else { | ||
| 1796 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1797 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1798 | add_global_var(c, full_type_name, enum_node); | ||
| 1799 | c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node); | ||
| 1800 | return enum_node; | ||
| 1801 | } | ||
| 1802 | } | ||
| 1803 | |||
| 1804 | // TODO after issue #305 is solved, make this be an enum with tag_int_type | ||
| 1805 | // as the integer type and set the custom enum values | ||
| 1806 | AstNode *enum_node = tag_int_type; | ||
| 1807 | |||
| 1808 | |||
| 1809 | // add variables for all the values with enum_node | ||
| 1810 | for (auto it = enum_def->enumerator_begin(), | ||
| 1811 | it_end = enum_def->enumerator_end(); | ||
| 1812 | it != it_end; ++it) | ||
| 1813 | { | ||
| 1814 | const EnumConstantDecl *enum_const = *it; | ||
| 1815 | |||
| 1816 | Buf *enum_val_name = buf_create_from_str(decl_name(enum_const)); | ||
| 1817 | AstNode *int_node = trans_create_node_apint(c, enum_const->getInitVal()); | ||
| 1818 | AstNode *var_node = add_global_var(c, enum_val_name, int_node); | ||
| 1819 | var_node->data.variable_declaration.type = tag_int_type; | ||
| 1820 | } | ||
| 1821 | |||
| 1822 | if (is_anonymous) { | ||
| 1823 | c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node); | ||
| 1824 | return enum_node; | ||
| 1825 | } else { | ||
| 1826 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1827 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1828 | add_global_var(c, full_type_name, enum_node); | ||
| 1829 | return symbol_node; | ||
| 1830 | } | ||
| 1831 | } | ||
| 1832 | |||
| 1833 | static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl, | ||
| 1834 | Buf *full_type_name, Buf *bare_name) | ||
| 1835 | { | ||
| 1836 | AstNode *opaque_node = trans_create_node_opaque(c); | ||
| 1837 | if (full_type_name == nullptr) { | ||
| 1838 | c->decl_table.put(record_decl->getCanonicalDecl(), opaque_node); | ||
| 1839 | return opaque_node; | ||
| 1840 | } | ||
| 1841 | AstNode *symbol_node = trans_create_node_symbol(c, full_type_name); | ||
| 1842 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1843 | add_global_var(c, full_type_name, opaque_node); | ||
| 1844 | c->decl_table.put(record_decl->getCanonicalDecl(), symbol_node); | ||
| 1845 | return symbol_node; | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) { | ||
| 1849 | auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl()); | ||
| 1850 | if (existing_entry) { | ||
| 1851 | return existing_entry->value; | ||
| 1852 | } | ||
| 1853 | |||
| 1854 | const char *raw_name = decl_name(record_decl); | ||
| 1855 | |||
| 1856 | if (!record_decl->isStruct()) { | ||
| 1857 | emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct", raw_name); | ||
| 1858 | c->decl_table.put(record_decl->getCanonicalDecl(), nullptr); | ||
| 1859 | return nullptr; | ||
| 1860 | } | ||
| 1861 | |||
| 1862 | bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0; | ||
| 1863 | Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name); | ||
| 1864 | Buf *full_type_name = (bare_name == nullptr) ? nullptr : buf_sprintf("struct_%s", buf_ptr(bare_name)); | ||
| 1865 | |||
| 1866 | RecordDecl *record_def = record_decl->getDefinition(); | ||
| 1867 | if (record_def == nullptr) { | ||
| 1868 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); | ||
| 1869 | } | ||
| 1870 | |||
| 1871 | // count fields and validate | ||
| 1872 | uint32_t field_count = 0; | ||
| 1873 | for (auto it = record_def->field_begin(), | ||
| 1874 | it_end = record_def->field_end(); | ||
| 1875 | it != it_end; ++it, field_count += 1) | ||
| 1876 | { | ||
| 1877 | const FieldDecl *field_decl = *it; | ||
| 1878 | |||
| 1879 | if (field_decl->isBitField()) { | ||
| 1880 | emit_warning(c, field_decl->getLocation(), "struct %s demoted to opaque type - has bitfield", | ||
| 1881 | is_anonymous ? "(anon)" : buf_ptr(bare_name)); | ||
| 1882 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); | ||
| 1883 | } | ||
| 1884 | } | ||
| 1885 | |||
| 1886 | AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl); | ||
| 1887 | struct_node->data.container_decl.kind = ContainerKindStruct; | ||
| 1888 | struct_node->data.container_decl.layout = ContainerLayoutExtern; | ||
| 1889 | |||
| 1890 | // TODO handle attribute packed | ||
| 1891 | |||
| 1892 | struct_node->data.container_decl.fields.resize(field_count); | ||
| 1893 | |||
| 1894 | // must be before fields in case a circular reference happens | ||
| 1895 | if (is_anonymous) { | ||
| 1896 | c->decl_table.put(record_decl->getCanonicalDecl(), struct_node); | ||
| 1897 | } else { | ||
| 1898 | c->decl_table.put(record_decl->getCanonicalDecl(), trans_create_node_symbol(c, full_type_name)); | ||
| 1899 | } | ||
| 1900 | |||
| 1901 | uint32_t i = 0; | ||
| 1902 | for (auto it = record_def->field_begin(), | ||
| 1903 | it_end = record_def->field_end(); | ||
| 1904 | it != it_end; ++it, i += 1) | ||
| 1905 | { | ||
| 1906 | const FieldDecl *field_decl = *it; | ||
| 1907 | |||
| 1908 | AstNode *field_node = trans_create_node(c, NodeTypeStructField); | ||
| 1909 | field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl)); | ||
| 1910 | field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation()); | ||
| 1911 | |||
| 1912 | if (field_node->data.struct_field.type == nullptr) { | ||
| 1913 | emit_warning(c, field_decl->getLocation(), | ||
| 1914 | "struct %s demoted to opaque type - unresolved type", | ||
| 1915 | is_anonymous ? "(anon)" : buf_ptr(bare_name)); | ||
| 1916 | |||
| 1917 | return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name); | ||
| 1918 | } | ||
| 1919 | |||
| 1920 | struct_node->data.container_decl.fields.items[i] = field_node; | ||
| 1921 | } | ||
| 1922 | |||
| 1923 | if (is_anonymous) { | ||
| 1924 | return struct_node; | ||
| 1925 | } else { | ||
| 1926 | add_global_weak_alias(c, bare_name, full_type_name); | ||
| 1927 | add_global_var(c, full_type_name, struct_node); | ||
| 1928 | return trans_create_node_symbol(c, full_type_name); | ||
| 1929 | } | ||
| 1930 | } | ||
| 1931 | |||
| 1932 | static void visit_var_decl(Context *c, const VarDecl *var_decl) { | ||
| 1933 | Buf *name = buf_create_from_str(decl_name(var_decl)); | ||
| 1934 | |||
| 1935 | switch (var_decl->getTLSKind()) { | ||
| 1936 | case VarDecl::TLS_None: | ||
| 1937 | break; | ||
| 1938 | case VarDecl::TLS_Static: | ||
| 1939 | emit_warning(c, var_decl->getLocation(), | ||
| 1940 | "ignoring variable '%s' - static thread local storage", buf_ptr(name)); | ||
| 1941 | return; | ||
| 1942 | case VarDecl::TLS_Dynamic: | ||
| 1943 | emit_warning(c, var_decl->getLocation(), | ||
| 1944 | "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name)); | ||
| 1945 | return; | ||
| 1946 | } | ||
| 1947 | |||
| 1948 | QualType qt = var_decl->getType(); | ||
| 1949 | AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation()); | ||
| 1950 | if (var_type == nullptr) { | ||
| 1951 | emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name)); | ||
| 1952 | return; | ||
| 1953 | } | ||
| 1954 | |||
| 1955 | bool is_extern = var_decl->hasExternalStorage(); | ||
| 1956 | bool is_static = var_decl->isFileVarDecl(); | ||
| 1957 | bool is_const = qt.isConstQualified(); | ||
| 1958 | |||
| 1959 | if (is_static && !is_extern) { | ||
| 1960 | AstNode *init_node; | ||
| 1961 | if (var_decl->hasInit()) { | ||
| 1962 | APValue *ap_value = var_decl->evaluateValue(); | ||
| 1963 | if (ap_value == nullptr) { | ||
| 1964 | emit_warning(c, var_decl->getLocation(), | ||
| 1965 | "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name)); | ||
| 1966 | return; | ||
| 1967 | } | ||
| 1968 | switch (ap_value->getKind()) { | ||
| 1969 | case APValue::Int: | ||
| 1970 | init_node = trans_create_node_apint(c, ap_value->getInt()); | ||
| 1971 | break; | ||
| 1972 | case APValue::Uninitialized: | ||
| 1973 | init_node = trans_create_node_symbol_str(c, "undefined"); | ||
| 1974 | break; | ||
| 1975 | case APValue::Float: | ||
| 1976 | case APValue::ComplexInt: | ||
| 1977 | case APValue::ComplexFloat: | ||
| 1978 | case APValue::LValue: | ||
| 1979 | case APValue::Vector: | ||
| 1980 | case APValue::Array: | ||
| 1981 | case APValue::Struct: | ||
| 1982 | case APValue::Union: | ||
| 1983 | case APValue::MemberPointer: | ||
| 1984 | case APValue::AddrLabelDiff: | ||
| 1985 | emit_warning(c, var_decl->getLocation(), | ||
| 1986 | "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name)); | ||
| 1987 | return; | ||
| 1988 | } | ||
| 1989 | } else { | ||
| 1990 | init_node = trans_create_node_symbol_str(c, "undefined"); | ||
| 1991 | } | ||
| 1992 | |||
| 1993 | AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, init_node); | ||
| 1994 | c->root->data.root.top_level_decls.append(var_node); | ||
| 1995 | return; | ||
| 1996 | } | ||
| 1997 | |||
| 1998 | if (is_extern) { | ||
| 1999 | AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, nullptr); | ||
| 2000 | var_node->data.variable_declaration.is_extern = true; | ||
| 2001 | c->root->data.root.top_level_decls.append(var_node); | ||
| 2002 | return; | ||
| 2003 | } | ||
| 2004 | |||
| 2005 | emit_warning(c, var_decl->getLocation(), | ||
| 2006 | "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name)); | ||
| 2007 | return; | ||
| 2008 | } | ||
| 2009 | |||
| 2010 | static bool decl_visitor(void *context, const Decl *decl) { | ||
| 2011 | Context *c = (Context*)context; | ||
| 2012 | |||
| 2013 | switch (decl->getKind()) { | ||
| 2014 | case Decl::Function: | ||
| 2015 | visit_fn_decl(c, static_cast<const FunctionDecl*>(decl)); | ||
| 2016 | break; | ||
| 2017 | case Decl::Typedef: | ||
| 2018 | resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl)); | ||
| 2019 | break; | ||
| 2020 | case Decl::Enum: | ||
| 2021 | resolve_enum_decl(c, static_cast<const EnumDecl *>(decl)); | ||
| 2022 | break; | ||
| 2023 | case Decl::Record: | ||
| 2024 | resolve_record_decl(c, static_cast<const RecordDecl *>(decl)); | ||
| 2025 | break; | ||
| 2026 | case Decl::Var: | ||
| 2027 | visit_var_decl(c, static_cast<const VarDecl *>(decl)); | ||
| 2028 | break; | ||
| 2029 | default: | ||
| 2030 | emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName()); | ||
| 2031 | } | ||
| 2032 | |||
| 2033 | return true; | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | static bool name_exists(Context *c, Buf *name) { | ||
| 2037 | return get_global(c, name) != nullptr; | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | static void render_aliases(Context *c) { | ||
| 2041 | for (size_t i = 0; i < c->aliases.length; i += 1) { | ||
| 2042 | Alias *alias = &c->aliases.at(i); | ||
| 2043 | if (name_exists(c, alias->new_name)) | ||
| 2044 | continue; | ||
| 2045 | |||
| 2046 | add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name)); | ||
| 2047 | } | ||
| 2048 | } | ||
| 2049 | |||
| 2050 | static void render_macros(Context *c) { | ||
| 2051 | auto it = c->macro_table.entry_iterator(); | ||
| 2052 | for (;;) { | ||
| 2053 | auto *entry = it.next(); | ||
| 2054 | if (!entry) | ||
| 2055 | break; | ||
| 2056 | |||
| 2057 | AstNode *value_node = entry->value; | ||
| 2058 | if (value_node->type == NodeTypeFnDef) { | ||
| 2059 | c->root->data.root.top_level_decls.append(value_node); | ||
| 2060 | } else { | ||
| 2061 | add_global_var(c, entry->key, value_node); | ||
| 2062 | } | ||
| 2063 | } | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) { | ||
| 2067 | tokenize_c_macro(ctok, (const uint8_t *)char_ptr); | ||
| 2068 | |||
| 2069 | if (ctok->error) { | ||
| 2070 | return; | ||
| 2071 | } | ||
| 2072 | |||
| 2073 | bool negate = false; | ||
| 2074 | for (size_t i = 0; i < ctok->tokens.length; i += 1) { | ||
| 2075 | bool is_first = (i == 0); | ||
| 2076 | bool is_last = (i == ctok->tokens.length - 1); | ||
| 2077 | CTok *tok = &ctok->tokens.at(i); | ||
| 2078 | switch (tok->id) { | ||
| 2079 | case CTokIdCharLit: | ||
| 2080 | if (is_last && is_first) { | ||
| 2081 | AstNode *node = trans_create_node_unsigned(c, tok->data.char_lit); | ||
| 2082 | c->macro_table.put(name, node); | ||
| 2083 | } | ||
| 2084 | return; | ||
| 2085 | case CTokIdStrLit: | ||
| 2086 | if (is_last && is_first) { | ||
| 2087 | AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit)); | ||
| 2088 | c->macro_table.put(name, node); | ||
| 2089 | } | ||
| 2090 | return; | ||
| 2091 | case CTokIdNumLitInt: | ||
| 2092 | if (is_last) { | ||
| 2093 | AstNode *node; | ||
| 2094 | switch (tok->data.num_lit_int.suffix) { | ||
| 2095 | case CNumLitSuffixNone: | ||
| 2096 | node = trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate); | ||
| 2097 | break; | ||
| 2098 | case CNumLitSuffixL: | ||
| 2099 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2100 | "c_long"); | ||
| 2101 | break; | ||
| 2102 | case CNumLitSuffixU: | ||
| 2103 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2104 | "c_uint"); | ||
| 2105 | break; | ||
| 2106 | case CNumLitSuffixLU: | ||
| 2107 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2108 | "c_ulong"); | ||
| 2109 | break; | ||
| 2110 | case CNumLitSuffixLL: | ||
| 2111 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2112 | "c_longlong"); | ||
| 2113 | break; | ||
| 2114 | case CNumLitSuffixLLU: | ||
| 2115 | node = trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, | ||
| 2116 | "c_ulonglong"); | ||
| 2117 | break; | ||
| 2118 | } | ||
| 2119 | c->macro_table.put(name, node); | ||
| 2120 | } | ||
| 2121 | return; | ||
| 2122 | case CTokIdNumLitFloat: | ||
| 2123 | if (is_last) { | ||
| 2124 | double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float; | ||
| 2125 | AstNode *node = trans_create_node_float_lit(c, value); | ||
| 2126 | c->macro_table.put(name, node); | ||
| 2127 | } | ||
| 2128 | return; | ||
| 2129 | case CTokIdSymbol: | ||
| 2130 | if (is_last && is_first) { | ||
| 2131 | // if it equals itself, ignore. for example, from stdio.h: | ||
| 2132 | // #define stdin stdin | ||
| 2133 | Buf *symbol_name = buf_create_from_buf(&tok->data.symbol); | ||
| 2134 | if (buf_eql_buf(name, symbol_name)) { | ||
| 2135 | return; | ||
| 2136 | } | ||
| 2137 | c->macro_symbols.append({name, symbol_name}); | ||
| 2138 | return; | ||
| 2139 | } | ||
| 2140 | case CTokIdMinus: | ||
| 2141 | if (is_first) { | ||
| 2142 | negate = true; | ||
| 2143 | break; | ||
| 2144 | } else { | ||
| 2145 | return; | ||
| 2146 | } | ||
| 2147 | } | ||
| 2148 | } | ||
| 2149 | } | ||
| 2150 | |||
| 2151 | static void process_symbol_macros(Context *c) { | ||
| 2152 | for (size_t i = 0; i < c->macro_symbols.length; i += 1) { | ||
| 2153 | MacroSymbol ms = c->macro_symbols.at(i); | ||
| 2154 | |||
| 2155 | // Check if this macro aliases another top level declaration | ||
| 2156 | AstNode *existing_node = get_global(c, ms.value); | ||
| 2157 | if (!existing_node || name_exists(c, ms.name)) | ||
| 2158 | continue; | ||
| 2159 | |||
| 2160 | // If a macro aliases a global variable which is a function pointer, we conclude that | ||
| 2161 | // the macro is intended to represent a function that assumes the function pointer | ||
| 2162 | // variable is non-null and calls it. | ||
| 2163 | if (existing_node->type == NodeTypeVariableDeclaration) { | ||
| 2164 | AstNode *var_type = existing_node->data.variable_declaration.type; | ||
| 2165 | if (var_type != nullptr && var_type->type == NodeTypePrefixOpExpr && | ||
| 2166 | var_type->data.prefix_op_expr.prefix_op == PrefixOpMaybe) | ||
| 2167 | { | ||
| 2168 | AstNode *fn_proto_node = var_type->data.prefix_op_expr.primary_expr; | ||
| 2169 | if (fn_proto_node->type == NodeTypeFnProto) { | ||
| 2170 | AstNode *inline_fn_node = trans_create_node_inline_fn(c, ms.name, ms.value, fn_proto_node); | ||
| 2171 | c->macro_table.put(ms.name, inline_fn_node); | ||
| 2172 | continue; | ||
| 2173 | } | ||
| 2174 | } | ||
| 2175 | } | ||
| 2176 | |||
| 2177 | add_global_var(c, ms.name, trans_create_node_symbol(c, ms.value)); | ||
| 2178 | } | ||
| 2179 | } | ||
| 2180 | |||
| 2181 | static void process_preprocessor_entities(Context *c, ASTUnit &unit) { | ||
| 2182 | CTokenize ctok = {{0}}; | ||
| 2183 | |||
| 2184 | // TODO if we see #undef, delete it from the table | ||
| 2185 | |||
| 2186 | for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) { | ||
| 2187 | switch (entity->getKind()) { | ||
| 2188 | case PreprocessedEntity::InvalidKind: | ||
| 2189 | case PreprocessedEntity::InclusionDirectiveKind: | ||
| 2190 | case PreprocessedEntity::MacroExpansionKind: | ||
| 2191 | continue; | ||
| 2192 | case PreprocessedEntity::MacroDefinitionKind: | ||
| 2193 | { | ||
| 2194 | MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity); | ||
| 2195 | const char *raw_name = macro->getName()->getNameStart(); | ||
| 2196 | SourceRange range = macro->getSourceRange(); | ||
| 2197 | SourceLocation begin_loc = range.getBegin(); | ||
| 2198 | SourceLocation end_loc = range.getEnd(); | ||
| 2199 | |||
| 2200 | if (begin_loc == end_loc) { | ||
| 2201 | // this means it is a macro without a value | ||
| 2202 | // we don't care about such things | ||
| 2203 | continue; | ||
| 2204 | } | ||
| 2205 | Buf *name = buf_create_from_str(raw_name); | ||
| 2206 | if (name_exists(c, name)) { | ||
| 2207 | continue; | ||
| 2208 | } | ||
| 2209 | |||
| 2210 | const char *end_c = c->source_manager->getCharacterData(end_loc); | ||
| 2211 | process_macro(c, &ctok, name, end_c); | ||
| 2212 | } | ||
| 2213 | } | ||
| 2214 | } | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source, | ||
| 2218 | CodeGen *codegen, AstNode *source_node) | ||
| 2219 | { | ||
| 2220 | int err; | ||
| 2221 | Buf tmp_file_path = BUF_INIT; | ||
| 2222 | if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) { | ||
| 2223 | return err; | ||
| 2224 | } | ||
| 2225 | |||
| 2226 | err = parse_h_file(import, errors, buf_ptr(&tmp_file_path), codegen, source_node); | ||
| 2227 | |||
| 2228 | os_delete_file(&tmp_file_path); | ||
| 2229 | |||
| 2230 | return err; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file, | ||
| 2234 | CodeGen *codegen, AstNode *source_node) | ||
| 2235 | { | ||
| 2236 | Context context = {0}; | ||
| 2237 | Context *c = &context; | ||
| 2238 | c->warnings_on = codegen->verbose; | ||
| 2239 | c->import = import; | ||
| 2240 | c->errors = errors; | ||
| 2241 | c->visib_mod = VisibModPub; | ||
| 2242 | c->decl_table.init(8); | ||
| 2243 | c->macro_table.init(8); | ||
| 2244 | c->codegen = codegen; | ||
| 2245 | c->source_node = source_node; | ||
| 2246 | |||
| 2247 | ZigList<const char *> clang_argv = {0}; | ||
| 2248 | |||
| 2249 | clang_argv.append("-x"); | ||
| 2250 | clang_argv.append("c"); | ||
| 2251 | |||
| 2252 | if (c->codegen->is_native_target) { | ||
| 2253 | char *ZIG_PARSEH_CFLAGS = getenv("ZIG_NATIVE_PARSEH_CFLAGS"); | ||
| 2254 | if (ZIG_PARSEH_CFLAGS) { | ||
| 2255 | Buf tmp_buf = BUF_INIT; | ||
| 2256 | char *start = ZIG_PARSEH_CFLAGS; | ||
| 2257 | char *space = strstr(start, " "); | ||
| 2258 | while (space) { | ||
| 2259 | if (space - start > 0) { | ||
| 2260 | buf_init_from_mem(&tmp_buf, start, space - start); | ||
| 2261 | clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf))); | ||
| 2262 | } | ||
| 2263 | start = space + 1; | ||
| 2264 | space = strstr(start, " "); | ||
| 2265 | } | ||
| 2266 | buf_init_from_str(&tmp_buf, start); | ||
| 2267 | clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf))); | ||
| 2268 | } | ||
| 2269 | } | ||
| 2270 | |||
| 2271 | clang_argv.append("-isystem"); | ||
| 2272 | clang_argv.append(ZIG_HEADERS_DIR); | ||
| 2273 | |||
| 2274 | clang_argv.append("-isystem"); | ||
| 2275 | clang_argv.append(buf_ptr(codegen->libc_include_dir)); | ||
| 2276 | |||
| 2277 | for (size_t i = 0; i < codegen->clang_argv_len; i += 1) { | ||
| 2278 | clang_argv.append(codegen->clang_argv[i]); | ||
| 2279 | } | ||
| 2280 | |||
| 2281 | // we don't need spell checking and it slows things down | ||
| 2282 | clang_argv.append("-fno-spell-checking"); | ||
| 2283 | |||
| 2284 | // this gives us access to preprocessing entities, presumably at | ||
| 2285 | // the cost of performance | ||
| 2286 | clang_argv.append("-Xclang"); | ||
| 2287 | clang_argv.append("-detailed-preprocessing-record"); | ||
| 2288 | |||
| 2289 | if (!c->codegen->is_native_target) { | ||
| 2290 | clang_argv.append("-target"); | ||
| 2291 | clang_argv.append(buf_ptr(&c->codegen->triple_str)); | ||
| 2292 | } | ||
| 2293 | |||
| 2294 | clang_argv.append(target_file); | ||
| 2295 | |||
| 2296 | // to make the [start...end] argument work | ||
| 2297 | clang_argv.append(nullptr); | ||
| 2298 | |||
| 2299 | IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); | ||
| 2300 | |||
| 2301 | std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>(); | ||
| 2302 | |||
| 2303 | bool skip_function_bodies = false; | ||
| 2304 | bool only_local_decls = true; | ||
| 2305 | bool capture_diagnostics = true; | ||
| 2306 | bool user_files_are_volatile = true; | ||
| 2307 | bool allow_pch_with_compiler_errors = false; | ||
| 2308 | bool single_file_parse = false; | ||
| 2309 | bool for_serialization = false; | ||
| 2310 | const char *resources_path = ZIG_HEADERS_DIR; | ||
| 2311 | std::unique_ptr<ASTUnit> err_unit; | ||
| 2312 | std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine( | ||
| 2313 | &clang_argv.at(0), &clang_argv.last(), | ||
| 2314 | pch_container_ops, diags, resources_path, | ||
| 2315 | only_local_decls, capture_diagnostics, None, true, 0, TU_Complete, | ||
| 2316 | false, false, allow_pch_with_compiler_errors, skip_function_bodies, | ||
| 2317 | single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit, | ||
| 2318 | nullptr)); | ||
| 2319 | |||
| 2320 | // Early failures in LoadFromCommandLine may return with ErrUnit unset. | ||
| 2321 | if (!ast_unit && !err_unit) { | ||
| 2322 | return ErrorFileSystem; | ||
| 2323 | } | ||
| 2324 | |||
| 2325 | if (diags->getClient()->getNumErrors() > 0) { | ||
| 2326 | if (ast_unit) { | ||
| 2327 | err_unit = std::move(ast_unit); | ||
| 2328 | } | ||
| 2329 | |||
| 2330 | for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(), | ||
| 2331 | it_end = err_unit->stored_diag_end(); | ||
| 2332 | it != it_end; ++it) | ||
| 2333 | { | ||
| 2334 | switch (it->getLevel()) { | ||
| 2335 | case DiagnosticsEngine::Ignored: | ||
| 2336 | case DiagnosticsEngine::Note: | ||
| 2337 | case DiagnosticsEngine::Remark: | ||
| 2338 | case DiagnosticsEngine::Warning: | ||
| 2339 | continue; | ||
| 2340 | case DiagnosticsEngine::Error: | ||
| 2341 | case DiagnosticsEngine::Fatal: | ||
| 2342 | break; | ||
| 2343 | } | ||
| 2344 | StringRef msg_str_ref = it->getMessage(); | ||
| 2345 | Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin()); | ||
| 2346 | FullSourceLoc fsl = it->getLocation(); | ||
| 2347 | if (fsl.hasManager()) { | ||
| 2348 | FileID file_id = fsl.getFileID(); | ||
| 2349 | StringRef filename = fsl.getManager().getFilename(fsl); | ||
| 2350 | unsigned line = fsl.getSpellingLineNumber() - 1; | ||
| 2351 | unsigned column = fsl.getSpellingColumnNumber() - 1; | ||
| 2352 | unsigned offset = fsl.getManager().getFileOffset(fsl); | ||
| 2353 | const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); | ||
| 2354 | Buf *path; | ||
| 2355 | if (filename.empty()) { | ||
| 2356 | path = buf_alloc(); | ||
| 2357 | } else { | ||
| 2358 | path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size()); | ||
| 2359 | } | ||
| 2360 | |||
| 2361 | ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg); | ||
| 2362 | |||
| 2363 | c->errors->append(err_msg); | ||
| 2364 | } else { | ||
| 2365 | // NOTE the only known way this gets triggered right now is if you have a lot of errors | ||
| 2366 | // clang emits "too many errors emitted, stopping now" | ||
| 2367 | fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg)); | ||
| 2368 | } | ||
| 2369 | } | ||
| 2370 | |||
| 2371 | return 0; | ||
| 2372 | } | ||
| 2373 | |||
| 2374 | c->ctx = &ast_unit->getASTContext(); | ||
| 2375 | c->source_manager = &ast_unit->getSourceManager(); | ||
| 2376 | c->root = trans_create_node(c, NodeTypeRoot); | ||
| 2377 | |||
| 2378 | ast_unit->visitLocalTopLevelDecls(c, decl_visitor); | ||
| 2379 | |||
| 2380 | process_preprocessor_entities(c, *ast_unit); | ||
| 2381 | |||
| 2382 | process_symbol_macros(c); | ||
| 2383 | render_macros(c); | ||
| 2384 | render_aliases(c); | ||
| 2385 | |||
| 2386 | import->root = c->root; | ||
| 2387 | |||
| 2388 | return 0; | ||
| 2389 | } | ||
src/parseh.hpp deleted-20| ... | @@ -1,20 +0,0 @@ | ||
| 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 | |||
| 9 | #ifndef ZIG_PARSEH_HPP | ||
| 10 | #define ZIG_PARSEH_HPP | ||
| 11 | |||
| 12 | #include "all_types.hpp" | ||
| 13 | |||
| 14 | int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file, | ||
| 15 | CodeGen *codegen, AstNode *source_node); | ||
| 16 | |||
| 17 | int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source, | ||
| 18 | CodeGen *codegen, AstNode *source_node); | ||
| 19 | |||
| 20 | #endif | ||
test/parsec.zig created+299| ... | @@ -0,0 +1,299 @@ | ||
| 1 | const tests = @import("tests.zig"); | ||
| 2 | |||
| 3 | pub fn addCases(cases: &tests.ParseCContext) { | ||
| 4 | cases.addAllowWarnings("simple data types", | ||
| 5 | \\#include <stdint.h> | ||
| 6 | \\int foo(char a, unsigned char b, signed char c); | ||
| 7 | \\int foo(char a, unsigned char b, signed char c); // test a duplicate prototype | ||
| 8 | \\void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); | ||
| 9 | \\void baz(int8_t a, int16_t b, int32_t c, int64_t d); | ||
| 10 | , | ||
| 11 | \\pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; | ||
| 12 | , | ||
| 13 | \\pub extern fn bar(a: u8, b: u16, c: u32, d: u64); | ||
| 14 | , | ||
| 15 | \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64); | ||
| 16 | ); | ||
| 17 | |||
| 18 | cases.add("noreturn attribute", | ||
| 19 | \\void foo(void) __attribute__((noreturn)); | ||
| 20 | , | ||
| 21 | \\pub extern fn foo() -> noreturn; | ||
| 22 | ); | ||
| 23 | |||
| 24 | cases.add("simple function", | ||
| 25 | \\int abs(int a) { | ||
| 26 | \\ return a < 0 ? -a : a; | ||
| 27 | \\} | ||
| 28 | , | ||
| 29 | \\export fn abs(a: c_int) -> c_int { | ||
| 30 | \\ return if (a < 0) -a else a; | ||
| 31 | \\} | ||
| 32 | ); | ||
| 33 | |||
| 34 | cases.add("enums", | ||
| 35 | \\enum Foo { | ||
| 36 | \\ FooA, | ||
| 37 | \\ FooB, | ||
| 38 | \\ Foo1, | ||
| 39 | \\}; | ||
| 40 | , | ||
| 41 | \\pub const enum_Foo = extern enum { | ||
| 42 | \\ A, | ||
| 43 | \\ B, | ||
| 44 | \\ @"1", | ||
| 45 | \\}; | ||
| 46 | , | ||
| 47 | \\pub const FooA = enum_Foo.A; | ||
| 48 | , | ||
| 49 | \\pub const FooB = enum_Foo.B; | ||
| 50 | , | ||
| 51 | \\pub const Foo1 = enum_Foo.@"1"; | ||
| 52 | , | ||
| 53 | \\pub const Foo = enum_Foo; | ||
| 54 | ); | ||
| 55 | |||
| 56 | cases.add("restrict -> noalias", | ||
| 57 | \\void foo(void *restrict bar, void *restrict); | ||
| 58 | , | ||
| 59 | \\pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void); | ||
| 60 | ); | ||
| 61 | |||
| 62 | cases.add("simple struct", | ||
| 63 | \\struct Foo { | ||
| 64 | \\ int x; | ||
| 65 | \\ char *y; | ||
| 66 | \\}; | ||
| 67 | , | ||
| 68 | \\const struct_Foo = extern struct { | ||
| 69 | \\ x: c_int, | ||
| 70 | \\ y: ?&u8, | ||
| 71 | \\}; | ||
| 72 | , | ||
| 73 | \\pub const Foo = struct_Foo; | ||
| 74 | ); | ||
| 75 | |||
| 76 | cases.add("qualified struct and enum", | ||
| 77 | \\struct Foo { | ||
| 78 | \\ int x; | ||
| 79 | \\ int y; | ||
| 80 | \\}; | ||
| 81 | \\enum Bar { | ||
| 82 | \\ BarA, | ||
| 83 | \\ BarB, | ||
| 84 | \\}; | ||
| 85 | \\void func(struct Foo *a, enum Bar **b); | ||
| 86 | , | ||
| 87 | \\pub const struct_Foo = extern struct { | ||
| 88 | \\ x: c_int, | ||
| 89 | \\ y: c_int, | ||
| 90 | \\}; | ||
| 91 | , | ||
| 92 | \\pub const enum_Bar = extern enum { | ||
| 93 | \\ A, | ||
| 94 | \\ B, | ||
| 95 | \\}; | ||
| 96 | , | ||
| 97 | \\pub const BarA = enum_Bar.A; | ||
| 98 | , | ||
| 99 | \\pub const BarB = enum_Bar.B; | ||
| 100 | , | ||
| 101 | \\pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar); | ||
| 102 | , | ||
| 103 | \\pub const Foo = struct_Foo; | ||
| 104 | , | ||
| 105 | \\pub const Bar = enum_Bar; | ||
| 106 | ); | ||
| 107 | |||
| 108 | cases.add("constant size array", | ||
| 109 | \\void func(int array[20]); | ||
| 110 | , | ||
| 111 | \\pub extern fn func(array: ?&c_int); | ||
| 112 | ); | ||
| 113 | |||
| 114 | cases.add("self referential struct with function pointer", | ||
| 115 | \\struct Foo { | ||
| 116 | \\ void (*derp)(struct Foo *foo); | ||
| 117 | \\}; | ||
| 118 | , | ||
| 119 | \\pub const struct_Foo = extern struct { | ||
| 120 | \\ derp: ?extern fn(?&struct_Foo), | ||
| 121 | \\}; | ||
| 122 | , | ||
| 123 | \\pub const Foo = struct_Foo; | ||
| 124 | ); | ||
| 125 | |||
| 126 | cases.add("struct prototype used in func", | ||
| 127 | \\struct Foo; | ||
| 128 | \\struct Foo *some_func(struct Foo *foo, int x); | ||
| 129 | , | ||
| 130 | \\pub const struct_Foo = @OpaqueType(); | ||
| 131 | , | ||
| 132 | \\pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo; | ||
| 133 | , | ||
| 134 | \\pub const Foo = struct_Foo; | ||
| 135 | ); | ||
| 136 | |||
| 137 | cases.add("#define a char literal", | ||
| 138 | \\#define A_CHAR 'a' | ||
| 139 | , | ||
| 140 | \\pub const A_CHAR = 97; | ||
| 141 | ); | ||
| 142 | |||
| 143 | cases.add("#define an unsigned integer literal", | ||
| 144 | \\#define CHANNEL_COUNT 24 | ||
| 145 | , | ||
| 146 | \\pub const CHANNEL_COUNT = 24; | ||
| 147 | ); | ||
| 148 | |||
| 149 | cases.add("#define referencing another #define", | ||
| 150 | \\#define THING2 THING1 | ||
| 151 | \\#define THING1 1234 | ||
| 152 | , | ||
| 153 | \\pub const THING1 = 1234; | ||
| 154 | , | ||
| 155 | \\pub const THING2 = THING1; | ||
| 156 | ); | ||
| 157 | |||
| 158 | cases.add("variables", | ||
| 159 | \\extern int extern_var; | ||
| 160 | \\static const int int_var = 13; | ||
| 161 | , | ||
| 162 | \\pub extern var extern_var: c_int; | ||
| 163 | , | ||
| 164 | \\pub const int_var: c_int = 13; | ||
| 165 | ); | ||
| 166 | |||
| 167 | cases.add("circular struct definitions", | ||
| 168 | \\struct Bar; | ||
| 169 | \\ | ||
| 170 | \\struct Foo { | ||
| 171 | \\ struct Bar *next; | ||
| 172 | \\}; | ||
| 173 | \\ | ||
| 174 | \\struct Bar { | ||
| 175 | \\ struct Foo *next; | ||
| 176 | \\}; | ||
| 177 | , | ||
| 178 | \\pub const struct_Bar = extern struct { | ||
| 179 | \\ next: ?&struct_Foo, | ||
| 180 | \\}; | ||
| 181 | , | ||
| 182 | \\pub const struct_Foo = extern struct { | ||
| 183 | \\ next: ?&struct_Bar, | ||
| 184 | \\}; | ||
| 185 | ); | ||
| 186 | |||
| 187 | cases.add("typedef void", | ||
| 188 | \\typedef void Foo; | ||
| 189 | \\Foo fun(Foo *a); | ||
| 190 | , | ||
| 191 | \\pub const Foo = c_void; | ||
| 192 | , | ||
| 193 | \\pub extern fn fun(a: ?&Foo) -> Foo; | ||
| 194 | ); | ||
| 195 | |||
| 196 | cases.add("generate inline func for #define global extern fn", | ||
| 197 | \\extern void (*fn_ptr)(void); | ||
| 198 | \\#define foo fn_ptr | ||
| 199 | \\ | ||
| 200 | \\extern char (*fn_ptr2)(int, float); | ||
| 201 | \\#define bar fn_ptr2 | ||
| 202 | , | ||
| 203 | \\pub extern var fn_ptr: ?extern fn(); | ||
| 204 | , | ||
| 205 | \\pub inline fn foo() { | ||
| 206 | \\ ??fn_ptr() | ||
| 207 | \\} | ||
| 208 | , | ||
| 209 | \\pub extern var fn_ptr2: ?extern fn(c_int, f32) -> u8; | ||
| 210 | , | ||
| 211 | \\pub inline fn bar(arg0: c_int, arg1: f32) -> u8 { | ||
| 212 | \\ ??fn_ptr2(arg0, arg1) | ||
| 213 | \\} | ||
| 214 | ); | ||
| 215 | |||
| 216 | cases.add("#define string", | ||
| 217 | \\#define foo "a string" | ||
| 218 | , | ||
| 219 | \\pub const foo = c"a string"; | ||
| 220 | ); | ||
| 221 | |||
| 222 | cases.add("__cdecl doesn't mess up function pointers", | ||
| 223 | \\void foo(void (__cdecl *fn_ptr)(void)); | ||
| 224 | , | ||
| 225 | \\pub extern fn foo(fn_ptr: ?extern fn()); | ||
| 226 | ); | ||
| 227 | |||
| 228 | cases.add("comment after integer literal", | ||
| 229 | \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 230 | , | ||
| 231 | \\pub const SDL_INIT_VIDEO = 32; | ||
| 232 | ); | ||
| 233 | |||
| 234 | cases.add("u integer suffix after hex literal", | ||
| 235 | \\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 236 | , | ||
| 237 | \\pub const SDL_INIT_VIDEO = c_uint(32); | ||
| 238 | ); | ||
| 239 | |||
| 240 | cases.add("l integer suffix after hex literal", | ||
| 241 | \\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 242 | , | ||
| 243 | \\pub const SDL_INIT_VIDEO = c_long(32); | ||
| 244 | ); | ||
| 245 | |||
| 246 | cases.add("ul integer suffix after hex literal", | ||
| 247 | \\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 248 | , | ||
| 249 | \\pub const SDL_INIT_VIDEO = c_ulong(32); | ||
| 250 | ); | ||
| 251 | |||
| 252 | cases.add("lu integer suffix after hex literal", | ||
| 253 | \\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 254 | , | ||
| 255 | \\pub const SDL_INIT_VIDEO = c_ulong(32); | ||
| 256 | ); | ||
| 257 | |||
| 258 | cases.add("ll integer suffix after hex literal", | ||
| 259 | \\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 260 | , | ||
| 261 | \\pub const SDL_INIT_VIDEO = c_longlong(32); | ||
| 262 | ); | ||
| 263 | |||
| 264 | cases.add("ull integer suffix after hex literal", | ||
| 265 | \\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 266 | , | ||
| 267 | \\pub const SDL_INIT_VIDEO = c_ulonglong(32); | ||
| 268 | ); | ||
| 269 | |||
| 270 | cases.add("llu integer suffix after hex literal", | ||
| 271 | \\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 272 | , | ||
| 273 | \\pub const SDL_INIT_VIDEO = c_ulonglong(32); | ||
| 274 | ); | ||
| 275 | |||
| 276 | cases.add("zig keywords in C code", | ||
| 277 | \\struct comptime { | ||
| 278 | \\ int defer; | ||
| 279 | \\}; | ||
| 280 | , | ||
| 281 | \\pub const struct_comptime = extern struct { | ||
| 282 | \\ @"defer": c_int, | ||
| 283 | \\}; | ||
| 284 | , | ||
| 285 | \\pub const @"comptime" = struct_comptime; | ||
| 286 | ); | ||
| 287 | |||
| 288 | cases.add("macro defines string literal with octal", | ||
| 289 | \\#define FOO "aoeu\023 derp" | ||
| 290 | \\#define FOO2 "aoeu\0234 derp" | ||
| 291 | \\#define FOO_CHAR '\077' | ||
| 292 | , | ||
| 293 | \\pub const FOO = c"aoeu\x13 derp"; | ||
| 294 | , | ||
| 295 | \\pub const FOO2 = c"aoeu\x134 derp"; | ||
| 296 | , | ||
| 297 | \\pub const FOO_CHAR = 63; | ||
| 298 | ); | ||
| 299 | } | ||
test/parseh.zig deleted-299| ... | @@ -1,299 +0,0 @@ | ||
| 1 | const tests = @import("tests.zig"); | ||
| 2 | |||
| 3 | pub fn addCases(cases: &tests.ParseHContext) { | ||
| 4 | cases.addAllowWarnings("simple data types", | ||
| 5 | \\#include <stdint.h> | ||
| 6 | \\int foo(char a, unsigned char b, signed char c); | ||
| 7 | \\int foo(char a, unsigned char b, signed char c); // test a duplicate prototype | ||
| 8 | \\void bar(uint8_t a, uint16_t b, uint32_t c, uint64_t d); | ||
| 9 | \\void baz(int8_t a, int16_t b, int32_t c, int64_t d); | ||
| 10 | , | ||
| 11 | \\pub extern fn foo(a: u8, b: u8, c: i8) -> c_int; | ||
| 12 | , | ||
| 13 | \\pub extern fn bar(a: u8, b: u16, c: u32, d: u64); | ||
| 14 | , | ||
| 15 | \\pub extern fn baz(a: i8, b: i16, c: i32, d: i64); | ||
| 16 | ); | ||
| 17 | |||
| 18 | cases.add("noreturn attribute", | ||
| 19 | \\void foo(void) __attribute__((noreturn)); | ||
| 20 | , | ||
| 21 | \\pub extern fn foo() -> noreturn; | ||
| 22 | ); | ||
| 23 | |||
| 24 | cases.add("simple function", | ||
| 25 | \\int abs(int a) { | ||
| 26 | \\ return a < 0 ? -a : a; | ||
| 27 | \\} | ||
| 28 | , | ||
| 29 | \\export fn abs(a: c_int) -> c_int { | ||
| 30 | \\ return if (a < 0) -a else a; | ||
| 31 | \\} | ||
| 32 | ); | ||
| 33 | |||
| 34 | cases.add("enums", | ||
| 35 | \\enum Foo { | ||
| 36 | \\ FooA, | ||
| 37 | \\ FooB, | ||
| 38 | \\ Foo1, | ||
| 39 | \\}; | ||
| 40 | , | ||
| 41 | \\pub const enum_Foo = extern enum { | ||
| 42 | \\ A, | ||
| 43 | \\ B, | ||
| 44 | \\ @"1", | ||
| 45 | \\}; | ||
| 46 | , | ||
| 47 | \\pub const FooA = enum_Foo.A; | ||
| 48 | , | ||
| 49 | \\pub const FooB = enum_Foo.B; | ||
| 50 | , | ||
| 51 | \\pub const Foo1 = enum_Foo.@"1"; | ||
| 52 | , | ||
| 53 | \\pub const Foo = enum_Foo; | ||
| 54 | ); | ||
| 55 | |||
| 56 | cases.add("restrict -> noalias", | ||
| 57 | \\void foo(void *restrict bar, void *restrict); | ||
| 58 | , | ||
| 59 | \\pub extern fn foo(noalias bar: ?&c_void, noalias arg1: ?&c_void); | ||
| 60 | ); | ||
| 61 | |||
| 62 | cases.add("simple struct", | ||
| 63 | \\struct Foo { | ||
| 64 | \\ int x; | ||
| 65 | \\ char *y; | ||
| 66 | \\}; | ||
| 67 | , | ||
| 68 | \\const struct_Foo = extern struct { | ||
| 69 | \\ x: c_int, | ||
| 70 | \\ y: ?&u8, | ||
| 71 | \\}; | ||
| 72 | , | ||
| 73 | \\pub const Foo = struct_Foo; | ||
| 74 | ); | ||
| 75 | |||
| 76 | cases.add("qualified struct and enum", | ||
| 77 | \\struct Foo { | ||
| 78 | \\ int x; | ||
| 79 | \\ int y; | ||
| 80 | \\}; | ||
| 81 | \\enum Bar { | ||
| 82 | \\ BarA, | ||
| 83 | \\ BarB, | ||
| 84 | \\}; | ||
| 85 | \\void func(struct Foo *a, enum Bar **b); | ||
| 86 | , | ||
| 87 | \\pub const struct_Foo = extern struct { | ||
| 88 | \\ x: c_int, | ||
| 89 | \\ y: c_int, | ||
| 90 | \\}; | ||
| 91 | , | ||
| 92 | \\pub const enum_Bar = extern enum { | ||
| 93 | \\ A, | ||
| 94 | \\ B, | ||
| 95 | \\}; | ||
| 96 | , | ||
| 97 | \\pub const BarA = enum_Bar.A; | ||
| 98 | , | ||
| 99 | \\pub const BarB = enum_Bar.B; | ||
| 100 | , | ||
| 101 | \\pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar); | ||
| 102 | , | ||
| 103 | \\pub const Foo = struct_Foo; | ||
| 104 | , | ||
| 105 | \\pub const Bar = enum_Bar; | ||
| 106 | ); | ||
| 107 | |||
| 108 | cases.add("constant size array", | ||
| 109 | \\void func(int array[20]); | ||
| 110 | , | ||
| 111 | \\pub extern fn func(array: ?&c_int); | ||
| 112 | ); | ||
| 113 | |||
| 114 | cases.add("self referential struct with function pointer", | ||
| 115 | \\struct Foo { | ||
| 116 | \\ void (*derp)(struct Foo *foo); | ||
| 117 | \\}; | ||
| 118 | , | ||
| 119 | \\pub const struct_Foo = extern struct { | ||
| 120 | \\ derp: ?extern fn(?&struct_Foo), | ||
| 121 | \\}; | ||
| 122 | , | ||
| 123 | \\pub const Foo = struct_Foo; | ||
| 124 | ); | ||
| 125 | |||
| 126 | cases.add("struct prototype used in func", | ||
| 127 | \\struct Foo; | ||
| 128 | \\struct Foo *some_func(struct Foo *foo, int x); | ||
| 129 | , | ||
| 130 | \\pub const struct_Foo = @OpaqueType(); | ||
| 131 | , | ||
| 132 | \\pub extern fn some_func(foo: ?&struct_Foo, x: c_int) -> ?&struct_Foo; | ||
| 133 | , | ||
| 134 | \\pub const Foo = struct_Foo; | ||
| 135 | ); | ||
| 136 | |||
| 137 | cases.add("#define a char literal", | ||
| 138 | \\#define A_CHAR 'a' | ||
| 139 | , | ||
| 140 | \\pub const A_CHAR = 97; | ||
| 141 | ); | ||
| 142 | |||
| 143 | cases.add("#define an unsigned integer literal", | ||
| 144 | \\#define CHANNEL_COUNT 24 | ||
| 145 | , | ||
| 146 | \\pub const CHANNEL_COUNT = 24; | ||
| 147 | ); | ||
| 148 | |||
| 149 | cases.add("#define referencing another #define", | ||
| 150 | \\#define THING2 THING1 | ||
| 151 | \\#define THING1 1234 | ||
| 152 | , | ||
| 153 | \\pub const THING1 = 1234; | ||
| 154 | , | ||
| 155 | \\pub const THING2 = THING1; | ||
| 156 | ); | ||
| 157 | |||
| 158 | cases.add("variables", | ||
| 159 | \\extern int extern_var; | ||
| 160 | \\static const int int_var = 13; | ||
| 161 | , | ||
| 162 | \\pub extern var extern_var: c_int; | ||
| 163 | , | ||
| 164 | \\pub const int_var: c_int = 13; | ||
| 165 | ); | ||
| 166 | |||
| 167 | cases.add("circular struct definitions", | ||
| 168 | \\struct Bar; | ||
| 169 | \\ | ||
| 170 | \\struct Foo { | ||
| 171 | \\ struct Bar *next; | ||
| 172 | \\}; | ||
| 173 | \\ | ||
| 174 | \\struct Bar { | ||
| 175 | \\ struct Foo *next; | ||
| 176 | \\}; | ||
| 177 | , | ||
| 178 | \\pub const struct_Bar = extern struct { | ||
| 179 | \\ next: ?&struct_Foo, | ||
| 180 | \\}; | ||
| 181 | , | ||
| 182 | \\pub const struct_Foo = extern struct { | ||
| 183 | \\ next: ?&struct_Bar, | ||
| 184 | \\}; | ||
| 185 | ); | ||
| 186 | |||
| 187 | cases.add("typedef void", | ||
| 188 | \\typedef void Foo; | ||
| 189 | \\Foo fun(Foo *a); | ||
| 190 | , | ||
| 191 | \\pub const Foo = c_void; | ||
| 192 | , | ||
| 193 | \\pub extern fn fun(a: ?&Foo) -> Foo; | ||
| 194 | ); | ||
| 195 | |||
| 196 | cases.add("generate inline func for #define global extern fn", | ||
| 197 | \\extern void (*fn_ptr)(void); | ||
| 198 | \\#define foo fn_ptr | ||
| 199 | \\ | ||
| 200 | \\extern char (*fn_ptr2)(int, float); | ||
| 201 | \\#define bar fn_ptr2 | ||
| 202 | , | ||
| 203 | \\pub extern var fn_ptr: ?extern fn(); | ||
| 204 | , | ||
| 205 | \\pub inline fn foo() { | ||
| 206 | \\ ??fn_ptr() | ||
| 207 | \\} | ||
| 208 | , | ||
| 209 | \\pub extern var fn_ptr2: ?extern fn(c_int, f32) -> u8; | ||
| 210 | , | ||
| 211 | \\pub inline fn bar(arg0: c_int, arg1: f32) -> u8 { | ||
| 212 | \\ ??fn_ptr2(arg0, arg1) | ||
| 213 | \\} | ||
| 214 | ); | ||
| 215 | |||
| 216 | cases.add("#define string", | ||
| 217 | \\#define foo "a string" | ||
| 218 | , | ||
| 219 | \\pub const foo = c"a string"; | ||
| 220 | ); | ||
| 221 | |||
| 222 | cases.add("__cdecl doesn't mess up function pointers", | ||
| 223 | \\void foo(void (__cdecl *fn_ptr)(void)); | ||
| 224 | , | ||
| 225 | \\pub extern fn foo(fn_ptr: ?extern fn()); | ||
| 226 | ); | ||
| 227 | |||
| 228 | cases.add("comment after integer literal", | ||
| 229 | \\#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 230 | , | ||
| 231 | \\pub const SDL_INIT_VIDEO = 32; | ||
| 232 | ); | ||
| 233 | |||
| 234 | cases.add("u integer suffix after hex literal", | ||
| 235 | \\#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 236 | , | ||
| 237 | \\pub const SDL_INIT_VIDEO = c_uint(32); | ||
| 238 | ); | ||
| 239 | |||
| 240 | cases.add("l integer suffix after hex literal", | ||
| 241 | \\#define SDL_INIT_VIDEO 0x00000020l /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 242 | , | ||
| 243 | \\pub const SDL_INIT_VIDEO = c_long(32); | ||
| 244 | ); | ||
| 245 | |||
| 246 | cases.add("ul integer suffix after hex literal", | ||
| 247 | \\#define SDL_INIT_VIDEO 0x00000020ul /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 248 | , | ||
| 249 | \\pub const SDL_INIT_VIDEO = c_ulong(32); | ||
| 250 | ); | ||
| 251 | |||
| 252 | cases.add("lu integer suffix after hex literal", | ||
| 253 | \\#define SDL_INIT_VIDEO 0x00000020lu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 254 | , | ||
| 255 | \\pub const SDL_INIT_VIDEO = c_ulong(32); | ||
| 256 | ); | ||
| 257 | |||
| 258 | cases.add("ll integer suffix after hex literal", | ||
| 259 | \\#define SDL_INIT_VIDEO 0x00000020ll /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 260 | , | ||
| 261 | \\pub const SDL_INIT_VIDEO = c_longlong(32); | ||
| 262 | ); | ||
| 263 | |||
| 264 | cases.add("ull integer suffix after hex literal", | ||
| 265 | \\#define SDL_INIT_VIDEO 0x00000020ull /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 266 | , | ||
| 267 | \\pub const SDL_INIT_VIDEO = c_ulonglong(32); | ||
| 268 | ); | ||
| 269 | |||
| 270 | cases.add("llu integer suffix after hex literal", | ||
| 271 | \\#define SDL_INIT_VIDEO 0x00000020llu /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */ | ||
| 272 | , | ||
| 273 | \\pub const SDL_INIT_VIDEO = c_ulonglong(32); | ||
| 274 | ); | ||
| 275 | |||
| 276 | cases.add("zig keywords in C code", | ||
| 277 | \\struct comptime { | ||
| 278 | \\ int defer; | ||
| 279 | \\}; | ||
| 280 | , | ||
| 281 | \\pub const struct_comptime = extern struct { | ||
| 282 | \\ @"defer": c_int, | ||
| 283 | \\}; | ||
| 284 | , | ||
| 285 | \\pub const @"comptime" = struct_comptime; | ||
| 286 | ); | ||
| 287 | |||
| 288 | cases.add("macro defines string literal with octal", | ||
| 289 | \\#define FOO "aoeu\023 derp" | ||
| 290 | \\#define FOO2 "aoeu\0234 derp" | ||
| 291 | \\#define FOO_CHAR '\077' | ||
| 292 | , | ||
| 293 | \\pub const FOO = c"aoeu\x13 derp"; | ||
| 294 | , | ||
| 295 | \\pub const FOO2 = c"aoeu\x134 derp"; | ||
| 296 | , | ||
| 297 | \\pub const FOO_CHAR = 63; | ||
| 298 | ); | ||
| 299 | } | ||
test/tests.zig+24-24| ... | @@ -17,7 +17,7 @@ const build_examples = @import("build_examples.zig"); | ... | @@ -17,7 +17,7 @@ const build_examples = @import("build_examples.zig"); |
| 17 | const compile_errors = @import("compile_errors.zig"); | 17 | const compile_errors = @import("compile_errors.zig"); |
| 18 | const assemble_and_link = @import("assemble_and_link.zig"); | 18 | const assemble_and_link = @import("assemble_and_link.zig"); |
| 19 | const debug_safety = @import("debug_safety.zig"); | 19 | const debug_safety = @import("debug_safety.zig"); |
| 20 | const parseh = @import("parseh.zig"); | 20 | const parsec = @import("parsec.zig"); |
| 21 | 21 | ||
| 22 | const TestTarget = struct { | 22 | const TestTarget = struct { |
| 23 | os: builtin.Os, | 23 | os: builtin.Os, |
| ... | @@ -115,16 +115,16 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) -> & | ... | @@ -115,16 +115,16 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) -> & |
| 115 | return cases.step; | 115 | return cases.step; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | pub fn addParseHTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { | 118 | pub fn addParseCTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step { |
| 119 | const cases = %%b.allocator.create(ParseHContext); | 119 | const cases = %%b.allocator.create(ParseCContext); |
| 120 | *cases = ParseHContext { | 120 | *cases = ParseCContext { |
| 121 | .b = b, | 121 | .b = b, |
| 122 | .step = b.step("test-parseh", "Run the C header file parsing tests"), | 122 | .step = b.step("test-parsec", "Run the C header file parsing tests"), |
| 123 | .test_index = 0, | 123 | .test_index = 0, |
| 124 | .test_filter = test_filter, | 124 | .test_filter = test_filter, |
| 125 | }; | 125 | }; |
| 126 | 126 | ||
| 127 | parseh.addCases(cases); | 127 | parsec.addCases(cases); |
| 128 | 128 | ||
| 129 | return cases.step; | 129 | return cases.step; |
| 130 | } | 130 | } |
| ... | @@ -752,7 +752,7 @@ pub const BuildExamplesContext = struct { | ... | @@ -752,7 +752,7 @@ pub const BuildExamplesContext = struct { |
| 752 | } | 752 | } |
| 753 | }; | 753 | }; |
| 754 | 754 | ||
| 755 | pub const ParseHContext = struct { | 755 | pub const ParseCContext = struct { |
| 756 | b: &build.Builder, | 756 | b: &build.Builder, |
| 757 | step: &build.Step, | 757 | step: &build.Step, |
| 758 | test_index: usize, | 758 | test_index: usize, |
| ... | @@ -781,18 +781,18 @@ pub const ParseHContext = struct { | ... | @@ -781,18 +781,18 @@ pub const ParseHContext = struct { |
| 781 | } | 781 | } |
| 782 | }; | 782 | }; |
| 783 | 783 | ||
| 784 | const ParseHCmpOutputStep = struct { | 784 | const ParseCCmpOutputStep = struct { |
| 785 | step: build.Step, | 785 | step: build.Step, |
| 786 | context: &ParseHContext, | 786 | context: &ParseCContext, |
| 787 | name: []const u8, | 787 | name: []const u8, |
| 788 | test_index: usize, | 788 | test_index: usize, |
| 789 | case: &const TestCase, | 789 | case: &const TestCase, |
| 790 | 790 | ||
| 791 | pub fn create(context: &ParseHContext, name: []const u8, case: &const TestCase) -> &ParseHCmpOutputStep { | 791 | pub fn create(context: &ParseCContext, name: []const u8, case: &const TestCase) -> &ParseCCmpOutputStep { |
| 792 | const allocator = context.b.allocator; | 792 | const allocator = context.b.allocator; |
| 793 | const ptr = %%allocator.create(ParseHCmpOutputStep); | 793 | const ptr = %%allocator.create(ParseCCmpOutputStep); |
| 794 | *ptr = ParseHCmpOutputStep { | 794 | *ptr = ParseCCmpOutputStep { |
| 795 | .step = build.Step.init("ParseHCmpOutput", allocator, make), | 795 | .step = build.Step.init("ParseCCmpOutput", allocator, make), |
| 796 | .context = context, | 796 | .context = context, |
| 797 | .name = name, | 797 | .name = name, |
| 798 | .test_index = context.test_index, | 798 | .test_index = context.test_index, |
| ... | @@ -803,13 +803,13 @@ pub const ParseHContext = struct { | ... | @@ -803,13 +803,13 @@ pub const ParseHContext = struct { |
| 803 | } | 803 | } |
| 804 | 804 | ||
| 805 | fn make(step: &build.Step) -> %void { | 805 | fn make(step: &build.Step) -> %void { |
| 806 | const self = @fieldParentPtr(ParseHCmpOutputStep, "step", step); | 806 | const self = @fieldParentPtr(ParseCCmpOutputStep, "step", step); |
| 807 | const b = self.context.b; | 807 | const b = self.context.b; |
| 808 | 808 | ||
| 809 | const root_src = %%os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename); | 809 | const root_src = %%os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename); |
| 810 | 810 | ||
| 811 | var zig_args = ArrayList([]const u8).init(b.allocator); | 811 | var zig_args = ArrayList([]const u8).init(b.allocator); |
| 812 | %%zig_args.append("parseh"); | 812 | %%zig_args.append("parsec"); |
| 813 | %%zig_args.append(b.pathFromRoot(root_src)); | 813 | %%zig_args.append(b.pathFromRoot(root_src)); |
| 814 | 814 | ||
| 815 | %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); | 815 | %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); |
| ... | @@ -855,7 +855,7 @@ pub const ParseHContext = struct { | ... | @@ -855,7 +855,7 @@ pub const ParseHContext = struct { |
| 855 | 855 | ||
| 856 | if (stderr.len != 0 and !self.case.allow_warnings) { | 856 | if (stderr.len != 0 and !self.case.allow_warnings) { |
| 857 | %%io.stderr.printf( | 857 | %%io.stderr.printf( |
| 858 | \\====== parseh emitted warnings: ============ | 858 | \\====== parsec emitted warnings: ============ |
| 859 | \\{} | 859 | \\{} |
| 860 | \\============================================ | 860 | \\============================================ |
| 861 | \\ | 861 | \\ |
| ... | @@ -888,7 +888,7 @@ pub const ParseHContext = struct { | ... | @@ -888,7 +888,7 @@ pub const ParseHContext = struct { |
| 888 | %%io.stderr.printf("\n"); | 888 | %%io.stderr.printf("\n"); |
| 889 | } | 889 | } |
| 890 | 890 | ||
| 891 | pub fn create(self: &ParseHContext, allow_warnings: bool, name: []const u8, | 891 | pub fn create(self: &ParseCContext, allow_warnings: bool, name: []const u8, |
| 892 | source: []const u8, expected_lines: ...) -> &TestCase | 892 | source: []const u8, expected_lines: ...) -> &TestCase |
| 893 | { | 893 | { |
| 894 | const tc = %%self.b.allocator.create(TestCase); | 894 | const tc = %%self.b.allocator.create(TestCase); |
| ... | @@ -906,32 +906,32 @@ pub const ParseHContext = struct { | ... | @@ -906,32 +906,32 @@ pub const ParseHContext = struct { |
| 906 | return tc; | 906 | return tc; |
| 907 | } | 907 | } |
| 908 | 908 | ||
| 909 | pub fn add(self: &ParseHContext, name: []const u8, source: []const u8, expected_lines: ...) { | 909 | pub fn add(self: &ParseCContext, name: []const u8, source: []const u8, expected_lines: ...) { |
| 910 | const tc = self.create(false, name, source, expected_lines); | 910 | const tc = self.create(false, name, source, expected_lines); |
| 911 | self.addCase(tc); | 911 | self.addCase(tc); |
| 912 | } | 912 | } |
| 913 | 913 | ||
| 914 | pub fn addAllowWarnings(self: &ParseHContext, name: []const u8, source: []const u8, expected_lines: ...) { | 914 | pub fn addAllowWarnings(self: &ParseCContext, name: []const u8, source: []const u8, expected_lines: ...) { |
| 915 | const tc = self.create(true, name, source, expected_lines); | 915 | const tc = self.create(true, name, source, expected_lines); |
| 916 | self.addCase(tc); | 916 | self.addCase(tc); |
| 917 | } | 917 | } |
| 918 | 918 | ||
| 919 | pub fn addCase(self: &ParseHContext, case: &const TestCase) { | 919 | pub fn addCase(self: &ParseCContext, case: &const TestCase) { |
| 920 | const b = self.b; | 920 | const b = self.b; |
| 921 | 921 | ||
| 922 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "parseh {}", case.name); | 922 | const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "parsec {}", case.name); |
| 923 | if (self.test_filter) |filter| { | 923 | if (self.test_filter) |filter| { |
| 924 | if (mem.indexOf(u8, annotated_case_name, filter) == null) | 924 | if (mem.indexOf(u8, annotated_case_name, filter) == null) |
| 925 | return; | 925 | return; |
| 926 | } | 926 | } |
| 927 | 927 | ||
| 928 | const parseh_and_cmp = ParseHCmpOutputStep.create(self, annotated_case_name, case); | 928 | const parsec_and_cmp = ParseCCmpOutputStep.create(self, annotated_case_name, case); |
| 929 | self.step.dependOn(&parseh_and_cmp.step); | 929 | self.step.dependOn(&parsec_and_cmp.step); |
| 930 | 930 | ||
| 931 | for (case.sources.toSliceConst()) |src_file| { | 931 | for (case.sources.toSliceConst()) |src_file| { |
| 932 | const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename); | 932 | const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename); |
| 933 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); | 933 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 934 | parseh_and_cmp.step.dependOn(&write_src.step); | 934 | parsec_and_cmp.step.dependOn(&write_src.step); |
| 935 | } | 935 | } |
| 936 | } | 936 | } |
| 937 | }; | 937 | }; |