authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-24 14:56:05-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-11-24 14:56:05-05:00
log5a25505668bac9aed0ad8f3b23fe81c6aff29b71
treebd5cea1c33ca7d272690f5c13f97a97612a7a3e6
parentafbbdb2c67127985cadae7244348665ece8b2f25

rename "parsec" to "translate-c"


16 files changed, 4491 insertions(+), 4491 deletions(-)

CMakeLists.txt+1-1
...@@ -339,7 +339,7 @@ set(ZIG_SOURCES...@@ -339,7 +339,7 @@ set(ZIG_SOURCES
339 "${CMAKE_SOURCE_DIR}/src/target.cpp"339 "${CMAKE_SOURCE_DIR}/src/target.cpp"
340 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"340 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
341 "${CMAKE_SOURCE_DIR}/src/util.cpp"341 "${CMAKE_SOURCE_DIR}/src/util.cpp"
342 "${CMAKE_SOURCE_DIR}/src/parsec.cpp"342 "${CMAKE_SOURCE_DIR}/src/translate_c.cpp"
343 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"343 "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
344)344)
345345
build.zig+1-1
...@@ -58,5 +58,5 @@ pub fn build(b: &Builder) {...@@ -58,5 +58,5 @@ pub fn build(b: &Builder) {
58 test_step.dependOn(tests.addCompileErrorTests(b, test_filter));58 test_step.dependOn(tests.addCompileErrorTests(b, test_filter));
59 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter));59 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter));
60 test_step.dependOn(tests.addDebugSafetyTests(b, test_filter));60 test_step.dependOn(tests.addDebugSafetyTests(b, test_filter));
61 test_step.dependOn(tests.addParseCTests(b, test_filter));61 test_step.dependOn(tests.addTranslateCTests(b, test_filter));
62}62}
ci/travis_osx_script+1-1
...@@ -22,4 +22,4 @@ make install...@@ -22,4 +22,4 @@ make install
22./zig build --build-file ../build.zig test-compile-errors --verbose22./zig build --build-file ../build.zig test-compile-errors --verbose
23./zig build --build-file ../build.zig test-asm-link --verbose23./zig build --build-file ../build.zig test-asm-link --verbose
24./zig build --build-file ../build.zig test-debug-safety --verbose24./zig build --build-file ../build.zig test-debug-safety --verbose
25./zig build --build-file ../build.zig test-parsec --verbose25./zig build --build-file ../build.zig test-translate-c --verbose
src-self-hosted/main.zig+1-1
...@@ -208,7 +208,7 @@ fn printUsage(outstream: &io.OutStream) -> %void {...@@ -208,7 +208,7 @@ fn printUsage(outstream: &io.OutStream) -> %void {
208 \\ build-exe [source] create executable from source or object files208 \\ build-exe [source] create executable from source or object files
209 \\ build-lib [source] create library from source or object files209 \\ build-lib [source] create library from source or object files
210 \\ build-obj [source] create object from source or assembly210 \\ build-obj [source] create object from source or assembly
211 \\ parsec [source] convert c code to zig code211 \\ translate-c [source] convert c code to zig code
212 \\ targets list available compilation targets212 \\ targets list available compilation targets
213 \\ test [source] create and run a test build213 \\ test [source] create and run a test build
214 \\ version print version number and exit214 \\ version print version number and exit
src/analyze.cpp+2-2
...@@ -28,7 +28,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type);...@@ -28,7 +28,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type);
2828
29ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {29ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
30 if (node->owner->c_import_node != nullptr) {30 if (node->owner->c_import_node != nullptr) {
31 // if this happens, then parsec generated code that31 // if this happens, then translate_c generated code that
32 // failed semantic analysis, which isn't supposed to happen32 // failed semantic analysis, which isn't supposed to happen
33 ErrorMsg *err = add_node_error(g, node->owner->c_import_node,33 ErrorMsg *err = add_node_error(g, node->owner->c_import_node,
34 buf_sprintf("compiler bug: @cImport generated invalid zig code"));34 buf_sprintf("compiler bug: @cImport generated invalid zig code"));
...@@ -48,7 +48,7 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {...@@ -48,7 +48,7 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
4848
49ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {49ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
50 if (node->owner->c_import_node != nullptr) {50 if (node->owner->c_import_node != nullptr) {
51 // if this happens, then parsec generated code that51 // if this happens, then translate_c generated code that
52 // failed semantic analysis, which isn't supposed to happen52 // failed semantic analysis, which isn't supposed to happen
5353
54 Buf *note_path = buf_create_from_str("?.c");54 Buf *note_path = buf_create_from_str("?.c");
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 "parsec.hpp"18#include "translate_c.hpp"
19#include "target.hpp"19#include "target.hpp"
20#include "zig_llvm.hpp"20#include "zig_llvm.hpp"
2121
...@@ -5353,7 +5353,7 @@ static void init(CodeGen *g) {...@@ -5353,7 +5353,7 @@ static void init(CodeGen *g) {
5353 define_builtin_compile_vars(g);5353 define_builtin_compile_vars(g);
5354}5354}
53555355
5356void codegen_parsec(CodeGen *g, Buf *full_path) {5356void codegen_translate_c(CodeGen *g, Buf *full_path) {
5357 find_libc_include_path(g);5357 find_libc_include_path(g);
53585358
5359 Buf *src_basename = buf_alloc();5359 Buf *src_basename = buf_alloc();
src/codegen.hpp+1-1
...@@ -56,7 +56,7 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir,...@@ -56,7 +56,7 @@ PackageTableEntry *codegen_create_package(CodeGen *g, const char *root_src_dir,
56void codegen_add_assembly(CodeGen *g, Buf *path);56void codegen_add_assembly(CodeGen *g, Buf *path);
57void codegen_add_object(CodeGen *g, Buf *object_path);57void codegen_add_object(CodeGen *g, Buf *object_path);
5858
59void codegen_parsec(CodeGen *g, Buf *path);59void codegen_translate_c(CodeGen *g, Buf *path);
6060
6161
62#endif62#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 "parsec.hpp"14#include "translate_c.hpp"
15#include "range_set.hpp"15#include "range_set.hpp"
16#include "softfloat.hpp"16#include "softfloat.hpp"
1717
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 " parsec [source] convert c code to zig code\n"26 " translate-c [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"
...@@ -229,7 +229,7 @@ enum Cmd {...@@ -229,7 +229,7 @@ enum Cmd {
229 CmdTest,229 CmdTest,
230 CmdVersion,230 CmdVersion,
231 CmdZen,231 CmdZen,
232 CmdParseC,232 CmdTranslateC,
233 CmdTargets,233 CmdTargets,
234};234};
235235
...@@ -632,8 +632,8 @@ int main(int argc, char **argv) {...@@ -632,8 +632,8 @@ int main(int argc, char **argv) {
632 cmd = CmdVersion;632 cmd = CmdVersion;
633 } else if (strcmp(arg, "zen") == 0) {633 } else if (strcmp(arg, "zen") == 0) {
634 cmd = CmdZen;634 cmd = CmdZen;
635 } else if (strcmp(arg, "parsec") == 0) {635 } else if (strcmp(arg, "translate-c") == 0) {
636 cmd = CmdParseC;636 cmd = CmdTranslateC;
637 } else if (strcmp(arg, "test") == 0) {637 } else if (strcmp(arg, "test") == 0) {
638 cmd = CmdTest;638 cmd = CmdTest;
639 out_type = OutTypeExe;639 out_type = OutTypeExe;
...@@ -646,7 +646,7 @@ int main(int argc, char **argv) {...@@ -646,7 +646,7 @@ int main(int argc, char **argv) {
646 } else {646 } else {
647 switch (cmd) {647 switch (cmd) {
648 case CmdBuild:648 case CmdBuild:
649 case CmdParseC:649 case CmdTranslateC:
650 case CmdTest:650 case CmdTest:
651 if (!in_file) {651 if (!in_file) {
652 in_file = arg;652 in_file = arg;
...@@ -703,13 +703,13 @@ int main(int argc, char **argv) {...@@ -703,13 +703,13 @@ int main(int argc, char **argv) {
703703
704 switch (cmd) {704 switch (cmd) {
705 case CmdBuild:705 case CmdBuild:
706 case CmdParseC:706 case CmdTranslateC:
707 case CmdTest:707 case CmdTest:
708 {708 {
709 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {709 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
710 fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");710 fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
711 return usage(arg0);711 return usage(arg0);
712 } else if ((cmd == CmdParseC || cmd == CmdTest) && !in_file) {712 } else if ((cmd == CmdTranslateC || cmd == CmdTest) && !in_file) {
713 fprintf(stderr, "Expected source file argument.\n");713 fprintf(stderr, "Expected source file argument.\n");
714 return usage(arg0);714 return usage(arg0);
715 } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {715 } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
...@@ -719,7 +719,7 @@ int main(int argc, char **argv) {...@@ -719,7 +719,7 @@ int main(int argc, char **argv) {
719719
720 assert(cmd != CmdBuild || out_type != OutTypeUnknown);720 assert(cmd != CmdBuild || out_type != OutTypeUnknown);
721721
722 bool need_name = (cmd == CmdBuild || cmd == CmdParseC);722 bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);
723723
724 Buf *in_file_buf = nullptr;724 Buf *in_file_buf = nullptr;
725725
...@@ -742,7 +742,7 @@ int main(int argc, char **argv) {...@@ -742,7 +742,7 @@ int main(int argc, char **argv) {
742 return usage(arg0);742 return usage(arg0);
743 }743 }
744744
745 Buf *zig_root_source_file = (cmd == CmdParseC) ? nullptr : in_file_buf;745 Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf;
746746
747 Buf *full_cache_dir = buf_alloc();747 Buf *full_cache_dir = buf_alloc();
748 os_path_resolve(buf_create_from_str("."),748 os_path_resolve(buf_create_from_str("."),
...@@ -841,8 +841,8 @@ int main(int argc, char **argv) {...@@ -841,8 +841,8 @@ int main(int argc, char **argv) {
841 if (timing_info)841 if (timing_info)
842 codegen_print_timing_report(g, stdout);842 codegen_print_timing_report(g, stdout);
843 return EXIT_SUCCESS;843 return EXIT_SUCCESS;
844 } else if (cmd == CmdParseC) {844 } else if (cmd == CmdTranslateC) {
845 codegen_parsec(g, in_file_buf);845 codegen_translate_c(g, in_file_buf);
846 ast_render(g, stdout, g->root_import->root, 4);846 ast_render(g, stdout, g->root_import->root, 4);
847 if (timing_info)847 if (timing_info)
848 codegen_print_timing_report(g, stdout);848 codegen_print_timing_report(g, stdout);
src/parsec.cpp deleted-3527
...@@ -1,3527 +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 "error.hpp"
12#include "ir.hpp"
13#include "os.hpp"
14#include "parsec.hpp"
15#include "parser.hpp"
16
17
18#include <clang/Frontend/ASTUnit.h>
19#include <clang/Frontend/CompilerInstance.h>
20#include <clang/AST/Expr.h>
21
22#include <string.h>
23
24using namespace clang;
25
26struct MacroSymbol {
27 Buf *name;
28 Buf *value;
29};
30
31struct Alias {
32 Buf *new_name;
33 Buf *canon_name;
34};
35
36struct Context {
37 ImportTableEntry *import;
38 ZigList<ErrorMsg *> *errors;
39 VisibMod visib_mod;
40 VisibMod export_visib_mod;
41 AstNode *root;
42 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
43 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
44 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
45 SourceManager *source_manager;
46 ZigList<Alias> aliases;
47 ZigList<MacroSymbol> macro_symbols;
48 AstNode *source_node;
49 bool warnings_on;
50
51 CodeGen *codegen;
52 ASTContext *ctx;
53
54 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
55};
56
57static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
58static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
59static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);
60
61
62ATTRIBUTE_PRINTF(3, 4)
63static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {
64 if (!c->warnings_on) {
65 return;
66 }
67
68 va_list ap;
69 va_start(ap, format);
70 Buf *msg = buf_vprintf(format, ap);
71 va_end(ap);
72
73 StringRef filename = c->source_manager->getFilename(sl);
74 const char *filename_bytes = (const char *)filename.bytes_begin();
75 Buf *path;
76 if (filename_bytes) {
77 path = buf_create_from_str(filename_bytes);
78 } else {
79 path = buf_sprintf("(no file)");
80 }
81 unsigned line = c->source_manager->getSpellingLineNumber(sl);
82 unsigned column = c->source_manager->getSpellingColumnNumber(sl);
83 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
84}
85
86static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) {
87 Alias *alias = c->aliases.add_one();
88 alias->new_name = new_name;
89 alias->canon_name = canon_name;
90}
91
92static AstNode * trans_create_node(Context *c, NodeType id) {
93 AstNode *node = allocate<AstNode>(1);
94 node->type = id;
95 node->owner = c->import;
96 // TODO line/column. mapping to C file??
97 return node;
98}
99
100static AstNode *trans_create_node_float_lit(Context *c, double value) {
101 AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
102 node->data.float_literal.bigfloat = allocate<BigFloat>(1);
103 bigfloat_init_64(node->data.float_literal.bigfloat, value);
104 return node;
105}
106
107static AstNode *trans_create_node_symbol(Context *c, Buf *name) {
108 AstNode *node = trans_create_node(c, NodeTypeSymbol);
109 node->data.symbol_expr.symbol = name;
110 return node;
111}
112
113static AstNode *trans_create_node_symbol_str(Context *c, const char *name) {
114 return trans_create_node_symbol(c, buf_create_from_str(name));
115}
116
117static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) {
118 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
119 node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name);
120 node->data.fn_call_expr.is_builtin = true;
121 return node;
122}
123
124static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *name) {
125 return trans_create_node_builtin_fn_call(c, buf_create_from_str(name));
126}
127
128static AstNode *trans_create_node_opaque(Context *c) {
129 return trans_create_node_builtin_fn_call_str(c, "OpaqueType");
130}
131
132static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) {
133 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
134 node->data.fn_call_expr.fn_ref_expr = fn_ref_expr;
135 node->data.fn_call_expr.params.append(arg1);
136 return node;
137}
138
139static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {
140 AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr);
141 if (container->type == NodeTypeSymbol) {
142 assert(container->data.symbol_expr.symbol != nullptr);
143 }
144 node->data.field_access_expr.struct_expr = container;
145 node->data.field_access_expr.field_name = field_name;
146 return node;
147}
148
149static AstNode *trans_create_node_field_access_str(Context *c, AstNode *container, const char *field_name) {
150 return trans_create_node_field_access(c, container, buf_create_from_str(field_name));
151}
152
153static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
154 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
155 node->data.prefix_op_expr.prefix_op = op;
156 node->data.prefix_op_expr.primary_expr = child_node;
157 return node;
158}
159
160static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpType op, AstNode *rhs_node) {
161 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
162 node->data.bin_op_expr.op1 = lhs_node;
163 node->data.bin_op_expr.bin_op = op;
164 node->data.bin_op_expr.op2 = rhs_node;
165 return node;
166}
167
168static AstNode *maybe_suppress_result(Context *c, bool result_used, AstNode *node) {
169 if (result_used) return node;
170 return trans_create_node_bin_op(c,
171 trans_create_node_symbol_str(c, "_"),
172 BinOpTypeAssign,
173 node);
174}
175
176static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {
177 AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr);
178 node->data.addr_of_expr.is_const = is_const;
179 node->data.addr_of_expr.is_volatile = is_volatile;
180 node->data.addr_of_expr.op_expr = child_node;
181 return node;
182}
183
184static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
185 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
186 node->data.string_literal.buf = buf;
187 node->data.string_literal.c = true;
188 return node;
189}
190
191static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) {
192 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
193 node->data.string_literal.buf = buf;
194 node->data.string_literal.c = false;
195 return node;
196}
197
198static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) {
199 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
200 node->data.int_literal.bigint = allocate<BigInt>(1);
201 bigint_init_data(node->data.int_literal.bigint, &x, 1, is_negative);
202 return node;
203}
204
205static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) {
206 return trans_create_node_unsigned_negative(c, x, false);
207}
208
209static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) {
210 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
211 node->data.fn_call_expr.fn_ref_expr = dest;
212 node->data.fn_call_expr.params.resize(1);
213 node->data.fn_call_expr.params.items[0] = src;
214 return node;
215}
216
217static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative,
218 const char *type_name)
219{
220 AstNode *lit_node = trans_create_node_unsigned_negative(c, x, is_negative);
221 return trans_create_node_cast(c, trans_create_node_symbol_str(c, type_name), lit_node);
222}
223
224static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, AstNode *child_type_node) {
225 AstNode *node = trans_create_node(c, NodeTypeArrayType);
226 node->data.array_type.size = size_node;
227 node->data.array_type.child_type = child_type_node;
228 return node;
229}
230
231static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool is_const, Buf *var_name,
232 AstNode *type_node, AstNode *init_node)
233{
234 AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration);
235 node->data.variable_declaration.visib_mod = visib_mod;
236 node->data.variable_declaration.symbol = var_name;
237 node->data.variable_declaration.is_const = is_const;
238 node->data.variable_declaration.type = type_node;
239 node->data.variable_declaration.expr = init_node;
240 return node;
241}
242
243static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
244 AstNode *init_node)
245{
246 return trans_create_node_var_decl(c, c->visib_mod, is_const, var_name, type_node, init_node);
247}
248
249static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
250 AstNode *init_node)
251{
252 return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node);
253}
254
255
256static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) {
257 AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
258 AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
259 fn_proto->data.fn_proto.visib_mod = c->visib_mod;
260 fn_proto->data.fn_proto.name = fn_name;
261 fn_proto->data.fn_proto.is_inline = true;
262 fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
263
264 fn_def->data.fn_def.fn_proto = fn_proto;
265 fn_proto->data.fn_proto.fn_def_node = fn_def;
266
267 AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, trans_create_node_symbol(c, var_name));
268 AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr);
269 fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
270
271 for (size_t i = 0; i < src_proto_node->data.fn_proto.params.length; i += 1) {
272 AstNode *src_param_node = src_proto_node->data.fn_proto.params.at(i);
273 Buf *param_name = src_param_node->data.param_decl.name;
274 if (!param_name) param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
275
276 AstNode *dest_param_node = trans_create_node(c, NodeTypeParamDecl);
277 dest_param_node->data.param_decl.name = param_name;
278 dest_param_node->data.param_decl.type = src_param_node->data.param_decl.type;
279 dest_param_node->data.param_decl.is_noalias = src_param_node->data.param_decl.is_noalias;
280 fn_proto->data.fn_proto.params.append(dest_param_node);
281
282 fn_call_node->data.fn_call_expr.params.append(trans_create_node_symbol(c, param_name));
283
284 }
285
286 AstNode *block = trans_create_node(c, NodeTypeBlock);
287 block->data.block.statements.resize(1);
288 block->data.block.statements.items[0] = fn_call_node;
289 block->data.block.last_statement_is_result_expression = true;
290
291 fn_def->data.fn_def.body = block;
292 return fn_def;
293}
294
295static AstNode *trans_create_node_unwrap_null(Context *c, AstNode *child) {
296 return trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, child);
297}
298
299static AstNode *get_global(Context *c, Buf *name) {
300 {
301 auto entry = c->global_table.maybe_get(name);
302 if (entry) {
303 return entry->value;
304 }
305 }
306 {
307 auto entry = c->macro_table.maybe_get(name);
308 if (entry)
309 return entry->value;
310 }
311 return nullptr;
312}
313
314static void add_top_level_decl(Context *c, Buf *name, AstNode *node) {
315 c->global_table.put(name, node);
316 c->root->data.root.top_level_decls.append(node);
317}
318
319static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {
320 bool is_const = true;
321 AstNode *type_node = nullptr;
322 AstNode *node = trans_create_node_var_decl_global(c, is_const, var_name, type_node, value_node);
323 add_top_level_decl(c, var_name, node);
324 return node;
325}
326
327static const char *decl_name(const Decl *decl) {
328 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
329 return (const char *)named_decl->getName().bytes_begin();
330}
331
332static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
333 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
334 node->data.int_literal.bigint = allocate<BigInt>(1);
335 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative());
336 return node;
337
338}
339
340static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
341
342static bool is_c_void_type(AstNode *node) {
343 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
344}
345
346static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) {
347 // TODO: maybe widen to increase size
348 // TODO: maybe bitcast to change sign
349 // TODO: maybe truncate to reduce size
350 return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr);
351}
352
353static bool qual_type_is_fn_ptr(Context *c, const QualType &qt) {
354 const Type *ty = qt.getTypePtr();
355 if (ty->getTypeClass() != Type::Pointer) {
356 return false;
357 }
358 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
359 QualType child_qt = pointer_ty->getPointeeType();
360 const Type *child_ty = child_qt.getTypePtr();
361 if (child_ty->getTypeClass() != Type::Paren) {
362 return false;
363 }
364 const ParenType *paren_ty = static_cast<const ParenType *>(child_ty);
365 return paren_ty->getInnerType().getTypePtr()->getTypeClass() == Type::FunctionProto;
366}
367
368static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
369 const Type *ty = qt.getTypePtr();
370 switch (ty->getTypeClass()) {
371 case Type::Builtin:
372 {
373 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
374 switch (builtin_ty->getKind()) {
375 case BuiltinType::Char_U:
376 case BuiltinType::UChar:
377 case BuiltinType::Char_S:
378 case BuiltinType::SChar:
379 return 8;
380 case BuiltinType::UInt128:
381 case BuiltinType::Int128:
382 return 128;
383 default:
384 return 0;
385 }
386 zig_unreachable();
387 }
388 case Type::Typedef:
389 {
390 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
391 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
392 const char *type_name = decl_name(typedef_decl);
393 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
394 return 8;
395 } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) {
396 return 16;
397 } else if (strcmp(type_name, "uint32_t") == 0 || strcmp(type_name, "int32_t") == 0) {
398 return 32;
399 } else if (strcmp(type_name, "uint64_t") == 0 || strcmp(type_name, "int64_t") == 0) {
400 return 64;
401 } else {
402 return 0;
403 }
404 }
405 default:
406 return 0;
407 }
408 zig_unreachable();
409}
410
411
412static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
413 const SourceLocation &source_loc)
414{
415 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
416 if (int_bit_width != 0) {
417 // we can perform the log2 now.
418 uint64_t cast_bit_width = log2_u64(int_bit_width);
419 return trans_create_node_symbol(c, buf_sprintf("u%" ZIG_PRI_u64, cast_bit_width));
420 }
421
422 AstNode *zig_type_node = trans_qual_type(c, qt, source_loc);
423
424// @import("std").math.Log2Int(c_long);
425//
426// FnCall
427// FieldAccess
428// FieldAccess
429// FnCall (.builtin = true)
430// Symbol "import"
431// StringLiteral "std"
432// Symbol "math"
433// Symbol "Log2Int"
434// zig_type_node
435
436 AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");
437 import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std")));
438 AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
439 AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
440 AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);
441
442 return log2int_fn_call;
443}
444
445static bool qual_type_child_is_fn_proto(const QualType &qt) {
446 if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
447 const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
448 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
449 return true;
450 }
451 } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
452 const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());
453 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
454 }
455 return false;
456}
457
458static QualType resolve_any_typedef(Context *c, QualType qt) {
459 const Type * ty = qt.getTypePtr();
460 if (ty->getTypeClass() != Type::Typedef)
461 return qt;
462 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
463 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
464 return typedef_decl->getUnderlyingType();
465}
466
467static bool c_is_signed_integer(Context *c, QualType qt) {
468 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
469 if (c_type->getTypeClass() != Type::Builtin)
470 return false;
471 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
472 switch (builtin_ty->getKind()) {
473 case BuiltinType::SChar:
474 case BuiltinType::Short:
475 case BuiltinType::Int:
476 case BuiltinType::Long:
477 case BuiltinType::LongLong:
478 case BuiltinType::Int128:
479 case BuiltinType::WChar_S:
480 return true;
481 default:
482 return false;
483 }
484}
485
486static bool c_is_unsigned_integer(Context *c, QualType qt) {
487 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
488 if (c_type->getTypeClass() != Type::Builtin)
489 return false;
490 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
491 switch (builtin_ty->getKind()) {
492 case BuiltinType::Char_U:
493 case BuiltinType::UChar:
494 case BuiltinType::Char_S:
495 case BuiltinType::UShort:
496 case BuiltinType::UInt:
497 case BuiltinType::ULong:
498 case BuiltinType::ULongLong:
499 case BuiltinType::UInt128:
500 case BuiltinType::WChar_U:
501 return true;
502 default:
503 return false;
504 }
505}
506
507static bool c_is_float(Context *c, QualType qt) {
508 const Type *c_type = qt.getTypePtr();
509 if (c_type->getTypeClass() != Type::Builtin)
510 return false;
511 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
512 switch (builtin_ty->getKind()) {
513 case BuiltinType::Half:
514 case BuiltinType::Float:
515 case BuiltinType::Double:
516 case BuiltinType::Float128:
517 case BuiltinType::LongDouble:
518 return true;
519 default:
520 return false;
521 }
522}
523
524static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
525 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
526 // float and signed integer overflow is undefined behavior.
527 return false;
528 } else {
529 // unsigned integer overflow wraps around.
530 return true;
531 }
532}
533
534enum TransLRValue {
535 TransLValue,
536 TransRValue,
537};
538
539static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval);
540static AstNode *const skip_add_to_block_node = (AstNode *) 0x2;
541
542static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) {
543 return trans_stmt(c, result_used, block, expr, lrval);
544}
545
546static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
547 switch (ty->getTypeClass()) {
548 case Type::Builtin:
549 {
550 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
551 switch (builtin_ty->getKind()) {
552 case BuiltinType::Void:
553 return trans_create_node_symbol_str(c, "c_void");
554 case BuiltinType::Bool:
555 return trans_create_node_symbol_str(c, "bool");
556 case BuiltinType::Char_U:
557 case BuiltinType::UChar:
558 case BuiltinType::Char_S:
559 return trans_create_node_symbol_str(c, "u8");
560 case BuiltinType::SChar:
561 return trans_create_node_symbol_str(c, "i8");
562 case BuiltinType::UShort:
563 return trans_create_node_symbol_str(c, "c_ushort");
564 case BuiltinType::UInt:
565 return trans_create_node_symbol_str(c, "c_uint");
566 case BuiltinType::ULong:
567 return trans_create_node_symbol_str(c, "c_ulong");
568 case BuiltinType::ULongLong:
569 return trans_create_node_symbol_str(c, "c_ulonglong");
570 case BuiltinType::Short:
571 return trans_create_node_symbol_str(c, "c_short");
572 case BuiltinType::Int:
573 return trans_create_node_symbol_str(c, "c_int");
574 case BuiltinType::Long:
575 return trans_create_node_symbol_str(c, "c_long");
576 case BuiltinType::LongLong:
577 return trans_create_node_symbol_str(c, "c_longlong");
578 case BuiltinType::UInt128:
579 return trans_create_node_symbol_str(c, "u128");
580 case BuiltinType::Int128:
581 return trans_create_node_symbol_str(c, "i128");
582 case BuiltinType::Float:
583 return trans_create_node_symbol_str(c, "f32");
584 case BuiltinType::Double:
585 return trans_create_node_symbol_str(c, "f64");
586 case BuiltinType::Float128:
587 return trans_create_node_symbol_str(c, "f128");
588 case BuiltinType::LongDouble:
589 return trans_create_node_symbol_str(c, "c_longdouble");
590 case BuiltinType::WChar_U:
591 case BuiltinType::Char16:
592 case BuiltinType::Char32:
593 case BuiltinType::WChar_S:
594 case BuiltinType::Half:
595 case BuiltinType::NullPtr:
596 case BuiltinType::ObjCId:
597 case BuiltinType::ObjCClass:
598 case BuiltinType::ObjCSel:
599 case BuiltinType::OMPArraySection:
600 case BuiltinType::Dependent:
601 case BuiltinType::Overload:
602 case BuiltinType::BoundMember:
603 case BuiltinType::PseudoObject:
604 case BuiltinType::UnknownAny:
605 case BuiltinType::BuiltinFn:
606 case BuiltinType::ARCUnbridgedCast:
607
608 case BuiltinType::OCLImage1dRO:
609 case BuiltinType::OCLImage1dArrayRO:
610 case BuiltinType::OCLImage1dBufferRO:
611 case BuiltinType::OCLImage2dRO:
612 case BuiltinType::OCLImage2dArrayRO:
613 case BuiltinType::OCLImage2dDepthRO:
614 case BuiltinType::OCLImage2dArrayDepthRO:
615 case BuiltinType::OCLImage2dMSAARO:
616 case BuiltinType::OCLImage2dArrayMSAARO:
617 case BuiltinType::OCLImage2dMSAADepthRO:
618 case BuiltinType::OCLImage2dArrayMSAADepthRO:
619 case BuiltinType::OCLImage3dRO:
620 case BuiltinType::OCLImage1dWO:
621 case BuiltinType::OCLImage1dArrayWO:
622 case BuiltinType::OCLImage1dBufferWO:
623 case BuiltinType::OCLImage2dWO:
624 case BuiltinType::OCLImage2dArrayWO:
625 case BuiltinType::OCLImage2dDepthWO:
626 case BuiltinType::OCLImage2dArrayDepthWO:
627 case BuiltinType::OCLImage2dMSAAWO:
628 case BuiltinType::OCLImage2dArrayMSAAWO:
629 case BuiltinType::OCLImage2dMSAADepthWO:
630 case BuiltinType::OCLImage2dArrayMSAADepthWO:
631 case BuiltinType::OCLImage3dWO:
632 case BuiltinType::OCLImage1dRW:
633 case BuiltinType::OCLImage1dArrayRW:
634 case BuiltinType::OCLImage1dBufferRW:
635 case BuiltinType::OCLImage2dRW:
636 case BuiltinType::OCLImage2dArrayRW:
637 case BuiltinType::OCLImage2dDepthRW:
638 case BuiltinType::OCLImage2dArrayDepthRW:
639 case BuiltinType::OCLImage2dMSAARW:
640 case BuiltinType::OCLImage2dArrayMSAARW:
641 case BuiltinType::OCLImage2dMSAADepthRW:
642 case BuiltinType::OCLImage2dArrayMSAADepthRW:
643 case BuiltinType::OCLImage3dRW:
644 case BuiltinType::OCLSampler:
645 case BuiltinType::OCLEvent:
646 case BuiltinType::OCLClkEvent:
647 case BuiltinType::OCLQueue:
648 case BuiltinType::OCLReserveID:
649 emit_warning(c, source_loc, "unsupported builtin type");
650 return nullptr;
651 }
652 break;
653 }
654 case Type::Pointer:
655 {
656 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
657 QualType child_qt = pointer_ty->getPointeeType();
658 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
659 if (child_node == nullptr) {
660 emit_warning(c, source_loc, "pointer to unsupported type");
661 return nullptr;
662 }
663
664 if (qual_type_child_is_fn_proto(child_qt)) {
665 return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node);
666 }
667
668 AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(),
669 child_qt.isVolatileQualified(), child_node);
670 return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node);
671 }
672 case Type::Typedef:
673 {
674 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
675 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
676 return resolve_typedef_decl(c, typedef_decl);
677 }
678 case Type::Elaborated:
679 {
680 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
681 switch (elaborated_ty->getKeyword()) {
682 case ETK_Struct:
683 case ETK_Enum:
684 case ETK_Union:
685 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
686 case ETK_Interface:
687 case ETK_Class:
688 case ETK_Typename:
689 case ETK_None:
690 emit_warning(c, source_loc, "unsupported elaborated type");
691 return nullptr;
692 }
693 }
694 case Type::FunctionProto:
695 {
696 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
697
698 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
699 switch (fn_proto_ty->getCallConv()) {
700 case CC_C: // __attribute__((cdecl))
701 proto_node->data.fn_proto.cc = CallingConventionC;
702 proto_node->data.fn_proto.is_extern = true;
703 break;
704 case CC_X86StdCall: // __attribute__((stdcall))
705 proto_node->data.fn_proto.cc = CallingConventionStdcall;
706 break;
707 case CC_X86FastCall: // __attribute__((fastcall))
708 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
709 return nullptr;
710 case CC_X86ThisCall: // __attribute__((thiscall))
711 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
712 return nullptr;
713 case CC_X86VectorCall: // __attribute__((vectorcall))
714 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
715 return nullptr;
716 case CC_X86Pascal: // __attribute__((pascal))
717 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
718 return nullptr;
719 case CC_Win64: // __attribute__((ms_abi))
720 emit_warning(c, source_loc, "unsupported calling convention: win64");
721 return nullptr;
722 case CC_X86_64SysV: // __attribute__((sysv_abi))
723 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
724 return nullptr;
725 case CC_X86RegCall:
726 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
727 return nullptr;
728 case CC_AAPCS: // __attribute__((pcs("aapcs")))
729 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
730 return nullptr;
731 case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
732 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
733 return nullptr;
734 case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
735 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
736 return nullptr;
737 case CC_SpirFunction: // default for OpenCL functions on SPIR target
738 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
739 return nullptr;
740 case CC_OpenCLKernel:
741 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
742 return nullptr;
743 case CC_Swift:
744 emit_warning(c, source_loc, "unsupported calling convention: Swift");
745 return nullptr;
746 case CC_PreserveMost:
747 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
748 return nullptr;
749 case CC_PreserveAll:
750 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
751 return nullptr;
752 }
753
754 proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
755 size_t param_count = fn_proto_ty->getNumParams();
756
757 if (fn_proto_ty->getNoReturnAttr()) {
758 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
759 } else {
760 proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(),
761 source_loc);
762 if (proto_node->data.fn_proto.return_type == nullptr) {
763 emit_warning(c, source_loc, "unsupported function proto return type");
764 return nullptr;
765 }
766 // convert c_void to actual void (only for return type)
767 if (is_c_void_type(proto_node->data.fn_proto.return_type)) {
768 proto_node->data.fn_proto.return_type = nullptr;
769 }
770 }
771
772 //emit_warning(c, source_loc, "TODO figure out fn prototype fn name");
773 const char *fn_name = nullptr;
774 if (fn_name != nullptr) {
775 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
776 }
777
778 for (size_t i = 0; i < param_count; i += 1) {
779 QualType qt = fn_proto_ty->getParamType(i);
780 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
781
782 if (param_type_node == nullptr) {
783 emit_warning(c, source_loc, "unresolved function proto parameter type");
784 return nullptr;
785 }
786
787 AstNode *param_node = trans_create_node(c, NodeTypeParamDecl);
788 //emit_warning(c, source_loc, "TODO figure out fn prototype param name");
789 const char *param_name = nullptr;
790 if (param_name != nullptr) {
791 param_node->data.param_decl.name = buf_create_from_str(param_name);
792 }
793 param_node->data.param_decl.is_noalias = qt.isRestrictQualified();
794 param_node->data.param_decl.type = param_type_node;
795 proto_node->data.fn_proto.params.append(param_node);
796 }
797 // TODO check for always_inline attribute
798 // TODO check for align attribute
799
800 return proto_node;
801 }
802 case Type::Record:
803 {
804 const RecordType *record_ty = static_cast<const RecordType*>(ty);
805 return resolve_record_decl(c, record_ty->getDecl());
806 }
807 case Type::Enum:
808 {
809 const EnumType *enum_ty = static_cast<const EnumType*>(ty);
810 return resolve_enum_decl(c, enum_ty->getDecl());
811 }
812 case Type::ConstantArray:
813 {
814 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
815 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
816 if (child_type_node == nullptr) {
817 emit_warning(c, source_loc, "unresolved array element type");
818 return nullptr;
819 }
820 uint64_t size = const_arr_ty->getSize().getLimitedValue();
821 AstNode *size_node = trans_create_node_unsigned(c, size);
822 return trans_create_node_array_type(c, size_node, child_type_node);
823 }
824 case Type::Paren:
825 {
826 const ParenType *paren_ty = static_cast<const ParenType *>(ty);
827 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
828 }
829 case Type::Decayed:
830 {
831 const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);
832 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
833 }
834 case Type::Attributed:
835 {
836 const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);
837 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
838 }
839 case Type::BlockPointer:
840 case Type::LValueReference:
841 case Type::RValueReference:
842 case Type::MemberPointer:
843 case Type::IncompleteArray:
844 case Type::VariableArray:
845 case Type::DependentSizedArray:
846 case Type::DependentSizedExtVector:
847 case Type::Vector:
848 case Type::ExtVector:
849 case Type::FunctionNoProto:
850 case Type::UnresolvedUsing:
851 case Type::Adjusted:
852 case Type::TypeOfExpr:
853 case Type::TypeOf:
854 case Type::Decltype:
855 case Type::UnaryTransform:
856 case Type::TemplateTypeParm:
857 case Type::SubstTemplateTypeParm:
858 case Type::SubstTemplateTypeParmPack:
859 case Type::TemplateSpecialization:
860 case Type::Auto:
861 case Type::InjectedClassName:
862 case Type::DependentName:
863 case Type::DependentTemplateSpecialization:
864 case Type::PackExpansion:
865 case Type::ObjCObject:
866 case Type::ObjCInterface:
867 case Type::Complex:
868 case Type::ObjCObjectPointer:
869 case Type::Atomic:
870 case Type::Pipe:
871 case Type::ObjCTypeParam:
872 case Type::DeducedTemplateSpecialization:
873 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
874 return nullptr;
875 }
876 zig_unreachable();
877}
878
879static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) {
880 return trans_type(c, qt.getTypePtr(), source_loc);
881}
882
883static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) {
884 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
885 for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
886 AstNode *child_node = trans_stmt(c, false, child_block, *it, TransRValue);
887 if (child_node == nullptr)
888 return nullptr;
889 if (child_node != skip_add_to_block_node)
890 child_block->data.block.statements.append(child_node);
891 }
892 return child_block;
893}
894
895static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) {
896 Expr *value_expr = stmt->getRetValue();
897 if (value_expr == nullptr) {
898 emit_warning(c, stmt->getLocStart(), "TODO handle C return void");
899 return nullptr;
900 } else {
901 AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr);
902 return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr, TransRValue);
903 if (return_node->data.return_expr.expr == nullptr)
904 return nullptr;
905 return return_node;
906 }
907}
908
909static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) {
910 llvm::APSInt result;
911 if (!stmt->EvaluateAsInt(result, *c->ctx)) {
912 emit_warning(c, stmt->getLocStart(), "invalid integer literal");
913 return nullptr;
914 }
915 return trans_create_node_apint(c, result);
916}
917
918static AstNode *trans_conditional_operator(Context *c, bool result_used, AstNode *block, ConditionalOperator *stmt) {
919 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
920
921 Expr *cond_expr = stmt->getCond();
922 Expr *true_expr = stmt->getTrueExpr();
923 Expr *false_expr = stmt->getFalseExpr();
924
925 node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr, TransRValue);
926 if (node->data.if_bool_expr.condition == nullptr)
927 return nullptr;
928
929 node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr, TransRValue);
930 if (node->data.if_bool_expr.then_block == nullptr)
931 return nullptr;
932
933 node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr, TransRValue);
934 if (node->data.if_bool_expr.else_node == nullptr)
935 return nullptr;
936
937 return maybe_suppress_result(c, result_used, node);
938}
939
940static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) {
941 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
942 node->data.bin_op_expr.bin_op = bin_op;
943
944 node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransRValue);
945 if (node->data.bin_op_expr.op1 == nullptr)
946 return nullptr;
947
948 node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue);
949 if (node->data.bin_op_expr.op2 == nullptr)
950 return nullptr;
951
952 return node;
953}
954
955static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block, Expr *lhs, Expr *rhs) {
956 if (!result_used) {
957 // common case
958 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
959 node->data.bin_op_expr.bin_op = BinOpTypeAssign;
960
961 node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransLValue);
962 if (node->data.bin_op_expr.op1 == nullptr)
963 return nullptr;
964
965 node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue);
966 if (node->data.bin_op_expr.op2 == nullptr)
967 return nullptr;
968
969 return node;
970 } else {
971 // worst case
972 // c: lhs = rhs
973 // zig: {
974 // zig: const _tmp = rhs;
975 // zig: lhs = _tmp;
976 // zig: _tmp
977 // zig: }
978
979 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
980
981 // const _tmp = rhs;
982 AstNode *rhs_node = trans_expr(c, true, child_block, rhs, TransRValue);
983 if (rhs_node == nullptr) return nullptr;
984 // TODO: avoid name collisions with generated variable names
985 Buf* tmp_var_name = buf_create_from_str("_tmp");
986 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node);
987 child_block->data.block.statements.append(tmp_var_decl);
988
989 // lhs = _tmp;
990 AstNode *lhs_node = trans_expr(c, true, child_block, lhs, TransLValue);
991 if (lhs_node == nullptr) return nullptr;
992 child_block->data.block.statements.append(
993 trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign,
994 trans_create_node_symbol(c, tmp_var_name)));
995
996 // _tmp
997 child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name));
998 child_block->data.block.last_statement_is_result_expression = true;
999
1000 return child_block;
1001 }
1002}
1003
1004static AstNode *trans_create_shift_op(Context *c, AstNode *block, QualType result_type, Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) {
1005 const SourceLocation &rhs_location = rhs_expr->getLocStart();
1006 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
1007 // lhs >> u5(rh)
1008
1009 AstNode *lhs = trans_expr(c, true, block, lhs_expr, TransLValue);
1010 if (lhs == nullptr) return nullptr;
1011
1012 AstNode *rhs = trans_expr(c, true, block, rhs_expr, TransRValue);
1013 if (rhs == nullptr) return nullptr;
1014 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1015
1016 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
1017}
1018
1019static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *block, BinaryOperator *stmt) {
1020 switch (stmt->getOpcode()) {
1021 case BO_PtrMemD:
1022 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD");
1023 return nullptr;
1024 case BO_PtrMemI:
1025 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI");
1026 return nullptr;
1027 case BO_Mul:
1028 return trans_create_bin_op(c, block, stmt->getLHS(),
1029 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
1030 stmt->getRHS());
1031 case BO_Div:
1032 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1033 // unsigned/float division uses the operator
1034 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
1035 } else {
1036 // signed integer division uses @divTrunc
1037 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
1038 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1039 if (lhs == nullptr) return nullptr;
1040 fn_call->data.fn_call_expr.params.append(lhs);
1041 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
1042 if (rhs == nullptr) return nullptr;
1043 fn_call->data.fn_call_expr.params.append(rhs);
1044 return fn_call;
1045 }
1046 case BO_Rem:
1047 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1048 // unsigned/float division uses the operator
1049 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
1050 } else {
1051 // signed integer division uses @rem
1052 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
1053 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1054 if (lhs == nullptr) return nullptr;
1055 fn_call->data.fn_call_expr.params.append(lhs);
1056 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
1057 if (rhs == nullptr) return nullptr;
1058 fn_call->data.fn_call_expr.params.append(rhs);
1059 return fn_call;
1060 }
1061 case BO_Add:
1062 return trans_create_bin_op(c, block, stmt->getLHS(),
1063 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
1064 stmt->getRHS());
1065 case BO_Sub:
1066 return trans_create_bin_op(c, block, stmt->getLHS(),
1067 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
1068 stmt->getRHS());
1069 case BO_Shl:
1070 return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
1071 case BO_Shr:
1072 return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
1073 case BO_LT:
1074 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
1075 case BO_GT:
1076 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
1077 case BO_LE:
1078 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
1079 case BO_GE:
1080 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
1081 case BO_EQ:
1082 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
1083 case BO_NE:
1084 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
1085 case BO_And:
1086 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
1087 case BO_Xor:
1088 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
1089 case BO_Or:
1090 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
1091 case BO_LAnd:
1092 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
1093 case BO_LOr:
1094 // TODO: int vs bool
1095 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1096 case BO_Assign:
1097 return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS());
1098 case BO_Comma:
1099 {
1100 block = trans_create_node(c, NodeTypeBlock);
1101 AstNode *lhs = trans_expr(c, false, block, stmt->getLHS(), TransRValue);
1102 if (lhs == nullptr) return nullptr;
1103 block->data.block.statements.append(maybe_suppress_result(c, false, lhs));
1104 AstNode *rhs = trans_expr(c, result_used, block, stmt->getRHS(), TransRValue);
1105 if (rhs == nullptr) return nullptr;
1106 block->data.block.statements.append(maybe_suppress_result(c, result_used, rhs));
1107 block->data.block.last_statement_is_result_expression = true;
1108 return block;
1109 }
1110 case BO_MulAssign:
1111 case BO_DivAssign:
1112 case BO_RemAssign:
1113 case BO_AddAssign:
1114 case BO_SubAssign:
1115 case BO_ShlAssign:
1116 case BO_ShrAssign:
1117 case BO_AndAssign:
1118 case BO_XorAssign:
1119 case BO_OrAssign:
1120 zig_unreachable();
1121 }
1122
1123 zig_unreachable();
1124}
1125
1126static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) {
1127 const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
1128 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
1129
1130 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
1131 if (!use_intermediate_casts && !result_used) {
1132 // simple common case, where the C and Zig are identical:
1133 // lhs >>= rhs
1134 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1135 if (lhs == nullptr) return nullptr;
1136
1137 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue);
1138 if (rhs == nullptr) return nullptr;
1139 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1140
1141 return trans_create_node_bin_op(c, lhs, assign_op, coerced_rhs);
1142 } else {
1143 // need more complexity. worst case, this looks like this:
1144 // c: lhs >>= rhs
1145 // zig: {
1146 // zig: const _ref = &lhs;
1147 // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1148 // zig: *_ref
1149 // zig: }
1150 // where u5 is the appropriate type
1151
1152 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1153
1154 // const _ref = &lhs;
1155 AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue);
1156 if (lhs == nullptr) return nullptr;
1157 AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
1158 // TODO: avoid name collisions with generated variable names
1159 Buf* tmp_var_name = buf_create_from_str("_ref");
1160 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1161 child_block->data.block.statements.append(tmp_var_decl);
1162
1163 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1164
1165 AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue);
1166 if (rhs == nullptr) return nullptr;
1167 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1168
1169 AstNode *assign_statement = trans_create_node_bin_op(c,
1170 trans_create_node_prefix_op(c, PrefixOpDereference,
1171 trans_create_node_symbol(c, tmp_var_name)),
1172 BinOpTypeAssign,
1173 trans_c_cast(c, rhs_location,
1174 stmt->getComputationResultType(),
1175 trans_create_node_bin_op(c,
1176 trans_c_cast(c, rhs_location,
1177 stmt->getComputationLHSType(),
1178 trans_create_node_prefix_op(c, PrefixOpDereference,
1179 trans_create_node_symbol(c, tmp_var_name))),
1180 bin_op,
1181 coerced_rhs)));
1182 child_block->data.block.statements.append(assign_statement);
1183
1184 if (result_used) {
1185 // *_ref
1186 child_block->data.block.statements.append(
1187 trans_create_node_prefix_op(c, PrefixOpDereference,
1188 trans_create_node_symbol(c, tmp_var_name)));
1189 child_block->data.block.last_statement_is_result_expression = true;
1190 }
1191
1192 return child_block;
1193 }
1194}
1195
1196static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) {
1197 if (!result_used) {
1198 // simple common case, where the C and Zig are identical:
1199 // lhs += rhs
1200 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1201 if (lhs == nullptr) return nullptr;
1202 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue);
1203 if (rhs == nullptr) return nullptr;
1204 return trans_create_node_bin_op(c, lhs, assign_op, rhs);
1205 } else {
1206 // need more complexity. worst case, this looks like this:
1207 // c: lhs += rhs
1208 // zig: {
1209 // zig: const _ref = &lhs;
1210 // zig: *_ref = *_ref + rhs;
1211 // zig: *_ref
1212 // zig: }
1213
1214 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1215
1216 // const _ref = &lhs;
1217 AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue);
1218 if (lhs == nullptr) return nullptr;
1219 AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
1220 // TODO: avoid name collisions with generated variable names
1221 Buf* tmp_var_name = buf_create_from_str("_ref");
1222 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1223 child_block->data.block.statements.append(tmp_var_decl);
1224
1225 // *_ref = *_ref + rhs;
1226
1227 AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue);
1228 if (rhs == nullptr) return nullptr;
1229
1230 AstNode *assign_statement = trans_create_node_bin_op(c,
1231 trans_create_node_prefix_op(c, PrefixOpDereference,
1232 trans_create_node_symbol(c, tmp_var_name)),
1233 BinOpTypeAssign,
1234 trans_create_node_bin_op(c,
1235 trans_create_node_prefix_op(c, PrefixOpDereference,
1236 trans_create_node_symbol(c, tmp_var_name)),
1237 bin_op,
1238 rhs));
1239 child_block->data.block.statements.append(assign_statement);
1240
1241 // *_ref
1242 child_block->data.block.statements.append(
1243 trans_create_node_prefix_op(c, PrefixOpDereference,
1244 trans_create_node_symbol(c, tmp_var_name)));
1245 child_block->data.block.last_statement_is_result_expression = true;
1246
1247 return child_block;
1248 }
1249}
1250
1251
1252static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) {
1253 switch (stmt->getOpcode()) {
1254 case BO_MulAssign:
1255 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1256 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
1257 else
1258 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1259 case BO_DivAssign:
1260 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign");
1261 return nullptr;
1262 case BO_RemAssign:
1263 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign");
1264 return nullptr;
1265 case BO_AddAssign:
1266 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1267 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
1268 else
1269 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1270 case BO_SubAssign:
1271 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1272 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
1273 else
1274 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
1275 case BO_ShlAssign:
1276 return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
1277 case BO_ShrAssign:
1278 return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
1279 case BO_AndAssign:
1280 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
1281 case BO_XorAssign:
1282 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
1283 case BO_OrAssign:
1284 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
1285 case BO_PtrMemD:
1286 case BO_PtrMemI:
1287 case BO_Assign:
1288 case BO_Mul:
1289 case BO_Div:
1290 case BO_Rem:
1291 case BO_Add:
1292 case BO_Sub:
1293 case BO_Shl:
1294 case BO_Shr:
1295 case BO_LT:
1296 case BO_GT:
1297 case BO_LE:
1298 case BO_GE:
1299 case BO_EQ:
1300 case BO_NE:
1301 case BO_And:
1302 case BO_Xor:
1303 case BO_Or:
1304 case BO_LAnd:
1305 case BO_LOr:
1306 case BO_Comma:
1307 zig_unreachable();
1308 }
1309
1310 zig_unreachable();
1311}
1312
1313static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) {
1314 switch (stmt->getCastKind()) {
1315 case CK_LValueToRValue:
1316 return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1317 case CK_IntegralCast:
1318 {
1319 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1320 if (target_node == nullptr)
1321 return nullptr;
1322 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node);
1323 }
1324 case CK_FunctionToPointerDecay:
1325 case CK_ArrayToPointerDecay:
1326 {
1327 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1328 if (target_node == nullptr)
1329 return nullptr;
1330 return target_node;
1331 }
1332 case CK_BitCast:
1333 {
1334 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1335 if (target_node == nullptr)
1336 return nullptr;
1337
1338 AstNode *dest_type_node = trans_qual_type(c, stmt->getType(), stmt->getLocStart());
1339
1340 AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
1341 node->data.fn_call_expr.params.append(dest_type_node);
1342 node->data.fn_call_expr.params.append(target_node);
1343 return node;
1344 }
1345 case CK_NullToPointer:
1346 return trans_create_node(c, NodeTypeNullLiteral);
1347 case CK_Dependent:
1348 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
1349 return nullptr;
1350 case CK_LValueBitCast:
1351 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast");
1352 return nullptr;
1353 case CK_NoOp:
1354 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NoOp");
1355 return nullptr;
1356 case CK_BaseToDerived:
1357 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerived");
1358 return nullptr;
1359 case CK_DerivedToBase:
1360 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBase");
1361 return nullptr;
1362 case CK_UncheckedDerivedToBase:
1363 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
1364 return nullptr;
1365 case CK_Dynamic:
1366 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dynamic");
1367 return nullptr;
1368 case CK_ToUnion:
1369 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion");
1370 return nullptr;
1371 case CK_NullToMemberPointer:
1372 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToMemberPointer");
1373 return nullptr;
1374 case CK_BaseToDerivedMemberPointer:
1375 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
1376 return nullptr;
1377 case CK_DerivedToBaseMemberPointer:
1378 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
1379 return nullptr;
1380 case CK_MemberPointerToBoolean:
1381 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_MemberPointerToBoolean");
1382 return nullptr;
1383 case CK_ReinterpretMemberPointer:
1384 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
1385 return nullptr;
1386 case CK_UserDefinedConversion:
1387 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UserDefinedConversion");
1388 return nullptr;
1389 case CK_ConstructorConversion:
1390 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ConstructorConversion");
1391 return nullptr;
1392 case CK_IntegralToPointer:
1393 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToPointer");
1394 return nullptr;
1395 case CK_PointerToIntegral:
1396 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToIntegral");
1397 return nullptr;
1398 case CK_PointerToBoolean:
1399 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToBoolean");
1400 return nullptr;
1401 case CK_ToVoid:
1402 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToVoid");
1403 return nullptr;
1404 case CK_VectorSplat:
1405 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_VectorSplat");
1406 return nullptr;
1407 case CK_IntegralToBoolean:
1408 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToBoolean");
1409 return nullptr;
1410 case CK_IntegralToFloating:
1411 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToFloating");
1412 return nullptr;
1413 case CK_FloatingToIntegral:
1414 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToIntegral");
1415 return nullptr;
1416 case CK_FloatingToBoolean:
1417 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToBoolean");
1418 return nullptr;
1419 case CK_BooleanToSignedIntegral:
1420 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BooleanToSignedIntegral");
1421 return nullptr;
1422 case CK_FloatingCast:
1423 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingCast");
1424 return nullptr;
1425 case CK_CPointerToObjCPointerCast:
1426 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CPointerToObjCPointerCast");
1427 return nullptr;
1428 case CK_BlockPointerToObjCPointerCast:
1429 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast");
1430 return nullptr;
1431 case CK_AnyPointerToBlockPointerCast:
1432 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast");
1433 return nullptr;
1434 case CK_ObjCObjectLValueCast:
1435 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ObjCObjectLValueCast");
1436 return nullptr;
1437 case CK_FloatingRealToComplex:
1438 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingRealToComplex");
1439 return nullptr;
1440 case CK_FloatingComplexToReal:
1441 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToReal");
1442 return nullptr;
1443 case CK_FloatingComplexToBoolean:
1444 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToBoolean");
1445 return nullptr;
1446 case CK_FloatingComplexCast:
1447 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexCast");
1448 return nullptr;
1449 case CK_FloatingComplexToIntegralComplex:
1450 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex");
1451 return nullptr;
1452 case CK_IntegralRealToComplex:
1453 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralRealToComplex");
1454 return nullptr;
1455 case CK_IntegralComplexToReal:
1456 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToReal");
1457 return nullptr;
1458 case CK_IntegralComplexToBoolean:
1459 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToBoolean");
1460 return nullptr;
1461 case CK_IntegralComplexCast:
1462 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexCast");
1463 return nullptr;
1464 case CK_IntegralComplexToFloatingComplex:
1465 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex");
1466 return nullptr;
1467 case CK_ARCProduceObject:
1468 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCProduceObject");
1469 return nullptr;
1470 case CK_ARCConsumeObject:
1471 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCConsumeObject");
1472 return nullptr;
1473 case CK_ARCReclaimReturnedObject:
1474 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCReclaimReturnedObject");
1475 return nullptr;
1476 case CK_ARCExtendBlockObject:
1477 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCExtendBlockObject");
1478 return nullptr;
1479 case CK_AtomicToNonAtomic:
1480 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AtomicToNonAtomic");
1481 return nullptr;
1482 case CK_NonAtomicToAtomic:
1483 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NonAtomicToAtomic");
1484 return nullptr;
1485 case CK_CopyAndAutoreleaseBlockObject:
1486 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject");
1487 return nullptr;
1488 case CK_BuiltinFnToFnPtr:
1489 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BuiltinFnToFnPtr");
1490 return nullptr;
1491 case CK_ZeroToOCLEvent:
1492 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLEvent");
1493 return nullptr;
1494 case CK_ZeroToOCLQueue:
1495 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLQueue");
1496 return nullptr;
1497 case CK_AddressSpaceConversion:
1498 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AddressSpaceConversion");
1499 return nullptr;
1500 case CK_IntToOCLSampler:
1501 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntToOCLSampler");
1502 return nullptr;
1503 }
1504 zig_unreachable();
1505}
1506
1507static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue lrval) {
1508 ValueDecl *value_decl = stmt->getDecl();
1509 Buf *symbol_name = buf_create_from_str(decl_name(value_decl));
1510 if (lrval == TransLValue) {
1511 c->ptr_params.put(symbol_name, true);
1512 }
1513 return trans_create_node_symbol(c, symbol_name);
1514}
1515
1516static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) {
1517 Expr *op_expr = stmt->getSubExpr();
1518
1519 if (!result_used) {
1520 // common case
1521 // c: expr++
1522 // zig: expr += 1
1523 return trans_create_node_bin_op(c,
1524 trans_expr(c, true, block, op_expr, TransLValue),
1525 assign_op,
1526 trans_create_node_unsigned(c, 1));
1527 } else {
1528 // worst case
1529 // c: expr++
1530 // zig: {
1531 // zig: const _ref = &expr;
1532 // zig: const _tmp = *_ref;
1533 // zig: *_ref += 1;
1534 // zig: _tmp
1535 // zig: }
1536 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1537
1538 // const _ref = &expr;
1539 AstNode *expr = trans_expr(c, true, child_block, op_expr, TransLValue);
1540 if (expr == nullptr) return nullptr;
1541 AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr);
1542 // TODO: avoid name collisions with generated variable names
1543 Buf* ref_var_name = buf_create_from_str("_ref");
1544 AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr);
1545 child_block->data.block.statements.append(ref_var_decl);
1546
1547 // const _tmp = *_ref;
1548 Buf* tmp_var_name = buf_create_from_str("_tmp");
1549 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr,
1550 trans_create_node_prefix_op(c, PrefixOpDereference,
1551 trans_create_node_symbol(c, ref_var_name)));
1552 child_block->data.block.statements.append(tmp_var_decl);
1553
1554 // *_ref += 1;
1555 AstNode *assign_statement = trans_create_node_bin_op(c,
1556 trans_create_node_prefix_op(c, PrefixOpDereference,
1557 trans_create_node_symbol(c, ref_var_name)),
1558 assign_op,
1559 trans_create_node_unsigned(c, 1));
1560 child_block->data.block.statements.append(assign_statement);
1561
1562 // _tmp
1563 child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name));
1564 child_block->data.block.last_statement_is_result_expression = true;
1565
1566 return child_block;
1567 }
1568}
1569
1570static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) {
1571 switch (stmt->getOpcode()) {
1572 case UO_PostInc:
1573 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1574 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlusWrap);
1575 else
1576 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlus);
1577 case UO_PostDec:
1578 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1579 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinusWrap);
1580 else
1581 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinus);
1582 case UO_PreInc:
1583 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PreInc");
1584 return nullptr;
1585 case UO_PreDec:
1586 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PreDec");
1587 return nullptr;
1588 case UO_AddrOf:
1589 {
1590 AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransLValue);
1591 if (value_node == nullptr)
1592 return value_node;
1593 return trans_create_node_addr_of(c, false, false, value_node);
1594 }
1595 case UO_Deref:
1596 {
1597 AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransRValue);
1598 if (value_node == nullptr)
1599 return nullptr;
1600 bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType());
1601 if (is_fn_ptr)
1602 return value_node;
1603 AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node);
1604 return trans_create_node_prefix_op(c, PrefixOpDereference, unwrapped);
1605 }
1606 case UO_Plus:
1607 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus");
1608 return nullptr;
1609 case UO_Minus:
1610 {
1611 Expr *op_expr = stmt->getSubExpr();
1612 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
1613 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
1614 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
1615
1616 node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr, TransRValue);
1617 if (node->data.prefix_op_expr.primary_expr == nullptr)
1618 return nullptr;
1619
1620 return node;
1621 } else if (c_is_unsigned_integer(c, op_expr->getType())) {
1622 // we gotta emit 0 -% x
1623 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1624 node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0);
1625
1626 node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr, TransRValue);
1627 if (node->data.bin_op_expr.op2 == nullptr)
1628 return nullptr;
1629
1630 node->data.bin_op_expr.bin_op = BinOpTypeSubWrap;
1631 return node;
1632 } else {
1633 emit_warning(c, stmt->getLocStart(), "C negation with non float non integer");
1634 return nullptr;
1635 }
1636 }
1637 case UO_Not:
1638 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Not");
1639 return nullptr;
1640 case UO_LNot:
1641 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_LNot");
1642 return nullptr;
1643 case UO_Real:
1644 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real");
1645 return nullptr;
1646 case UO_Imag:
1647 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Imag");
1648 return nullptr;
1649 case UO_Extension:
1650 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Extension");
1651 return nullptr;
1652 case UO_Coawait:
1653 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Coawait");
1654 return nullptr;
1655 }
1656 zig_unreachable();
1657}
1658
1659static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *stmt) {
1660 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
1661 Decl *decl = *iter;
1662 switch (decl->getKind()) {
1663 case Decl::Var: {
1664 VarDecl *var_decl = (VarDecl *)decl;
1665 QualType qual_type = var_decl->getTypeSourceInfo()->getType();
1666 AstNode *init_node = nullptr;
1667 if (var_decl->hasInit()) {
1668 init_node = trans_expr(c, true, block, var_decl->getInit(), TransRValue);
1669 if (init_node == nullptr)
1670 return nullptr;
1671
1672 }
1673 AstNode *type_node = trans_qual_type(c, qual_type, stmt->getLocStart());
1674 if (type_node == nullptr)
1675 return nullptr;
1676
1677 Buf *symbol_name = buf_create_from_str(decl_name(var_decl));
1678
1679 AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(),
1680 symbol_name, type_node, init_node);
1681 block->data.block.statements.append(node);
1682 continue;
1683 }
1684 case Decl::AccessSpec:
1685 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec");
1686 return nullptr;
1687 case Decl::Block:
1688 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block");
1689 return nullptr;
1690 case Decl::Captured:
1691 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured");
1692 return nullptr;
1693 case Decl::ClassScopeFunctionSpecialization:
1694 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization");
1695 return nullptr;
1696 case Decl::Empty:
1697 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty");
1698 return nullptr;
1699 case Decl::Export:
1700 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export");
1701 return nullptr;
1702 case Decl::ExternCContext:
1703 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext");
1704 return nullptr;
1705 case Decl::FileScopeAsm:
1706 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm");
1707 return nullptr;
1708 case Decl::Friend:
1709 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend");
1710 return nullptr;
1711 case Decl::FriendTemplate:
1712 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate");
1713 return nullptr;
1714 case Decl::Import:
1715 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import");
1716 return nullptr;
1717 case Decl::LinkageSpec:
1718 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec");
1719 return nullptr;
1720 case Decl::Label:
1721 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label");
1722 return nullptr;
1723 case Decl::Namespace:
1724 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace");
1725 return nullptr;
1726 case Decl::NamespaceAlias:
1727 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias");
1728 return nullptr;
1729 case Decl::ObjCCompatibleAlias:
1730 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias");
1731 return nullptr;
1732 case Decl::ObjCCategory:
1733 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory");
1734 return nullptr;
1735 case Decl::ObjCCategoryImpl:
1736 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl");
1737 return nullptr;
1738 case Decl::ObjCImplementation:
1739 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation");
1740 return nullptr;
1741 case Decl::ObjCInterface:
1742 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface");
1743 return nullptr;
1744 case Decl::ObjCProtocol:
1745 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol");
1746 return nullptr;
1747 case Decl::ObjCMethod:
1748 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod");
1749 return nullptr;
1750 case Decl::ObjCProperty:
1751 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty");
1752 return nullptr;
1753 case Decl::BuiltinTemplate:
1754 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate");
1755 return nullptr;
1756 case Decl::ClassTemplate:
1757 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate");
1758 return nullptr;
1759 case Decl::FunctionTemplate:
1760 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate");
1761 return nullptr;
1762 case Decl::TypeAliasTemplate:
1763 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate");
1764 return nullptr;
1765 case Decl::VarTemplate:
1766 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate");
1767 return nullptr;
1768 case Decl::TemplateTemplateParm:
1769 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm");
1770 return nullptr;
1771 case Decl::Enum:
1772 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum");
1773 return nullptr;
1774 case Decl::Record:
1775 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record");
1776 return nullptr;
1777 case Decl::CXXRecord:
1778 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord");
1779 return nullptr;
1780 case Decl::ClassTemplateSpecialization:
1781 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization");
1782 return nullptr;
1783 case Decl::ClassTemplatePartialSpecialization:
1784 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization");
1785 return nullptr;
1786 case Decl::TemplateTypeParm:
1787 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm");
1788 return nullptr;
1789 case Decl::ObjCTypeParam:
1790 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam");
1791 return nullptr;
1792 case Decl::TypeAlias:
1793 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias");
1794 return nullptr;
1795 case Decl::Typedef:
1796 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef");
1797 return nullptr;
1798 case Decl::UnresolvedUsingTypename:
1799 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename");
1800 return nullptr;
1801 case Decl::Using:
1802 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using");
1803 return nullptr;
1804 case Decl::UsingDirective:
1805 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective");
1806 return nullptr;
1807 case Decl::UsingPack:
1808 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack");
1809 return nullptr;
1810 case Decl::UsingShadow:
1811 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow");
1812 return nullptr;
1813 case Decl::ConstructorUsingShadow:
1814 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow");
1815 return nullptr;
1816 case Decl::Binding:
1817 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding");
1818 return nullptr;
1819 case Decl::Field:
1820 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field");
1821 return nullptr;
1822 case Decl::ObjCAtDefsField:
1823 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField");
1824 return nullptr;
1825 case Decl::ObjCIvar:
1826 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar");
1827 return nullptr;
1828 case Decl::Function:
1829 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function");
1830 return nullptr;
1831 case Decl::CXXDeductionGuide:
1832 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide");
1833 return nullptr;
1834 case Decl::CXXMethod:
1835 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod");
1836 return nullptr;
1837 case Decl::CXXConstructor:
1838 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor");
1839 return nullptr;
1840 case Decl::CXXConversion:
1841 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion");
1842 return nullptr;
1843 case Decl::CXXDestructor:
1844 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor");
1845 return nullptr;
1846 case Decl::MSProperty:
1847 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty");
1848 return nullptr;
1849 case Decl::NonTypeTemplateParm:
1850 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm");
1851 return nullptr;
1852 case Decl::Decomposition:
1853 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition");
1854 return nullptr;
1855 case Decl::ImplicitParam:
1856 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam");
1857 return nullptr;
1858 case Decl::OMPCapturedExpr:
1859 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr");
1860 return nullptr;
1861 case Decl::ParmVar:
1862 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar");
1863 return nullptr;
1864 case Decl::VarTemplateSpecialization:
1865 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization");
1866 return nullptr;
1867 case Decl::VarTemplatePartialSpecialization:
1868 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization");
1869 return nullptr;
1870 case Decl::EnumConstant:
1871 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant");
1872 return nullptr;
1873 case Decl::IndirectField:
1874 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField");
1875 return nullptr;
1876 case Decl::OMPDeclareReduction:
1877 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction");
1878 return nullptr;
1879 case Decl::UnresolvedUsingValue:
1880 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue");
1881 return nullptr;
1882 case Decl::OMPThreadPrivate:
1883 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate");
1884 return nullptr;
1885 case Decl::ObjCPropertyImpl:
1886 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl");
1887 return nullptr;
1888 case Decl::PragmaComment:
1889 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment");
1890 return nullptr;
1891 case Decl::PragmaDetectMismatch:
1892 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch");
1893 return nullptr;
1894 case Decl::StaticAssert:
1895 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert");
1896 return nullptr;
1897 case Decl::TranslationUnit:
1898 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit");
1899 return nullptr;
1900 }
1901 zig_unreachable();
1902 }
1903
1904 // declarations were already added
1905 return skip_add_to_block_node;
1906}
1907
1908static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) {
1909 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);
1910
1911 while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond(), TransRValue);
1912 if (while_node->data.while_expr.condition == nullptr)
1913 return nullptr;
1914
1915 while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody(), TransRValue);
1916 if (while_node->data.while_expr.body == nullptr)
1917 return nullptr;
1918
1919 return while_node;
1920}
1921
1922static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) {
1923 // if (c) t
1924 // if (c) t else e
1925 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
1926
1927 // TODO: condition != 0
1928 AstNode *condition_node = trans_expr(c, true, block, stmt->getCond(), TransRValue);
1929 if (condition_node == nullptr)
1930 return nullptr;
1931 if_node->data.if_bool_expr.condition = condition_node;
1932
1933 if_node->data.if_bool_expr.then_block = trans_stmt(c, false, block, stmt->getThen(), TransRValue);
1934 if (if_node->data.if_bool_expr.then_block == nullptr)
1935 return nullptr;
1936
1937 if (stmt->getElse() != nullptr) {
1938 if_node->data.if_bool_expr.else_node = trans_stmt(c, false, block, stmt->getElse(), TransRValue);
1939 if (if_node->data.if_bool_expr.else_node == nullptr)
1940 return nullptr;
1941 }
1942
1943 return if_node;
1944}
1945
1946static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, CallExpr *stmt) {
1947 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
1948
1949 AstNode *callee_raw_node = trans_expr(c, true, block, stmt->getCallee(), TransRValue);
1950 if (callee_raw_node == nullptr)
1951 return nullptr;
1952
1953 AstNode *callee_node;
1954 if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) {
1955 callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node);
1956 } else {
1957 callee_node = callee_raw_node;
1958 }
1959
1960 node->data.fn_call_expr.fn_ref_expr = callee_node;
1961
1962 unsigned num_args = stmt->getNumArgs();
1963 Expr **args = stmt->getArgs();
1964 for (unsigned i = 0; i < num_args; i += 1) {
1965 AstNode *arg_node = trans_expr(c, true, block, args[i], TransRValue);
1966 if (arg_node == nullptr)
1967 return nullptr;
1968
1969 node->data.fn_call_expr.params.append(arg_node);
1970 }
1971
1972 return node;
1973}
1974
1975static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) {
1976 AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue);
1977 if (container_node == nullptr)
1978 return nullptr;
1979
1980 if (stmt->isArrow()) {
1981 container_node = trans_create_node_unwrap_null(c, container_node);
1982 }
1983
1984 const char *name = decl_name(stmt->getMemberDecl());
1985
1986 AstNode *node = trans_create_node_field_access_str(c, container_node, name);
1987 return node;
1988}
1989
1990static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubscriptExpr *stmt) {
1991 AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue);
1992 if (container_node == nullptr)
1993 return nullptr;
1994
1995 AstNode *idx_node = trans_expr(c, true, block, stmt->getIdx(), TransRValue);
1996 if (idx_node == nullptr)
1997 return nullptr;
1998
1999
2000 AstNode *node = trans_create_node(c, NodeTypeArrayAccessExpr);
2001 node->data.array_access_expr.array_ref_expr = container_node;
2002 node->data.array_access_expr.subscript = idx_node;
2003 return node;
2004}
2005
2006static AstNode *trans_c_style_cast_expr(Context *c, bool result_used, AstNode *block,
2007 CStyleCastExpr *stmt, TransLRValue lrvalue)
2008{
2009 AstNode *sub_expr_node = trans_expr(c, result_used, block, stmt->getSubExpr(), lrvalue);
2010 if (sub_expr_node == nullptr)
2011 return nullptr;
2012
2013 return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node);
2014}
2015
2016static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, UnaryExprOrTypeTraitExpr *stmt) {
2017 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());
2018 if (type_node == nullptr)
2019 return nullptr;
2020
2021 AstNode *node = trans_create_node_builtin_fn_call_str(c, "sizeOf");
2022 node->data.fn_call_expr.params.append(type_node);
2023 return node;
2024}
2025
2026static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) {
2027 stmt->getBody();
2028 stmt->getCond();
2029
2030 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);
2031
2032 AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral);
2033 true_node->data.bool_literal.value = true;
2034 while_node->data.while_expr.condition = true_node;
2035
2036 AstNode *body_node;
2037 if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {
2038 // there's already a block in C, so we'll append our condition to it.
2039 // c: do {
2040 // c: a;
2041 // c: b;
2042 // c: } while(c);
2043 // zig: while (true) {
2044 // zig: a;
2045 // zig: b;
2046 // zig: if (!cond) break;
2047 // zig: }
2048 body_node = trans_stmt(c, false, block, stmt->getBody(), TransRValue);
2049 if (body_node == nullptr) return nullptr;
2050 assert(body_node->type == NodeTypeBlock);
2051 } else {
2052 // the C statement is without a block, so we need to create a block to contain it.
2053 // c: do
2054 // c: a;
2055 // c: while(c);
2056 // zig: while (true) {
2057 // zig: a;
2058 // zig: if (!cond) break;
2059 // zig: }
2060 body_node = trans_create_node(c, NodeTypeBlock);
2061 AstNode *child_statement = trans_stmt(c, false, body_node, stmt->getBody(), TransRValue);
2062 if (child_statement == nullptr) return nullptr;
2063 body_node->data.block.statements.append(child_statement);
2064 }
2065
2066 // if (!cond) break;
2067 AstNode *condition_node = trans_expr(c, true, body_node, stmt->getCond(), TransRValue);
2068 if (condition_node == nullptr) return nullptr;
2069 AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr);
2070 terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node);
2071 terminator_node->data.if_bool_expr.then_block = trans_create_node(c, NodeTypeBreak);
2072 body_node->data.block.statements.append(terminator_node);
2073
2074 while_node->data.while_expr.body = body_node;
2075
2076 return while_node;
2077}
2078
2079static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) {
2080 Stmt::StmtClass sc = stmt->getStmtClass();
2081 switch (sc) {
2082 case Stmt::ReturnStmtClass:
2083 return trans_return_stmt(c, block, (ReturnStmt *)stmt);
2084 case Stmt::CompoundStmtClass:
2085 return trans_compound_stmt(c, block, (CompoundStmt *)stmt);
2086 case Stmt::IntegerLiteralClass:
2087 return trans_integer_literal(c, (IntegerLiteral *)stmt);
2088 case Stmt::ConditionalOperatorClass:
2089 return trans_conditional_operator(c, result_used, block, (ConditionalOperator *)stmt);
2090 case Stmt::BinaryOperatorClass:
2091 return trans_binary_operator(c, result_used, block, (BinaryOperator *)stmt);
2092 case Stmt::CompoundAssignOperatorClass:
2093 return trans_compound_assign_operator(c, result_used, block, (CompoundAssignOperator *)stmt);
2094 case Stmt::ImplicitCastExprClass:
2095 return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt);
2096 case Stmt::DeclRefExprClass:
2097 return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue);
2098 case Stmt::UnaryOperatorClass:
2099 return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt);
2100 case Stmt::DeclStmtClass:
2101 return trans_local_declaration(c, block, (DeclStmt *)stmt);
2102 case Stmt::WhileStmtClass:
2103 return trans_while_loop(c, block, (WhileStmt *)stmt);
2104 case Stmt::IfStmtClass:
2105 return trans_if_statement(c, block, (IfStmt *)stmt);
2106 case Stmt::CallExprClass:
2107 return trans_call_expr(c, result_used, block, (CallExpr *)stmt);
2108 case Stmt::NullStmtClass:
2109 return skip_add_to_block_node;
2110 case Stmt::MemberExprClass:
2111 return trans_member_expr(c, block, (MemberExpr *)stmt);
2112 case Stmt::ArraySubscriptExprClass:
2113 return trans_array_subscript_expr(c, block, (ArraySubscriptExpr *)stmt);
2114 case Stmt::CStyleCastExprClass:
2115 return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue);
2116 case Stmt::UnaryExprOrTypeTraitExprClass:
2117 return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt);
2118 case Stmt::DoStmtClass:
2119 return trans_do_loop(c, block, (DoStmt *)stmt);
2120 case Stmt::CaseStmtClass:
2121 emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");
2122 return nullptr;
2123 case Stmt::DefaultStmtClass:
2124 emit_warning(c, stmt->getLocStart(), "TODO handle C DefaultStmtClass");
2125 return nullptr;
2126 case Stmt::SwitchStmtClass:
2127 emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass");
2128 return nullptr;
2129 case Stmt::NoStmtClass:
2130 emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");
2131 return nullptr;
2132 case Stmt::GCCAsmStmtClass:
2133 emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass");
2134 return nullptr;
2135 case Stmt::MSAsmStmtClass:
2136 emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass");
2137 return nullptr;
2138 case Stmt::AttributedStmtClass:
2139 emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass");
2140 return nullptr;
2141 case Stmt::BreakStmtClass:
2142 emit_warning(c, stmt->getLocStart(), "TODO handle C BreakStmtClass");
2143 return nullptr;
2144 case Stmt::CXXCatchStmtClass:
2145 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass");
2146 return nullptr;
2147 case Stmt::CXXForRangeStmtClass:
2148 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass");
2149 return nullptr;
2150 case Stmt::CXXTryStmtClass:
2151 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass");
2152 return nullptr;
2153 case Stmt::CapturedStmtClass:
2154 emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass");
2155 return nullptr;
2156 case Stmt::ContinueStmtClass:
2157 emit_warning(c, stmt->getLocStart(), "TODO handle C ContinueStmtClass");
2158 return nullptr;
2159 case Stmt::CoreturnStmtClass:
2160 emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass");
2161 return nullptr;
2162 case Stmt::CoroutineBodyStmtClass:
2163 emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");
2164 return nullptr;
2165 case Stmt::BinaryConditionalOperatorClass:
2166 emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");
2167 return nullptr;
2168 case Stmt::AddrLabelExprClass:
2169 emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass");
2170 return nullptr;
2171 case Stmt::ArrayInitIndexExprClass:
2172 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass");
2173 return nullptr;
2174 case Stmt::ArrayInitLoopExprClass:
2175 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass");
2176 return nullptr;
2177 case Stmt::ArrayTypeTraitExprClass:
2178 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass");
2179 return nullptr;
2180 case Stmt::AsTypeExprClass:
2181 emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass");
2182 return nullptr;
2183 case Stmt::AtomicExprClass:
2184 emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");
2185 return nullptr;
2186 case Stmt::BlockExprClass:
2187 emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");
2188 return nullptr;
2189 case Stmt::CXXBindTemporaryExprClass:
2190 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass");
2191 return nullptr;
2192 case Stmt::CXXBoolLiteralExprClass:
2193 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass");
2194 return nullptr;
2195 case Stmt::CXXConstructExprClass:
2196 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass");
2197 return nullptr;
2198 case Stmt::CXXTemporaryObjectExprClass:
2199 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass");
2200 return nullptr;
2201 case Stmt::CXXDefaultArgExprClass:
2202 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass");
2203 return nullptr;
2204 case Stmt::CXXDefaultInitExprClass:
2205 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass");
2206 return nullptr;
2207 case Stmt::CXXDeleteExprClass:
2208 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass");
2209 return nullptr;
2210 case Stmt::CXXDependentScopeMemberExprClass:
2211 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass");
2212 return nullptr;
2213 case Stmt::CXXFoldExprClass:
2214 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass");
2215 return nullptr;
2216 case Stmt::CXXInheritedCtorInitExprClass:
2217 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass");
2218 return nullptr;
2219 case Stmt::CXXNewExprClass:
2220 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass");
2221 return nullptr;
2222 case Stmt::CXXNoexceptExprClass:
2223 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass");
2224 return nullptr;
2225 case Stmt::CXXNullPtrLiteralExprClass:
2226 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass");
2227 return nullptr;
2228 case Stmt::CXXPseudoDestructorExprClass:
2229 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass");
2230 return nullptr;
2231 case Stmt::CXXScalarValueInitExprClass:
2232 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass");
2233 return nullptr;
2234 case Stmt::CXXStdInitializerListExprClass:
2235 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass");
2236 return nullptr;
2237 case Stmt::CXXThisExprClass:
2238 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass");
2239 return nullptr;
2240 case Stmt::CXXThrowExprClass:
2241 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass");
2242 return nullptr;
2243 case Stmt::CXXTypeidExprClass:
2244 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass");
2245 return nullptr;
2246 case Stmt::CXXUnresolvedConstructExprClass:
2247 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass");
2248 return nullptr;
2249 case Stmt::CXXUuidofExprClass:
2250 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass");
2251 return nullptr;
2252 case Stmt::CUDAKernelCallExprClass:
2253 emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass");
2254 return nullptr;
2255 case Stmt::CXXMemberCallExprClass:
2256 (void)result_used;
2257 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass");
2258 return nullptr;
2259 case Stmt::CXXOperatorCallExprClass:
2260 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass");
2261 return nullptr;
2262 case Stmt::UserDefinedLiteralClass:
2263 emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass");
2264 return nullptr;
2265 case Stmt::CXXFunctionalCastExprClass:
2266 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass");
2267 return nullptr;
2268 case Stmt::CXXConstCastExprClass:
2269 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass");
2270 return nullptr;
2271 case Stmt::CXXDynamicCastExprClass:
2272 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass");
2273 return nullptr;
2274 case Stmt::CXXReinterpretCastExprClass:
2275 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass");
2276 return nullptr;
2277 case Stmt::CXXStaticCastExprClass:
2278 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass");
2279 return nullptr;
2280 case Stmt::ObjCBridgedCastExprClass:
2281 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass");
2282 return nullptr;
2283 case Stmt::CharacterLiteralClass:
2284 emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass");
2285 return nullptr;
2286 case Stmt::ChooseExprClass:
2287 emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass");
2288 return nullptr;
2289 case Stmt::CompoundLiteralExprClass:
2290 emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass");
2291 return nullptr;
2292 case Stmt::ConvertVectorExprClass:
2293 emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass");
2294 return nullptr;
2295 case Stmt::CoawaitExprClass:
2296 emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass");
2297 return nullptr;
2298 case Stmt::CoyieldExprClass:
2299 emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass");
2300 return nullptr;
2301 case Stmt::DependentCoawaitExprClass:
2302 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass");
2303 return nullptr;
2304 case Stmt::DependentScopeDeclRefExprClass:
2305 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass");
2306 return nullptr;
2307 case Stmt::DesignatedInitExprClass:
2308 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass");
2309 return nullptr;
2310 case Stmt::DesignatedInitUpdateExprClass:
2311 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass");
2312 return nullptr;
2313 case Stmt::ExprWithCleanupsClass:
2314 emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass");
2315 return nullptr;
2316 case Stmt::ExpressionTraitExprClass:
2317 emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass");
2318 return nullptr;
2319 case Stmt::ExtVectorElementExprClass:
2320 emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass");
2321 return nullptr;
2322 case Stmt::FloatingLiteralClass:
2323 emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass");
2324 return nullptr;
2325 case Stmt::FunctionParmPackExprClass:
2326 emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass");
2327 return nullptr;
2328 case Stmt::GNUNullExprClass:
2329 emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass");
2330 return nullptr;
2331 case Stmt::GenericSelectionExprClass:
2332 emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass");
2333 return nullptr;
2334 case Stmt::ImaginaryLiteralClass:
2335 emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass");
2336 return nullptr;
2337 case Stmt::ImplicitValueInitExprClass:
2338 emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass");
2339 return nullptr;
2340 case Stmt::InitListExprClass:
2341 emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass");
2342 return nullptr;
2343 case Stmt::LambdaExprClass:
2344 emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass");
2345 return nullptr;
2346 case Stmt::MSPropertyRefExprClass:
2347 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass");
2348 return nullptr;
2349 case Stmt::MSPropertySubscriptExprClass:
2350 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass");
2351 return nullptr;
2352 case Stmt::MaterializeTemporaryExprClass:
2353 emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass");
2354 return nullptr;
2355 case Stmt::NoInitExprClass:
2356 emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass");
2357 return nullptr;
2358 case Stmt::OMPArraySectionExprClass:
2359 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass");
2360 return nullptr;
2361 case Stmt::ObjCArrayLiteralClass:
2362 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass");
2363 return nullptr;
2364 case Stmt::ObjCAvailabilityCheckExprClass:
2365 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass");
2366 return nullptr;
2367 case Stmt::ObjCBoolLiteralExprClass:
2368 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass");
2369 return nullptr;
2370 case Stmt::ObjCBoxedExprClass:
2371 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass");
2372 return nullptr;
2373 case Stmt::ObjCDictionaryLiteralClass:
2374 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass");
2375 return nullptr;
2376 case Stmt::ObjCEncodeExprClass:
2377 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass");
2378 return nullptr;
2379 case Stmt::ObjCIndirectCopyRestoreExprClass:
2380 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass");
2381 return nullptr;
2382 case Stmt::ObjCIsaExprClass:
2383 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass");
2384 return nullptr;
2385 case Stmt::ObjCIvarRefExprClass:
2386 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass");
2387 return nullptr;
2388 case Stmt::ObjCMessageExprClass:
2389 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass");
2390 return nullptr;
2391 case Stmt::ObjCPropertyRefExprClass:
2392 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass");
2393 return nullptr;
2394 case Stmt::ObjCProtocolExprClass:
2395 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass");
2396 return nullptr;
2397 case Stmt::ObjCSelectorExprClass:
2398 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass");
2399 return nullptr;
2400 case Stmt::ObjCStringLiteralClass:
2401 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass");
2402 return nullptr;
2403 case Stmt::ObjCSubscriptRefExprClass:
2404 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass");
2405 return nullptr;
2406 case Stmt::OffsetOfExprClass:
2407 emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass");
2408 return nullptr;
2409 case Stmt::OpaqueValueExprClass:
2410 emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass");
2411 return nullptr;
2412 case Stmt::UnresolvedLookupExprClass:
2413 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass");
2414 return nullptr;
2415 case Stmt::UnresolvedMemberExprClass:
2416 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass");
2417 return nullptr;
2418 case Stmt::PackExpansionExprClass:
2419 emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass");
2420 return nullptr;
2421 case Stmt::ParenExprClass:
2422 return trans_expr(c, result_used, block, ((ParenExpr*)stmt)->getSubExpr(), lrvalue);
2423 case Stmt::ParenListExprClass:
2424 emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");
2425 return nullptr;
2426 case Stmt::PredefinedExprClass:
2427 emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass");
2428 return nullptr;
2429 case Stmt::PseudoObjectExprClass:
2430 emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass");
2431 return nullptr;
2432 case Stmt::ShuffleVectorExprClass:
2433 emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass");
2434 return nullptr;
2435 case Stmt::SizeOfPackExprClass:
2436 emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass");
2437 return nullptr;
2438 case Stmt::StmtExprClass:
2439 emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
2440 return nullptr;
2441 case Stmt::StringLiteralClass:
2442 emit_warning(c, stmt->getLocStart(), "TODO handle C StringLiteralClass");
2443 return nullptr;
2444 case Stmt::SubstNonTypeTemplateParmExprClass:
2445 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
2446 return nullptr;
2447 case Stmt::SubstNonTypeTemplateParmPackExprClass:
2448 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
2449 return nullptr;
2450 case Stmt::TypeTraitExprClass:
2451 emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass");
2452 return nullptr;
2453 case Stmt::TypoExprClass:
2454 emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass");
2455 return nullptr;
2456 case Stmt::VAArgExprClass:
2457 emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass");
2458 return nullptr;
2459 case Stmt::ForStmtClass:
2460 emit_warning(c, stmt->getLocStart(), "TODO handle C ForStmtClass");
2461 return nullptr;
2462 case Stmt::GotoStmtClass:
2463 emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass");
2464 return nullptr;
2465 case Stmt::IndirectGotoStmtClass:
2466 emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass");
2467 return nullptr;
2468 case Stmt::LabelStmtClass:
2469 emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass");
2470 return nullptr;
2471 case Stmt::MSDependentExistsStmtClass:
2472 emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass");
2473 return nullptr;
2474 case Stmt::OMPAtomicDirectiveClass:
2475 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass");
2476 return nullptr;
2477 case Stmt::OMPBarrierDirectiveClass:
2478 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass");
2479 return nullptr;
2480 case Stmt::OMPCancelDirectiveClass:
2481 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass");
2482 return nullptr;
2483 case Stmt::OMPCancellationPointDirectiveClass:
2484 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass");
2485 return nullptr;
2486 case Stmt::OMPCriticalDirectiveClass:
2487 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass");
2488 return nullptr;
2489 case Stmt::OMPFlushDirectiveClass:
2490 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass");
2491 return nullptr;
2492 case Stmt::OMPDistributeDirectiveClass:
2493 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass");
2494 return nullptr;
2495 case Stmt::OMPDistributeParallelForDirectiveClass:
2496 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass");
2497 return nullptr;
2498 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
2499 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
2500 return nullptr;
2501 case Stmt::OMPDistributeSimdDirectiveClass:
2502 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass");
2503 return nullptr;
2504 case Stmt::OMPForDirectiveClass:
2505 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass");
2506 return nullptr;
2507 case Stmt::OMPForSimdDirectiveClass:
2508 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass");
2509 return nullptr;
2510 case Stmt::OMPParallelForDirectiveClass:
2511 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass");
2512 return nullptr;
2513 case Stmt::OMPParallelForSimdDirectiveClass:
2514 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass");
2515 return nullptr;
2516 case Stmt::OMPSimdDirectiveClass:
2517 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass");
2518 return nullptr;
2519 case Stmt::OMPTargetParallelForSimdDirectiveClass:
2520 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
2521 return nullptr;
2522 case Stmt::OMPTargetSimdDirectiveClass:
2523 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass");
2524 return nullptr;
2525 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
2526 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
2527 return nullptr;
2528 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
2529 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
2530 return nullptr;
2531 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
2532 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
2533 return nullptr;
2534 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
2535 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
2536 return nullptr;
2537 case Stmt::OMPTaskLoopDirectiveClass:
2538 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass");
2539 return nullptr;
2540 case Stmt::OMPTaskLoopSimdDirectiveClass:
2541 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass");
2542 return nullptr;
2543 case Stmt::OMPTeamsDistributeDirectiveClass:
2544 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass");
2545 return nullptr;
2546 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
2547 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
2548 return nullptr;
2549 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
2550 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
2551 return nullptr;
2552 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
2553 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
2554 return nullptr;
2555 case Stmt::OMPMasterDirectiveClass:
2556 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass");
2557 return nullptr;
2558 case Stmt::OMPOrderedDirectiveClass:
2559 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass");
2560 return nullptr;
2561 case Stmt::OMPParallelDirectiveClass:
2562 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass");
2563 return nullptr;
2564 case Stmt::OMPParallelSectionsDirectiveClass:
2565 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass");
2566 return nullptr;
2567 case Stmt::OMPSectionDirectiveClass:
2568 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass");
2569 return nullptr;
2570 case Stmt::OMPSectionsDirectiveClass:
2571 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass");
2572 return nullptr;
2573 case Stmt::OMPSingleDirectiveClass:
2574 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass");
2575 return nullptr;
2576 case Stmt::OMPTargetDataDirectiveClass:
2577 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass");
2578 return nullptr;
2579 case Stmt::OMPTargetDirectiveClass:
2580 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass");
2581 return nullptr;
2582 case Stmt::OMPTargetEnterDataDirectiveClass:
2583 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass");
2584 return nullptr;
2585 case Stmt::OMPTargetExitDataDirectiveClass:
2586 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass");
2587 return nullptr;
2588 case Stmt::OMPTargetParallelDirectiveClass:
2589 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass");
2590 return nullptr;
2591 case Stmt::OMPTargetParallelForDirectiveClass:
2592 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass");
2593 return nullptr;
2594 case Stmt::OMPTargetTeamsDirectiveClass:
2595 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass");
2596 return nullptr;
2597 case Stmt::OMPTargetUpdateDirectiveClass:
2598 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass");
2599 return nullptr;
2600 case Stmt::OMPTaskDirectiveClass:
2601 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass");
2602 return nullptr;
2603 case Stmt::OMPTaskgroupDirectiveClass:
2604 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass");
2605 return nullptr;
2606 case Stmt::OMPTaskwaitDirectiveClass:
2607 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass");
2608 return nullptr;
2609 case Stmt::OMPTaskyieldDirectiveClass:
2610 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass");
2611 return nullptr;
2612 case Stmt::OMPTeamsDirectiveClass:
2613 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass");
2614 return nullptr;
2615 case Stmt::ObjCAtCatchStmtClass:
2616 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass");
2617 return nullptr;
2618 case Stmt::ObjCAtFinallyStmtClass:
2619 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass");
2620 return nullptr;
2621 case Stmt::ObjCAtSynchronizedStmtClass:
2622 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass");
2623 return nullptr;
2624 case Stmt::ObjCAtThrowStmtClass:
2625 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass");
2626 return nullptr;
2627 case Stmt::ObjCAtTryStmtClass:
2628 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass");
2629 return nullptr;
2630 case Stmt::ObjCAutoreleasePoolStmtClass:
2631 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass");
2632 return nullptr;
2633 case Stmt::ObjCForCollectionStmtClass:
2634 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass");
2635 return nullptr;
2636 case Stmt::SEHExceptStmtClass:
2637 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass");
2638 return nullptr;
2639 case Stmt::SEHFinallyStmtClass:
2640 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass");
2641 return nullptr;
2642 case Stmt::SEHLeaveStmtClass:
2643 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass");
2644 return nullptr;
2645 case Stmt::SEHTryStmtClass:
2646 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass");
2647 return nullptr;
2648 }
2649 zig_unreachable();
2650}
2651
2652static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
2653 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
2654
2655 if (get_global(c, fn_name)) {
2656 // we already saw this function
2657 return;
2658 }
2659
2660 AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation());
2661 if (proto_node == nullptr) {
2662 emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
2663 return;
2664 }
2665
2666 proto_node->data.fn_proto.name = fn_name;
2667 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
2668
2669 StorageClass sc = fn_decl->getStorageClass();
2670 if (sc == SC_None) {
2671 proto_node->data.fn_proto.visib_mod = fn_decl->hasBody() ? c->export_visib_mod : c->visib_mod;
2672 } else if (sc == SC_Extern || sc == SC_Static) {
2673 proto_node->data.fn_proto.visib_mod = c->visib_mod;
2674 } else if (sc == SC_PrivateExtern) {
2675 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
2676 return;
2677 } else {
2678 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown");
2679 return;
2680 }
2681
2682 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
2683 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
2684 const ParmVarDecl *param = fn_decl->getParamDecl(i);
2685 const char *name = decl_name(param);
2686 Buf *proto_param_name;
2687 if (strlen(name) != 0) {
2688 proto_param_name = buf_create_from_str(name);
2689 } else {
2690 proto_param_name = param_node->data.param_decl.name;
2691 if (proto_param_name == nullptr) {
2692 proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
2693 }
2694 }
2695 param_node->data.param_decl.name = proto_param_name;
2696 }
2697
2698 if (!fn_decl->hasBody()) {
2699 // just a prototype
2700 add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);
2701 return;
2702 }
2703
2704 // actual function definition with body
2705 c->ptr_params.clear();
2706 Stmt *body = fn_decl->getBody();
2707 AstNode *actual_body_node = trans_stmt(c, false, nullptr, body, TransRValue);
2708 assert(actual_body_node != skip_add_to_block_node);
2709 if (actual_body_node == nullptr) {
2710 emit_warning(c, fn_decl->getLocation(), "unable to translate function");
2711 return;
2712 }
2713
2714 // it worked
2715
2716 assert(actual_body_node->type == NodeTypeBlock);
2717 AstNode *body_node_with_param_inits = trans_create_node(c, NodeTypeBlock);
2718
2719 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
2720 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
2721 Buf *good_name = param_node->data.param_decl.name;
2722
2723 if (c->ptr_params.maybe_get(good_name) != nullptr) {
2724 // TODO: avoid name collisions
2725 Buf *mangled_name = buf_sprintf("_arg_%s", buf_ptr(good_name));
2726 param_node->data.param_decl.name = mangled_name;
2727
2728 // var c_name = _mangled_name;
2729 AstNode *parameter_init = trans_create_node_var_decl_local(c, false, good_name, nullptr, trans_create_node_symbol(c, mangled_name));
2730
2731 body_node_with_param_inits->data.block.statements.append(parameter_init);
2732 }
2733 }
2734
2735 for (size_t i = 0; i < actual_body_node->data.block.statements.length; i += 1) {
2736 body_node_with_param_inits->data.block.statements.append(actual_body_node->data.block.statements.at(i));
2737 }
2738
2739 AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef);
2740 fn_def_node->data.fn_def.fn_proto = proto_node;
2741 fn_def_node->data.fn_def.body = body_node_with_param_inits;
2742
2743 proto_node->data.fn_proto.fn_def_node = fn_def_node;
2744 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
2745}
2746
2747static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {
2748 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
2749 c->decl_table.put(typedef_decl, node);
2750 return node;
2751}
2752
2753static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
2754 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
2755 if (existing_entry) {
2756 return existing_entry->value;
2757 }
2758 QualType child_qt = typedef_decl->getUnderlyingType();
2759 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
2760
2761 if (buf_eql_str(type_name, "uint8_t")) {
2762 return resolve_typdef_as_builtin(c, typedef_decl, "u8");
2763 } else if (buf_eql_str(type_name, "int8_t")) {
2764 return resolve_typdef_as_builtin(c, typedef_decl, "i8");
2765 } else if (buf_eql_str(type_name, "uint16_t")) {
2766 return resolve_typdef_as_builtin(c, typedef_decl, "u16");
2767 } else if (buf_eql_str(type_name, "int16_t")) {
2768 return resolve_typdef_as_builtin(c, typedef_decl, "i16");
2769 } else if (buf_eql_str(type_name, "uint32_t")) {
2770 return resolve_typdef_as_builtin(c, typedef_decl, "u32");
2771 } else if (buf_eql_str(type_name, "int32_t")) {
2772 return resolve_typdef_as_builtin(c, typedef_decl, "i32");
2773 } else if (buf_eql_str(type_name, "uint64_t")) {
2774 return resolve_typdef_as_builtin(c, typedef_decl, "u64");
2775 } else if (buf_eql_str(type_name, "int64_t")) {
2776 return resolve_typdef_as_builtin(c, typedef_decl, "i64");
2777 } else if (buf_eql_str(type_name, "intptr_t")) {
2778 return resolve_typdef_as_builtin(c, typedef_decl, "isize");
2779 } else if (buf_eql_str(type_name, "uintptr_t")) {
2780 return resolve_typdef_as_builtin(c, typedef_decl, "usize");
2781 } else if (buf_eql_str(type_name, "ssize_t")) {
2782 return resolve_typdef_as_builtin(c, typedef_decl, "isize");
2783 } else if (buf_eql_str(type_name, "size_t")) {
2784 return resolve_typdef_as_builtin(c, typedef_decl, "usize");
2785 }
2786
2787 // if the underlying type is anonymous, we can special case it to just
2788 // use the name of this typedef
2789 // TODO
2790
2791 AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation());
2792 if (type_node == nullptr) {
2793 emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name));
2794 c->decl_table.put(typedef_decl, nullptr);
2795 return nullptr;
2796 }
2797 add_global_var(c, type_name, type_node);
2798
2799 AstNode *symbol_node = trans_create_node_symbol(c, type_name);
2800 c->decl_table.put(typedef_decl->getCanonicalDecl(), symbol_node);
2801 return symbol_node;
2802}
2803
2804struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
2805 Buf *full_type_name, Buf *bare_name)
2806{
2807 AstNode *opaque_node = trans_create_node_opaque(c);
2808 if (full_type_name == nullptr) {
2809 c->decl_table.put(enum_decl->getCanonicalDecl(), opaque_node);
2810 return opaque_node;
2811 }
2812 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2813 add_global_weak_alias(c, bare_name, full_type_name);
2814 add_global_var(c, full_type_name, opaque_node);
2815 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
2816 return symbol_node;
2817}
2818
2819static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
2820 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
2821 if (existing_entry) {
2822 return existing_entry->value;
2823 }
2824
2825 const char *raw_name = decl_name(enum_decl);
2826 bool is_anonymous = (raw_name[0] == 0);
2827 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
2828 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
2829
2830 const EnumDecl *enum_def = enum_decl->getDefinition();
2831 if (!enum_def) {
2832 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
2833 }
2834
2835 bool pure_enum = true;
2836 uint32_t field_count = 0;
2837 for (auto it = enum_def->enumerator_begin(),
2838 it_end = enum_def->enumerator_end();
2839 it != it_end; ++it, field_count += 1)
2840 {
2841 const EnumConstantDecl *enum_const = *it;
2842 if (enum_const->getInitExpr()) {
2843 pure_enum = false;
2844 }
2845 }
2846
2847 AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation());
2848 assert(tag_int_type);
2849
2850 if (pure_enum) {
2851 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
2852 enum_node->data.container_decl.kind = ContainerKindEnum;
2853 enum_node->data.container_decl.layout = ContainerLayoutExtern;
2854 enum_node->data.container_decl.init_arg_expr = tag_int_type;
2855
2856 enum_node->data.container_decl.fields.resize(field_count);
2857 uint32_t i = 0;
2858 for (auto it = enum_def->enumerator_begin(),
2859 it_end = enum_def->enumerator_end();
2860 it != it_end; ++it, i += 1)
2861 {
2862 const EnumConstantDecl *enum_const = *it;
2863
2864 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
2865 Buf *field_name;
2866 if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
2867 field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
2868 } else {
2869 field_name = enum_val_name;
2870 }
2871
2872 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
2873 field_node->data.struct_field.name = field_name;
2874 field_node->data.struct_field.type = nullptr;
2875 enum_node->data.container_decl.fields.items[i] = field_node;
2876
2877 // in C each enum value is in the global namespace. so we put them there too.
2878 // at this point we can rely on the enum emitting successfully
2879 if (is_anonymous) {
2880 AstNode *lit_node = trans_create_node_unsigned(c, i);
2881 add_global_var(c, enum_val_name, lit_node);
2882 } else {
2883 AstNode *field_access_node = trans_create_node_field_access(c,
2884 trans_create_node_symbol(c, full_type_name), field_name);
2885 add_global_var(c, enum_val_name, field_access_node);
2886 }
2887 }
2888
2889 if (is_anonymous) {
2890 c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node);
2891 return enum_node;
2892 } else {
2893 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2894 add_global_weak_alias(c, bare_name, full_type_name);
2895 add_global_var(c, full_type_name, enum_node);
2896 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
2897 return enum_node;
2898 }
2899 }
2900
2901 // TODO after issue #305 is solved, make this be an enum with tag_int_type
2902 // as the integer type and set the custom enum values
2903 AstNode *enum_node = tag_int_type;
2904
2905
2906 // add variables for all the values with enum_node
2907 for (auto it = enum_def->enumerator_begin(),
2908 it_end = enum_def->enumerator_end();
2909 it != it_end; ++it)
2910 {
2911 const EnumConstantDecl *enum_const = *it;
2912
2913 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
2914 AstNode *int_node = trans_create_node_apint(c, enum_const->getInitVal());
2915 AstNode *var_node = add_global_var(c, enum_val_name, int_node);
2916 var_node->data.variable_declaration.type = tag_int_type;
2917 }
2918
2919 if (is_anonymous) {
2920 c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node);
2921 return enum_node;
2922 } else {
2923 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2924 add_global_weak_alias(c, bare_name, full_type_name);
2925 add_global_var(c, full_type_name, enum_node);
2926 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
2927 return symbol_node;
2928 }
2929}
2930
2931static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl,
2932 Buf *full_type_name, Buf *bare_name)
2933{
2934 AstNode *opaque_node = trans_create_node_opaque(c);
2935 if (full_type_name == nullptr) {
2936 c->decl_table.put(record_decl->getCanonicalDecl(), opaque_node);
2937 return opaque_node;
2938 }
2939 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2940 add_global_weak_alias(c, bare_name, full_type_name);
2941 add_global_var(c, full_type_name, opaque_node);
2942 c->decl_table.put(record_decl->getCanonicalDecl(), symbol_node);
2943 return symbol_node;
2944}
2945
2946static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
2947 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
2948 if (existing_entry) {
2949 return existing_entry->value;
2950 }
2951
2952 const char *raw_name = decl_name(record_decl);
2953
2954 const char *container_kind_name;
2955 ContainerKind container_kind;
2956 if (record_decl->isUnion()) {
2957 container_kind_name = "union";
2958 container_kind = ContainerKindUnion;
2959 } else if (record_decl->isStruct()) {
2960 container_kind_name = "struct";
2961 container_kind = ContainerKindStruct;
2962 } else {
2963 emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct or union", raw_name);
2964 c->decl_table.put(record_decl->getCanonicalDecl(), nullptr);
2965 return nullptr;
2966 }
2967
2968 bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0;
2969 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
2970 Buf *full_type_name = (bare_name == nullptr) ?
2971 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
2972
2973 RecordDecl *record_def = record_decl->getDefinition();
2974 if (record_def == nullptr) {
2975 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
2976 }
2977
2978 // count fields and validate
2979 uint32_t field_count = 0;
2980 for (auto it = record_def->field_begin(),
2981 it_end = record_def->field_end();
2982 it != it_end; ++it, field_count += 1)
2983 {
2984 const FieldDecl *field_decl = *it;
2985
2986 if (field_decl->isBitField()) {
2987 emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",
2988 container_kind_name,
2989 is_anonymous ? "(anon)" : buf_ptr(bare_name));
2990 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
2991 }
2992 }
2993
2994 AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl);
2995 struct_node->data.container_decl.kind = container_kind;
2996 struct_node->data.container_decl.layout = ContainerLayoutExtern;
2997
2998 // TODO handle attribute packed
2999
3000 struct_node->data.container_decl.fields.resize(field_count);
3001
3002 // must be before fields in case a circular reference happens
3003 if (is_anonymous) {
3004 c->decl_table.put(record_decl->getCanonicalDecl(), struct_node);
3005 } else {
3006 c->decl_table.put(record_decl->getCanonicalDecl(), trans_create_node_symbol(c, full_type_name));
3007 }
3008
3009 uint32_t i = 0;
3010 for (auto it = record_def->field_begin(),
3011 it_end = record_def->field_end();
3012 it != it_end; ++it, i += 1)
3013 {
3014 const FieldDecl *field_decl = *it;
3015
3016 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
3017 field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));
3018 field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation());
3019
3020 if (field_node->data.struct_field.type == nullptr) {
3021 emit_warning(c, field_decl->getLocation(),
3022 "%s %s demoted to opaque type - unresolved type",
3023 container_kind_name,
3024 is_anonymous ? "(anon)" : buf_ptr(bare_name));
3025
3026 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
3027 }
3028
3029 struct_node->data.container_decl.fields.items[i] = field_node;
3030 }
3031
3032 if (is_anonymous) {
3033 return struct_node;
3034 } else {
3035 add_global_weak_alias(c, bare_name, full_type_name);
3036 add_global_var(c, full_type_name, struct_node);
3037 return trans_create_node_symbol(c, full_type_name);
3038 }
3039}
3040
3041static void visit_var_decl(Context *c, const VarDecl *var_decl) {
3042 Buf *name = buf_create_from_str(decl_name(var_decl));
3043
3044 switch (var_decl->getTLSKind()) {
3045 case VarDecl::TLS_None:
3046 break;
3047 case VarDecl::TLS_Static:
3048 emit_warning(c, var_decl->getLocation(),
3049 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
3050 return;
3051 case VarDecl::TLS_Dynamic:
3052 emit_warning(c, var_decl->getLocation(),
3053 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
3054 return;
3055 }
3056
3057 QualType qt = var_decl->getType();
3058 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
3059 if (var_type == nullptr) {
3060 emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));
3061 return;
3062 }
3063
3064 bool is_extern = var_decl->hasExternalStorage();
3065 bool is_static = var_decl->isFileVarDecl();
3066 bool is_const = qt.isConstQualified();
3067
3068 if (is_static && !is_extern) {
3069 AstNode *init_node;
3070 if (var_decl->hasInit()) {
3071 APValue *ap_value = var_decl->evaluateValue();
3072 if (ap_value == nullptr) {
3073 emit_warning(c, var_decl->getLocation(),
3074 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
3075 return;
3076 }
3077 switch (ap_value->getKind()) {
3078 case APValue::Int:
3079 init_node = trans_create_node_apint(c, ap_value->getInt());
3080 break;
3081 case APValue::Uninitialized:
3082 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
3083 break;
3084 case APValue::Float:
3085 case APValue::ComplexInt:
3086 case APValue::ComplexFloat:
3087 case APValue::LValue:
3088 case APValue::Vector:
3089 case APValue::Array:
3090 case APValue::Struct:
3091 case APValue::Union:
3092 case APValue::MemberPointer:
3093 case APValue::AddrLabelDiff:
3094 emit_warning(c, var_decl->getLocation(),
3095 "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name));
3096 return;
3097 }
3098 } else {
3099 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
3100 }
3101
3102 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, init_node);
3103 add_top_level_decl(c, name, var_node);
3104 return;
3105 }
3106
3107 if (is_extern) {
3108 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, nullptr);
3109 var_node->data.variable_declaration.is_extern = true;
3110 add_top_level_decl(c, name, var_node);
3111 return;
3112 }
3113
3114 emit_warning(c, var_decl->getLocation(),
3115 "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name));
3116 return;
3117}
3118
3119static bool decl_visitor(void *context, const Decl *decl) {
3120 Context *c = (Context*)context;
3121
3122 switch (decl->getKind()) {
3123 case Decl::Function:
3124 visit_fn_decl(c, static_cast<const FunctionDecl*>(decl));
3125 break;
3126 case Decl::Typedef:
3127 resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
3128 break;
3129 case Decl::Enum:
3130 resolve_enum_decl(c, static_cast<const EnumDecl *>(decl));
3131 break;
3132 case Decl::Record:
3133 resolve_record_decl(c, static_cast<const RecordDecl *>(decl));
3134 break;
3135 case Decl::Var:
3136 visit_var_decl(c, static_cast<const VarDecl *>(decl));
3137 break;
3138 default:
3139 emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());
3140 }
3141
3142 return true;
3143}
3144
3145static bool name_exists(Context *c, Buf *name) {
3146 return get_global(c, name) != nullptr;
3147}
3148
3149static void render_aliases(Context *c) {
3150 for (size_t i = 0; i < c->aliases.length; i += 1) {
3151 Alias *alias = &c->aliases.at(i);
3152 if (name_exists(c, alias->new_name))
3153 continue;
3154
3155 add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name));
3156 }
3157}
3158
3159static void render_macros(Context *c) {
3160 auto it = c->macro_table.entry_iterator();
3161 for (;;) {
3162 auto *entry = it.next();
3163 if (!entry)
3164 break;
3165
3166 AstNode *value_node = entry->value;
3167 if (value_node->type == NodeTypeFnDef) {
3168 add_top_level_decl(c, value_node->data.fn_def.fn_proto->data.fn_proto.name, value_node);
3169 } else {
3170 add_global_var(c, entry->key, value_node);
3171 }
3172 }
3173}
3174
3175static AstNode *parse_ctok_num_lit(Context *c, CTokenize *ctok, size_t *tok_i, bool negate) {
3176 CTok *tok = &ctok->tokens.at(*tok_i);
3177 if (tok->id == CTokIdNumLitInt) {
3178 *tok_i += 1;
3179 switch (tok->data.num_lit_int.suffix) {
3180 case CNumLitSuffixNone:
3181 return trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate);
3182 case CNumLitSuffixL:
3183 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_long");
3184 case CNumLitSuffixU:
3185 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_uint");
3186 case CNumLitSuffixLU:
3187 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulong");
3188 case CNumLitSuffixLL:
3189 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_longlong");
3190 case CNumLitSuffixLLU:
3191 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulonglong");
3192 }
3193 zig_unreachable();
3194 } else if (tok->id == CTokIdNumLitFloat) {
3195 *tok_i += 1;
3196 double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float;
3197 return trans_create_node_float_lit(c, value);
3198 }
3199 return nullptr;
3200}
3201
3202static AstNode *parse_ctok(Context *c, CTokenize *ctok, size_t *tok_i) {
3203 CTok *tok = &ctok->tokens.at(*tok_i);
3204 switch (tok->id) {
3205 case CTokIdCharLit:
3206 *tok_i += 1;
3207 return trans_create_node_unsigned(c, tok->data.char_lit);
3208 case CTokIdStrLit:
3209 *tok_i += 1;
3210 return trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));
3211 case CTokIdMinus:
3212 *tok_i += 1;
3213 return parse_ctok_num_lit(c, ctok, tok_i, true);
3214 case CTokIdNumLitInt:
3215 case CTokIdNumLitFloat:
3216 return parse_ctok_num_lit(c, ctok, tok_i, false);
3217 case CTokIdSymbol:
3218 {
3219 *tok_i += 1;
3220 Buf *symbol_name = buf_create_from_buf(&tok->data.symbol);
3221 return trans_create_node_symbol(c, symbol_name);
3222 }
3223 case CTokIdLParen:
3224 {
3225 *tok_i += 1;
3226 AstNode *inner_node = parse_ctok(c, ctok, tok_i);
3227
3228 CTok *next_tok = &ctok->tokens.at(*tok_i);
3229 if (next_tok->id != CTokIdRParen) {
3230 return nullptr;
3231 }
3232 *tok_i += 1;
3233 return inner_node;
3234 }
3235 case CTokIdEOF:
3236 case CTokIdRParen:
3237 // not able to make sense of this
3238 return nullptr;
3239 }
3240 zig_unreachable();
3241}
3242
3243static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {
3244 tokenize_c_macro(ctok, (const uint8_t *)char_ptr);
3245
3246 if (ctok->error) {
3247 return;
3248 }
3249
3250 size_t tok_i = 0;
3251 CTok *name_tok = &ctok->tokens.at(tok_i);
3252 assert(name_tok->id == CTokIdSymbol && buf_eql_buf(&name_tok->data.symbol, name));
3253 tok_i += 1;
3254
3255 AstNode *result_node = parse_ctok(c, ctok, &tok_i);
3256 if (result_node == nullptr) {
3257 return;
3258 }
3259 CTok *eof_tok = &ctok->tokens.at(tok_i);
3260 if (eof_tok->id != CTokIdEOF) {
3261 return;
3262 }
3263 if (result_node->type == NodeTypeSymbol) {
3264 // if it equals itself, ignore. for example, from stdio.h:
3265 // #define stdin stdin
3266 Buf *symbol_name = result_node->data.symbol_expr.symbol;
3267 if (buf_eql_buf(name, symbol_name)) {
3268 return;
3269 }
3270 c->macro_symbols.append({name, symbol_name});
3271 } else {
3272 c->macro_table.put(name, result_node);
3273 }
3274}
3275
3276static void process_symbol_macros(Context *c) {
3277 for (size_t i = 0; i < c->macro_symbols.length; i += 1) {
3278 MacroSymbol ms = c->macro_symbols.at(i);
3279
3280 // Check if this macro aliases another top level declaration
3281 AstNode *existing_node = get_global(c, ms.value);
3282 if (!existing_node || name_exists(c, ms.name))
3283 continue;
3284
3285 // If a macro aliases a global variable which is a function pointer, we conclude that
3286 // the macro is intended to represent a function that assumes the function pointer
3287 // variable is non-null and calls it.
3288 if (existing_node->type == NodeTypeVariableDeclaration) {
3289 AstNode *var_type = existing_node->data.variable_declaration.type;
3290 if (var_type != nullptr && var_type->type == NodeTypePrefixOpExpr &&
3291 var_type->data.prefix_op_expr.prefix_op == PrefixOpMaybe)
3292 {
3293 AstNode *fn_proto_node = var_type->data.prefix_op_expr.primary_expr;
3294 if (fn_proto_node->type == NodeTypeFnProto) {
3295 AstNode *inline_fn_node = trans_create_node_inline_fn(c, ms.name, ms.value, fn_proto_node);
3296 c->macro_table.put(ms.name, inline_fn_node);
3297 continue;
3298 }
3299 }
3300 }
3301
3302 add_global_var(c, ms.name, trans_create_node_symbol(c, ms.value));
3303 }
3304}
3305
3306static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
3307 CTokenize ctok = {{0}};
3308
3309 // TODO if we see #undef, delete it from the table
3310
3311 for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {
3312 switch (entity->getKind()) {
3313 case PreprocessedEntity::InvalidKind:
3314 case PreprocessedEntity::InclusionDirectiveKind:
3315 case PreprocessedEntity::MacroExpansionKind:
3316 continue;
3317 case PreprocessedEntity::MacroDefinitionKind:
3318 {
3319 MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity);
3320 const char *raw_name = macro->getName()->getNameStart();
3321 SourceRange range = macro->getSourceRange();
3322 SourceLocation begin_loc = range.getBegin();
3323 SourceLocation end_loc = range.getEnd();
3324
3325 if (begin_loc == end_loc) {
3326 // this means it is a macro without a value
3327 // we don't care about such things
3328 continue;
3329 }
3330 Buf *name = buf_create_from_str(raw_name);
3331 if (name_exists(c, name)) {
3332 continue;
3333 }
3334
3335 const char *begin_c = c->source_manager->getCharacterData(begin_loc);
3336 process_macro(c, &ctok, name, begin_c);
3337 }
3338 }
3339 }
3340}
3341
3342int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
3343 CodeGen *codegen, AstNode *source_node)
3344{
3345 int err;
3346 Buf tmp_file_path = BUF_INIT;
3347 if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {
3348 return err;
3349 }
3350
3351 err = parse_h_file(import, errors, buf_ptr(&tmp_file_path), codegen, source_node);
3352
3353 os_delete_file(&tmp_file_path);
3354
3355 return err;
3356}
3357
3358int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
3359 CodeGen *codegen, AstNode *source_node)
3360{
3361 Context context = {0};
3362 Context *c = &context;
3363 c->warnings_on = codegen->verbose_cimport;
3364 c->import = import;
3365 c->errors = errors;
3366 if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) {
3367 c->visib_mod = VisibModPub;
3368 c->export_visib_mod = VisibModPub;
3369 } else {
3370 c->visib_mod = VisibModPub;
3371 c->export_visib_mod = VisibModExport;
3372 }
3373 c->decl_table.init(8);
3374 c->macro_table.init(8);
3375 c->global_table.init(8);
3376 c->ptr_params.init(8);
3377 c->codegen = codegen;
3378 c->source_node = source_node;
3379
3380 ZigList<const char *> clang_argv = {0};
3381
3382 clang_argv.append("-x");
3383 clang_argv.append("c");
3384
3385 if (c->codegen->is_native_target) {
3386 char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
3387 if (ZIG_PARSEC_CFLAGS) {
3388 Buf tmp_buf = BUF_INIT;
3389 char *start = ZIG_PARSEC_CFLAGS;
3390 char *space = strstr(start, " ");
3391 while (space) {
3392 if (space - start > 0) {
3393 buf_init_from_mem(&tmp_buf, start, space - start);
3394 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
3395 }
3396 start = space + 1;
3397 space = strstr(start, " ");
3398 }
3399 buf_init_from_str(&tmp_buf, start);
3400 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
3401 }
3402 }
3403
3404 clang_argv.append("-isystem");
3405 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
3406
3407 clang_argv.append("-isystem");
3408 clang_argv.append(buf_ptr(codegen->libc_include_dir));
3409
3410 // windows c runtime requires -D_DEBUG if using debug libraries
3411 if (codegen->build_mode == BuildModeDebug) {
3412 clang_argv.append("-D_DEBUG");
3413 }
3414
3415 for (size_t i = 0; i < codegen->clang_argv_len; i += 1) {
3416 clang_argv.append(codegen->clang_argv[i]);
3417 }
3418
3419 // we don't need spell checking and it slows things down
3420 clang_argv.append("-fno-spell-checking");
3421
3422 // this gives us access to preprocessing entities, presumably at
3423 // the cost of performance
3424 clang_argv.append("-Xclang");
3425 clang_argv.append("-detailed-preprocessing-record");
3426
3427 if (!c->codegen->is_native_target) {
3428 clang_argv.append("-target");
3429 clang_argv.append(buf_ptr(&c->codegen->triple_str));
3430 }
3431
3432 clang_argv.append(target_file);
3433
3434 // to make the [start...end] argument work
3435 clang_argv.append(nullptr);
3436
3437 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
3438
3439 std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>();
3440
3441 bool skip_function_bodies = false;
3442 bool only_local_decls = true;
3443 bool capture_diagnostics = true;
3444 bool user_files_are_volatile = true;
3445 bool allow_pch_with_compiler_errors = false;
3446 bool single_file_parse = false;
3447 bool for_serialization = false;
3448 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
3449 std::unique_ptr<ASTUnit> err_unit;
3450 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
3451 &clang_argv.at(0), &clang_argv.last(),
3452 pch_container_ops, diags, resources_path,
3453 only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,
3454 false, false, allow_pch_with_compiler_errors, skip_function_bodies,
3455 single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,
3456 nullptr));
3457
3458 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
3459 if (!ast_unit && !err_unit) {
3460 return ErrorFileSystem;
3461 }
3462
3463 if (diags->getClient()->getNumErrors() > 0) {
3464 if (ast_unit) {
3465 err_unit = std::move(ast_unit);
3466 }
3467
3468 for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
3469 it_end = err_unit->stored_diag_end();
3470 it != it_end; ++it)
3471 {
3472 switch (it->getLevel()) {
3473 case DiagnosticsEngine::Ignored:
3474 case DiagnosticsEngine::Note:
3475 case DiagnosticsEngine::Remark:
3476 case DiagnosticsEngine::Warning:
3477 continue;
3478 case DiagnosticsEngine::Error:
3479 case DiagnosticsEngine::Fatal:
3480 break;
3481 }
3482 StringRef msg_str_ref = it->getMessage();
3483 Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin());
3484 FullSourceLoc fsl = it->getLocation();
3485 if (fsl.hasManager()) {
3486 FileID file_id = fsl.getFileID();
3487 StringRef filename = fsl.getManager().getFilename(fsl);
3488 unsigned line = fsl.getSpellingLineNumber() - 1;
3489 unsigned column = fsl.getSpellingColumnNumber() - 1;
3490 unsigned offset = fsl.getManager().getFileOffset(fsl);
3491 const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
3492 Buf *path;
3493 if (filename.empty()) {
3494 path = buf_alloc();
3495 } else {
3496 path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size());
3497 }
3498
3499 ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
3500
3501 c->errors->append(err_msg);
3502 } else {
3503 // NOTE the only known way this gets triggered right now is if you have a lot of errors
3504 // clang emits "too many errors emitted, stopping now"
3505 fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg));
3506 }
3507 }
3508
3509 return 0;
3510 }
3511
3512 c->ctx = &ast_unit->getASTContext();
3513 c->source_manager = &ast_unit->getSourceManager();
3514 c->root = trans_create_node(c, NodeTypeRoot);
3515
3516 ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
3517
3518 process_preprocessor_entities(c, *ast_unit);
3519
3520 process_symbol_macros(c);
3521 render_macros(c);
3522 render_aliases(c);
3523
3524 import->root = c->root;
3525
3526 return 0;
3527}
src/parsec.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_PARSEC_HPP
10#define ZIG_PARSEC_HPP
11
12#include "all_types.hpp"
13
14int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
15 CodeGen *codegen, AstNode *source_node);
16
17int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
18 CodeGen *codegen, AstNode *source_node);
19
20#endif
src/translate_c.cpp created+3527
...@@ -0,0 +1,3527 @@
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 "error.hpp"
12#include "ir.hpp"
13#include "os.hpp"
14#include "translate_c.hpp"
15#include "parser.hpp"
16
17
18#include <clang/Frontend/ASTUnit.h>
19#include <clang/Frontend/CompilerInstance.h>
20#include <clang/AST/Expr.h>
21
22#include <string.h>
23
24using namespace clang;
25
26struct MacroSymbol {
27 Buf *name;
28 Buf *value;
29};
30
31struct Alias {
32 Buf *new_name;
33 Buf *canon_name;
34};
35
36struct Context {
37 ImportTableEntry *import;
38 ZigList<ErrorMsg *> *errors;
39 VisibMod visib_mod;
40 VisibMod export_visib_mod;
41 AstNode *root;
42 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
43 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
44 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
45 SourceManager *source_manager;
46 ZigList<Alias> aliases;
47 ZigList<MacroSymbol> macro_symbols;
48 AstNode *source_node;
49 bool warnings_on;
50
51 CodeGen *codegen;
52 ASTContext *ctx;
53
54 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
55};
56
57static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
58static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
59static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);
60
61
62ATTRIBUTE_PRINTF(3, 4)
63static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {
64 if (!c->warnings_on) {
65 return;
66 }
67
68 va_list ap;
69 va_start(ap, format);
70 Buf *msg = buf_vprintf(format, ap);
71 va_end(ap);
72
73 StringRef filename = c->source_manager->getFilename(sl);
74 const char *filename_bytes = (const char *)filename.bytes_begin();
75 Buf *path;
76 if (filename_bytes) {
77 path = buf_create_from_str(filename_bytes);
78 } else {
79 path = buf_sprintf("(no file)");
80 }
81 unsigned line = c->source_manager->getSpellingLineNumber(sl);
82 unsigned column = c->source_manager->getSpellingColumnNumber(sl);
83 fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
84}
85
86static void add_global_weak_alias(Context *c, Buf *new_name, Buf *canon_name) {
87 Alias *alias = c->aliases.add_one();
88 alias->new_name = new_name;
89 alias->canon_name = canon_name;
90}
91
92static AstNode * trans_create_node(Context *c, NodeType id) {
93 AstNode *node = allocate<AstNode>(1);
94 node->type = id;
95 node->owner = c->import;
96 // TODO line/column. mapping to C file??
97 return node;
98}
99
100static AstNode *trans_create_node_float_lit(Context *c, double value) {
101 AstNode *node = trans_create_node(c, NodeTypeFloatLiteral);
102 node->data.float_literal.bigfloat = allocate<BigFloat>(1);
103 bigfloat_init_64(node->data.float_literal.bigfloat, value);
104 return node;
105}
106
107static AstNode *trans_create_node_symbol(Context *c, Buf *name) {
108 AstNode *node = trans_create_node(c, NodeTypeSymbol);
109 node->data.symbol_expr.symbol = name;
110 return node;
111}
112
113static AstNode *trans_create_node_symbol_str(Context *c, const char *name) {
114 return trans_create_node_symbol(c, buf_create_from_str(name));
115}
116
117static AstNode *trans_create_node_builtin_fn_call(Context *c, Buf *name) {
118 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
119 node->data.fn_call_expr.fn_ref_expr = trans_create_node_symbol(c, name);
120 node->data.fn_call_expr.is_builtin = true;
121 return node;
122}
123
124static AstNode *trans_create_node_builtin_fn_call_str(Context *c, const char *name) {
125 return trans_create_node_builtin_fn_call(c, buf_create_from_str(name));
126}
127
128static AstNode *trans_create_node_opaque(Context *c) {
129 return trans_create_node_builtin_fn_call_str(c, "OpaqueType");
130}
131
132static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) {
133 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
134 node->data.fn_call_expr.fn_ref_expr = fn_ref_expr;
135 node->data.fn_call_expr.params.append(arg1);
136 return node;
137}
138
139static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {
140 AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr);
141 if (container->type == NodeTypeSymbol) {
142 assert(container->data.symbol_expr.symbol != nullptr);
143 }
144 node->data.field_access_expr.struct_expr = container;
145 node->data.field_access_expr.field_name = field_name;
146 return node;
147}
148
149static AstNode *trans_create_node_field_access_str(Context *c, AstNode *container, const char *field_name) {
150 return trans_create_node_field_access(c, container, buf_create_from_str(field_name));
151}
152
153static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
154 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
155 node->data.prefix_op_expr.prefix_op = op;
156 node->data.prefix_op_expr.primary_expr = child_node;
157 return node;
158}
159
160static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpType op, AstNode *rhs_node) {
161 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
162 node->data.bin_op_expr.op1 = lhs_node;
163 node->data.bin_op_expr.bin_op = op;
164 node->data.bin_op_expr.op2 = rhs_node;
165 return node;
166}
167
168static AstNode *maybe_suppress_result(Context *c, bool result_used, AstNode *node) {
169 if (result_used) return node;
170 return trans_create_node_bin_op(c,
171 trans_create_node_symbol_str(c, "_"),
172 BinOpTypeAssign,
173 node);
174}
175
176static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {
177 AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr);
178 node->data.addr_of_expr.is_const = is_const;
179 node->data.addr_of_expr.is_volatile = is_volatile;
180 node->data.addr_of_expr.op_expr = child_node;
181 return node;
182}
183
184static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
185 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
186 node->data.string_literal.buf = buf;
187 node->data.string_literal.c = true;
188 return node;
189}
190
191static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) {
192 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
193 node->data.string_literal.buf = buf;
194 node->data.string_literal.c = false;
195 return node;
196}
197
198static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) {
199 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
200 node->data.int_literal.bigint = allocate<BigInt>(1);
201 bigint_init_data(node->data.int_literal.bigint, &x, 1, is_negative);
202 return node;
203}
204
205static AstNode *trans_create_node_unsigned(Context *c, uint64_t x) {
206 return trans_create_node_unsigned_negative(c, x, false);
207}
208
209static AstNode *trans_create_node_cast(Context *c, AstNode *dest, AstNode *src) {
210 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
211 node->data.fn_call_expr.fn_ref_expr = dest;
212 node->data.fn_call_expr.params.resize(1);
213 node->data.fn_call_expr.params.items[0] = src;
214 return node;
215}
216
217static AstNode *trans_create_node_unsigned_negative_type(Context *c, uint64_t x, bool is_negative,
218 const char *type_name)
219{
220 AstNode *lit_node = trans_create_node_unsigned_negative(c, x, is_negative);
221 return trans_create_node_cast(c, trans_create_node_symbol_str(c, type_name), lit_node);
222}
223
224static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, AstNode *child_type_node) {
225 AstNode *node = trans_create_node(c, NodeTypeArrayType);
226 node->data.array_type.size = size_node;
227 node->data.array_type.child_type = child_type_node;
228 return node;
229}
230
231static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool is_const, Buf *var_name,
232 AstNode *type_node, AstNode *init_node)
233{
234 AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration);
235 node->data.variable_declaration.visib_mod = visib_mod;
236 node->data.variable_declaration.symbol = var_name;
237 node->data.variable_declaration.is_const = is_const;
238 node->data.variable_declaration.type = type_node;
239 node->data.variable_declaration.expr = init_node;
240 return node;
241}
242
243static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
244 AstNode *init_node)
245{
246 return trans_create_node_var_decl(c, c->visib_mod, is_const, var_name, type_node, init_node);
247}
248
249static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
250 AstNode *init_node)
251{
252 return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node);
253}
254
255
256static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) {
257 AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
258 AstNode *fn_proto = trans_create_node(c, NodeTypeFnProto);
259 fn_proto->data.fn_proto.visib_mod = c->visib_mod;
260 fn_proto->data.fn_proto.name = fn_name;
261 fn_proto->data.fn_proto.is_inline = true;
262 fn_proto->data.fn_proto.return_type = src_proto_node->data.fn_proto.return_type; // TODO ok for these to alias?
263
264 fn_def->data.fn_def.fn_proto = fn_proto;
265 fn_proto->data.fn_proto.fn_def_node = fn_def;
266
267 AstNode *unwrap_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, trans_create_node_symbol(c, var_name));
268 AstNode *fn_call_node = trans_create_node(c, NodeTypeFnCallExpr);
269 fn_call_node->data.fn_call_expr.fn_ref_expr = unwrap_node;
270
271 for (size_t i = 0; i < src_proto_node->data.fn_proto.params.length; i += 1) {
272 AstNode *src_param_node = src_proto_node->data.fn_proto.params.at(i);
273 Buf *param_name = src_param_node->data.param_decl.name;
274 if (!param_name) param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
275
276 AstNode *dest_param_node = trans_create_node(c, NodeTypeParamDecl);
277 dest_param_node->data.param_decl.name = param_name;
278 dest_param_node->data.param_decl.type = src_param_node->data.param_decl.type;
279 dest_param_node->data.param_decl.is_noalias = src_param_node->data.param_decl.is_noalias;
280 fn_proto->data.fn_proto.params.append(dest_param_node);
281
282 fn_call_node->data.fn_call_expr.params.append(trans_create_node_symbol(c, param_name));
283
284 }
285
286 AstNode *block = trans_create_node(c, NodeTypeBlock);
287 block->data.block.statements.resize(1);
288 block->data.block.statements.items[0] = fn_call_node;
289 block->data.block.last_statement_is_result_expression = true;
290
291 fn_def->data.fn_def.body = block;
292 return fn_def;
293}
294
295static AstNode *trans_create_node_unwrap_null(Context *c, AstNode *child) {
296 return trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, child);
297}
298
299static AstNode *get_global(Context *c, Buf *name) {
300 {
301 auto entry = c->global_table.maybe_get(name);
302 if (entry) {
303 return entry->value;
304 }
305 }
306 {
307 auto entry = c->macro_table.maybe_get(name);
308 if (entry)
309 return entry->value;
310 }
311 return nullptr;
312}
313
314static void add_top_level_decl(Context *c, Buf *name, AstNode *node) {
315 c->global_table.put(name, node);
316 c->root->data.root.top_level_decls.append(node);
317}
318
319static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {
320 bool is_const = true;
321 AstNode *type_node = nullptr;
322 AstNode *node = trans_create_node_var_decl_global(c, is_const, var_name, type_node, value_node);
323 add_top_level_decl(c, var_name, node);
324 return node;
325}
326
327static const char *decl_name(const Decl *decl) {
328 const NamedDecl *named_decl = static_cast<const NamedDecl *>(decl);
329 return (const char *)named_decl->getName().bytes_begin();
330}
331
332static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
333 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
334 node->data.int_literal.bigint = allocate<BigInt>(1);
335 bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), aps_int.isNegative());
336 return node;
337
338}
339
340static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
341
342static bool is_c_void_type(AstNode *node) {
343 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
344}
345
346static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) {
347 // TODO: maybe widen to increase size
348 // TODO: maybe bitcast to change sign
349 // TODO: maybe truncate to reduce size
350 return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr);
351}
352
353static bool qual_type_is_fn_ptr(Context *c, const QualType &qt) {
354 const Type *ty = qt.getTypePtr();
355 if (ty->getTypeClass() != Type::Pointer) {
356 return false;
357 }
358 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
359 QualType child_qt = pointer_ty->getPointeeType();
360 const Type *child_ty = child_qt.getTypePtr();
361 if (child_ty->getTypeClass() != Type::Paren) {
362 return false;
363 }
364 const ParenType *paren_ty = static_cast<const ParenType *>(child_ty);
365 return paren_ty->getInnerType().getTypePtr()->getTypeClass() == Type::FunctionProto;
366}
367
368static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
369 const Type *ty = qt.getTypePtr();
370 switch (ty->getTypeClass()) {
371 case Type::Builtin:
372 {
373 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
374 switch (builtin_ty->getKind()) {
375 case BuiltinType::Char_U:
376 case BuiltinType::UChar:
377 case BuiltinType::Char_S:
378 case BuiltinType::SChar:
379 return 8;
380 case BuiltinType::UInt128:
381 case BuiltinType::Int128:
382 return 128;
383 default:
384 return 0;
385 }
386 zig_unreachable();
387 }
388 case Type::Typedef:
389 {
390 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
391 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
392 const char *type_name = decl_name(typedef_decl);
393 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
394 return 8;
395 } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) {
396 return 16;
397 } else if (strcmp(type_name, "uint32_t") == 0 || strcmp(type_name, "int32_t") == 0) {
398 return 32;
399 } else if (strcmp(type_name, "uint64_t") == 0 || strcmp(type_name, "int64_t") == 0) {
400 return 64;
401 } else {
402 return 0;
403 }
404 }
405 default:
406 return 0;
407 }
408 zig_unreachable();
409}
410
411
412static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
413 const SourceLocation &source_loc)
414{
415 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
416 if (int_bit_width != 0) {
417 // we can perform the log2 now.
418 uint64_t cast_bit_width = log2_u64(int_bit_width);
419 return trans_create_node_symbol(c, buf_sprintf("u%" ZIG_PRI_u64, cast_bit_width));
420 }
421
422 AstNode *zig_type_node = trans_qual_type(c, qt, source_loc);
423
424// @import("std").math.Log2Int(c_long);
425//
426// FnCall
427// FieldAccess
428// FieldAccess
429// FnCall (.builtin = true)
430// Symbol "import"
431// StringLiteral "std"
432// Symbol "math"
433// Symbol "Log2Int"
434// zig_type_node
435
436 AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");
437 import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std")));
438 AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
439 AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
440 AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);
441
442 return log2int_fn_call;
443}
444
445static bool qual_type_child_is_fn_proto(const QualType &qt) {
446 if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
447 const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
448 if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
449 return true;
450 }
451 } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
452 const AttributedType *attr_type = static_cast<const AttributedType *>(qt.getTypePtr());
453 return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
454 }
455 return false;
456}
457
458static QualType resolve_any_typedef(Context *c, QualType qt) {
459 const Type * ty = qt.getTypePtr();
460 if (ty->getTypeClass() != Type::Typedef)
461 return qt;
462 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
463 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
464 return typedef_decl->getUnderlyingType();
465}
466
467static bool c_is_signed_integer(Context *c, QualType qt) {
468 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
469 if (c_type->getTypeClass() != Type::Builtin)
470 return false;
471 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
472 switch (builtin_ty->getKind()) {
473 case BuiltinType::SChar:
474 case BuiltinType::Short:
475 case BuiltinType::Int:
476 case BuiltinType::Long:
477 case BuiltinType::LongLong:
478 case BuiltinType::Int128:
479 case BuiltinType::WChar_S:
480 return true;
481 default:
482 return false;
483 }
484}
485
486static bool c_is_unsigned_integer(Context *c, QualType qt) {
487 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
488 if (c_type->getTypeClass() != Type::Builtin)
489 return false;
490 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
491 switch (builtin_ty->getKind()) {
492 case BuiltinType::Char_U:
493 case BuiltinType::UChar:
494 case BuiltinType::Char_S:
495 case BuiltinType::UShort:
496 case BuiltinType::UInt:
497 case BuiltinType::ULong:
498 case BuiltinType::ULongLong:
499 case BuiltinType::UInt128:
500 case BuiltinType::WChar_U:
501 return true;
502 default:
503 return false;
504 }
505}
506
507static bool c_is_float(Context *c, QualType qt) {
508 const Type *c_type = qt.getTypePtr();
509 if (c_type->getTypeClass() != Type::Builtin)
510 return false;
511 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
512 switch (builtin_ty->getKind()) {
513 case BuiltinType::Half:
514 case BuiltinType::Float:
515 case BuiltinType::Double:
516 case BuiltinType::Float128:
517 case BuiltinType::LongDouble:
518 return true;
519 default:
520 return false;
521 }
522}
523
524static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
525 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
526 // float and signed integer overflow is undefined behavior.
527 return false;
528 } else {
529 // unsigned integer overflow wraps around.
530 return true;
531 }
532}
533
534enum TransLRValue {
535 TransLValue,
536 TransRValue,
537};
538
539static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval);
540static AstNode *const skip_add_to_block_node = (AstNode *) 0x2;
541
542static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) {
543 return trans_stmt(c, result_used, block, expr, lrval);
544}
545
546static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
547 switch (ty->getTypeClass()) {
548 case Type::Builtin:
549 {
550 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
551 switch (builtin_ty->getKind()) {
552 case BuiltinType::Void:
553 return trans_create_node_symbol_str(c, "c_void");
554 case BuiltinType::Bool:
555 return trans_create_node_symbol_str(c, "bool");
556 case BuiltinType::Char_U:
557 case BuiltinType::UChar:
558 case BuiltinType::Char_S:
559 return trans_create_node_symbol_str(c, "u8");
560 case BuiltinType::SChar:
561 return trans_create_node_symbol_str(c, "i8");
562 case BuiltinType::UShort:
563 return trans_create_node_symbol_str(c, "c_ushort");
564 case BuiltinType::UInt:
565 return trans_create_node_symbol_str(c, "c_uint");
566 case BuiltinType::ULong:
567 return trans_create_node_symbol_str(c, "c_ulong");
568 case BuiltinType::ULongLong:
569 return trans_create_node_symbol_str(c, "c_ulonglong");
570 case BuiltinType::Short:
571 return trans_create_node_symbol_str(c, "c_short");
572 case BuiltinType::Int:
573 return trans_create_node_symbol_str(c, "c_int");
574 case BuiltinType::Long:
575 return trans_create_node_symbol_str(c, "c_long");
576 case BuiltinType::LongLong:
577 return trans_create_node_symbol_str(c, "c_longlong");
578 case BuiltinType::UInt128:
579 return trans_create_node_symbol_str(c, "u128");
580 case BuiltinType::Int128:
581 return trans_create_node_symbol_str(c, "i128");
582 case BuiltinType::Float:
583 return trans_create_node_symbol_str(c, "f32");
584 case BuiltinType::Double:
585 return trans_create_node_symbol_str(c, "f64");
586 case BuiltinType::Float128:
587 return trans_create_node_symbol_str(c, "f128");
588 case BuiltinType::LongDouble:
589 return trans_create_node_symbol_str(c, "c_longdouble");
590 case BuiltinType::WChar_U:
591 case BuiltinType::Char16:
592 case BuiltinType::Char32:
593 case BuiltinType::WChar_S:
594 case BuiltinType::Half:
595 case BuiltinType::NullPtr:
596 case BuiltinType::ObjCId:
597 case BuiltinType::ObjCClass:
598 case BuiltinType::ObjCSel:
599 case BuiltinType::OMPArraySection:
600 case BuiltinType::Dependent:
601 case BuiltinType::Overload:
602 case BuiltinType::BoundMember:
603 case BuiltinType::PseudoObject:
604 case BuiltinType::UnknownAny:
605 case BuiltinType::BuiltinFn:
606 case BuiltinType::ARCUnbridgedCast:
607
608 case BuiltinType::OCLImage1dRO:
609 case BuiltinType::OCLImage1dArrayRO:
610 case BuiltinType::OCLImage1dBufferRO:
611 case BuiltinType::OCLImage2dRO:
612 case BuiltinType::OCLImage2dArrayRO:
613 case BuiltinType::OCLImage2dDepthRO:
614 case BuiltinType::OCLImage2dArrayDepthRO:
615 case BuiltinType::OCLImage2dMSAARO:
616 case BuiltinType::OCLImage2dArrayMSAARO:
617 case BuiltinType::OCLImage2dMSAADepthRO:
618 case BuiltinType::OCLImage2dArrayMSAADepthRO:
619 case BuiltinType::OCLImage3dRO:
620 case BuiltinType::OCLImage1dWO:
621 case BuiltinType::OCLImage1dArrayWO:
622 case BuiltinType::OCLImage1dBufferWO:
623 case BuiltinType::OCLImage2dWO:
624 case BuiltinType::OCLImage2dArrayWO:
625 case BuiltinType::OCLImage2dDepthWO:
626 case BuiltinType::OCLImage2dArrayDepthWO:
627 case BuiltinType::OCLImage2dMSAAWO:
628 case BuiltinType::OCLImage2dArrayMSAAWO:
629 case BuiltinType::OCLImage2dMSAADepthWO:
630 case BuiltinType::OCLImage2dArrayMSAADepthWO:
631 case BuiltinType::OCLImage3dWO:
632 case BuiltinType::OCLImage1dRW:
633 case BuiltinType::OCLImage1dArrayRW:
634 case BuiltinType::OCLImage1dBufferRW:
635 case BuiltinType::OCLImage2dRW:
636 case BuiltinType::OCLImage2dArrayRW:
637 case BuiltinType::OCLImage2dDepthRW:
638 case BuiltinType::OCLImage2dArrayDepthRW:
639 case BuiltinType::OCLImage2dMSAARW:
640 case BuiltinType::OCLImage2dArrayMSAARW:
641 case BuiltinType::OCLImage2dMSAADepthRW:
642 case BuiltinType::OCLImage2dArrayMSAADepthRW:
643 case BuiltinType::OCLImage3dRW:
644 case BuiltinType::OCLSampler:
645 case BuiltinType::OCLEvent:
646 case BuiltinType::OCLClkEvent:
647 case BuiltinType::OCLQueue:
648 case BuiltinType::OCLReserveID:
649 emit_warning(c, source_loc, "unsupported builtin type");
650 return nullptr;
651 }
652 break;
653 }
654 case Type::Pointer:
655 {
656 const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
657 QualType child_qt = pointer_ty->getPointeeType();
658 AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
659 if (child_node == nullptr) {
660 emit_warning(c, source_loc, "pointer to unsupported type");
661 return nullptr;
662 }
663
664 if (qual_type_child_is_fn_proto(child_qt)) {
665 return trans_create_node_prefix_op(c, PrefixOpMaybe, child_node);
666 }
667
668 AstNode *pointer_node = trans_create_node_addr_of(c, child_qt.isConstQualified(),
669 child_qt.isVolatileQualified(), child_node);
670 return trans_create_node_prefix_op(c, PrefixOpMaybe, pointer_node);
671 }
672 case Type::Typedef:
673 {
674 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
675 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
676 return resolve_typedef_decl(c, typedef_decl);
677 }
678 case Type::Elaborated:
679 {
680 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
681 switch (elaborated_ty->getKeyword()) {
682 case ETK_Struct:
683 case ETK_Enum:
684 case ETK_Union:
685 return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
686 case ETK_Interface:
687 case ETK_Class:
688 case ETK_Typename:
689 case ETK_None:
690 emit_warning(c, source_loc, "unsupported elaborated type");
691 return nullptr;
692 }
693 }
694 case Type::FunctionProto:
695 {
696 const FunctionProtoType *fn_proto_ty = static_cast<const FunctionProtoType*>(ty);
697
698 AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
699 switch (fn_proto_ty->getCallConv()) {
700 case CC_C: // __attribute__((cdecl))
701 proto_node->data.fn_proto.cc = CallingConventionC;
702 proto_node->data.fn_proto.is_extern = true;
703 break;
704 case CC_X86StdCall: // __attribute__((stdcall))
705 proto_node->data.fn_proto.cc = CallingConventionStdcall;
706 break;
707 case CC_X86FastCall: // __attribute__((fastcall))
708 emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
709 return nullptr;
710 case CC_X86ThisCall: // __attribute__((thiscall))
711 emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
712 return nullptr;
713 case CC_X86VectorCall: // __attribute__((vectorcall))
714 emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
715 return nullptr;
716 case CC_X86Pascal: // __attribute__((pascal))
717 emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
718 return nullptr;
719 case CC_Win64: // __attribute__((ms_abi))
720 emit_warning(c, source_loc, "unsupported calling convention: win64");
721 return nullptr;
722 case CC_X86_64SysV: // __attribute__((sysv_abi))
723 emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
724 return nullptr;
725 case CC_X86RegCall:
726 emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
727 return nullptr;
728 case CC_AAPCS: // __attribute__((pcs("aapcs")))
729 emit_warning(c, source_loc, "unsupported calling convention: aapcs");
730 return nullptr;
731 case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
732 emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
733 return nullptr;
734 case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
735 emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
736 return nullptr;
737 case CC_SpirFunction: // default for OpenCL functions on SPIR target
738 emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
739 return nullptr;
740 case CC_OpenCLKernel:
741 emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
742 return nullptr;
743 case CC_Swift:
744 emit_warning(c, source_loc, "unsupported calling convention: Swift");
745 return nullptr;
746 case CC_PreserveMost:
747 emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
748 return nullptr;
749 case CC_PreserveAll:
750 emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
751 return nullptr;
752 }
753
754 proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
755 size_t param_count = fn_proto_ty->getNumParams();
756
757 if (fn_proto_ty->getNoReturnAttr()) {
758 proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
759 } else {
760 proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(),
761 source_loc);
762 if (proto_node->data.fn_proto.return_type == nullptr) {
763 emit_warning(c, source_loc, "unsupported function proto return type");
764 return nullptr;
765 }
766 // convert c_void to actual void (only for return type)
767 if (is_c_void_type(proto_node->data.fn_proto.return_type)) {
768 proto_node->data.fn_proto.return_type = nullptr;
769 }
770 }
771
772 //emit_warning(c, source_loc, "TODO figure out fn prototype fn name");
773 const char *fn_name = nullptr;
774 if (fn_name != nullptr) {
775 proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
776 }
777
778 for (size_t i = 0; i < param_count; i += 1) {
779 QualType qt = fn_proto_ty->getParamType(i);
780 AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
781
782 if (param_type_node == nullptr) {
783 emit_warning(c, source_loc, "unresolved function proto parameter type");
784 return nullptr;
785 }
786
787 AstNode *param_node = trans_create_node(c, NodeTypeParamDecl);
788 //emit_warning(c, source_loc, "TODO figure out fn prototype param name");
789 const char *param_name = nullptr;
790 if (param_name != nullptr) {
791 param_node->data.param_decl.name = buf_create_from_str(param_name);
792 }
793 param_node->data.param_decl.is_noalias = qt.isRestrictQualified();
794 param_node->data.param_decl.type = param_type_node;
795 proto_node->data.fn_proto.params.append(param_node);
796 }
797 // TODO check for always_inline attribute
798 // TODO check for align attribute
799
800 return proto_node;
801 }
802 case Type::Record:
803 {
804 const RecordType *record_ty = static_cast<const RecordType*>(ty);
805 return resolve_record_decl(c, record_ty->getDecl());
806 }
807 case Type::Enum:
808 {
809 const EnumType *enum_ty = static_cast<const EnumType*>(ty);
810 return resolve_enum_decl(c, enum_ty->getDecl());
811 }
812 case Type::ConstantArray:
813 {
814 const ConstantArrayType *const_arr_ty = static_cast<const ConstantArrayType *>(ty);
815 AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
816 if (child_type_node == nullptr) {
817 emit_warning(c, source_loc, "unresolved array element type");
818 return nullptr;
819 }
820 uint64_t size = const_arr_ty->getSize().getLimitedValue();
821 AstNode *size_node = trans_create_node_unsigned(c, size);
822 return trans_create_node_array_type(c, size_node, child_type_node);
823 }
824 case Type::Paren:
825 {
826 const ParenType *paren_ty = static_cast<const ParenType *>(ty);
827 return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
828 }
829 case Type::Decayed:
830 {
831 const DecayedType *decayed_ty = static_cast<const DecayedType *>(ty);
832 return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
833 }
834 case Type::Attributed:
835 {
836 const AttributedType *attributed_ty = static_cast<const AttributedType *>(ty);
837 return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
838 }
839 case Type::BlockPointer:
840 case Type::LValueReference:
841 case Type::RValueReference:
842 case Type::MemberPointer:
843 case Type::IncompleteArray:
844 case Type::VariableArray:
845 case Type::DependentSizedArray:
846 case Type::DependentSizedExtVector:
847 case Type::Vector:
848 case Type::ExtVector:
849 case Type::FunctionNoProto:
850 case Type::UnresolvedUsing:
851 case Type::Adjusted:
852 case Type::TypeOfExpr:
853 case Type::TypeOf:
854 case Type::Decltype:
855 case Type::UnaryTransform:
856 case Type::TemplateTypeParm:
857 case Type::SubstTemplateTypeParm:
858 case Type::SubstTemplateTypeParmPack:
859 case Type::TemplateSpecialization:
860 case Type::Auto:
861 case Type::InjectedClassName:
862 case Type::DependentName:
863 case Type::DependentTemplateSpecialization:
864 case Type::PackExpansion:
865 case Type::ObjCObject:
866 case Type::ObjCInterface:
867 case Type::Complex:
868 case Type::ObjCObjectPointer:
869 case Type::Atomic:
870 case Type::Pipe:
871 case Type::ObjCTypeParam:
872 case Type::DeducedTemplateSpecialization:
873 emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
874 return nullptr;
875 }
876 zig_unreachable();
877}
878
879static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) {
880 return trans_type(c, qt.getTypePtr(), source_loc);
881}
882
883static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) {
884 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
885 for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
886 AstNode *child_node = trans_stmt(c, false, child_block, *it, TransRValue);
887 if (child_node == nullptr)
888 return nullptr;
889 if (child_node != skip_add_to_block_node)
890 child_block->data.block.statements.append(child_node);
891 }
892 return child_block;
893}
894
895static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt) {
896 Expr *value_expr = stmt->getRetValue();
897 if (value_expr == nullptr) {
898 emit_warning(c, stmt->getLocStart(), "TODO handle C return void");
899 return nullptr;
900 } else {
901 AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr);
902 return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr, TransRValue);
903 if (return_node->data.return_expr.expr == nullptr)
904 return nullptr;
905 return return_node;
906 }
907}
908
909static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) {
910 llvm::APSInt result;
911 if (!stmt->EvaluateAsInt(result, *c->ctx)) {
912 emit_warning(c, stmt->getLocStart(), "invalid integer literal");
913 return nullptr;
914 }
915 return trans_create_node_apint(c, result);
916}
917
918static AstNode *trans_conditional_operator(Context *c, bool result_used, AstNode *block, ConditionalOperator *stmt) {
919 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
920
921 Expr *cond_expr = stmt->getCond();
922 Expr *true_expr = stmt->getTrueExpr();
923 Expr *false_expr = stmt->getFalseExpr();
924
925 node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr, TransRValue);
926 if (node->data.if_bool_expr.condition == nullptr)
927 return nullptr;
928
929 node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr, TransRValue);
930 if (node->data.if_bool_expr.then_block == nullptr)
931 return nullptr;
932
933 node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr, TransRValue);
934 if (node->data.if_bool_expr.else_node == nullptr)
935 return nullptr;
936
937 return maybe_suppress_result(c, result_used, node);
938}
939
940static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) {
941 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
942 node->data.bin_op_expr.bin_op = bin_op;
943
944 node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransRValue);
945 if (node->data.bin_op_expr.op1 == nullptr)
946 return nullptr;
947
948 node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue);
949 if (node->data.bin_op_expr.op2 == nullptr)
950 return nullptr;
951
952 return node;
953}
954
955static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block, Expr *lhs, Expr *rhs) {
956 if (!result_used) {
957 // common case
958 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
959 node->data.bin_op_expr.bin_op = BinOpTypeAssign;
960
961 node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransLValue);
962 if (node->data.bin_op_expr.op1 == nullptr)
963 return nullptr;
964
965 node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue);
966 if (node->data.bin_op_expr.op2 == nullptr)
967 return nullptr;
968
969 return node;
970 } else {
971 // worst case
972 // c: lhs = rhs
973 // zig: {
974 // zig: const _tmp = rhs;
975 // zig: lhs = _tmp;
976 // zig: _tmp
977 // zig: }
978
979 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
980
981 // const _tmp = rhs;
982 AstNode *rhs_node = trans_expr(c, true, child_block, rhs, TransRValue);
983 if (rhs_node == nullptr) return nullptr;
984 // TODO: avoid name collisions with generated variable names
985 Buf* tmp_var_name = buf_create_from_str("_tmp");
986 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node);
987 child_block->data.block.statements.append(tmp_var_decl);
988
989 // lhs = _tmp;
990 AstNode *lhs_node = trans_expr(c, true, child_block, lhs, TransLValue);
991 if (lhs_node == nullptr) return nullptr;
992 child_block->data.block.statements.append(
993 trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign,
994 trans_create_node_symbol(c, tmp_var_name)));
995
996 // _tmp
997 child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name));
998 child_block->data.block.last_statement_is_result_expression = true;
999
1000 return child_block;
1001 }
1002}
1003
1004static AstNode *trans_create_shift_op(Context *c, AstNode *block, QualType result_type, Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr) {
1005 const SourceLocation &rhs_location = rhs_expr->getLocStart();
1006 AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
1007 // lhs >> u5(rh)
1008
1009 AstNode *lhs = trans_expr(c, true, block, lhs_expr, TransLValue);
1010 if (lhs == nullptr) return nullptr;
1011
1012 AstNode *rhs = trans_expr(c, true, block, rhs_expr, TransRValue);
1013 if (rhs == nullptr) return nullptr;
1014 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1015
1016 return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
1017}
1018
1019static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *block, BinaryOperator *stmt) {
1020 switch (stmt->getOpcode()) {
1021 case BO_PtrMemD:
1022 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD");
1023 return nullptr;
1024 case BO_PtrMemI:
1025 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI");
1026 return nullptr;
1027 case BO_Mul:
1028 return trans_create_bin_op(c, block, stmt->getLHS(),
1029 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
1030 stmt->getRHS());
1031 case BO_Div:
1032 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1033 // unsigned/float division uses the operator
1034 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
1035 } else {
1036 // signed integer division uses @divTrunc
1037 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
1038 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1039 if (lhs == nullptr) return nullptr;
1040 fn_call->data.fn_call_expr.params.append(lhs);
1041 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
1042 if (rhs == nullptr) return nullptr;
1043 fn_call->data.fn_call_expr.params.append(rhs);
1044 return fn_call;
1045 }
1046 case BO_Rem:
1047 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1048 // unsigned/float division uses the operator
1049 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
1050 } else {
1051 // signed integer division uses @rem
1052 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
1053 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1054 if (lhs == nullptr) return nullptr;
1055 fn_call->data.fn_call_expr.params.append(lhs);
1056 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
1057 if (rhs == nullptr) return nullptr;
1058 fn_call->data.fn_call_expr.params.append(rhs);
1059 return fn_call;
1060 }
1061 case BO_Add:
1062 return trans_create_bin_op(c, block, stmt->getLHS(),
1063 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
1064 stmt->getRHS());
1065 case BO_Sub:
1066 return trans_create_bin_op(c, block, stmt->getLHS(),
1067 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
1068 stmt->getRHS());
1069 case BO_Shl:
1070 return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
1071 case BO_Shr:
1072 return trans_create_shift_op(c, block, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
1073 case BO_LT:
1074 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
1075 case BO_GT:
1076 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
1077 case BO_LE:
1078 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
1079 case BO_GE:
1080 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
1081 case BO_EQ:
1082 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
1083 case BO_NE:
1084 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
1085 case BO_And:
1086 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
1087 case BO_Xor:
1088 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
1089 case BO_Or:
1090 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
1091 case BO_LAnd:
1092 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
1093 case BO_LOr:
1094 // TODO: int vs bool
1095 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1096 case BO_Assign:
1097 return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS());
1098 case BO_Comma:
1099 {
1100 block = trans_create_node(c, NodeTypeBlock);
1101 AstNode *lhs = trans_expr(c, false, block, stmt->getLHS(), TransRValue);
1102 if (lhs == nullptr) return nullptr;
1103 block->data.block.statements.append(maybe_suppress_result(c, false, lhs));
1104 AstNode *rhs = trans_expr(c, result_used, block, stmt->getRHS(), TransRValue);
1105 if (rhs == nullptr) return nullptr;
1106 block->data.block.statements.append(maybe_suppress_result(c, result_used, rhs));
1107 block->data.block.last_statement_is_result_expression = true;
1108 return block;
1109 }
1110 case BO_MulAssign:
1111 case BO_DivAssign:
1112 case BO_RemAssign:
1113 case BO_AddAssign:
1114 case BO_SubAssign:
1115 case BO_ShlAssign:
1116 case BO_ShrAssign:
1117 case BO_AndAssign:
1118 case BO_XorAssign:
1119 case BO_OrAssign:
1120 zig_unreachable();
1121 }
1122
1123 zig_unreachable();
1124}
1125
1126static AstNode *trans_create_compound_assign_shift(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) {
1127 const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
1128 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
1129
1130 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
1131 if (!use_intermediate_casts && !result_used) {
1132 // simple common case, where the C and Zig are identical:
1133 // lhs >>= rhs
1134 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1135 if (lhs == nullptr) return nullptr;
1136
1137 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue);
1138 if (rhs == nullptr) return nullptr;
1139 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1140
1141 return trans_create_node_bin_op(c, lhs, assign_op, coerced_rhs);
1142 } else {
1143 // need more complexity. worst case, this looks like this:
1144 // c: lhs >>= rhs
1145 // zig: {
1146 // zig: const _ref = &lhs;
1147 // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1148 // zig: *_ref
1149 // zig: }
1150 // where u5 is the appropriate type
1151
1152 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1153
1154 // const _ref = &lhs;
1155 AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue);
1156 if (lhs == nullptr) return nullptr;
1157 AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
1158 // TODO: avoid name collisions with generated variable names
1159 Buf* tmp_var_name = buf_create_from_str("_ref");
1160 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1161 child_block->data.block.statements.append(tmp_var_decl);
1162
1163 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1164
1165 AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue);
1166 if (rhs == nullptr) return nullptr;
1167 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1168
1169 AstNode *assign_statement = trans_create_node_bin_op(c,
1170 trans_create_node_prefix_op(c, PrefixOpDereference,
1171 trans_create_node_symbol(c, tmp_var_name)),
1172 BinOpTypeAssign,
1173 trans_c_cast(c, rhs_location,
1174 stmt->getComputationResultType(),
1175 trans_create_node_bin_op(c,
1176 trans_c_cast(c, rhs_location,
1177 stmt->getComputationLHSType(),
1178 trans_create_node_prefix_op(c, PrefixOpDereference,
1179 trans_create_node_symbol(c, tmp_var_name))),
1180 bin_op,
1181 coerced_rhs)));
1182 child_block->data.block.statements.append(assign_statement);
1183
1184 if (result_used) {
1185 // *_ref
1186 child_block->data.block.statements.append(
1187 trans_create_node_prefix_op(c, PrefixOpDereference,
1188 trans_create_node_symbol(c, tmp_var_name)));
1189 child_block->data.block.last_statement_is_result_expression = true;
1190 }
1191
1192 return child_block;
1193 }
1194}
1195
1196static AstNode *trans_create_compound_assign(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op) {
1197 if (!result_used) {
1198 // simple common case, where the C and Zig are identical:
1199 // lhs += rhs
1200 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1201 if (lhs == nullptr) return nullptr;
1202 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue);
1203 if (rhs == nullptr) return nullptr;
1204 return trans_create_node_bin_op(c, lhs, assign_op, rhs);
1205 } else {
1206 // need more complexity. worst case, this looks like this:
1207 // c: lhs += rhs
1208 // zig: {
1209 // zig: const _ref = &lhs;
1210 // zig: *_ref = *_ref + rhs;
1211 // zig: *_ref
1212 // zig: }
1213
1214 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1215
1216 // const _ref = &lhs;
1217 AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue);
1218 if (lhs == nullptr) return nullptr;
1219 AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
1220 // TODO: avoid name collisions with generated variable names
1221 Buf* tmp_var_name = buf_create_from_str("_ref");
1222 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1223 child_block->data.block.statements.append(tmp_var_decl);
1224
1225 // *_ref = *_ref + rhs;
1226
1227 AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue);
1228 if (rhs == nullptr) return nullptr;
1229
1230 AstNode *assign_statement = trans_create_node_bin_op(c,
1231 trans_create_node_prefix_op(c, PrefixOpDereference,
1232 trans_create_node_symbol(c, tmp_var_name)),
1233 BinOpTypeAssign,
1234 trans_create_node_bin_op(c,
1235 trans_create_node_prefix_op(c, PrefixOpDereference,
1236 trans_create_node_symbol(c, tmp_var_name)),
1237 bin_op,
1238 rhs));
1239 child_block->data.block.statements.append(assign_statement);
1240
1241 // *_ref
1242 child_block->data.block.statements.append(
1243 trans_create_node_prefix_op(c, PrefixOpDereference,
1244 trans_create_node_symbol(c, tmp_var_name)));
1245 child_block->data.block.last_statement_is_result_expression = true;
1246
1247 return child_block;
1248 }
1249}
1250
1251
1252static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) {
1253 switch (stmt->getOpcode()) {
1254 case BO_MulAssign:
1255 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1256 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
1257 else
1258 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
1259 case BO_DivAssign:
1260 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign");
1261 return nullptr;
1262 case BO_RemAssign:
1263 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign");
1264 return nullptr;
1265 case BO_AddAssign:
1266 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1267 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
1268 else
1269 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
1270 case BO_SubAssign:
1271 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1272 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
1273 else
1274 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
1275 case BO_ShlAssign:
1276 return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
1277 case BO_ShrAssign:
1278 return trans_create_compound_assign_shift(c, result_used, block, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
1279 case BO_AndAssign:
1280 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
1281 case BO_XorAssign:
1282 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
1283 case BO_OrAssign:
1284 return trans_create_compound_assign(c, result_used, block, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
1285 case BO_PtrMemD:
1286 case BO_PtrMemI:
1287 case BO_Assign:
1288 case BO_Mul:
1289 case BO_Div:
1290 case BO_Rem:
1291 case BO_Add:
1292 case BO_Sub:
1293 case BO_Shl:
1294 case BO_Shr:
1295 case BO_LT:
1296 case BO_GT:
1297 case BO_LE:
1298 case BO_GE:
1299 case BO_EQ:
1300 case BO_NE:
1301 case BO_And:
1302 case BO_Xor:
1303 case BO_Or:
1304 case BO_LAnd:
1305 case BO_LOr:
1306 case BO_Comma:
1307 zig_unreachable();
1308 }
1309
1310 zig_unreachable();
1311}
1312
1313static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) {
1314 switch (stmt->getCastKind()) {
1315 case CK_LValueToRValue:
1316 return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1317 case CK_IntegralCast:
1318 {
1319 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1320 if (target_node == nullptr)
1321 return nullptr;
1322 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node);
1323 }
1324 case CK_FunctionToPointerDecay:
1325 case CK_ArrayToPointerDecay:
1326 {
1327 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1328 if (target_node == nullptr)
1329 return nullptr;
1330 return target_node;
1331 }
1332 case CK_BitCast:
1333 {
1334 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1335 if (target_node == nullptr)
1336 return nullptr;
1337
1338 AstNode *dest_type_node = trans_qual_type(c, stmt->getType(), stmt->getLocStart());
1339
1340 AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
1341 node->data.fn_call_expr.params.append(dest_type_node);
1342 node->data.fn_call_expr.params.append(target_node);
1343 return node;
1344 }
1345 case CK_NullToPointer:
1346 return trans_create_node(c, NodeTypeNullLiteral);
1347 case CK_Dependent:
1348 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
1349 return nullptr;
1350 case CK_LValueBitCast:
1351 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast");
1352 return nullptr;
1353 case CK_NoOp:
1354 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NoOp");
1355 return nullptr;
1356 case CK_BaseToDerived:
1357 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerived");
1358 return nullptr;
1359 case CK_DerivedToBase:
1360 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBase");
1361 return nullptr;
1362 case CK_UncheckedDerivedToBase:
1363 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
1364 return nullptr;
1365 case CK_Dynamic:
1366 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dynamic");
1367 return nullptr;
1368 case CK_ToUnion:
1369 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion");
1370 return nullptr;
1371 case CK_NullToMemberPointer:
1372 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToMemberPointer");
1373 return nullptr;
1374 case CK_BaseToDerivedMemberPointer:
1375 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
1376 return nullptr;
1377 case CK_DerivedToBaseMemberPointer:
1378 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
1379 return nullptr;
1380 case CK_MemberPointerToBoolean:
1381 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_MemberPointerToBoolean");
1382 return nullptr;
1383 case CK_ReinterpretMemberPointer:
1384 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
1385 return nullptr;
1386 case CK_UserDefinedConversion:
1387 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_UserDefinedConversion");
1388 return nullptr;
1389 case CK_ConstructorConversion:
1390 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ConstructorConversion");
1391 return nullptr;
1392 case CK_IntegralToPointer:
1393 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToPointer");
1394 return nullptr;
1395 case CK_PointerToIntegral:
1396 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToIntegral");
1397 return nullptr;
1398 case CK_PointerToBoolean:
1399 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_PointerToBoolean");
1400 return nullptr;
1401 case CK_ToVoid:
1402 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToVoid");
1403 return nullptr;
1404 case CK_VectorSplat:
1405 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_VectorSplat");
1406 return nullptr;
1407 case CK_IntegralToBoolean:
1408 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToBoolean");
1409 return nullptr;
1410 case CK_IntegralToFloating:
1411 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralToFloating");
1412 return nullptr;
1413 case CK_FloatingToIntegral:
1414 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToIntegral");
1415 return nullptr;
1416 case CK_FloatingToBoolean:
1417 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingToBoolean");
1418 return nullptr;
1419 case CK_BooleanToSignedIntegral:
1420 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BooleanToSignedIntegral");
1421 return nullptr;
1422 case CK_FloatingCast:
1423 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingCast");
1424 return nullptr;
1425 case CK_CPointerToObjCPointerCast:
1426 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CPointerToObjCPointerCast");
1427 return nullptr;
1428 case CK_BlockPointerToObjCPointerCast:
1429 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast");
1430 return nullptr;
1431 case CK_AnyPointerToBlockPointerCast:
1432 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast");
1433 return nullptr;
1434 case CK_ObjCObjectLValueCast:
1435 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ObjCObjectLValueCast");
1436 return nullptr;
1437 case CK_FloatingRealToComplex:
1438 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingRealToComplex");
1439 return nullptr;
1440 case CK_FloatingComplexToReal:
1441 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToReal");
1442 return nullptr;
1443 case CK_FloatingComplexToBoolean:
1444 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToBoolean");
1445 return nullptr;
1446 case CK_FloatingComplexCast:
1447 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexCast");
1448 return nullptr;
1449 case CK_FloatingComplexToIntegralComplex:
1450 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex");
1451 return nullptr;
1452 case CK_IntegralRealToComplex:
1453 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralRealToComplex");
1454 return nullptr;
1455 case CK_IntegralComplexToReal:
1456 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToReal");
1457 return nullptr;
1458 case CK_IntegralComplexToBoolean:
1459 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToBoolean");
1460 return nullptr;
1461 case CK_IntegralComplexCast:
1462 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexCast");
1463 return nullptr;
1464 case CK_IntegralComplexToFloatingComplex:
1465 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex");
1466 return nullptr;
1467 case CK_ARCProduceObject:
1468 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCProduceObject");
1469 return nullptr;
1470 case CK_ARCConsumeObject:
1471 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCConsumeObject");
1472 return nullptr;
1473 case CK_ARCReclaimReturnedObject:
1474 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCReclaimReturnedObject");
1475 return nullptr;
1476 case CK_ARCExtendBlockObject:
1477 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ARCExtendBlockObject");
1478 return nullptr;
1479 case CK_AtomicToNonAtomic:
1480 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AtomicToNonAtomic");
1481 return nullptr;
1482 case CK_NonAtomicToAtomic:
1483 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NonAtomicToAtomic");
1484 return nullptr;
1485 case CK_CopyAndAutoreleaseBlockObject:
1486 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject");
1487 return nullptr;
1488 case CK_BuiltinFnToFnPtr:
1489 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BuiltinFnToFnPtr");
1490 return nullptr;
1491 case CK_ZeroToOCLEvent:
1492 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLEvent");
1493 return nullptr;
1494 case CK_ZeroToOCLQueue:
1495 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ZeroToOCLQueue");
1496 return nullptr;
1497 case CK_AddressSpaceConversion:
1498 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_AddressSpaceConversion");
1499 return nullptr;
1500 case CK_IntToOCLSampler:
1501 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_IntToOCLSampler");
1502 return nullptr;
1503 }
1504 zig_unreachable();
1505}
1506
1507static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue lrval) {
1508 ValueDecl *value_decl = stmt->getDecl();
1509 Buf *symbol_name = buf_create_from_str(decl_name(value_decl));
1510 if (lrval == TransLValue) {
1511 c->ptr_params.put(symbol_name, true);
1512 }
1513 return trans_create_node_symbol(c, symbol_name);
1514}
1515
1516static AstNode *trans_create_post_crement(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt, BinOpType assign_op) {
1517 Expr *op_expr = stmt->getSubExpr();
1518
1519 if (!result_used) {
1520 // common case
1521 // c: expr++
1522 // zig: expr += 1
1523 return trans_create_node_bin_op(c,
1524 trans_expr(c, true, block, op_expr, TransLValue),
1525 assign_op,
1526 trans_create_node_unsigned(c, 1));
1527 } else {
1528 // worst case
1529 // c: expr++
1530 // zig: {
1531 // zig: const _ref = &expr;
1532 // zig: const _tmp = *_ref;
1533 // zig: *_ref += 1;
1534 // zig: _tmp
1535 // zig: }
1536 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1537
1538 // const _ref = &expr;
1539 AstNode *expr = trans_expr(c, true, child_block, op_expr, TransLValue);
1540 if (expr == nullptr) return nullptr;
1541 AstNode *addr_of_expr = trans_create_node_addr_of(c, false, false, expr);
1542 // TODO: avoid name collisions with generated variable names
1543 Buf* ref_var_name = buf_create_from_str("_ref");
1544 AstNode *ref_var_decl = trans_create_node_var_decl_local(c, true, ref_var_name, nullptr, addr_of_expr);
1545 child_block->data.block.statements.append(ref_var_decl);
1546
1547 // const _tmp = *_ref;
1548 Buf* tmp_var_name = buf_create_from_str("_tmp");
1549 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr,
1550 trans_create_node_prefix_op(c, PrefixOpDereference,
1551 trans_create_node_symbol(c, ref_var_name)));
1552 child_block->data.block.statements.append(tmp_var_decl);
1553
1554 // *_ref += 1;
1555 AstNode *assign_statement = trans_create_node_bin_op(c,
1556 trans_create_node_prefix_op(c, PrefixOpDereference,
1557 trans_create_node_symbol(c, ref_var_name)),
1558 assign_op,
1559 trans_create_node_unsigned(c, 1));
1560 child_block->data.block.statements.append(assign_statement);
1561
1562 // _tmp
1563 child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name));
1564 child_block->data.block.last_statement_is_result_expression = true;
1565
1566 return child_block;
1567 }
1568}
1569
1570static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) {
1571 switch (stmt->getOpcode()) {
1572 case UO_PostInc:
1573 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1574 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlusWrap);
1575 else
1576 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignPlus);
1577 case UO_PostDec:
1578 if (qual_type_has_wrapping_overflow(c, stmt->getType()))
1579 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinusWrap);
1580 else
1581 return trans_create_post_crement(c, result_used, block, stmt, BinOpTypeAssignMinus);
1582 case UO_PreInc:
1583 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PreInc");
1584 return nullptr;
1585 case UO_PreDec:
1586 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PreDec");
1587 return nullptr;
1588 case UO_AddrOf:
1589 {
1590 AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransLValue);
1591 if (value_node == nullptr)
1592 return value_node;
1593 return trans_create_node_addr_of(c, false, false, value_node);
1594 }
1595 case UO_Deref:
1596 {
1597 AstNode *value_node = trans_expr(c, result_used, block, stmt->getSubExpr(), TransRValue);
1598 if (value_node == nullptr)
1599 return nullptr;
1600 bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType());
1601 if (is_fn_ptr)
1602 return value_node;
1603 AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node);
1604 return trans_create_node_prefix_op(c, PrefixOpDereference, unwrapped);
1605 }
1606 case UO_Plus:
1607 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Plus");
1608 return nullptr;
1609 case UO_Minus:
1610 {
1611 Expr *op_expr = stmt->getSubExpr();
1612 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
1613 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
1614 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
1615
1616 node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr, TransRValue);
1617 if (node->data.prefix_op_expr.primary_expr == nullptr)
1618 return nullptr;
1619
1620 return node;
1621 } else if (c_is_unsigned_integer(c, op_expr->getType())) {
1622 // we gotta emit 0 -% x
1623 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1624 node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0);
1625
1626 node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr, TransRValue);
1627 if (node->data.bin_op_expr.op2 == nullptr)
1628 return nullptr;
1629
1630 node->data.bin_op_expr.bin_op = BinOpTypeSubWrap;
1631 return node;
1632 } else {
1633 emit_warning(c, stmt->getLocStart(), "C negation with non float non integer");
1634 return nullptr;
1635 }
1636 }
1637 case UO_Not:
1638 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Not");
1639 return nullptr;
1640 case UO_LNot:
1641 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_LNot");
1642 return nullptr;
1643 case UO_Real:
1644 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real");
1645 return nullptr;
1646 case UO_Imag:
1647 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Imag");
1648 return nullptr;
1649 case UO_Extension:
1650 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Extension");
1651 return nullptr;
1652 case UO_Coawait:
1653 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Coawait");
1654 return nullptr;
1655 }
1656 zig_unreachable();
1657}
1658
1659static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *stmt) {
1660 for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
1661 Decl *decl = *iter;
1662 switch (decl->getKind()) {
1663 case Decl::Var: {
1664 VarDecl *var_decl = (VarDecl *)decl;
1665 QualType qual_type = var_decl->getTypeSourceInfo()->getType();
1666 AstNode *init_node = nullptr;
1667 if (var_decl->hasInit()) {
1668 init_node = trans_expr(c, true, block, var_decl->getInit(), TransRValue);
1669 if (init_node == nullptr)
1670 return nullptr;
1671
1672 }
1673 AstNode *type_node = trans_qual_type(c, qual_type, stmt->getLocStart());
1674 if (type_node == nullptr)
1675 return nullptr;
1676
1677 Buf *symbol_name = buf_create_from_str(decl_name(var_decl));
1678
1679 AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(),
1680 symbol_name, type_node, init_node);
1681 block->data.block.statements.append(node);
1682 continue;
1683 }
1684 case Decl::AccessSpec:
1685 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind AccessSpec");
1686 return nullptr;
1687 case Decl::Block:
1688 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Block");
1689 return nullptr;
1690 case Decl::Captured:
1691 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Captured");
1692 return nullptr;
1693 case Decl::ClassScopeFunctionSpecialization:
1694 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassScopeFunctionSpecialization");
1695 return nullptr;
1696 case Decl::Empty:
1697 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Empty");
1698 return nullptr;
1699 case Decl::Export:
1700 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Export");
1701 return nullptr;
1702 case Decl::ExternCContext:
1703 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ExternCContext");
1704 return nullptr;
1705 case Decl::FileScopeAsm:
1706 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FileScopeAsm");
1707 return nullptr;
1708 case Decl::Friend:
1709 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Friend");
1710 return nullptr;
1711 case Decl::FriendTemplate:
1712 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FriendTemplate");
1713 return nullptr;
1714 case Decl::Import:
1715 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Import");
1716 return nullptr;
1717 case Decl::LinkageSpec:
1718 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind LinkageSpec");
1719 return nullptr;
1720 case Decl::Label:
1721 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Label");
1722 return nullptr;
1723 case Decl::Namespace:
1724 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Namespace");
1725 return nullptr;
1726 case Decl::NamespaceAlias:
1727 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NamespaceAlias");
1728 return nullptr;
1729 case Decl::ObjCCompatibleAlias:
1730 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCompatibleAlias");
1731 return nullptr;
1732 case Decl::ObjCCategory:
1733 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategory");
1734 return nullptr;
1735 case Decl::ObjCCategoryImpl:
1736 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCCategoryImpl");
1737 return nullptr;
1738 case Decl::ObjCImplementation:
1739 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCImplementation");
1740 return nullptr;
1741 case Decl::ObjCInterface:
1742 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCInterface");
1743 return nullptr;
1744 case Decl::ObjCProtocol:
1745 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProtocol");
1746 return nullptr;
1747 case Decl::ObjCMethod:
1748 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCMethod");
1749 return nullptr;
1750 case Decl::ObjCProperty:
1751 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCProperty");
1752 return nullptr;
1753 case Decl::BuiltinTemplate:
1754 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind BuiltinTemplate");
1755 return nullptr;
1756 case Decl::ClassTemplate:
1757 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplate");
1758 return nullptr;
1759 case Decl::FunctionTemplate:
1760 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind FunctionTemplate");
1761 return nullptr;
1762 case Decl::TypeAliasTemplate:
1763 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAliasTemplate");
1764 return nullptr;
1765 case Decl::VarTemplate:
1766 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplate");
1767 return nullptr;
1768 case Decl::TemplateTemplateParm:
1769 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTemplateParm");
1770 return nullptr;
1771 case Decl::Enum:
1772 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Enum");
1773 return nullptr;
1774 case Decl::Record:
1775 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Record");
1776 return nullptr;
1777 case Decl::CXXRecord:
1778 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXRecord");
1779 return nullptr;
1780 case Decl::ClassTemplateSpecialization:
1781 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplateSpecialization");
1782 return nullptr;
1783 case Decl::ClassTemplatePartialSpecialization:
1784 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ClassTemplatePartialSpecialization");
1785 return nullptr;
1786 case Decl::TemplateTypeParm:
1787 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TemplateTypeParm");
1788 return nullptr;
1789 case Decl::ObjCTypeParam:
1790 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCTypeParam");
1791 return nullptr;
1792 case Decl::TypeAlias:
1793 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TypeAlias");
1794 return nullptr;
1795 case Decl::Typedef:
1796 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Typedef");
1797 return nullptr;
1798 case Decl::UnresolvedUsingTypename:
1799 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingTypename");
1800 return nullptr;
1801 case Decl::Using:
1802 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Using");
1803 return nullptr;
1804 case Decl::UsingDirective:
1805 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingDirective");
1806 return nullptr;
1807 case Decl::UsingPack:
1808 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingPack");
1809 return nullptr;
1810 case Decl::UsingShadow:
1811 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UsingShadow");
1812 return nullptr;
1813 case Decl::ConstructorUsingShadow:
1814 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ConstructorUsingShadow");
1815 return nullptr;
1816 case Decl::Binding:
1817 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Binding");
1818 return nullptr;
1819 case Decl::Field:
1820 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Field");
1821 return nullptr;
1822 case Decl::ObjCAtDefsField:
1823 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCAtDefsField");
1824 return nullptr;
1825 case Decl::ObjCIvar:
1826 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCIvar");
1827 return nullptr;
1828 case Decl::Function:
1829 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Function");
1830 return nullptr;
1831 case Decl::CXXDeductionGuide:
1832 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDeductionGuide");
1833 return nullptr;
1834 case Decl::CXXMethod:
1835 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXMethod");
1836 return nullptr;
1837 case Decl::CXXConstructor:
1838 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConstructor");
1839 return nullptr;
1840 case Decl::CXXConversion:
1841 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXConversion");
1842 return nullptr;
1843 case Decl::CXXDestructor:
1844 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind CXXDestructor");
1845 return nullptr;
1846 case Decl::MSProperty:
1847 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind MSProperty");
1848 return nullptr;
1849 case Decl::NonTypeTemplateParm:
1850 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind NonTypeTemplateParm");
1851 return nullptr;
1852 case Decl::Decomposition:
1853 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind Decomposition");
1854 return nullptr;
1855 case Decl::ImplicitParam:
1856 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ImplicitParam");
1857 return nullptr;
1858 case Decl::OMPCapturedExpr:
1859 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPCapturedExpr");
1860 return nullptr;
1861 case Decl::ParmVar:
1862 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ParmVar");
1863 return nullptr;
1864 case Decl::VarTemplateSpecialization:
1865 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplateSpecialization");
1866 return nullptr;
1867 case Decl::VarTemplatePartialSpecialization:
1868 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind VarTemplatePartialSpecialization");
1869 return nullptr;
1870 case Decl::EnumConstant:
1871 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind EnumConstant");
1872 return nullptr;
1873 case Decl::IndirectField:
1874 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind IndirectField");
1875 return nullptr;
1876 case Decl::OMPDeclareReduction:
1877 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPDeclareReduction");
1878 return nullptr;
1879 case Decl::UnresolvedUsingValue:
1880 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind UnresolvedUsingValue");
1881 return nullptr;
1882 case Decl::OMPThreadPrivate:
1883 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind OMPThreadPrivate");
1884 return nullptr;
1885 case Decl::ObjCPropertyImpl:
1886 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind ObjCPropertyImpl");
1887 return nullptr;
1888 case Decl::PragmaComment:
1889 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaComment");
1890 return nullptr;
1891 case Decl::PragmaDetectMismatch:
1892 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind PragmaDetectMismatch");
1893 return nullptr;
1894 case Decl::StaticAssert:
1895 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind StaticAssert");
1896 return nullptr;
1897 case Decl::TranslationUnit:
1898 emit_warning(c, stmt->getLocStart(), "TODO handle decl kind TranslationUnit");
1899 return nullptr;
1900 }
1901 zig_unreachable();
1902 }
1903
1904 // declarations were already added
1905 return skip_add_to_block_node;
1906}
1907
1908static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) {
1909 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);
1910
1911 while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond(), TransRValue);
1912 if (while_node->data.while_expr.condition == nullptr)
1913 return nullptr;
1914
1915 while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody(), TransRValue);
1916 if (while_node->data.while_expr.body == nullptr)
1917 return nullptr;
1918
1919 return while_node;
1920}
1921
1922static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) {
1923 // if (c) t
1924 // if (c) t else e
1925 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
1926
1927 // TODO: condition != 0
1928 AstNode *condition_node = trans_expr(c, true, block, stmt->getCond(), TransRValue);
1929 if (condition_node == nullptr)
1930 return nullptr;
1931 if_node->data.if_bool_expr.condition = condition_node;
1932
1933 if_node->data.if_bool_expr.then_block = trans_stmt(c, false, block, stmt->getThen(), TransRValue);
1934 if (if_node->data.if_bool_expr.then_block == nullptr)
1935 return nullptr;
1936
1937 if (stmt->getElse() != nullptr) {
1938 if_node->data.if_bool_expr.else_node = trans_stmt(c, false, block, stmt->getElse(), TransRValue);
1939 if (if_node->data.if_bool_expr.else_node == nullptr)
1940 return nullptr;
1941 }
1942
1943 return if_node;
1944}
1945
1946static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, CallExpr *stmt) {
1947 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
1948
1949 AstNode *callee_raw_node = trans_expr(c, true, block, stmt->getCallee(), TransRValue);
1950 if (callee_raw_node == nullptr)
1951 return nullptr;
1952
1953 AstNode *callee_node;
1954 if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) {
1955 callee_node = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, callee_raw_node);
1956 } else {
1957 callee_node = callee_raw_node;
1958 }
1959
1960 node->data.fn_call_expr.fn_ref_expr = callee_node;
1961
1962 unsigned num_args = stmt->getNumArgs();
1963 Expr **args = stmt->getArgs();
1964 for (unsigned i = 0; i < num_args; i += 1) {
1965 AstNode *arg_node = trans_expr(c, true, block, args[i], TransRValue);
1966 if (arg_node == nullptr)
1967 return nullptr;
1968
1969 node->data.fn_call_expr.params.append(arg_node);
1970 }
1971
1972 return node;
1973}
1974
1975static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) {
1976 AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue);
1977 if (container_node == nullptr)
1978 return nullptr;
1979
1980 if (stmt->isArrow()) {
1981 container_node = trans_create_node_unwrap_null(c, container_node);
1982 }
1983
1984 const char *name = decl_name(stmt->getMemberDecl());
1985
1986 AstNode *node = trans_create_node_field_access_str(c, container_node, name);
1987 return node;
1988}
1989
1990static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubscriptExpr *stmt) {
1991 AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue);
1992 if (container_node == nullptr)
1993 return nullptr;
1994
1995 AstNode *idx_node = trans_expr(c, true, block, stmt->getIdx(), TransRValue);
1996 if (idx_node == nullptr)
1997 return nullptr;
1998
1999
2000 AstNode *node = trans_create_node(c, NodeTypeArrayAccessExpr);
2001 node->data.array_access_expr.array_ref_expr = container_node;
2002 node->data.array_access_expr.subscript = idx_node;
2003 return node;
2004}
2005
2006static AstNode *trans_c_style_cast_expr(Context *c, bool result_used, AstNode *block,
2007 CStyleCastExpr *stmt, TransLRValue lrvalue)
2008{
2009 AstNode *sub_expr_node = trans_expr(c, result_used, block, stmt->getSubExpr(), lrvalue);
2010 if (sub_expr_node == nullptr)
2011 return nullptr;
2012
2013 return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node);
2014}
2015
2016static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, UnaryExprOrTypeTraitExpr *stmt) {
2017 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());
2018 if (type_node == nullptr)
2019 return nullptr;
2020
2021 AstNode *node = trans_create_node_builtin_fn_call_str(c, "sizeOf");
2022 node->data.fn_call_expr.params.append(type_node);
2023 return node;
2024}
2025
2026static AstNode *trans_do_loop(Context *c, AstNode *block, DoStmt *stmt) {
2027 stmt->getBody();
2028 stmt->getCond();
2029
2030 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);
2031
2032 AstNode *true_node = trans_create_node(c, NodeTypeBoolLiteral);
2033 true_node->data.bool_literal.value = true;
2034 while_node->data.while_expr.condition = true_node;
2035
2036 AstNode *body_node;
2037 if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {
2038 // there's already a block in C, so we'll append our condition to it.
2039 // c: do {
2040 // c: a;
2041 // c: b;
2042 // c: } while(c);
2043 // zig: while (true) {
2044 // zig: a;
2045 // zig: b;
2046 // zig: if (!cond) break;
2047 // zig: }
2048 body_node = trans_stmt(c, false, block, stmt->getBody(), TransRValue);
2049 if (body_node == nullptr) return nullptr;
2050 assert(body_node->type == NodeTypeBlock);
2051 } else {
2052 // the C statement is without a block, so we need to create a block to contain it.
2053 // c: do
2054 // c: a;
2055 // c: while(c);
2056 // zig: while (true) {
2057 // zig: a;
2058 // zig: if (!cond) break;
2059 // zig: }
2060 body_node = trans_create_node(c, NodeTypeBlock);
2061 AstNode *child_statement = trans_stmt(c, false, body_node, stmt->getBody(), TransRValue);
2062 if (child_statement == nullptr) return nullptr;
2063 body_node->data.block.statements.append(child_statement);
2064 }
2065
2066 // if (!cond) break;
2067 AstNode *condition_node = trans_expr(c, true, body_node, stmt->getCond(), TransRValue);
2068 if (condition_node == nullptr) return nullptr;
2069 AstNode *terminator_node = trans_create_node(c, NodeTypeIfBoolExpr);
2070 terminator_node->data.if_bool_expr.condition = trans_create_node_prefix_op(c, PrefixOpBoolNot, condition_node);
2071 terminator_node->data.if_bool_expr.then_block = trans_create_node(c, NodeTypeBreak);
2072 body_node->data.block.statements.append(terminator_node);
2073
2074 while_node->data.while_expr.body = body_node;
2075
2076 return while_node;
2077}
2078
2079static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) {
2080 Stmt::StmtClass sc = stmt->getStmtClass();
2081 switch (sc) {
2082 case Stmt::ReturnStmtClass:
2083 return trans_return_stmt(c, block, (ReturnStmt *)stmt);
2084 case Stmt::CompoundStmtClass:
2085 return trans_compound_stmt(c, block, (CompoundStmt *)stmt);
2086 case Stmt::IntegerLiteralClass:
2087 return trans_integer_literal(c, (IntegerLiteral *)stmt);
2088 case Stmt::ConditionalOperatorClass:
2089 return trans_conditional_operator(c, result_used, block, (ConditionalOperator *)stmt);
2090 case Stmt::BinaryOperatorClass:
2091 return trans_binary_operator(c, result_used, block, (BinaryOperator *)stmt);
2092 case Stmt::CompoundAssignOperatorClass:
2093 return trans_compound_assign_operator(c, result_used, block, (CompoundAssignOperator *)stmt);
2094 case Stmt::ImplicitCastExprClass:
2095 return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt);
2096 case Stmt::DeclRefExprClass:
2097 return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue);
2098 case Stmt::UnaryOperatorClass:
2099 return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt);
2100 case Stmt::DeclStmtClass:
2101 return trans_local_declaration(c, block, (DeclStmt *)stmt);
2102 case Stmt::WhileStmtClass:
2103 return trans_while_loop(c, block, (WhileStmt *)stmt);
2104 case Stmt::IfStmtClass:
2105 return trans_if_statement(c, block, (IfStmt *)stmt);
2106 case Stmt::CallExprClass:
2107 return trans_call_expr(c, result_used, block, (CallExpr *)stmt);
2108 case Stmt::NullStmtClass:
2109 return skip_add_to_block_node;
2110 case Stmt::MemberExprClass:
2111 return trans_member_expr(c, block, (MemberExpr *)stmt);
2112 case Stmt::ArraySubscriptExprClass:
2113 return trans_array_subscript_expr(c, block, (ArraySubscriptExpr *)stmt);
2114 case Stmt::CStyleCastExprClass:
2115 return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue);
2116 case Stmt::UnaryExprOrTypeTraitExprClass:
2117 return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt);
2118 case Stmt::DoStmtClass:
2119 return trans_do_loop(c, block, (DoStmt *)stmt);
2120 case Stmt::CaseStmtClass:
2121 emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");
2122 return nullptr;
2123 case Stmt::DefaultStmtClass:
2124 emit_warning(c, stmt->getLocStart(), "TODO handle C DefaultStmtClass");
2125 return nullptr;
2126 case Stmt::SwitchStmtClass:
2127 emit_warning(c, stmt->getLocStart(), "TODO handle C SwitchStmtClass");
2128 return nullptr;
2129 case Stmt::NoStmtClass:
2130 emit_warning(c, stmt->getLocStart(), "TODO handle C NoStmtClass");
2131 return nullptr;
2132 case Stmt::GCCAsmStmtClass:
2133 emit_warning(c, stmt->getLocStart(), "TODO handle C GCCAsmStmtClass");
2134 return nullptr;
2135 case Stmt::MSAsmStmtClass:
2136 emit_warning(c, stmt->getLocStart(), "TODO handle C MSAsmStmtClass");
2137 return nullptr;
2138 case Stmt::AttributedStmtClass:
2139 emit_warning(c, stmt->getLocStart(), "TODO handle C AttributedStmtClass");
2140 return nullptr;
2141 case Stmt::BreakStmtClass:
2142 emit_warning(c, stmt->getLocStart(), "TODO handle C BreakStmtClass");
2143 return nullptr;
2144 case Stmt::CXXCatchStmtClass:
2145 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXCatchStmtClass");
2146 return nullptr;
2147 case Stmt::CXXForRangeStmtClass:
2148 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXForRangeStmtClass");
2149 return nullptr;
2150 case Stmt::CXXTryStmtClass:
2151 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTryStmtClass");
2152 return nullptr;
2153 case Stmt::CapturedStmtClass:
2154 emit_warning(c, stmt->getLocStart(), "TODO handle C CapturedStmtClass");
2155 return nullptr;
2156 case Stmt::ContinueStmtClass:
2157 emit_warning(c, stmt->getLocStart(), "TODO handle C ContinueStmtClass");
2158 return nullptr;
2159 case Stmt::CoreturnStmtClass:
2160 emit_warning(c, stmt->getLocStart(), "TODO handle C CoreturnStmtClass");
2161 return nullptr;
2162 case Stmt::CoroutineBodyStmtClass:
2163 emit_warning(c, stmt->getLocStart(), "TODO handle C CoroutineBodyStmtClass");
2164 return nullptr;
2165 case Stmt::BinaryConditionalOperatorClass:
2166 emit_warning(c, stmt->getLocStart(), "TODO handle C BinaryConditionalOperatorClass");
2167 return nullptr;
2168 case Stmt::AddrLabelExprClass:
2169 emit_warning(c, stmt->getLocStart(), "TODO handle C AddrLabelExprClass");
2170 return nullptr;
2171 case Stmt::ArrayInitIndexExprClass:
2172 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitIndexExprClass");
2173 return nullptr;
2174 case Stmt::ArrayInitLoopExprClass:
2175 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass");
2176 return nullptr;
2177 case Stmt::ArrayTypeTraitExprClass:
2178 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass");
2179 return nullptr;
2180 case Stmt::AsTypeExprClass:
2181 emit_warning(c, stmt->getLocStart(), "TODO handle C AsTypeExprClass");
2182 return nullptr;
2183 case Stmt::AtomicExprClass:
2184 emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");
2185 return nullptr;
2186 case Stmt::BlockExprClass:
2187 emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");
2188 return nullptr;
2189 case Stmt::CXXBindTemporaryExprClass:
2190 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBindTemporaryExprClass");
2191 return nullptr;
2192 case Stmt::CXXBoolLiteralExprClass:
2193 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXBoolLiteralExprClass");
2194 return nullptr;
2195 case Stmt::CXXConstructExprClass:
2196 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstructExprClass");
2197 return nullptr;
2198 case Stmt::CXXTemporaryObjectExprClass:
2199 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTemporaryObjectExprClass");
2200 return nullptr;
2201 case Stmt::CXXDefaultArgExprClass:
2202 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultArgExprClass");
2203 return nullptr;
2204 case Stmt::CXXDefaultInitExprClass:
2205 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDefaultInitExprClass");
2206 return nullptr;
2207 case Stmt::CXXDeleteExprClass:
2208 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDeleteExprClass");
2209 return nullptr;
2210 case Stmt::CXXDependentScopeMemberExprClass:
2211 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDependentScopeMemberExprClass");
2212 return nullptr;
2213 case Stmt::CXXFoldExprClass:
2214 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFoldExprClass");
2215 return nullptr;
2216 case Stmt::CXXInheritedCtorInitExprClass:
2217 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXInheritedCtorInitExprClass");
2218 return nullptr;
2219 case Stmt::CXXNewExprClass:
2220 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNewExprClass");
2221 return nullptr;
2222 case Stmt::CXXNoexceptExprClass:
2223 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNoexceptExprClass");
2224 return nullptr;
2225 case Stmt::CXXNullPtrLiteralExprClass:
2226 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXNullPtrLiteralExprClass");
2227 return nullptr;
2228 case Stmt::CXXPseudoDestructorExprClass:
2229 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXPseudoDestructorExprClass");
2230 return nullptr;
2231 case Stmt::CXXScalarValueInitExprClass:
2232 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXScalarValueInitExprClass");
2233 return nullptr;
2234 case Stmt::CXXStdInitializerListExprClass:
2235 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStdInitializerListExprClass");
2236 return nullptr;
2237 case Stmt::CXXThisExprClass:
2238 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThisExprClass");
2239 return nullptr;
2240 case Stmt::CXXThrowExprClass:
2241 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXThrowExprClass");
2242 return nullptr;
2243 case Stmt::CXXTypeidExprClass:
2244 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXTypeidExprClass");
2245 return nullptr;
2246 case Stmt::CXXUnresolvedConstructExprClass:
2247 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUnresolvedConstructExprClass");
2248 return nullptr;
2249 case Stmt::CXXUuidofExprClass:
2250 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass");
2251 return nullptr;
2252 case Stmt::CUDAKernelCallExprClass:
2253 emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass");
2254 return nullptr;
2255 case Stmt::CXXMemberCallExprClass:
2256 (void)result_used;
2257 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass");
2258 return nullptr;
2259 case Stmt::CXXOperatorCallExprClass:
2260 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXOperatorCallExprClass");
2261 return nullptr;
2262 case Stmt::UserDefinedLiteralClass:
2263 emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass");
2264 return nullptr;
2265 case Stmt::CXXFunctionalCastExprClass:
2266 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass");
2267 return nullptr;
2268 case Stmt::CXXConstCastExprClass:
2269 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXConstCastExprClass");
2270 return nullptr;
2271 case Stmt::CXXDynamicCastExprClass:
2272 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXDynamicCastExprClass");
2273 return nullptr;
2274 case Stmt::CXXReinterpretCastExprClass:
2275 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXReinterpretCastExprClass");
2276 return nullptr;
2277 case Stmt::CXXStaticCastExprClass:
2278 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXStaticCastExprClass");
2279 return nullptr;
2280 case Stmt::ObjCBridgedCastExprClass:
2281 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBridgedCastExprClass");
2282 return nullptr;
2283 case Stmt::CharacterLiteralClass:
2284 emit_warning(c, stmt->getLocStart(), "TODO handle C CharacterLiteralClass");
2285 return nullptr;
2286 case Stmt::ChooseExprClass:
2287 emit_warning(c, stmt->getLocStart(), "TODO handle C ChooseExprClass");
2288 return nullptr;
2289 case Stmt::CompoundLiteralExprClass:
2290 emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundLiteralExprClass");
2291 return nullptr;
2292 case Stmt::ConvertVectorExprClass:
2293 emit_warning(c, stmt->getLocStart(), "TODO handle C ConvertVectorExprClass");
2294 return nullptr;
2295 case Stmt::CoawaitExprClass:
2296 emit_warning(c, stmt->getLocStart(), "TODO handle C CoawaitExprClass");
2297 return nullptr;
2298 case Stmt::CoyieldExprClass:
2299 emit_warning(c, stmt->getLocStart(), "TODO handle C CoyieldExprClass");
2300 return nullptr;
2301 case Stmt::DependentCoawaitExprClass:
2302 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentCoawaitExprClass");
2303 return nullptr;
2304 case Stmt::DependentScopeDeclRefExprClass:
2305 emit_warning(c, stmt->getLocStart(), "TODO handle C DependentScopeDeclRefExprClass");
2306 return nullptr;
2307 case Stmt::DesignatedInitExprClass:
2308 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitExprClass");
2309 return nullptr;
2310 case Stmt::DesignatedInitUpdateExprClass:
2311 emit_warning(c, stmt->getLocStart(), "TODO handle C DesignatedInitUpdateExprClass");
2312 return nullptr;
2313 case Stmt::ExprWithCleanupsClass:
2314 emit_warning(c, stmt->getLocStart(), "TODO handle C ExprWithCleanupsClass");
2315 return nullptr;
2316 case Stmt::ExpressionTraitExprClass:
2317 emit_warning(c, stmt->getLocStart(), "TODO handle C ExpressionTraitExprClass");
2318 return nullptr;
2319 case Stmt::ExtVectorElementExprClass:
2320 emit_warning(c, stmt->getLocStart(), "TODO handle C ExtVectorElementExprClass");
2321 return nullptr;
2322 case Stmt::FloatingLiteralClass:
2323 emit_warning(c, stmt->getLocStart(), "TODO handle C FloatingLiteralClass");
2324 return nullptr;
2325 case Stmt::FunctionParmPackExprClass:
2326 emit_warning(c, stmt->getLocStart(), "TODO handle C FunctionParmPackExprClass");
2327 return nullptr;
2328 case Stmt::GNUNullExprClass:
2329 emit_warning(c, stmt->getLocStart(), "TODO handle C GNUNullExprClass");
2330 return nullptr;
2331 case Stmt::GenericSelectionExprClass:
2332 emit_warning(c, stmt->getLocStart(), "TODO handle C GenericSelectionExprClass");
2333 return nullptr;
2334 case Stmt::ImaginaryLiteralClass:
2335 emit_warning(c, stmt->getLocStart(), "TODO handle C ImaginaryLiteralClass");
2336 return nullptr;
2337 case Stmt::ImplicitValueInitExprClass:
2338 emit_warning(c, stmt->getLocStart(), "TODO handle C ImplicitValueInitExprClass");
2339 return nullptr;
2340 case Stmt::InitListExprClass:
2341 emit_warning(c, stmt->getLocStart(), "TODO handle C InitListExprClass");
2342 return nullptr;
2343 case Stmt::LambdaExprClass:
2344 emit_warning(c, stmt->getLocStart(), "TODO handle C LambdaExprClass");
2345 return nullptr;
2346 case Stmt::MSPropertyRefExprClass:
2347 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertyRefExprClass");
2348 return nullptr;
2349 case Stmt::MSPropertySubscriptExprClass:
2350 emit_warning(c, stmt->getLocStart(), "TODO handle C MSPropertySubscriptExprClass");
2351 return nullptr;
2352 case Stmt::MaterializeTemporaryExprClass:
2353 emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass");
2354 return nullptr;
2355 case Stmt::NoInitExprClass:
2356 emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass");
2357 return nullptr;
2358 case Stmt::OMPArraySectionExprClass:
2359 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPArraySectionExprClass");
2360 return nullptr;
2361 case Stmt::ObjCArrayLiteralClass:
2362 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCArrayLiteralClass");
2363 return nullptr;
2364 case Stmt::ObjCAvailabilityCheckExprClass:
2365 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAvailabilityCheckExprClass");
2366 return nullptr;
2367 case Stmt::ObjCBoolLiteralExprClass:
2368 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoolLiteralExprClass");
2369 return nullptr;
2370 case Stmt::ObjCBoxedExprClass:
2371 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCBoxedExprClass");
2372 return nullptr;
2373 case Stmt::ObjCDictionaryLiteralClass:
2374 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCDictionaryLiteralClass");
2375 return nullptr;
2376 case Stmt::ObjCEncodeExprClass:
2377 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCEncodeExprClass");
2378 return nullptr;
2379 case Stmt::ObjCIndirectCopyRestoreExprClass:
2380 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIndirectCopyRestoreExprClass");
2381 return nullptr;
2382 case Stmt::ObjCIsaExprClass:
2383 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIsaExprClass");
2384 return nullptr;
2385 case Stmt::ObjCIvarRefExprClass:
2386 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCIvarRefExprClass");
2387 return nullptr;
2388 case Stmt::ObjCMessageExprClass:
2389 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCMessageExprClass");
2390 return nullptr;
2391 case Stmt::ObjCPropertyRefExprClass:
2392 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCPropertyRefExprClass");
2393 return nullptr;
2394 case Stmt::ObjCProtocolExprClass:
2395 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCProtocolExprClass");
2396 return nullptr;
2397 case Stmt::ObjCSelectorExprClass:
2398 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSelectorExprClass");
2399 return nullptr;
2400 case Stmt::ObjCStringLiteralClass:
2401 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCStringLiteralClass");
2402 return nullptr;
2403 case Stmt::ObjCSubscriptRefExprClass:
2404 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCSubscriptRefExprClass");
2405 return nullptr;
2406 case Stmt::OffsetOfExprClass:
2407 emit_warning(c, stmt->getLocStart(), "TODO handle C OffsetOfExprClass");
2408 return nullptr;
2409 case Stmt::OpaqueValueExprClass:
2410 emit_warning(c, stmt->getLocStart(), "TODO handle C OpaqueValueExprClass");
2411 return nullptr;
2412 case Stmt::UnresolvedLookupExprClass:
2413 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedLookupExprClass");
2414 return nullptr;
2415 case Stmt::UnresolvedMemberExprClass:
2416 emit_warning(c, stmt->getLocStart(), "TODO handle C UnresolvedMemberExprClass");
2417 return nullptr;
2418 case Stmt::PackExpansionExprClass:
2419 emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass");
2420 return nullptr;
2421 case Stmt::ParenExprClass:
2422 return trans_expr(c, result_used, block, ((ParenExpr*)stmt)->getSubExpr(), lrvalue);
2423 case Stmt::ParenListExprClass:
2424 emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");
2425 return nullptr;
2426 case Stmt::PredefinedExprClass:
2427 emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass");
2428 return nullptr;
2429 case Stmt::PseudoObjectExprClass:
2430 emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass");
2431 return nullptr;
2432 case Stmt::ShuffleVectorExprClass:
2433 emit_warning(c, stmt->getLocStart(), "TODO handle C ShuffleVectorExprClass");
2434 return nullptr;
2435 case Stmt::SizeOfPackExprClass:
2436 emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass");
2437 return nullptr;
2438 case Stmt::StmtExprClass:
2439 emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass");
2440 return nullptr;
2441 case Stmt::StringLiteralClass:
2442 emit_warning(c, stmt->getLocStart(), "TODO handle C StringLiteralClass");
2443 return nullptr;
2444 case Stmt::SubstNonTypeTemplateParmExprClass:
2445 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass");
2446 return nullptr;
2447 case Stmt::SubstNonTypeTemplateParmPackExprClass:
2448 emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
2449 return nullptr;
2450 case Stmt::TypeTraitExprClass:
2451 emit_warning(c, stmt->getLocStart(), "TODO handle C TypeTraitExprClass");
2452 return nullptr;
2453 case Stmt::TypoExprClass:
2454 emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass");
2455 return nullptr;
2456 case Stmt::VAArgExprClass:
2457 emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass");
2458 return nullptr;
2459 case Stmt::ForStmtClass:
2460 emit_warning(c, stmt->getLocStart(), "TODO handle C ForStmtClass");
2461 return nullptr;
2462 case Stmt::GotoStmtClass:
2463 emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass");
2464 return nullptr;
2465 case Stmt::IndirectGotoStmtClass:
2466 emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass");
2467 return nullptr;
2468 case Stmt::LabelStmtClass:
2469 emit_warning(c, stmt->getLocStart(), "TODO handle C LabelStmtClass");
2470 return nullptr;
2471 case Stmt::MSDependentExistsStmtClass:
2472 emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass");
2473 return nullptr;
2474 case Stmt::OMPAtomicDirectiveClass:
2475 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass");
2476 return nullptr;
2477 case Stmt::OMPBarrierDirectiveClass:
2478 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPBarrierDirectiveClass");
2479 return nullptr;
2480 case Stmt::OMPCancelDirectiveClass:
2481 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancelDirectiveClass");
2482 return nullptr;
2483 case Stmt::OMPCancellationPointDirectiveClass:
2484 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCancellationPointDirectiveClass");
2485 return nullptr;
2486 case Stmt::OMPCriticalDirectiveClass:
2487 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPCriticalDirectiveClass");
2488 return nullptr;
2489 case Stmt::OMPFlushDirectiveClass:
2490 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPFlushDirectiveClass");
2491 return nullptr;
2492 case Stmt::OMPDistributeDirectiveClass:
2493 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeDirectiveClass");
2494 return nullptr;
2495 case Stmt::OMPDistributeParallelForDirectiveClass:
2496 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForDirectiveClass");
2497 return nullptr;
2498 case Stmt::OMPDistributeParallelForSimdDirectiveClass:
2499 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
2500 return nullptr;
2501 case Stmt::OMPDistributeSimdDirectiveClass:
2502 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPDistributeSimdDirectiveClass");
2503 return nullptr;
2504 case Stmt::OMPForDirectiveClass:
2505 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForDirectiveClass");
2506 return nullptr;
2507 case Stmt::OMPForSimdDirectiveClass:
2508 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPForSimdDirectiveClass");
2509 return nullptr;
2510 case Stmt::OMPParallelForDirectiveClass:
2511 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForDirectiveClass");
2512 return nullptr;
2513 case Stmt::OMPParallelForSimdDirectiveClass:
2514 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelForSimdDirectiveClass");
2515 return nullptr;
2516 case Stmt::OMPSimdDirectiveClass:
2517 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSimdDirectiveClass");
2518 return nullptr;
2519 case Stmt::OMPTargetParallelForSimdDirectiveClass:
2520 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
2521 return nullptr;
2522 case Stmt::OMPTargetSimdDirectiveClass:
2523 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetSimdDirectiveClass");
2524 return nullptr;
2525 case Stmt::OMPTargetTeamsDistributeDirectiveClass:
2526 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
2527 return nullptr;
2528 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
2529 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
2530 return nullptr;
2531 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
2532 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
2533 return nullptr;
2534 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
2535 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
2536 return nullptr;
2537 case Stmt::OMPTaskLoopDirectiveClass:
2538 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopDirectiveClass");
2539 return nullptr;
2540 case Stmt::OMPTaskLoopSimdDirectiveClass:
2541 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskLoopSimdDirectiveClass");
2542 return nullptr;
2543 case Stmt::OMPTeamsDistributeDirectiveClass:
2544 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeDirectiveClass");
2545 return nullptr;
2546 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
2547 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
2548 return nullptr;
2549 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
2550 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
2551 return nullptr;
2552 case Stmt::OMPTeamsDistributeSimdDirectiveClass:
2553 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
2554 return nullptr;
2555 case Stmt::OMPMasterDirectiveClass:
2556 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPMasterDirectiveClass");
2557 return nullptr;
2558 case Stmt::OMPOrderedDirectiveClass:
2559 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPOrderedDirectiveClass");
2560 return nullptr;
2561 case Stmt::OMPParallelDirectiveClass:
2562 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelDirectiveClass");
2563 return nullptr;
2564 case Stmt::OMPParallelSectionsDirectiveClass:
2565 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPParallelSectionsDirectiveClass");
2566 return nullptr;
2567 case Stmt::OMPSectionDirectiveClass:
2568 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionDirectiveClass");
2569 return nullptr;
2570 case Stmt::OMPSectionsDirectiveClass:
2571 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSectionsDirectiveClass");
2572 return nullptr;
2573 case Stmt::OMPSingleDirectiveClass:
2574 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPSingleDirectiveClass");
2575 return nullptr;
2576 case Stmt::OMPTargetDataDirectiveClass:
2577 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDataDirectiveClass");
2578 return nullptr;
2579 case Stmt::OMPTargetDirectiveClass:
2580 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetDirectiveClass");
2581 return nullptr;
2582 case Stmt::OMPTargetEnterDataDirectiveClass:
2583 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetEnterDataDirectiveClass");
2584 return nullptr;
2585 case Stmt::OMPTargetExitDataDirectiveClass:
2586 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetExitDataDirectiveClass");
2587 return nullptr;
2588 case Stmt::OMPTargetParallelDirectiveClass:
2589 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelDirectiveClass");
2590 return nullptr;
2591 case Stmt::OMPTargetParallelForDirectiveClass:
2592 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetParallelForDirectiveClass");
2593 return nullptr;
2594 case Stmt::OMPTargetTeamsDirectiveClass:
2595 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetTeamsDirectiveClass");
2596 return nullptr;
2597 case Stmt::OMPTargetUpdateDirectiveClass:
2598 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTargetUpdateDirectiveClass");
2599 return nullptr;
2600 case Stmt::OMPTaskDirectiveClass:
2601 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskDirectiveClass");
2602 return nullptr;
2603 case Stmt::OMPTaskgroupDirectiveClass:
2604 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskgroupDirectiveClass");
2605 return nullptr;
2606 case Stmt::OMPTaskwaitDirectiveClass:
2607 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskwaitDirectiveClass");
2608 return nullptr;
2609 case Stmt::OMPTaskyieldDirectiveClass:
2610 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTaskyieldDirectiveClass");
2611 return nullptr;
2612 case Stmt::OMPTeamsDirectiveClass:
2613 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPTeamsDirectiveClass");
2614 return nullptr;
2615 case Stmt::ObjCAtCatchStmtClass:
2616 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtCatchStmtClass");
2617 return nullptr;
2618 case Stmt::ObjCAtFinallyStmtClass:
2619 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtFinallyStmtClass");
2620 return nullptr;
2621 case Stmt::ObjCAtSynchronizedStmtClass:
2622 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtSynchronizedStmtClass");
2623 return nullptr;
2624 case Stmt::ObjCAtThrowStmtClass:
2625 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtThrowStmtClass");
2626 return nullptr;
2627 case Stmt::ObjCAtTryStmtClass:
2628 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAtTryStmtClass");
2629 return nullptr;
2630 case Stmt::ObjCAutoreleasePoolStmtClass:
2631 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCAutoreleasePoolStmtClass");
2632 return nullptr;
2633 case Stmt::ObjCForCollectionStmtClass:
2634 emit_warning(c, stmt->getLocStart(), "TODO handle C ObjCForCollectionStmtClass");
2635 return nullptr;
2636 case Stmt::SEHExceptStmtClass:
2637 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHExceptStmtClass");
2638 return nullptr;
2639 case Stmt::SEHFinallyStmtClass:
2640 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHFinallyStmtClass");
2641 return nullptr;
2642 case Stmt::SEHLeaveStmtClass:
2643 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHLeaveStmtClass");
2644 return nullptr;
2645 case Stmt::SEHTryStmtClass:
2646 emit_warning(c, stmt->getLocStart(), "TODO handle C SEHTryStmtClass");
2647 return nullptr;
2648 }
2649 zig_unreachable();
2650}
2651
2652static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
2653 Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
2654
2655 if (get_global(c, fn_name)) {
2656 // we already saw this function
2657 return;
2658 }
2659
2660 AstNode *proto_node = trans_qual_type(c, fn_decl->getType(), fn_decl->getLocation());
2661 if (proto_node == nullptr) {
2662 emit_warning(c, fn_decl->getLocation(), "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
2663 return;
2664 }
2665
2666 proto_node->data.fn_proto.name = fn_name;
2667 proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
2668
2669 StorageClass sc = fn_decl->getStorageClass();
2670 if (sc == SC_None) {
2671 proto_node->data.fn_proto.visib_mod = fn_decl->hasBody() ? c->export_visib_mod : c->visib_mod;
2672 } else if (sc == SC_Extern || sc == SC_Static) {
2673 proto_node->data.fn_proto.visib_mod = c->visib_mod;
2674 } else if (sc == SC_PrivateExtern) {
2675 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
2676 return;
2677 } else {
2678 emit_warning(c, fn_decl->getLocation(), "unsupported storage class: unknown");
2679 return;
2680 }
2681
2682 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
2683 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
2684 const ParmVarDecl *param = fn_decl->getParamDecl(i);
2685 const char *name = decl_name(param);
2686 Buf *proto_param_name;
2687 if (strlen(name) != 0) {
2688 proto_param_name = buf_create_from_str(name);
2689 } else {
2690 proto_param_name = param_node->data.param_decl.name;
2691 if (proto_param_name == nullptr) {
2692 proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
2693 }
2694 }
2695 param_node->data.param_decl.name = proto_param_name;
2696 }
2697
2698 if (!fn_decl->hasBody()) {
2699 // just a prototype
2700 add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);
2701 return;
2702 }
2703
2704 // actual function definition with body
2705 c->ptr_params.clear();
2706 Stmt *body = fn_decl->getBody();
2707 AstNode *actual_body_node = trans_stmt(c, false, nullptr, body, TransRValue);
2708 assert(actual_body_node != skip_add_to_block_node);
2709 if (actual_body_node == nullptr) {
2710 emit_warning(c, fn_decl->getLocation(), "unable to translate function");
2711 return;
2712 }
2713
2714 // it worked
2715
2716 assert(actual_body_node->type == NodeTypeBlock);
2717 AstNode *body_node_with_param_inits = trans_create_node(c, NodeTypeBlock);
2718
2719 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
2720 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
2721 Buf *good_name = param_node->data.param_decl.name;
2722
2723 if (c->ptr_params.maybe_get(good_name) != nullptr) {
2724 // TODO: avoid name collisions
2725 Buf *mangled_name = buf_sprintf("_arg_%s", buf_ptr(good_name));
2726 param_node->data.param_decl.name = mangled_name;
2727
2728 // var c_name = _mangled_name;
2729 AstNode *parameter_init = trans_create_node_var_decl_local(c, false, good_name, nullptr, trans_create_node_symbol(c, mangled_name));
2730
2731 body_node_with_param_inits->data.block.statements.append(parameter_init);
2732 }
2733 }
2734
2735 for (size_t i = 0; i < actual_body_node->data.block.statements.length; i += 1) {
2736 body_node_with_param_inits->data.block.statements.append(actual_body_node->data.block.statements.at(i));
2737 }
2738
2739 AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef);
2740 fn_def_node->data.fn_def.fn_proto = proto_node;
2741 fn_def_node->data.fn_def.body = body_node_with_param_inits;
2742
2743 proto_node->data.fn_proto.fn_def_node = fn_def_node;
2744 add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
2745}
2746
2747static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {
2748 AstNode *node = trans_create_node_symbol_str(c, primitive_name);
2749 c->decl_table.put(typedef_decl, node);
2750 return node;
2751}
2752
2753static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
2754 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
2755 if (existing_entry) {
2756 return existing_entry->value;
2757 }
2758 QualType child_qt = typedef_decl->getUnderlyingType();
2759 Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
2760
2761 if (buf_eql_str(type_name, "uint8_t")) {
2762 return resolve_typdef_as_builtin(c, typedef_decl, "u8");
2763 } else if (buf_eql_str(type_name, "int8_t")) {
2764 return resolve_typdef_as_builtin(c, typedef_decl, "i8");
2765 } else if (buf_eql_str(type_name, "uint16_t")) {
2766 return resolve_typdef_as_builtin(c, typedef_decl, "u16");
2767 } else if (buf_eql_str(type_name, "int16_t")) {
2768 return resolve_typdef_as_builtin(c, typedef_decl, "i16");
2769 } else if (buf_eql_str(type_name, "uint32_t")) {
2770 return resolve_typdef_as_builtin(c, typedef_decl, "u32");
2771 } else if (buf_eql_str(type_name, "int32_t")) {
2772 return resolve_typdef_as_builtin(c, typedef_decl, "i32");
2773 } else if (buf_eql_str(type_name, "uint64_t")) {
2774 return resolve_typdef_as_builtin(c, typedef_decl, "u64");
2775 } else if (buf_eql_str(type_name, "int64_t")) {
2776 return resolve_typdef_as_builtin(c, typedef_decl, "i64");
2777 } else if (buf_eql_str(type_name, "intptr_t")) {
2778 return resolve_typdef_as_builtin(c, typedef_decl, "isize");
2779 } else if (buf_eql_str(type_name, "uintptr_t")) {
2780 return resolve_typdef_as_builtin(c, typedef_decl, "usize");
2781 } else if (buf_eql_str(type_name, "ssize_t")) {
2782 return resolve_typdef_as_builtin(c, typedef_decl, "isize");
2783 } else if (buf_eql_str(type_name, "size_t")) {
2784 return resolve_typdef_as_builtin(c, typedef_decl, "usize");
2785 }
2786
2787 // if the underlying type is anonymous, we can special case it to just
2788 // use the name of this typedef
2789 // TODO
2790
2791 AstNode *type_node = trans_qual_type(c, child_qt, typedef_decl->getLocation());
2792 if (type_node == nullptr) {
2793 emit_warning(c, typedef_decl->getLocation(), "typedef %s - unresolved child type", buf_ptr(type_name));
2794 c->decl_table.put(typedef_decl, nullptr);
2795 return nullptr;
2796 }
2797 add_global_var(c, type_name, type_node);
2798
2799 AstNode *symbol_node = trans_create_node_symbol(c, type_name);
2800 c->decl_table.put(typedef_decl->getCanonicalDecl(), symbol_node);
2801 return symbol_node;
2802}
2803
2804struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
2805 Buf *full_type_name, Buf *bare_name)
2806{
2807 AstNode *opaque_node = trans_create_node_opaque(c);
2808 if (full_type_name == nullptr) {
2809 c->decl_table.put(enum_decl->getCanonicalDecl(), opaque_node);
2810 return opaque_node;
2811 }
2812 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2813 add_global_weak_alias(c, bare_name, full_type_name);
2814 add_global_var(c, full_type_name, opaque_node);
2815 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
2816 return symbol_node;
2817}
2818
2819static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
2820 auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
2821 if (existing_entry) {
2822 return existing_entry->value;
2823 }
2824
2825 const char *raw_name = decl_name(enum_decl);
2826 bool is_anonymous = (raw_name[0] == 0);
2827 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
2828 Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
2829
2830 const EnumDecl *enum_def = enum_decl->getDefinition();
2831 if (!enum_def) {
2832 return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
2833 }
2834
2835 bool pure_enum = true;
2836 uint32_t field_count = 0;
2837 for (auto it = enum_def->enumerator_begin(),
2838 it_end = enum_def->enumerator_end();
2839 it != it_end; ++it, field_count += 1)
2840 {
2841 const EnumConstantDecl *enum_const = *it;
2842 if (enum_const->getInitExpr()) {
2843 pure_enum = false;
2844 }
2845 }
2846
2847 AstNode *tag_int_type = trans_qual_type(c, enum_decl->getIntegerType(), enum_decl->getLocation());
2848 assert(tag_int_type);
2849
2850 if (pure_enum) {
2851 AstNode *enum_node = trans_create_node(c, NodeTypeContainerDecl);
2852 enum_node->data.container_decl.kind = ContainerKindEnum;
2853 enum_node->data.container_decl.layout = ContainerLayoutExtern;
2854 enum_node->data.container_decl.init_arg_expr = tag_int_type;
2855
2856 enum_node->data.container_decl.fields.resize(field_count);
2857 uint32_t i = 0;
2858 for (auto it = enum_def->enumerator_begin(),
2859 it_end = enum_def->enumerator_end();
2860 it != it_end; ++it, i += 1)
2861 {
2862 const EnumConstantDecl *enum_const = *it;
2863
2864 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
2865 Buf *field_name;
2866 if (bare_name != nullptr && buf_starts_with_buf(enum_val_name, bare_name)) {
2867 field_name = buf_slice(enum_val_name, buf_len(bare_name), buf_len(enum_val_name));
2868 } else {
2869 field_name = enum_val_name;
2870 }
2871
2872 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
2873 field_node->data.struct_field.name = field_name;
2874 field_node->data.struct_field.type = nullptr;
2875 enum_node->data.container_decl.fields.items[i] = field_node;
2876
2877 // in C each enum value is in the global namespace. so we put them there too.
2878 // at this point we can rely on the enum emitting successfully
2879 if (is_anonymous) {
2880 AstNode *lit_node = trans_create_node_unsigned(c, i);
2881 add_global_var(c, enum_val_name, lit_node);
2882 } else {
2883 AstNode *field_access_node = trans_create_node_field_access(c,
2884 trans_create_node_symbol(c, full_type_name), field_name);
2885 add_global_var(c, enum_val_name, field_access_node);
2886 }
2887 }
2888
2889 if (is_anonymous) {
2890 c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node);
2891 return enum_node;
2892 } else {
2893 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2894 add_global_weak_alias(c, bare_name, full_type_name);
2895 add_global_var(c, full_type_name, enum_node);
2896 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
2897 return enum_node;
2898 }
2899 }
2900
2901 // TODO after issue #305 is solved, make this be an enum with tag_int_type
2902 // as the integer type and set the custom enum values
2903 AstNode *enum_node = tag_int_type;
2904
2905
2906 // add variables for all the values with enum_node
2907 for (auto it = enum_def->enumerator_begin(),
2908 it_end = enum_def->enumerator_end();
2909 it != it_end; ++it)
2910 {
2911 const EnumConstantDecl *enum_const = *it;
2912
2913 Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
2914 AstNode *int_node = trans_create_node_apint(c, enum_const->getInitVal());
2915 AstNode *var_node = add_global_var(c, enum_val_name, int_node);
2916 var_node->data.variable_declaration.type = tag_int_type;
2917 }
2918
2919 if (is_anonymous) {
2920 c->decl_table.put(enum_decl->getCanonicalDecl(), enum_node);
2921 return enum_node;
2922 } else {
2923 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2924 add_global_weak_alias(c, bare_name, full_type_name);
2925 add_global_var(c, full_type_name, enum_node);
2926 c->decl_table.put(enum_decl->getCanonicalDecl(), symbol_node);
2927 return symbol_node;
2928 }
2929}
2930
2931static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl,
2932 Buf *full_type_name, Buf *bare_name)
2933{
2934 AstNode *opaque_node = trans_create_node_opaque(c);
2935 if (full_type_name == nullptr) {
2936 c->decl_table.put(record_decl->getCanonicalDecl(), opaque_node);
2937 return opaque_node;
2938 }
2939 AstNode *symbol_node = trans_create_node_symbol(c, full_type_name);
2940 add_global_weak_alias(c, bare_name, full_type_name);
2941 add_global_var(c, full_type_name, opaque_node);
2942 c->decl_table.put(record_decl->getCanonicalDecl(), symbol_node);
2943 return symbol_node;
2944}
2945
2946static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
2947 auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
2948 if (existing_entry) {
2949 return existing_entry->value;
2950 }
2951
2952 const char *raw_name = decl_name(record_decl);
2953
2954 const char *container_kind_name;
2955 ContainerKind container_kind;
2956 if (record_decl->isUnion()) {
2957 container_kind_name = "union";
2958 container_kind = ContainerKindUnion;
2959 } else if (record_decl->isStruct()) {
2960 container_kind_name = "struct";
2961 container_kind = ContainerKindStruct;
2962 } else {
2963 emit_warning(c, record_decl->getLocation(), "skipping record %s, not a struct or union", raw_name);
2964 c->decl_table.put(record_decl->getCanonicalDecl(), nullptr);
2965 return nullptr;
2966 }
2967
2968 bool is_anonymous = record_decl->isAnonymousStructOrUnion() || raw_name[0] == 0;
2969 Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
2970 Buf *full_type_name = (bare_name == nullptr) ?
2971 nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
2972
2973 RecordDecl *record_def = record_decl->getDefinition();
2974 if (record_def == nullptr) {
2975 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
2976 }
2977
2978 // count fields and validate
2979 uint32_t field_count = 0;
2980 for (auto it = record_def->field_begin(),
2981 it_end = record_def->field_end();
2982 it != it_end; ++it, field_count += 1)
2983 {
2984 const FieldDecl *field_decl = *it;
2985
2986 if (field_decl->isBitField()) {
2987 emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",
2988 container_kind_name,
2989 is_anonymous ? "(anon)" : buf_ptr(bare_name));
2990 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
2991 }
2992 }
2993
2994 AstNode *struct_node = trans_create_node(c, NodeTypeContainerDecl);
2995 struct_node->data.container_decl.kind = container_kind;
2996 struct_node->data.container_decl.layout = ContainerLayoutExtern;
2997
2998 // TODO handle attribute packed
2999
3000 struct_node->data.container_decl.fields.resize(field_count);
3001
3002 // must be before fields in case a circular reference happens
3003 if (is_anonymous) {
3004 c->decl_table.put(record_decl->getCanonicalDecl(), struct_node);
3005 } else {
3006 c->decl_table.put(record_decl->getCanonicalDecl(), trans_create_node_symbol(c, full_type_name));
3007 }
3008
3009 uint32_t i = 0;
3010 for (auto it = record_def->field_begin(),
3011 it_end = record_def->field_end();
3012 it != it_end; ++it, i += 1)
3013 {
3014 const FieldDecl *field_decl = *it;
3015
3016 AstNode *field_node = trans_create_node(c, NodeTypeStructField);
3017 field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));
3018 field_node->data.struct_field.type = trans_qual_type(c, field_decl->getType(), field_decl->getLocation());
3019
3020 if (field_node->data.struct_field.type == nullptr) {
3021 emit_warning(c, field_decl->getLocation(),
3022 "%s %s demoted to opaque type - unresolved type",
3023 container_kind_name,
3024 is_anonymous ? "(anon)" : buf_ptr(bare_name));
3025
3026 return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
3027 }
3028
3029 struct_node->data.container_decl.fields.items[i] = field_node;
3030 }
3031
3032 if (is_anonymous) {
3033 return struct_node;
3034 } else {
3035 add_global_weak_alias(c, bare_name, full_type_name);
3036 add_global_var(c, full_type_name, struct_node);
3037 return trans_create_node_symbol(c, full_type_name);
3038 }
3039}
3040
3041static void visit_var_decl(Context *c, const VarDecl *var_decl) {
3042 Buf *name = buf_create_from_str(decl_name(var_decl));
3043
3044 switch (var_decl->getTLSKind()) {
3045 case VarDecl::TLS_None:
3046 break;
3047 case VarDecl::TLS_Static:
3048 emit_warning(c, var_decl->getLocation(),
3049 "ignoring variable '%s' - static thread local storage", buf_ptr(name));
3050 return;
3051 case VarDecl::TLS_Dynamic:
3052 emit_warning(c, var_decl->getLocation(),
3053 "ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
3054 return;
3055 }
3056
3057 QualType qt = var_decl->getType();
3058 AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
3059 if (var_type == nullptr) {
3060 emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));
3061 return;
3062 }
3063
3064 bool is_extern = var_decl->hasExternalStorage();
3065 bool is_static = var_decl->isFileVarDecl();
3066 bool is_const = qt.isConstQualified();
3067
3068 if (is_static && !is_extern) {
3069 AstNode *init_node;
3070 if (var_decl->hasInit()) {
3071 APValue *ap_value = var_decl->evaluateValue();
3072 if (ap_value == nullptr) {
3073 emit_warning(c, var_decl->getLocation(),
3074 "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
3075 return;
3076 }
3077 switch (ap_value->getKind()) {
3078 case APValue::Int:
3079 init_node = trans_create_node_apint(c, ap_value->getInt());
3080 break;
3081 case APValue::Uninitialized:
3082 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
3083 break;
3084 case APValue::Float:
3085 case APValue::ComplexInt:
3086 case APValue::ComplexFloat:
3087 case APValue::LValue:
3088 case APValue::Vector:
3089 case APValue::Array:
3090 case APValue::Struct:
3091 case APValue::Union:
3092 case APValue::MemberPointer:
3093 case APValue::AddrLabelDiff:
3094 emit_warning(c, var_decl->getLocation(),
3095 "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name));
3096 return;
3097 }
3098 } else {
3099 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
3100 }
3101
3102 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, init_node);
3103 add_top_level_decl(c, name, var_node);
3104 return;
3105 }
3106
3107 if (is_extern) {
3108 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, nullptr);
3109 var_node->data.variable_declaration.is_extern = true;
3110 add_top_level_decl(c, name, var_node);
3111 return;
3112 }
3113
3114 emit_warning(c, var_decl->getLocation(),
3115 "ignoring variable '%s' - non-extern, non-static variable", buf_ptr(name));
3116 return;
3117}
3118
3119static bool decl_visitor(void *context, const Decl *decl) {
3120 Context *c = (Context*)context;
3121
3122 switch (decl->getKind()) {
3123 case Decl::Function:
3124 visit_fn_decl(c, static_cast<const FunctionDecl*>(decl));
3125 break;
3126 case Decl::Typedef:
3127 resolve_typedef_decl(c, static_cast<const TypedefNameDecl *>(decl));
3128 break;
3129 case Decl::Enum:
3130 resolve_enum_decl(c, static_cast<const EnumDecl *>(decl));
3131 break;
3132 case Decl::Record:
3133 resolve_record_decl(c, static_cast<const RecordDecl *>(decl));
3134 break;
3135 case Decl::Var:
3136 visit_var_decl(c, static_cast<const VarDecl *>(decl));
3137 break;
3138 default:
3139 emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());
3140 }
3141
3142 return true;
3143}
3144
3145static bool name_exists(Context *c, Buf *name) {
3146 return get_global(c, name) != nullptr;
3147}
3148
3149static void render_aliases(Context *c) {
3150 for (size_t i = 0; i < c->aliases.length; i += 1) {
3151 Alias *alias = &c->aliases.at(i);
3152 if (name_exists(c, alias->new_name))
3153 continue;
3154
3155 add_global_var(c, alias->new_name, trans_create_node_symbol(c, alias->canon_name));
3156 }
3157}
3158
3159static void render_macros(Context *c) {
3160 auto it = c->macro_table.entry_iterator();
3161 for (;;) {
3162 auto *entry = it.next();
3163 if (!entry)
3164 break;
3165
3166 AstNode *value_node = entry->value;
3167 if (value_node->type == NodeTypeFnDef) {
3168 add_top_level_decl(c, value_node->data.fn_def.fn_proto->data.fn_proto.name, value_node);
3169 } else {
3170 add_global_var(c, entry->key, value_node);
3171 }
3172 }
3173}
3174
3175static AstNode *parse_ctok_num_lit(Context *c, CTokenize *ctok, size_t *tok_i, bool negate) {
3176 CTok *tok = &ctok->tokens.at(*tok_i);
3177 if (tok->id == CTokIdNumLitInt) {
3178 *tok_i += 1;
3179 switch (tok->data.num_lit_int.suffix) {
3180 case CNumLitSuffixNone:
3181 return trans_create_node_unsigned_negative(c, tok->data.num_lit_int.x, negate);
3182 case CNumLitSuffixL:
3183 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_long");
3184 case CNumLitSuffixU:
3185 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_uint");
3186 case CNumLitSuffixLU:
3187 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulong");
3188 case CNumLitSuffixLL:
3189 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_longlong");
3190 case CNumLitSuffixLLU:
3191 return trans_create_node_unsigned_negative_type(c, tok->data.num_lit_int.x, negate, "c_ulonglong");
3192 }
3193 zig_unreachable();
3194 } else if (tok->id == CTokIdNumLitFloat) {
3195 *tok_i += 1;
3196 double value = negate ? -tok->data.num_lit_float : tok->data.num_lit_float;
3197 return trans_create_node_float_lit(c, value);
3198 }
3199 return nullptr;
3200}
3201
3202static AstNode *parse_ctok(Context *c, CTokenize *ctok, size_t *tok_i) {
3203 CTok *tok = &ctok->tokens.at(*tok_i);
3204 switch (tok->id) {
3205 case CTokIdCharLit:
3206 *tok_i += 1;
3207 return trans_create_node_unsigned(c, tok->data.char_lit);
3208 case CTokIdStrLit:
3209 *tok_i += 1;
3210 return trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));
3211 case CTokIdMinus:
3212 *tok_i += 1;
3213 return parse_ctok_num_lit(c, ctok, tok_i, true);
3214 case CTokIdNumLitInt:
3215 case CTokIdNumLitFloat:
3216 return parse_ctok_num_lit(c, ctok, tok_i, false);
3217 case CTokIdSymbol:
3218 {
3219 *tok_i += 1;
3220 Buf *symbol_name = buf_create_from_buf(&tok->data.symbol);
3221 return trans_create_node_symbol(c, symbol_name);
3222 }
3223 case CTokIdLParen:
3224 {
3225 *tok_i += 1;
3226 AstNode *inner_node = parse_ctok(c, ctok, tok_i);
3227
3228 CTok *next_tok = &ctok->tokens.at(*tok_i);
3229 if (next_tok->id != CTokIdRParen) {
3230 return nullptr;
3231 }
3232 *tok_i += 1;
3233 return inner_node;
3234 }
3235 case CTokIdEOF:
3236 case CTokIdRParen:
3237 // not able to make sense of this
3238 return nullptr;
3239 }
3240 zig_unreachable();
3241}
3242
3243static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *char_ptr) {
3244 tokenize_c_macro(ctok, (const uint8_t *)char_ptr);
3245
3246 if (ctok->error) {
3247 return;
3248 }
3249
3250 size_t tok_i = 0;
3251 CTok *name_tok = &ctok->tokens.at(tok_i);
3252 assert(name_tok->id == CTokIdSymbol && buf_eql_buf(&name_tok->data.symbol, name));
3253 tok_i += 1;
3254
3255 AstNode *result_node = parse_ctok(c, ctok, &tok_i);
3256 if (result_node == nullptr) {
3257 return;
3258 }
3259 CTok *eof_tok = &ctok->tokens.at(tok_i);
3260 if (eof_tok->id != CTokIdEOF) {
3261 return;
3262 }
3263 if (result_node->type == NodeTypeSymbol) {
3264 // if it equals itself, ignore. for example, from stdio.h:
3265 // #define stdin stdin
3266 Buf *symbol_name = result_node->data.symbol_expr.symbol;
3267 if (buf_eql_buf(name, symbol_name)) {
3268 return;
3269 }
3270 c->macro_symbols.append({name, symbol_name});
3271 } else {
3272 c->macro_table.put(name, result_node);
3273 }
3274}
3275
3276static void process_symbol_macros(Context *c) {
3277 for (size_t i = 0; i < c->macro_symbols.length; i += 1) {
3278 MacroSymbol ms = c->macro_symbols.at(i);
3279
3280 // Check if this macro aliases another top level declaration
3281 AstNode *existing_node = get_global(c, ms.value);
3282 if (!existing_node || name_exists(c, ms.name))
3283 continue;
3284
3285 // If a macro aliases a global variable which is a function pointer, we conclude that
3286 // the macro is intended to represent a function that assumes the function pointer
3287 // variable is non-null and calls it.
3288 if (existing_node->type == NodeTypeVariableDeclaration) {
3289 AstNode *var_type = existing_node->data.variable_declaration.type;
3290 if (var_type != nullptr && var_type->type == NodeTypePrefixOpExpr &&
3291 var_type->data.prefix_op_expr.prefix_op == PrefixOpMaybe)
3292 {
3293 AstNode *fn_proto_node = var_type->data.prefix_op_expr.primary_expr;
3294 if (fn_proto_node->type == NodeTypeFnProto) {
3295 AstNode *inline_fn_node = trans_create_node_inline_fn(c, ms.name, ms.value, fn_proto_node);
3296 c->macro_table.put(ms.name, inline_fn_node);
3297 continue;
3298 }
3299 }
3300 }
3301
3302 add_global_var(c, ms.name, trans_create_node_symbol(c, ms.value));
3303 }
3304}
3305
3306static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
3307 CTokenize ctok = {{0}};
3308
3309 // TODO if we see #undef, delete it from the table
3310
3311 for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {
3312 switch (entity->getKind()) {
3313 case PreprocessedEntity::InvalidKind:
3314 case PreprocessedEntity::InclusionDirectiveKind:
3315 case PreprocessedEntity::MacroExpansionKind:
3316 continue;
3317 case PreprocessedEntity::MacroDefinitionKind:
3318 {
3319 MacroDefinitionRecord *macro = static_cast<MacroDefinitionRecord *>(entity);
3320 const char *raw_name = macro->getName()->getNameStart();
3321 SourceRange range = macro->getSourceRange();
3322 SourceLocation begin_loc = range.getBegin();
3323 SourceLocation end_loc = range.getEnd();
3324
3325 if (begin_loc == end_loc) {
3326 // this means it is a macro without a value
3327 // we don't care about such things
3328 continue;
3329 }
3330 Buf *name = buf_create_from_str(raw_name);
3331 if (name_exists(c, name)) {
3332 continue;
3333 }
3334
3335 const char *begin_c = c->source_manager->getCharacterData(begin_loc);
3336 process_macro(c, &ctok, name, begin_c);
3337 }
3338 }
3339 }
3340}
3341
3342int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
3343 CodeGen *codegen, AstNode *source_node)
3344{
3345 int err;
3346 Buf tmp_file_path = BUF_INIT;
3347 if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {
3348 return err;
3349 }
3350
3351 err = parse_h_file(import, errors, buf_ptr(&tmp_file_path), codegen, source_node);
3352
3353 os_delete_file(&tmp_file_path);
3354
3355 return err;
3356}
3357
3358int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
3359 CodeGen *codegen, AstNode *source_node)
3360{
3361 Context context = {0};
3362 Context *c = &context;
3363 c->warnings_on = codegen->verbose_cimport;
3364 c->import = import;
3365 c->errors = errors;
3366 if (buf_ends_with_str(buf_create_from_str(target_file), ".h")) {
3367 c->visib_mod = VisibModPub;
3368 c->export_visib_mod = VisibModPub;
3369 } else {
3370 c->visib_mod = VisibModPub;
3371 c->export_visib_mod = VisibModExport;
3372 }
3373 c->decl_table.init(8);
3374 c->macro_table.init(8);
3375 c->global_table.init(8);
3376 c->ptr_params.init(8);
3377 c->codegen = codegen;
3378 c->source_node = source_node;
3379
3380 ZigList<const char *> clang_argv = {0};
3381
3382 clang_argv.append("-x");
3383 clang_argv.append("c");
3384
3385 if (c->codegen->is_native_target) {
3386 char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
3387 if (ZIG_PARSEC_CFLAGS) {
3388 Buf tmp_buf = BUF_INIT;
3389 char *start = ZIG_PARSEC_CFLAGS;
3390 char *space = strstr(start, " ");
3391 while (space) {
3392 if (space - start > 0) {
3393 buf_init_from_mem(&tmp_buf, start, space - start);
3394 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
3395 }
3396 start = space + 1;
3397 space = strstr(start, " ");
3398 }
3399 buf_init_from_str(&tmp_buf, start);
3400 clang_argv.append(buf_ptr(buf_create_from_buf(&tmp_buf)));
3401 }
3402 }
3403
3404 clang_argv.append("-isystem");
3405 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
3406
3407 clang_argv.append("-isystem");
3408 clang_argv.append(buf_ptr(codegen->libc_include_dir));
3409
3410 // windows c runtime requires -D_DEBUG if using debug libraries
3411 if (codegen->build_mode == BuildModeDebug) {
3412 clang_argv.append("-D_DEBUG");
3413 }
3414
3415 for (size_t i = 0; i < codegen->clang_argv_len; i += 1) {
3416 clang_argv.append(codegen->clang_argv[i]);
3417 }
3418
3419 // we don't need spell checking and it slows things down
3420 clang_argv.append("-fno-spell-checking");
3421
3422 // this gives us access to preprocessing entities, presumably at
3423 // the cost of performance
3424 clang_argv.append("-Xclang");
3425 clang_argv.append("-detailed-preprocessing-record");
3426
3427 if (!c->codegen->is_native_target) {
3428 clang_argv.append("-target");
3429 clang_argv.append(buf_ptr(&c->codegen->triple_str));
3430 }
3431
3432 clang_argv.append(target_file);
3433
3434 // to make the [start...end] argument work
3435 clang_argv.append(nullptr);
3436
3437 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
3438
3439 std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>();
3440
3441 bool skip_function_bodies = false;
3442 bool only_local_decls = true;
3443 bool capture_diagnostics = true;
3444 bool user_files_are_volatile = true;
3445 bool allow_pch_with_compiler_errors = false;
3446 bool single_file_parse = false;
3447 bool for_serialization = false;
3448 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
3449 std::unique_ptr<ASTUnit> err_unit;
3450 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
3451 &clang_argv.at(0), &clang_argv.last(),
3452 pch_container_ops, diags, resources_path,
3453 only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,
3454 false, false, allow_pch_with_compiler_errors, skip_function_bodies,
3455 single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,
3456 nullptr));
3457
3458 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
3459 if (!ast_unit && !err_unit) {
3460 return ErrorFileSystem;
3461 }
3462
3463 if (diags->getClient()->getNumErrors() > 0) {
3464 if (ast_unit) {
3465 err_unit = std::move(ast_unit);
3466 }
3467
3468 for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
3469 it_end = err_unit->stored_diag_end();
3470 it != it_end; ++it)
3471 {
3472 switch (it->getLevel()) {
3473 case DiagnosticsEngine::Ignored:
3474 case DiagnosticsEngine::Note:
3475 case DiagnosticsEngine::Remark:
3476 case DiagnosticsEngine::Warning:
3477 continue;
3478 case DiagnosticsEngine::Error:
3479 case DiagnosticsEngine::Fatal:
3480 break;
3481 }
3482 StringRef msg_str_ref = it->getMessage();
3483 Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin());
3484 FullSourceLoc fsl = it->getLocation();
3485 if (fsl.hasManager()) {
3486 FileID file_id = fsl.getFileID();
3487 StringRef filename = fsl.getManager().getFilename(fsl);
3488 unsigned line = fsl.getSpellingLineNumber() - 1;
3489 unsigned column = fsl.getSpellingColumnNumber() - 1;
3490 unsigned offset = fsl.getManager().getFileOffset(fsl);
3491 const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
3492 Buf *path;
3493 if (filename.empty()) {
3494 path = buf_alloc();
3495 } else {
3496 path = buf_create_from_mem((const char *)filename.bytes_begin(), filename.size());
3497 }
3498
3499 ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
3500
3501 c->errors->append(err_msg);
3502 } else {
3503 // NOTE the only known way this gets triggered right now is if you have a lot of errors
3504 // clang emits "too many errors emitted, stopping now"
3505 fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg));
3506 }
3507 }
3508
3509 return 0;
3510 }
3511
3512 c->ctx = &ast_unit->getASTContext();
3513 c->source_manager = &ast_unit->getSourceManager();
3514 c->root = trans_create_node(c, NodeTypeRoot);
3515
3516 ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
3517
3518 process_preprocessor_entities(c, *ast_unit);
3519
3520 process_symbol_macros(c);
3521 render_macros(c);
3522 render_aliases(c);
3523
3524 import->root = c->root;
3525
3526 return 0;
3527}
src/translate_c.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
14int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const char *target_file,
15 CodeGen *codegen, AstNode *source_node);
16
17int parse_h_buf(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, Buf *source,
18 CodeGen *codegen, AstNode *source_node);
19
20#endif
test/parsec.zig deleted-899
...@@ -1,899 +0,0 @@
1const tests = @import("tests.zig");
2
3pub 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.addC("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 hex",
289 \\#define FOO "aoeu\xab derp"
290 \\#define FOO2 "aoeu\x0007a derp"
291 \\#define FOO_CHAR '\xfF'
292 ,
293 \\pub const FOO = c"aoeu\xab derp";
294 ,
295 \\pub const FOO2 = c"aoeuz derp";
296 ,
297 \\pub const FOO_CHAR = 255;
298 );
299
300 cases.add("macro defines string literal with octal",
301 \\#define FOO "aoeu\023 derp"
302 \\#define FOO2 "aoeu\0234 derp"
303 \\#define FOO_CHAR '\077'
304 ,
305 \\pub const FOO = c"aoeu\x13 derp";
306 ,
307 \\pub const FOO2 = c"aoeu\x134 derp";
308 ,
309 \\pub const FOO_CHAR = 63;
310 );
311
312 cases.add("macro with parens around negative number",
313 \\#define LUA_GLOBALSINDEX (-10002)
314 ,
315 \\pub const LUA_GLOBALSINDEX = -10002;
316 );
317
318 cases.addC("post increment",
319 \\unsigned foo1(unsigned a) {
320 \\ a++;
321 \\ return a;
322 \\}
323 \\int foo2(int a) {
324 \\ a++;
325 \\ return a;
326 \\}
327 ,
328 \\export fn foo1(_arg_a: c_uint) -> c_uint {
329 \\ var a = _arg_a;
330 \\ a +%= 1;
331 \\ return a;
332 \\}
333 \\export fn foo2(_arg_a: c_int) -> c_int {
334 \\ var a = _arg_a;
335 \\ a += 1;
336 \\ return a;
337 \\}
338 );
339
340 cases.addC("shift right assign",
341 \\int log2(unsigned a) {
342 \\ int i = 0;
343 \\ while (a > 0) {
344 \\ a >>= 1;
345 \\ }
346 \\ return i;
347 \\}
348 ,
349 \\export fn log2(_arg_a: c_uint) -> c_int {
350 \\ var a = _arg_a;
351 \\ var i: c_int = 0;
352 \\ while (a > c_uint(0)) {
353 \\ a >>= @import("std").math.Log2Int(c_uint)(1);
354 \\ };
355 \\ return i;
356 \\}
357 );
358
359 cases.addC("if statement",
360 \\int max(int a, int b) {
361 \\ if (a < b)
362 \\ return b;
363 \\
364 \\ if (a < b)
365 \\ return b;
366 \\ else
367 \\ return a;
368 \\}
369 ,
370 \\export fn max(a: c_int, b: c_int) -> c_int {
371 \\ if (a < b) return b;
372 \\ if (a < b) return b else return a;
373 \\}
374 );
375
376 cases.addC("==, !=",
377 \\int max(int a, int b) {
378 \\ if (a == b)
379 \\ return a;
380 \\ if (a != b)
381 \\ return b;
382 \\ return a;
383 \\}
384 ,
385 \\export fn max(a: c_int, b: c_int) -> c_int {
386 \\ if (a == b) return a;
387 \\ if (a != b) return b;
388 \\ return a;
389 \\}
390 );
391
392 cases.addC("add, sub, mul, div, rem",
393 \\int s(int a, int b) {
394 \\ int c;
395 \\ c = a + b;
396 \\ c = a - b;
397 \\ c = a * b;
398 \\ c = a / b;
399 \\ c = a % b;
400 \\}
401 \\unsigned u(unsigned a, unsigned b) {
402 \\ unsigned c;
403 \\ c = a + b;
404 \\ c = a - b;
405 \\ c = a * b;
406 \\ c = a / b;
407 \\ c = a % b;
408 \\}
409 ,
410 \\export fn s(a: c_int, b: c_int) -> c_int {
411 \\ var c: c_int;
412 \\ c = (a + b);
413 \\ c = (a - b);
414 \\ c = (a * b);
415 \\ c = @divTrunc(a, b);
416 \\ c = @rem(a, b);
417 \\}
418 \\export fn u(a: c_uint, b: c_uint) -> c_uint {
419 \\ var c: c_uint;
420 \\ c = (a +% b);
421 \\ c = (a -% b);
422 \\ c = (a *% b);
423 \\ c = (a / b);
424 \\ c = (a % b);
425 \\}
426 );
427
428 cases.addC("bitwise binary operators",
429 \\int max(int a, int b) {
430 \\ return (a & b) ^ (a | b);
431 \\}
432 ,
433 \\export fn max(a: c_int, b: c_int) -> c_int {
434 \\ return (a & b) ^ (a | b);
435 \\}
436 );
437
438 cases.addC("logical and, logical or",
439 \\int max(int a, int b) {
440 \\ if (a < b || a == b)
441 \\ return b;
442 \\ if (a >= b && a == b)
443 \\ return a;
444 \\ return a;
445 \\}
446 ,
447 \\export fn max(a: c_int, b: c_int) -> c_int {
448 \\ if ((a < b) or (a == b)) return b;
449 \\ if ((a >= b) and (a == b)) return a;
450 \\ return a;
451 \\}
452 );
453
454 cases.addC("assign",
455 \\int max(int a) {
456 \\ int tmp;
457 \\ tmp = a;
458 \\ a = tmp;
459 \\}
460 ,
461 \\export fn max(_arg_a: c_int) -> c_int {
462 \\ var a = _arg_a;
463 \\ var tmp: c_int;
464 \\ tmp = a;
465 \\ a = tmp;
466 \\}
467 );
468
469 cases.addC("chaining assign",
470 \\void max(int a) {
471 \\ int b, c;
472 \\ c = b = a;
473 \\}
474 ,
475 \\export fn max(a: c_int) {
476 \\ var b: c_int;
477 \\ var c: c_int;
478 \\ c = {
479 \\ const _tmp = a;
480 \\ b = _tmp;
481 \\ _tmp
482 \\ };
483 \\}
484 );
485
486 cases.addC("shift right assign with a fixed size type",
487 \\#include <stdint.h>
488 \\int log2(uint32_t a) {
489 \\ int i = 0;
490 \\ while (a > 0) {
491 \\ a >>= 1;
492 \\ }
493 \\ return i;
494 \\}
495 ,
496 \\export fn log2(_arg_a: u32) -> c_int {
497 \\ var a = _arg_a;
498 \\ var i: c_int = 0;
499 \\ while (a > c_uint(0)) {
500 \\ a >>= u5(1);
501 \\ };
502 \\ return i;
503 \\}
504 );
505
506 cases.add("anonymous enum",
507 \\enum {
508 \\ One,
509 \\ Two,
510 \\};
511 ,
512 \\pub const One = 0;
513 \\pub const Two = 1;
514 );
515
516 cases.addC("function call",
517 \\static void bar(void) { }
518 \\void foo(void) { bar(); }
519 ,
520 \\pub fn bar() {}
521 \\export fn foo() {
522 \\ bar();
523 \\}
524 );
525
526 cases.addC("field access expression",
527 \\struct Foo {
528 \\ int field;
529 \\};
530 \\int read_field(struct Foo *foo) {
531 \\ return foo->field;
532 \\}
533 ,
534 \\pub const struct_Foo = extern struct {
535 \\ field: c_int,
536 \\};
537 \\export fn read_field(foo: ?&struct_Foo) -> c_int {
538 \\ return (??foo).field;
539 \\}
540 );
541
542 cases.addC("null statements",
543 \\void foo(void) {
544 \\ ;;;;;
545 \\}
546 ,
547 \\export fn foo() {}
548 );
549
550 cases.add("undefined array global",
551 \\int array[100];
552 ,
553 \\pub var array: [100]c_int = undefined;
554 );
555
556 cases.addC("array access",
557 \\int array[100];
558 \\int foo(int index) {
559 \\ return array[index];
560 \\}
561 ,
562 \\pub var array: [100]c_int = undefined;
563 \\export fn foo(index: c_int) -> c_int {
564 \\ return array[index];
565 \\}
566 );
567
568
569 cases.addC("c style cast",
570 \\int float_to_int(float a) {
571 \\ return (int)a;
572 \\}
573 ,
574 \\export fn float_to_int(a: f32) -> c_int {
575 \\ return c_int(a);
576 \\}
577 );
578
579 cases.addC("implicit cast to void *",
580 \\void *foo(unsigned short *x) {
581 \\ return x;
582 \\}
583 ,
584 \\export fn foo(x: ?&c_ushort) -> ?&c_void {
585 \\ return @ptrCast(?&c_void, x);
586 \\}
587 );
588
589 cases.addC("sizeof",
590 \\#include <stddef.h>
591 \\size_t size_of(void) {
592 \\ return sizeof(int);
593 \\}
594 ,
595 \\export fn size_of() -> usize {
596 \\ return @sizeOf(c_int);
597 \\}
598 );
599
600 cases.addC("null pointer implicit cast",
601 \\int* foo(void) {
602 \\ return 0;
603 \\}
604 ,
605 \\export fn foo() -> ?&c_int {
606 \\ return null;
607 \\}
608 );
609
610 cases.addC("comma operator",
611 \\int foo(void) {
612 \\ return 1, 2;
613 \\}
614 ,
615 \\export fn foo() -> c_int {
616 \\ return {
617 \\ _ = 1;
618 \\ 2
619 \\ };
620 \\}
621 );
622
623 cases.addC("bitshift",
624 \\int foo(void) {
625 \\ return (1 << 2) >> 1;
626 \\}
627 ,
628 \\export fn foo() -> c_int {
629 \\ return (1 << @import("std").math.Log2Int(c_int)(2)) >> @import("std").math.Log2Int(c_int)(1);
630 \\}
631 );
632
633 cases.addC("compound assignment operators",
634 \\void foo(void) {
635 \\ int a = 0;
636 \\ a += (a += 1);
637 \\ a -= (a -= 1);
638 \\ a *= (a *= 1);
639 \\ a &= (a &= 1);
640 \\ a |= (a |= 1);
641 \\ a ^= (a ^= 1);
642 \\ a >>= (a >>= 1);
643 \\ a <<= (a <<= 1);
644 \\}
645 ,
646 \\export fn foo() {
647 \\ var a: c_int = 0;
648 \\ a += {
649 \\ const _ref = &a;
650 \\ (*_ref) = ((*_ref) + 1);
651 \\ *_ref
652 \\ };
653 \\ a -= {
654 \\ const _ref = &a;
655 \\ (*_ref) = ((*_ref) - 1);
656 \\ *_ref
657 \\ };
658 \\ a *= {
659 \\ const _ref = &a;
660 \\ (*_ref) = ((*_ref) * 1);
661 \\ *_ref
662 \\ };
663 \\ a &= {
664 \\ const _ref = &a;
665 \\ (*_ref) = ((*_ref) & 1);
666 \\ *_ref
667 \\ };
668 \\ a |= {
669 \\ const _ref = &a;
670 \\ (*_ref) = ((*_ref) | 1);
671 \\ *_ref
672 \\ };
673 \\ a ^= {
674 \\ const _ref = &a;
675 \\ (*_ref) = ((*_ref) ^ 1);
676 \\ *_ref
677 \\ };
678 \\ a >>= @import("std").math.Log2Int(c_int)({
679 \\ const _ref = &a;
680 \\ (*_ref) = c_int(c_int(*_ref) >> @import("std").math.Log2Int(c_int)(1));
681 \\ *_ref
682 \\ });
683 \\ a <<= @import("std").math.Log2Int(c_int)({
684 \\ const _ref = &a;
685 \\ (*_ref) = c_int(c_int(*_ref) << @import("std").math.Log2Int(c_int)(1));
686 \\ *_ref
687 \\ });
688 \\}
689 );
690
691 cases.addC("compound assignment operators unsigned",
692 \\void foo(void) {
693 \\ unsigned a = 0;
694 \\ a += (a += 1);
695 \\ a -= (a -= 1);
696 \\ a *= (a *= 1);
697 \\ a &= (a &= 1);
698 \\ a |= (a |= 1);
699 \\ a ^= (a ^= 1);
700 \\ a >>= (a >>= 1);
701 \\ a <<= (a <<= 1);
702 \\}
703 ,
704 \\export fn foo() {
705 \\ var a: c_uint = c_uint(0);
706 \\ a +%= {
707 \\ const _ref = &a;
708 \\ (*_ref) = ((*_ref) +% c_uint(1));
709 \\ *_ref
710 \\ };
711 \\ a -%= {
712 \\ const _ref = &a;
713 \\ (*_ref) = ((*_ref) -% c_uint(1));
714 \\ *_ref
715 \\ };
716 \\ a *%= {
717 \\ const _ref = &a;
718 \\ (*_ref) = ((*_ref) *% c_uint(1));
719 \\ *_ref
720 \\ };
721 \\ a &= {
722 \\ const _ref = &a;
723 \\ (*_ref) = ((*_ref) & c_uint(1));
724 \\ *_ref
725 \\ };
726 \\ a |= {
727 \\ const _ref = &a;
728 \\ (*_ref) = ((*_ref) | c_uint(1));
729 \\ *_ref
730 \\ };
731 \\ a ^= {
732 \\ const _ref = &a;
733 \\ (*_ref) = ((*_ref) ^ c_uint(1));
734 \\ *_ref
735 \\ };
736 \\ a >>= @import("std").math.Log2Int(c_uint)({
737 \\ const _ref = &a;
738 \\ (*_ref) = c_uint(c_uint(*_ref) >> @import("std").math.Log2Int(c_uint)(1));
739 \\ *_ref
740 \\ });
741 \\ a <<= @import("std").math.Log2Int(c_uint)({
742 \\ const _ref = &a;
743 \\ (*_ref) = c_uint(c_uint(*_ref) << @import("std").math.Log2Int(c_uint)(1));
744 \\ *_ref
745 \\ });
746 \\}
747 );
748
749 cases.addC("duplicate typedef",
750 \\typedef long foo;
751 \\typedef int bar;
752 \\typedef long foo;
753 \\typedef int baz;
754 ,
755 \\pub const foo = c_long;
756 \\pub const bar = c_int;
757 \\pub const baz = c_int;
758 );
759
760 cases.addC("post increment/decrement",
761 \\void foo(void) {
762 \\ int i = 0;
763 \\ unsigned u = 0;
764 \\ i++;
765 \\ i--;
766 \\ u++;
767 \\ u--;
768 \\ i = i++;
769 \\ i = i--;
770 \\ u = u++;
771 \\ u = u--;
772 \\}
773 ,
774 \\export fn foo() {
775 \\ var i: c_int = 0;
776 \\ var u: c_uint = c_uint(0);
777 \\ i += 1;
778 \\ i -= 1;
779 \\ u +%= 1;
780 \\ u -%= 1;
781 \\ i = {
782 \\ const _ref = &i;
783 \\ const _tmp = *_ref;
784 \\ (*_ref) += 1;
785 \\ _tmp
786 \\ };
787 \\ i = {
788 \\ const _ref = &i;
789 \\ const _tmp = *_ref;
790 \\ (*_ref) -= 1;
791 \\ _tmp
792 \\ };
793 \\ u = {
794 \\ const _ref = &u;
795 \\ const _tmp = *_ref;
796 \\ (*_ref) +%= 1;
797 \\ _tmp
798 \\ };
799 \\ u = {
800 \\ const _ref = &u;
801 \\ const _tmp = *_ref;
802 \\ (*_ref) -%= 1;
803 \\ _tmp
804 \\ };
805 \\}
806 );
807
808 cases.addC("do loop",
809 \\void foo(void) {
810 \\ int a = 2;
811 \\ do {
812 \\ a--;
813 \\ } while (a != 0);
814 \\
815 \\ int b = 2;
816 \\ do
817 \\ b--;
818 \\ while (b != 0);
819 \\}
820 ,
821 \\export fn foo() {
822 \\ var a: c_int = 2;
823 \\ while (true) {
824 \\ a -= 1;
825 \\ if (!(a != 0)) break;
826 \\ };
827 \\ var b: c_int = 2;
828 \\ while (true) {
829 \\ b -= 1;
830 \\ if (!(b != 0)) break;
831 \\ };
832 \\}
833 );
834
835 cases.addC("deref function pointer",
836 \\void foo(void) {}
837 \\void bar(void) {
838 \\ void(*f)(void) = foo;
839 \\ f();
840 \\ (*(f))();
841 \\}
842 ,
843 \\export fn foo() {}
844 \\export fn bar() {
845 \\ var f: ?extern fn() = foo;
846 \\ (??f)();
847 \\ (??f)();
848 \\}
849 );
850
851 cases.addC("normal deref",
852 \\void foo(int *x) {
853 \\ *x = 1;
854 \\}
855 ,
856 \\export fn foo(x: ?&c_int) {
857 \\ (*(??x)) = 1;
858 \\}
859 );
860
861 cases.add("simple union",
862 \\union Foo {
863 \\ int x;
864 \\ double y;
865 \\};
866 ,
867 \\pub const union_Foo = extern union {
868 \\ x: c_int,
869 \\ y: f64,
870 \\};
871 ,
872 \\pub const Foo = union_Foo;
873 );
874
875 cases.add("address of operator",
876 \\int foo(void) {
877 \\ int x = 1234;
878 \\ int *ptr = &x;
879 \\ return *ptr;
880 \\}
881 ,
882 \\pub fn foo() -> c_int {
883 \\ var x: c_int = 1234;
884 \\ var ptr: ?&c_int = &x;
885 \\ return *(??ptr);
886 \\}
887 );
888}
889
890
891
892// TODO
893//float *ptrcast(int *a) {
894// return (float *)a;
895//}
896// should translate to
897// fn ptrcast(a: ?&c_int) -> ?&f32 {
898// return @ptrCast(?&f32, a);
899// }
test/tests.zig+24-24
...@@ -18,7 +18,7 @@ const build_examples = @import("build_examples.zig");...@@ -18,7 +18,7 @@ const build_examples = @import("build_examples.zig");
18const compile_errors = @import("compile_errors.zig");18const compile_errors = @import("compile_errors.zig");
19const assemble_and_link = @import("assemble_and_link.zig");19const assemble_and_link = @import("assemble_and_link.zig");
20const debug_safety = @import("debug_safety.zig");20const debug_safety = @import("debug_safety.zig");
21const parsec = @import("parsec.zig");21const translate_c = @import("translate_c.zig");
2222
23const TestTarget = struct {23const TestTarget = struct {
24 os: builtin.Os,24 os: builtin.Os,
...@@ -123,16 +123,16 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) -> &...@@ -123,16 +123,16 @@ pub fn addAssembleAndLinkTests(b: &build.Builder, test_filter: ?[]const u8) -> &
123 return cases.step;123 return cases.step;
124}124}
125125
126pub fn addParseCTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step {126pub fn addTranslateCTests(b: &build.Builder, test_filter: ?[]const u8) -> &build.Step {
127 const cases = %%b.allocator.create(ParseCContext);127 const cases = %%b.allocator.create(TranslateCContext);
128 *cases = ParseCContext {128 *cases = TranslateCContext {
129 .b = b,129 .b = b,
130 .step = b.step("test-parsec", "Run the C header file parsing tests"),130 .step = b.step("test-translate-c", "Run the C header file parsing tests"),
131 .test_index = 0,131 .test_index = 0,
132 .test_filter = test_filter,132 .test_filter = test_filter,
133 };133 };
134134
135 parsec.addCases(cases);135 translate_c.addCases(cases);
136136
137 return cases.step;137 return cases.step;
138}138}
...@@ -770,7 +770,7 @@ pub const BuildExamplesContext = struct {...@@ -770,7 +770,7 @@ pub const BuildExamplesContext = struct {
770 }770 }
771};771};
772772
773pub const ParseCContext = struct {773pub const TranslateCContext = struct {
774 b: &build.Builder,774 b: &build.Builder,
775 step: &build.Step,775 step: &build.Step,
776 test_index: usize,776 test_index: usize,
...@@ -799,17 +799,17 @@ pub const ParseCContext = struct {...@@ -799,17 +799,17 @@ pub const ParseCContext = struct {
799 }799 }
800 };800 };
801801
802 const ParseCCmpOutputStep = struct {802 const TranslateCCmpOutputStep = struct {
803 step: build.Step,803 step: build.Step,
804 context: &ParseCContext,804 context: &TranslateCContext,
805 name: []const u8,805 name: []const u8,
806 test_index: usize,806 test_index: usize,
807 case: &const TestCase,807 case: &const TestCase,
808808
809 pub fn create(context: &ParseCContext, name: []const u8, case: &const TestCase) -> &ParseCCmpOutputStep {809 pub fn create(context: &TranslateCContext, name: []const u8, case: &const TestCase) -> &TranslateCCmpOutputStep {
810 const allocator = context.b.allocator;810 const allocator = context.b.allocator;
811 const ptr = %%allocator.create(ParseCCmpOutputStep);811 const ptr = %%allocator.create(TranslateCCmpOutputStep);
812 *ptr = ParseCCmpOutputStep {812 *ptr = TranslateCCmpOutputStep {
813 .step = build.Step.init("ParseCCmpOutput", allocator, make),813 .step = build.Step.init("ParseCCmpOutput", allocator, make),
814 .context = context,814 .context = context,
815 .name = name,815 .name = name,
...@@ -821,7 +821,7 @@ pub const ParseCContext = struct {...@@ -821,7 +821,7 @@ pub const ParseCContext = struct {
821 }821 }
822822
823 fn make(step: &build.Step) -> %void {823 fn make(step: &build.Step) -> %void {
824 const self = @fieldParentPtr(ParseCCmpOutputStep, "step", step);824 const self = @fieldParentPtr(TranslateCCmpOutputStep, "step", step);
825 const b = self.context.b;825 const b = self.context.b;
826826
827 const root_src = %%os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename);827 const root_src = %%os.path.join(b.allocator, b.cache_root, self.case.sources.items[0].filename);
...@@ -829,7 +829,7 @@ pub const ParseCContext = struct {...@@ -829,7 +829,7 @@ pub const ParseCContext = struct {
829 var zig_args = ArrayList([]const u8).init(b.allocator);829 var zig_args = ArrayList([]const u8).init(b.allocator);
830 %%zig_args.append(b.zig_exe);830 %%zig_args.append(b.zig_exe);
831831
832 %%zig_args.append("parsec");832 %%zig_args.append("translate-c");
833 %%zig_args.append(b.pathFromRoot(root_src));833 %%zig_args.append(b.pathFromRoot(root_src));
834834
835 warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);835 warn("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
...@@ -882,7 +882,7 @@ pub const ParseCContext = struct {...@@ -882,7 +882,7 @@ pub const ParseCContext = struct {
882882
883 if (stderr.len != 0 and !self.case.allow_warnings) {883 if (stderr.len != 0 and !self.case.allow_warnings) {
884 warn(884 warn(
885 \\====== parsec emitted warnings: ============885 \\====== translate-c emitted warnings: =======
886 \\{}886 \\{}
887 \\============================================887 \\============================================
888 \\888 \\
...@@ -914,7 +914,7 @@ pub const ParseCContext = struct {...@@ -914,7 +914,7 @@ pub const ParseCContext = struct {
914 warn("\n");914 warn("\n");
915 }915 }
916916
917 pub fn create(self: &ParseCContext, allow_warnings: bool, filename: []const u8, name: []const u8,917 pub fn create(self: &TranslateCContext, allow_warnings: bool, filename: []const u8, name: []const u8,
918 source: []const u8, expected_lines: ...) -> &TestCase918 source: []const u8, expected_lines: ...) -> &TestCase
919 {919 {
920 const tc = %%self.b.allocator.create(TestCase);920 const tc = %%self.b.allocator.create(TestCase);
...@@ -932,37 +932,37 @@ pub const ParseCContext = struct {...@@ -932,37 +932,37 @@ pub const ParseCContext = struct {
932 return tc;932 return tc;
933 }933 }
934934
935 pub fn add(self: &ParseCContext, name: []const u8, source: []const u8, expected_lines: ...) {935 pub fn add(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) {
936 const tc = self.create(false, "source.h", name, source, expected_lines);936 const tc = self.create(false, "source.h", name, source, expected_lines);
937 self.addCase(tc);937 self.addCase(tc);
938 }938 }
939939
940 pub fn addC(self: &ParseCContext, name: []const u8, source: []const u8, expected_lines: ...) {940 pub fn addC(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) {
941 const tc = self.create(false, "source.c", name, source, expected_lines);941 const tc = self.create(false, "source.c", name, source, expected_lines);
942 self.addCase(tc);942 self.addCase(tc);
943 }943 }
944944
945 pub fn addAllowWarnings(self: &ParseCContext, name: []const u8, source: []const u8, expected_lines: ...) {945 pub fn addAllowWarnings(self: &TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) {
946 const tc = self.create(true, "source.h", name, source, expected_lines);946 const tc = self.create(true, "source.h", name, source, expected_lines);
947 self.addCase(tc);947 self.addCase(tc);
948 }948 }
949949
950 pub fn addCase(self: &ParseCContext, case: &const TestCase) {950 pub fn addCase(self: &TranslateCContext, case: &const TestCase) {
951 const b = self.b;951 const b = self.b;
952952
953 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "parsec {}", case.name);953 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "translate-c {}", case.name);
954 if (self.test_filter) |filter| {954 if (self.test_filter) |filter| {
955 if (mem.indexOf(u8, annotated_case_name, filter) == null)955 if (mem.indexOf(u8, annotated_case_name, filter) == null)
956 return;956 return;
957 }957 }
958958
959 const parsec_and_cmp = ParseCCmpOutputStep.create(self, annotated_case_name, case);959 const translate_c_and_cmp = TranslateCCmpOutputStep.create(self, annotated_case_name, case);
960 self.step.dependOn(&parsec_and_cmp.step);960 self.step.dependOn(&translate_c_and_cmp.step);
961961
962 for (case.sources.toSliceConst()) |src_file| {962 for (case.sources.toSliceConst()) |src_file| {
963 const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename);963 const expanded_src_path = %%os.path.join(b.allocator, b.cache_root, src_file.filename);
964 const write_src = b.addWriteFile(expanded_src_path, src_file.source);964 const write_src = b.addWriteFile(expanded_src_path, src_file.source);
965 parsec_and_cmp.step.dependOn(&write_src.step);965 translate_c_and_cmp.step.dependOn(&write_src.step);
966 }966 }
967 }967 }
968};968};
test/translate_c.zig created+899
...@@ -0,0 +1,899 @@
1const tests = @import("tests.zig");
2
3pub fn addCases(cases: &tests.TranslateCContext) {
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.addC("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 hex",
289 \\#define FOO "aoeu\xab derp"
290 \\#define FOO2 "aoeu\x0007a derp"
291 \\#define FOO_CHAR '\xfF'
292 ,
293 \\pub const FOO = c"aoeu\xab derp";
294 ,
295 \\pub const FOO2 = c"aoeuz derp";
296 ,
297 \\pub const FOO_CHAR = 255;
298 );
299
300 cases.add("macro defines string literal with octal",
301 \\#define FOO "aoeu\023 derp"
302 \\#define FOO2 "aoeu\0234 derp"
303 \\#define FOO_CHAR '\077'
304 ,
305 \\pub const FOO = c"aoeu\x13 derp";
306 ,
307 \\pub const FOO2 = c"aoeu\x134 derp";
308 ,
309 \\pub const FOO_CHAR = 63;
310 );
311
312 cases.add("macro with parens around negative number",
313 \\#define LUA_GLOBALSINDEX (-10002)
314 ,
315 \\pub const LUA_GLOBALSINDEX = -10002;
316 );
317
318 cases.addC("post increment",
319 \\unsigned foo1(unsigned a) {
320 \\ a++;
321 \\ return a;
322 \\}
323 \\int foo2(int a) {
324 \\ a++;
325 \\ return a;
326 \\}
327 ,
328 \\export fn foo1(_arg_a: c_uint) -> c_uint {
329 \\ var a = _arg_a;
330 \\ a +%= 1;
331 \\ return a;
332 \\}
333 \\export fn foo2(_arg_a: c_int) -> c_int {
334 \\ var a = _arg_a;
335 \\ a += 1;
336 \\ return a;
337 \\}
338 );
339
340 cases.addC("shift right assign",
341 \\int log2(unsigned a) {
342 \\ int i = 0;
343 \\ while (a > 0) {
344 \\ a >>= 1;
345 \\ }
346 \\ return i;
347 \\}
348 ,
349 \\export fn log2(_arg_a: c_uint) -> c_int {
350 \\ var a = _arg_a;
351 \\ var i: c_int = 0;
352 \\ while (a > c_uint(0)) {
353 \\ a >>= @import("std").math.Log2Int(c_uint)(1);
354 \\ };
355 \\ return i;
356 \\}
357 );
358
359 cases.addC("if statement",
360 \\int max(int a, int b) {
361 \\ if (a < b)
362 \\ return b;
363 \\
364 \\ if (a < b)
365 \\ return b;
366 \\ else
367 \\ return a;
368 \\}
369 ,
370 \\export fn max(a: c_int, b: c_int) -> c_int {
371 \\ if (a < b) return b;
372 \\ if (a < b) return b else return a;
373 \\}
374 );
375
376 cases.addC("==, !=",
377 \\int max(int a, int b) {
378 \\ if (a == b)
379 \\ return a;
380 \\ if (a != b)
381 \\ return b;
382 \\ return a;
383 \\}
384 ,
385 \\export fn max(a: c_int, b: c_int) -> c_int {
386 \\ if (a == b) return a;
387 \\ if (a != b) return b;
388 \\ return a;
389 \\}
390 );
391
392 cases.addC("add, sub, mul, div, rem",
393 \\int s(int a, int b) {
394 \\ int c;
395 \\ c = a + b;
396 \\ c = a - b;
397 \\ c = a * b;
398 \\ c = a / b;
399 \\ c = a % b;
400 \\}
401 \\unsigned u(unsigned a, unsigned b) {
402 \\ unsigned c;
403 \\ c = a + b;
404 \\ c = a - b;
405 \\ c = a * b;
406 \\ c = a / b;
407 \\ c = a % b;
408 \\}
409 ,
410 \\export fn s(a: c_int, b: c_int) -> c_int {
411 \\ var c: c_int;
412 \\ c = (a + b);
413 \\ c = (a - b);
414 \\ c = (a * b);
415 \\ c = @divTrunc(a, b);
416 \\ c = @rem(a, b);
417 \\}
418 \\export fn u(a: c_uint, b: c_uint) -> c_uint {
419 \\ var c: c_uint;
420 \\ c = (a +% b);
421 \\ c = (a -% b);
422 \\ c = (a *% b);
423 \\ c = (a / b);
424 \\ c = (a % b);
425 \\}
426 );
427
428 cases.addC("bitwise binary operators",
429 \\int max(int a, int b) {
430 \\ return (a & b) ^ (a | b);
431 \\}
432 ,
433 \\export fn max(a: c_int, b: c_int) -> c_int {
434 \\ return (a & b) ^ (a | b);
435 \\}
436 );
437
438 cases.addC("logical and, logical or",
439 \\int max(int a, int b) {
440 \\ if (a < b || a == b)
441 \\ return b;
442 \\ if (a >= b && a == b)
443 \\ return a;
444 \\ return a;
445 \\}
446 ,
447 \\export fn max(a: c_int, b: c_int) -> c_int {
448 \\ if ((a < b) or (a == b)) return b;
449 \\ if ((a >= b) and (a == b)) return a;
450 \\ return a;
451 \\}
452 );
453
454 cases.addC("assign",
455 \\int max(int a) {
456 \\ int tmp;
457 \\ tmp = a;
458 \\ a = tmp;
459 \\}
460 ,
461 \\export fn max(_arg_a: c_int) -> c_int {
462 \\ var a = _arg_a;
463 \\ var tmp: c_int;
464 \\ tmp = a;
465 \\ a = tmp;
466 \\}
467 );
468
469 cases.addC("chaining assign",
470 \\void max(int a) {
471 \\ int b, c;
472 \\ c = b = a;
473 \\}
474 ,
475 \\export fn max(a: c_int) {
476 \\ var b: c_int;
477 \\ var c: c_int;
478 \\ c = {
479 \\ const _tmp = a;
480 \\ b = _tmp;
481 \\ _tmp
482 \\ };
483 \\}
484 );
485
486 cases.addC("shift right assign with a fixed size type",
487 \\#include <stdint.h>
488 \\int log2(uint32_t a) {
489 \\ int i = 0;
490 \\ while (a > 0) {
491 \\ a >>= 1;
492 \\ }
493 \\ return i;
494 \\}
495 ,
496 \\export fn log2(_arg_a: u32) -> c_int {
497 \\ var a = _arg_a;
498 \\ var i: c_int = 0;
499 \\ while (a > c_uint(0)) {
500 \\ a >>= u5(1);
501 \\ };
502 \\ return i;
503 \\}
504 );
505
506 cases.add("anonymous enum",
507 \\enum {
508 \\ One,
509 \\ Two,
510 \\};
511 ,
512 \\pub const One = 0;
513 \\pub const Two = 1;
514 );
515
516 cases.addC("function call",
517 \\static void bar(void) { }
518 \\void foo(void) { bar(); }
519 ,
520 \\pub fn bar() {}
521 \\export fn foo() {
522 \\ bar();
523 \\}
524 );
525
526 cases.addC("field access expression",
527 \\struct Foo {
528 \\ int field;
529 \\};
530 \\int read_field(struct Foo *foo) {
531 \\ return foo->field;
532 \\}
533 ,
534 \\pub const struct_Foo = extern struct {
535 \\ field: c_int,
536 \\};
537 \\export fn read_field(foo: ?&struct_Foo) -> c_int {
538 \\ return (??foo).field;
539 \\}
540 );
541
542 cases.addC("null statements",
543 \\void foo(void) {
544 \\ ;;;;;
545 \\}
546 ,
547 \\export fn foo() {}
548 );
549
550 cases.add("undefined array global",
551 \\int array[100];
552 ,
553 \\pub var array: [100]c_int = undefined;
554 );
555
556 cases.addC("array access",
557 \\int array[100];
558 \\int foo(int index) {
559 \\ return array[index];
560 \\}
561 ,
562 \\pub var array: [100]c_int = undefined;
563 \\export fn foo(index: c_int) -> c_int {
564 \\ return array[index];
565 \\}
566 );
567
568
569 cases.addC("c style cast",
570 \\int float_to_int(float a) {
571 \\ return (int)a;
572 \\}
573 ,
574 \\export fn float_to_int(a: f32) -> c_int {
575 \\ return c_int(a);
576 \\}
577 );
578
579 cases.addC("implicit cast to void *",
580 \\void *foo(unsigned short *x) {
581 \\ return x;
582 \\}
583 ,
584 \\export fn foo(x: ?&c_ushort) -> ?&c_void {
585 \\ return @ptrCast(?&c_void, x);
586 \\}
587 );
588
589 cases.addC("sizeof",
590 \\#include <stddef.h>
591 \\size_t size_of(void) {
592 \\ return sizeof(int);
593 \\}
594 ,
595 \\export fn size_of() -> usize {
596 \\ return @sizeOf(c_int);
597 \\}
598 );
599
600 cases.addC("null pointer implicit cast",
601 \\int* foo(void) {
602 \\ return 0;
603 \\}
604 ,
605 \\export fn foo() -> ?&c_int {
606 \\ return null;
607 \\}
608 );
609
610 cases.addC("comma operator",
611 \\int foo(void) {
612 \\ return 1, 2;
613 \\}
614 ,
615 \\export fn foo() -> c_int {
616 \\ return {
617 \\ _ = 1;
618 \\ 2
619 \\ };
620 \\}
621 );
622
623 cases.addC("bitshift",
624 \\int foo(void) {
625 \\ return (1 << 2) >> 1;
626 \\}
627 ,
628 \\export fn foo() -> c_int {
629 \\ return (1 << @import("std").math.Log2Int(c_int)(2)) >> @import("std").math.Log2Int(c_int)(1);
630 \\}
631 );
632
633 cases.addC("compound assignment operators",
634 \\void foo(void) {
635 \\ int a = 0;
636 \\ a += (a += 1);
637 \\ a -= (a -= 1);
638 \\ a *= (a *= 1);
639 \\ a &= (a &= 1);
640 \\ a |= (a |= 1);
641 \\ a ^= (a ^= 1);
642 \\ a >>= (a >>= 1);
643 \\ a <<= (a <<= 1);
644 \\}
645 ,
646 \\export fn foo() {
647 \\ var a: c_int = 0;
648 \\ a += {
649 \\ const _ref = &a;
650 \\ (*_ref) = ((*_ref) + 1);
651 \\ *_ref
652 \\ };
653 \\ a -= {
654 \\ const _ref = &a;
655 \\ (*_ref) = ((*_ref) - 1);
656 \\ *_ref
657 \\ };
658 \\ a *= {
659 \\ const _ref = &a;
660 \\ (*_ref) = ((*_ref) * 1);
661 \\ *_ref
662 \\ };
663 \\ a &= {
664 \\ const _ref = &a;
665 \\ (*_ref) = ((*_ref) & 1);
666 \\ *_ref
667 \\ };
668 \\ a |= {
669 \\ const _ref = &a;
670 \\ (*_ref) = ((*_ref) | 1);
671 \\ *_ref
672 \\ };
673 \\ a ^= {
674 \\ const _ref = &a;
675 \\ (*_ref) = ((*_ref) ^ 1);
676 \\ *_ref
677 \\ };
678 \\ a >>= @import("std").math.Log2Int(c_int)({
679 \\ const _ref = &a;
680 \\ (*_ref) = c_int(c_int(*_ref) >> @import("std").math.Log2Int(c_int)(1));
681 \\ *_ref
682 \\ });
683 \\ a <<= @import("std").math.Log2Int(c_int)({
684 \\ const _ref = &a;
685 \\ (*_ref) = c_int(c_int(*_ref) << @import("std").math.Log2Int(c_int)(1));
686 \\ *_ref
687 \\ });
688 \\}
689 );
690
691 cases.addC("compound assignment operators unsigned",
692 \\void foo(void) {
693 \\ unsigned a = 0;
694 \\ a += (a += 1);
695 \\ a -= (a -= 1);
696 \\ a *= (a *= 1);
697 \\ a &= (a &= 1);
698 \\ a |= (a |= 1);
699 \\ a ^= (a ^= 1);
700 \\ a >>= (a >>= 1);
701 \\ a <<= (a <<= 1);
702 \\}
703 ,
704 \\export fn foo() {
705 \\ var a: c_uint = c_uint(0);
706 \\ a +%= {
707 \\ const _ref = &a;
708 \\ (*_ref) = ((*_ref) +% c_uint(1));
709 \\ *_ref
710 \\ };
711 \\ a -%= {
712 \\ const _ref = &a;
713 \\ (*_ref) = ((*_ref) -% c_uint(1));
714 \\ *_ref
715 \\ };
716 \\ a *%= {
717 \\ const _ref = &a;
718 \\ (*_ref) = ((*_ref) *% c_uint(1));
719 \\ *_ref
720 \\ };
721 \\ a &= {
722 \\ const _ref = &a;
723 \\ (*_ref) = ((*_ref) & c_uint(1));
724 \\ *_ref
725 \\ };
726 \\ a |= {
727 \\ const _ref = &a;
728 \\ (*_ref) = ((*_ref) | c_uint(1));
729 \\ *_ref
730 \\ };
731 \\ a ^= {
732 \\ const _ref = &a;
733 \\ (*_ref) = ((*_ref) ^ c_uint(1));
734 \\ *_ref
735 \\ };
736 \\ a >>= @import("std").math.Log2Int(c_uint)({
737 \\ const _ref = &a;
738 \\ (*_ref) = c_uint(c_uint(*_ref) >> @import("std").math.Log2Int(c_uint)(1));
739 \\ *_ref
740 \\ });
741 \\ a <<= @import("std").math.Log2Int(c_uint)({
742 \\ const _ref = &a;
743 \\ (*_ref) = c_uint(c_uint(*_ref) << @import("std").math.Log2Int(c_uint)(1));
744 \\ *_ref
745 \\ });
746 \\}
747 );
748
749 cases.addC("duplicate typedef",
750 \\typedef long foo;
751 \\typedef int bar;
752 \\typedef long foo;
753 \\typedef int baz;
754 ,
755 \\pub const foo = c_long;
756 \\pub const bar = c_int;
757 \\pub const baz = c_int;
758 );
759
760 cases.addC("post increment/decrement",
761 \\void foo(void) {
762 \\ int i = 0;
763 \\ unsigned u = 0;
764 \\ i++;
765 \\ i--;
766 \\ u++;
767 \\ u--;
768 \\ i = i++;
769 \\ i = i--;
770 \\ u = u++;
771 \\ u = u--;
772 \\}
773 ,
774 \\export fn foo() {
775 \\ var i: c_int = 0;
776 \\ var u: c_uint = c_uint(0);
777 \\ i += 1;
778 \\ i -= 1;
779 \\ u +%= 1;
780 \\ u -%= 1;
781 \\ i = {
782 \\ const _ref = &i;
783 \\ const _tmp = *_ref;
784 \\ (*_ref) += 1;
785 \\ _tmp
786 \\ };
787 \\ i = {
788 \\ const _ref = &i;
789 \\ const _tmp = *_ref;
790 \\ (*_ref) -= 1;
791 \\ _tmp
792 \\ };
793 \\ u = {
794 \\ const _ref = &u;
795 \\ const _tmp = *_ref;
796 \\ (*_ref) +%= 1;
797 \\ _tmp
798 \\ };
799 \\ u = {
800 \\ const _ref = &u;
801 \\ const _tmp = *_ref;
802 \\ (*_ref) -%= 1;
803 \\ _tmp
804 \\ };
805 \\}
806 );
807
808 cases.addC("do loop",
809 \\void foo(void) {
810 \\ int a = 2;
811 \\ do {
812 \\ a--;
813 \\ } while (a != 0);
814 \\
815 \\ int b = 2;
816 \\ do
817 \\ b--;
818 \\ while (b != 0);
819 \\}
820 ,
821 \\export fn foo() {
822 \\ var a: c_int = 2;
823 \\ while (true) {
824 \\ a -= 1;
825 \\ if (!(a != 0)) break;
826 \\ };
827 \\ var b: c_int = 2;
828 \\ while (true) {
829 \\ b -= 1;
830 \\ if (!(b != 0)) break;
831 \\ };
832 \\}
833 );
834
835 cases.addC("deref function pointer",
836 \\void foo(void) {}
837 \\void bar(void) {
838 \\ void(*f)(void) = foo;
839 \\ f();
840 \\ (*(f))();
841 \\}
842 ,
843 \\export fn foo() {}
844 \\export fn bar() {
845 \\ var f: ?extern fn() = foo;
846 \\ (??f)();
847 \\ (??f)();
848 \\}
849 );
850
851 cases.addC("normal deref",
852 \\void foo(int *x) {
853 \\ *x = 1;
854 \\}
855 ,
856 \\export fn foo(x: ?&c_int) {
857 \\ (*(??x)) = 1;
858 \\}
859 );
860
861 cases.add("simple union",
862 \\union Foo {
863 \\ int x;
864 \\ double y;
865 \\};
866 ,
867 \\pub const union_Foo = extern union {
868 \\ x: c_int,
869 \\ y: f64,
870 \\};
871 ,
872 \\pub const Foo = union_Foo;
873 );
874
875 cases.add("address of operator",
876 \\int foo(void) {
877 \\ int x = 1234;
878 \\ int *ptr = &x;
879 \\ return *ptr;
880 \\}
881 ,
882 \\pub fn foo() -> c_int {
883 \\ var x: c_int = 1234;
884 \\ var ptr: ?&c_int = &x;
885 \\ return *(??ptr);
886 \\}
887 );
888}
889
890
891
892// TODO
893//float *ptrcast(int *a) {
894// return (float *)a;
895//}
896// should translate to
897// fn ptrcast(a: ?&c_int) -> ?&f32 {
898// return @ptrCast(?&f32, a);
899// }