authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-21 02:56:06-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-09-21 02:56:06-04:00
logc2f3dc94eba85a32f3b7ab5857b33636a0a2e4df
treebb809f8eb6a1d7fb709607dcadce511b2a58dd8f
parentc4a54377e3f07bbd2f9c54c1962c7941792c2c1f
parentee42caee0e6a24aa252845a72733007ed384d2bf

Merge branch 'c-to-zig'


8 files changed, 958 insertions(+), 147 deletions(-)

src/analyze.cpp-4
......@@ -163,10 +163,6 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so
163163 return entry;
164164}
165165
166static uint8_t log2_u64(uint64_t x) {
167 return (63 - clzll(x));
168}
169
170166static uint8_t bits_needed_for_unsigned(uint64_t x) {
171167 if (x == 0) {
172168 return 0;
src/ast_render.cpp+4-2
......@@ -14,8 +14,8 @@
1414static const char *bin_op_str(BinOpType bin_op) {
1515 switch (bin_op) {
1616 case BinOpTypeInvalid: return "(invalid)";
17 case BinOpTypeBoolOr: return "||";
18 case BinOpTypeBoolAnd: return "&&";
17 case BinOpTypeBoolOr: return "or";
18 case BinOpTypeBoolAnd: return "and";
1919 case BinOpTypeCmpEq: return "==";
2020 case BinOpTypeCmpNotEq: return "!=";
2121 case BinOpTypeCmpLessThan: return "<";
......@@ -580,10 +580,12 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
580580 break;
581581 case NodeTypePrefixOpExpr:
582582 {
583 if (!grouped) fprintf(ar->f, "(");
583584 PrefixOp op = node->data.prefix_op_expr.prefix_op;
584585 fprintf(ar->f, "%s", prefix_op_str(op));
585586
586587 render_node_ungrouped(ar, node->data.prefix_op_expr.primary_expr);
588 if (!grouped) fprintf(ar->f, ")");
587589 break;
588590 }
589591 case NodeTypeAddrOfExpr:
src/codegen.cpp+1-1
......@@ -5037,7 +5037,7 @@ void codegen_parsec(CodeGen *g, Buf *full_path) {
50375037 ZigList<ErrorMsg *> errors = {0};
50385038 int err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr);
50395039 if (err) {
5040 fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
5040 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
50415041 exit(1);
50425042 }
50435043
src/ir.cpp+1-1
......@@ -13459,7 +13459,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
1345913459
1346013460 int err;
1346113461 if ((err = parse_h_buf(child_import, &errors, &cimport_scope->buf, ira->codegen, node))) {
13462 zig_panic("unable to parse h file: %s\n", err_str(err));
13462 zig_panic("unable to parse C file: %s\n", err_str(err));
1346313463 }
1346413464
1346513465 if (errors.length > 0) {
src/parsec.cpp+651-136
......@@ -49,6 +49,8 @@ struct Context {
4949
5050 CodeGen *codegen;
5151 ASTContext *ctx;
52
53 HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
5254};
5355
5456static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
......@@ -126,13 +128,27 @@ static AstNode *trans_create_node_opaque(Context *c) {
126128 return trans_create_node_builtin_fn_call_str(c, "OpaqueType");
127129}
128130
131static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) {
132 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
133 node->data.fn_call_expr.fn_ref_expr = fn_ref_expr;
134 node->data.fn_call_expr.params.append(arg1);
135 return node;
136}
137
129138static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {
130139 AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr);
140 if (container->type == NodeTypeSymbol) {
141 assert(container->data.symbol_expr.symbol != nullptr);
142 }
131143 node->data.field_access_expr.struct_expr = container;
132144 node->data.field_access_expr.field_name = field_name;
133145 return node;
134146}
135147
148static AstNode *trans_create_node_field_access_str(Context *c, AstNode *container, const char *field_name) {
149 return trans_create_node_field_access(c, container, buf_create_from_str(field_name));
150}
151
136152static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
137153 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
138154 node->data.prefix_op_expr.prefix_op = op;
......@@ -140,6 +156,22 @@ static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *ch
140156 return node;
141157}
142158
159static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpType op, AstNode *rhs_node) {
160 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
161 node->data.bin_op_expr.op1 = lhs_node;
162 node->data.bin_op_expr.bin_op = op;
163 node->data.bin_op_expr.op2 = rhs_node;
164 return node;
165}
166
167static AstNode *maybe_suppress_result(Context *c, bool result_used, AstNode *node) {
168 if (result_used) return node;
169 return trans_create_node_bin_op(c,
170 trans_create_node_symbol_str(c, "_"),
171 BinOpTypeAssign,
172 node);
173}
174
143175static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {
144176 AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr);
145177 node->data.addr_of_expr.is_const = is_const;
......@@ -155,6 +187,13 @@ static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
155187 return node;
156188}
157189
190static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) {
191 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
192 node->data.string_literal.buf = buf;
193 node->data.string_literal.c = false;
194 return node;
195}
196
158197static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) {
159198 AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
160199 node->data.int_literal.bigint = allocate<BigInt>(1);
......@@ -188,11 +227,11 @@ static AstNode *trans_create_node_array_type(Context *c, AstNode *size_node, Ast
188227 return node;
189228}
190229
191static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
192 AstNode *init_node)
230static AstNode *trans_create_node_var_decl(Context *c, VisibMod visib_mod, bool is_const, Buf *var_name,
231 AstNode *type_node, AstNode *init_node)
193232{
194233 AstNode *node = trans_create_node(c, NodeTypeVariableDeclaration);
195 node->data.variable_declaration.visib_mod = c->visib_mod;
234 node->data.variable_declaration.visib_mod = visib_mod;
196235 node->data.variable_declaration.symbol = var_name;
197236 node->data.variable_declaration.is_const = is_const;
198237 node->data.variable_declaration.type = type_node;
......@@ -200,6 +239,18 @@ static AstNode *trans_create_node_var_decl(Context *c, bool is_const, Buf *var_n
200239 return node;
201240}
202241
242static AstNode *trans_create_node_var_decl_global(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
243 AstNode *init_node)
244{
245 return trans_create_node_var_decl(c, c->visib_mod, is_const, var_name, type_node, init_node);
246}
247
248static AstNode *trans_create_node_var_decl_local(Context *c, bool is_const, Buf *var_name, AstNode *type_node,
249 AstNode *init_node)
250{
251 return trans_create_node_var_decl(c, VisibModPrivate, is_const, var_name, type_node, init_node);
252}
253
203254
204255static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_name, AstNode *src_proto_node) {
205256 AstNode *fn_def = trans_create_node(c, NodeTypeFnDef);
......@@ -240,6 +291,10 @@ static AstNode *trans_create_node_inline_fn(Context *c, Buf *fn_name, Buf *var_n
240291 return fn_def;
241292}
242293
294static AstNode *trans_create_node_unwrap_null(Context *c, AstNode *child) {
295 return trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, child);
296}
297
243298static AstNode *get_global(Context *c, Buf *name) {
244299 for (size_t i = 0; i < c->root->data.root.top_level_decls.length; i += 1) {
245300 AstNode *decl_node = c->root->data.root.top_level_decls.items[i];
......@@ -268,7 +323,7 @@ static AstNode *get_global(Context *c, Buf *name) {
268323static AstNode *add_global_var(Context *c, Buf *var_name, AstNode *value_node) {
269324 bool is_const = true;
270325 AstNode *type_node = nullptr;
271 AstNode *node = trans_create_node_var_decl(c, is_const, var_name, type_node, value_node);
326 AstNode *node = trans_create_node_var_decl_global(c, is_const, var_name, type_node, value_node);
272327 c->root->data.root.top_level_decls.append(node);
273328 return node;
274329}
......@@ -286,10 +341,96 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
286341
287342}
288343
344static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
345
289346static bool is_c_void_type(AstNode *node) {
290347 return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
291348}
292349
350static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) {
351 // TODO: maybe widen to increase size
352 // TODO: maybe bitcast to change sign
353 // TODO: maybe truncate to reduce size
354 return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr);
355}
356
357static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
358 const Type *ty = qt.getTypePtr();
359 switch (ty->getTypeClass()) {
360 case Type::Builtin:
361 {
362 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
363 switch (builtin_ty->getKind()) {
364 case BuiltinType::Char_U:
365 case BuiltinType::UChar:
366 case BuiltinType::Char_S:
367 case BuiltinType::SChar:
368 return 8;
369 case BuiltinType::UInt128:
370 case BuiltinType::Int128:
371 return 128;
372 default:
373 return 0;
374 }
375 zig_unreachable();
376 }
377 case Type::Typedef:
378 {
379 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
380 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
381 const char *type_name = decl_name(typedef_decl);
382 if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
383 return 8;
384 } else if (strcmp(type_name, "uint16_t") == 0 || strcmp(type_name, "int16_t") == 0) {
385 return 16;
386 } else if (strcmp(type_name, "uint32_t") == 0 || strcmp(type_name, "int32_t") == 0) {
387 return 32;
388 } else if (strcmp(type_name, "uint64_t") == 0 || strcmp(type_name, "int64_t") == 0) {
389 return 64;
390 } else {
391 return 0;
392 }
393 }
394 default:
395 return 0;
396 }
397 zig_unreachable();
398}
399
400
401static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
402 const SourceLocation &source_loc)
403{
404 uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
405 if (int_bit_width != 0) {
406 // we can perform the log2 now.
407 uint64_t cast_bit_width = log2_u64(int_bit_width);
408 return trans_create_node_symbol(c, buf_sprintf("u%" ZIG_PRI_u64, cast_bit_width));
409 }
410
411 AstNode *zig_type_node = trans_qual_type(c, qt, source_loc);
412
413// @import("std").math.Log2Int(c_long);
414//
415// FnCall
416// FieldAccess
417// FieldAccess
418// FnCall (.builtin = true)
419// Symbol "import"
420// StringLiteral "std"
421// Symbol "math"
422// Symbol "Log2Int"
423// zig_type_node
424
425 AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");
426 import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std")));
427 AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
428 AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
429 AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);
430
431 return log2int_fn_call;
432}
433
293434static bool qual_type_child_is_fn_proto(const QualType &qt) {
294435 if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
295436 const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
......@@ -303,8 +444,17 @@ static bool qual_type_child_is_fn_proto(const QualType &qt) {
303444 return false;
304445}
305446
447static QualType resolve_any_typedef(Context *c, QualType qt) {
448 const Type * ty = qt.getTypePtr();
449 if (ty->getTypeClass() != Type::Typedef)
450 return qt;
451 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
452 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
453 return typedef_decl->getUnderlyingType();
454}
455
306456static bool c_is_signed_integer(Context *c, QualType qt) {
307 const Type *c_type = qt.getTypePtr();
457 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
308458 if (c_type->getTypeClass() != Type::Builtin)
309459 return false;
310460 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
......@@ -323,7 +473,7 @@ static bool c_is_signed_integer(Context *c, QualType qt) {
323473}
324474
325475static bool c_is_unsigned_integer(Context *c, QualType qt) {
326 const Type *c_type = qt.getTypePtr();
476 const Type *c_type = resolve_any_typedef(c, qt).getTypePtr();
327477 if (c_type->getTypeClass() != Type::Builtin)
328478 return false;
329479 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(c_type);
......@@ -360,12 +510,26 @@ static bool c_is_float(Context *c, QualType qt) {
360510 }
361511}
362512
363static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt);
364static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
513static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
514 if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
515 // float and signed integer overflow is undefined behavior.
516 return false;
517 } else {
518 // unsigned integer overflow wraps around.
519 return true;
520 }
521}
522
523enum TransLRValue {
524 TransLValue,
525 TransRValue,
526};
527
528static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrval);
365529static AstNode *const skip_add_to_block_node = (AstNode *) 0x2;
366530
367static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) {
368 return trans_stmt(c, block, expr);
531static AstNode *trans_expr(Context *c, bool result_used, AstNode *block, Expr *expr, TransLRValue lrval) {
532 return trans_stmt(c, result_used, block, expr, lrval);
369533}
370534
371535static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
......@@ -709,7 +873,7 @@ static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &s
709873static AstNode *trans_compound_stmt(Context *c, AstNode *parent, CompoundStmt *stmt) {
710874 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
711875 for (CompoundStmt::body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
712 AstNode *child_node = trans_stmt(c, child_block, *it);
876 AstNode *child_node = trans_stmt(c, false, child_block, *it, TransRValue);
713877 if (child_node == nullptr)
714878 return nullptr;
715879 if (child_node != skip_add_to_block_node)
......@@ -725,7 +889,7 @@ static AstNode *trans_return_stmt(Context *c, AstNode *block, ReturnStmt *stmt)
725889 return nullptr;
726890 } else {
727891 AstNode *return_node = trans_create_node(c, NodeTypeReturnExpr);
728 return_node->data.return_expr.expr = trans_expr(c, block, value_expr);
892 return_node->data.return_expr.expr = trans_expr(c, true, block, value_expr, TransRValue);
729893 if (return_node->data.return_expr.expr == nullptr)
730894 return nullptr;
731895 return return_node;
......@@ -741,44 +905,93 @@ static AstNode *trans_integer_literal(Context *c, IntegerLiteral *stmt) {
741905 return trans_create_node_apint(c, result);
742906}
743907
744static AstNode *trans_conditional_operator(Context *c, AstNode *block, ConditionalOperator *stmt) {
908static AstNode *trans_conditional_operator(Context *c, bool result_used, AstNode *block, ConditionalOperator *stmt) {
745909 AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
746910
747911 Expr *cond_expr = stmt->getCond();
748912 Expr *true_expr = stmt->getTrueExpr();
749913 Expr *false_expr = stmt->getFalseExpr();
750914
751 node->data.if_bool_expr.condition = trans_expr(c, block, cond_expr);
915 node->data.if_bool_expr.condition = trans_expr(c, true, block, cond_expr, TransRValue);
752916 if (node->data.if_bool_expr.condition == nullptr)
753917 return nullptr;
754918
755 node->data.if_bool_expr.then_block = trans_expr(c, block, true_expr);
919 node->data.if_bool_expr.then_block = trans_expr(c, result_used, block, true_expr, TransRValue);
756920 if (node->data.if_bool_expr.then_block == nullptr)
757921 return nullptr;
758922
759 node->data.if_bool_expr.else_node = trans_expr(c, block, false_expr);
923 node->data.if_bool_expr.else_node = trans_expr(c, result_used, block, false_expr, TransRValue);
760924 if (node->data.if_bool_expr.else_node == nullptr)
761925 return nullptr;
762926
763 return node;
927 return maybe_suppress_result(c, result_used, node);
764928}
765929
766930static AstNode *trans_create_bin_op(Context *c, AstNode *block, Expr *lhs, BinOpType bin_op, Expr *rhs) {
767931 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
768932 node->data.bin_op_expr.bin_op = bin_op;
769933
770 node->data.bin_op_expr.op1 = trans_expr(c, block, lhs);
934 node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransRValue);
771935 if (node->data.bin_op_expr.op1 == nullptr)
772936 return nullptr;
773937
774 node->data.bin_op_expr.op2 = trans_expr(c, block, rhs);
938 node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue);
775939 if (node->data.bin_op_expr.op2 == nullptr)
776940 return nullptr;
777941
778942 return node;
779943}
780944
781static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator *stmt) {
945static AstNode *trans_create_assign(Context *c, bool result_used, AstNode *block, Expr *lhs, Expr *rhs) {
946 if (!result_used) {
947 // common case
948 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
949 node->data.bin_op_expr.bin_op = BinOpTypeAssign;
950
951 node->data.bin_op_expr.op1 = trans_expr(c, true, block, lhs, TransLValue);
952 if (node->data.bin_op_expr.op1 == nullptr)
953 return nullptr;
954
955 node->data.bin_op_expr.op2 = trans_expr(c, true, block, rhs, TransRValue);
956 if (node->data.bin_op_expr.op2 == nullptr)
957 return nullptr;
958
959 return node;
960 } else {
961 // worst case
962 // c: lhs = rhs
963 // zig: {
964 // zig: const _tmp = rhs;
965 // zig: lhs = _tmp;
966 // zig: _tmp
967 // zig: }
968
969 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
970
971 // const _tmp = rhs;
972 AstNode *rhs_node = trans_expr(c, true, child_block, rhs, TransRValue);
973 if (rhs_node == nullptr) return nullptr;
974 // TODO: avoid name collisions with generated variable names
975 Buf* tmp_var_name = buf_create_from_str("_tmp");
976 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, rhs_node);
977 child_block->data.block.statements.append(tmp_var_decl);
978
979 // lhs = _tmp;
980 AstNode *lhs_node = trans_expr(c, true, child_block, lhs, TransLValue);
981 if (lhs_node == nullptr) return nullptr;
982 child_block->data.block.statements.append(
983 trans_create_node_bin_op(c, lhs_node, BinOpTypeAssign,
984 trans_create_node_symbol(c, tmp_var_name)));
985
986 // _tmp
987 child_block->data.block.statements.append(trans_create_node_symbol(c, tmp_var_name));
988 child_block->data.block.last_statement_is_result_expression = true;
989
990 return child_block;
991 }
992}
993
994static AstNode *trans_binary_operator(Context *c, bool result_used, AstNode *block, BinaryOperator *stmt) {
782995 switch (stmt->getOpcode()) {
783996 case BO_PtrMemD:
784997 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemD");
......@@ -787,20 +1000,47 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator
7871000 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_PtrMemI");
7881001 return nullptr;
7891002 case BO_Mul:
790 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Mul");
791 return nullptr;
1003 return trans_create_bin_op(c, block, stmt->getLHS(),
1004 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
1005 stmt->getRHS());
7921006 case BO_Div:
793 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Div");
794 return nullptr;
1007 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1008 // unsigned/float division uses the operator
1009 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
1010 } else {
1011 // signed integer division uses @divTrunc
1012 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc");
1013 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1014 if (lhs == nullptr) return nullptr;
1015 fn_call->data.fn_call_expr.params.append(lhs);
1016 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
1017 if (rhs == nullptr) return nullptr;
1018 fn_call->data.fn_call_expr.params.append(rhs);
1019 return fn_call;
1020 }
7951021 case BO_Rem:
796 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Rem");
797 return nullptr;
1022 if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
1023 // unsigned/float division uses the operator
1024 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
1025 } else {
1026 // signed integer division uses @divTrunc
1027 AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem");
1028 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1029 if (lhs == nullptr) return nullptr;
1030 fn_call->data.fn_call_expr.params.append(lhs);
1031 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransLValue);
1032 if (rhs == nullptr) return nullptr;
1033 fn_call->data.fn_call_expr.params.append(rhs);
1034 return fn_call;
1035 }
7981036 case BO_Add:
799 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Add");
800 return nullptr;
1037 return trans_create_bin_op(c, block, stmt->getLHS(),
1038 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
1039 stmt->getRHS());
8011040 case BO_Sub:
802 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Sub");
803 return nullptr;
1041 return trans_create_bin_op(c, block, stmt->getLHS(),
1042 qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
1043 stmt->getRHS());
8041044 case BO_Shl:
8051045 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Shl");
8061046 return nullptr;
......@@ -816,29 +1056,22 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator
8161056 case BO_GE:
8171057 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
8181058 case BO_EQ:
819 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_EQ");
820 return nullptr;
1059 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
8211060 case BO_NE:
822 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_NE");
823 return nullptr;
1061 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
8241062 case BO_And:
825 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_And");
826 return nullptr;
1063 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
8271064 case BO_Xor:
828 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Xor");
829 return nullptr;
1065 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
8301066 case BO_Or:
831 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Or");
832 return nullptr;
1067 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
8331068 case BO_LAnd:
834 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_LAnd");
835 return nullptr;
1069 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
8361070 case BO_LOr:
837 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_LOr");
838 return nullptr;
1071 // TODO: int vs bool
1072 return trans_create_bin_op(c, block, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
8391073 case BO_Assign:
840 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_Assign");
841 return nullptr;
1074 return trans_create_assign(c, result_used, block, stmt->getLHS(), stmt->getRHS());
8421075 case BO_MulAssign:
8431076 emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: BO_MulAssign");
8441077 return nullptr;
......@@ -877,32 +1110,170 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator
8771110 zig_unreachable();
8781111}
8791112
1113static AstNode *trans_compound_assign_operator(Context *c, bool result_used, AstNode *block, CompoundAssignOperator *stmt) {
1114 switch (stmt->getOpcode()) {
1115 case BO_MulAssign:
1116 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_MulAssign");
1117 return nullptr;
1118 case BO_DivAssign:
1119 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign");
1120 return nullptr;
1121 case BO_RemAssign:
1122 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign");
1123 return nullptr;
1124 case BO_AddAssign:
1125 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AddAssign");
1126 return nullptr;
1127 case BO_SubAssign:
1128 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_SubAssign");
1129 return nullptr;
1130 case BO_ShlAssign:
1131 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_ShlAssign");
1132 return nullptr;
1133 case BO_ShrAssign: {
1134 BinOpType bin_op = BinOpTypeBitShiftRight;
1135
1136 const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
1137 AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
1138
1139 bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
1140 if (!use_intermediate_casts && !result_used) {
1141 // simple common case, where the C and Zig are identical:
1142 // lhs >>= rh* s
1143 AstNode *lhs = trans_expr(c, true, block, stmt->getLHS(), TransLValue);
1144 if (lhs == nullptr) return nullptr;
1145
1146 AstNode *rhs = trans_expr(c, true, block, stmt->getRHS(), TransRValue);
1147 if (rhs == nullptr) return nullptr;
1148 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1149
1150 return trans_create_node_bin_op(c, lhs, BinOpTypeAssignBitShiftRight, coerced_rhs);
1151 } else {
1152 // need more complexity. worst case, this looks like this:
1153 // c: lhs >>= rhs
1154 // zig: {
1155 // zig: const _ref = &lhs;
1156 // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1157 // zig: *_ref
1158 // zig: }
1159 // where u5 is the appropriate type
1160
1161 // TODO: avoid mess when we don't need the assignment value for chained assignments or anything.
1162 AstNode *child_block = trans_create_node(c, NodeTypeBlock);
1163
1164 // const _ref = &lhs;
1165 AstNode *lhs = trans_expr(c, true, child_block, stmt->getLHS(), TransLValue);
1166 if (lhs == nullptr) return nullptr;
1167 AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
1168 // TODO: avoid name collisions with generated variable names
1169 Buf* tmp_var_name = buf_create_from_str("_ref");
1170 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, addr_of_lhs);
1171 child_block->data.block.statements.append(tmp_var_decl);
1172
1173 // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
1174
1175 AstNode *rhs = trans_expr(c, true, child_block, stmt->getRHS(), TransRValue);
1176 if (rhs == nullptr) return nullptr;
1177 AstNode *coerced_rhs = trans_create_node_fn_call_1(c, rhs_type, rhs);
1178
1179 AstNode *assign_statement = trans_create_node_bin_op(c,
1180 trans_create_node_prefix_op(c, PrefixOpDereference,
1181 trans_create_node_symbol(c, tmp_var_name)),
1182 BinOpTypeAssign,
1183 trans_c_cast(c, rhs_location,
1184 stmt->getComputationResultType(),
1185 trans_create_node_bin_op(c,
1186 trans_c_cast(c, rhs_location,
1187 stmt->getComputationLHSType(),
1188 trans_create_node_prefix_op(c, PrefixOpDereference,
1189 trans_create_node_symbol(c, tmp_var_name))),
1190 bin_op,
1191 coerced_rhs)));
1192 child_block->data.block.statements.append(assign_statement);
1193
1194 if (result_used) {
1195 // *_ref
1196 child_block->data.block.statements.append(
1197 trans_create_node_prefix_op(c, PrefixOpDereference,
1198 trans_create_node_symbol(c, tmp_var_name)));
1199 child_block->data.block.last_statement_is_result_expression = true;
1200 }
1201
1202 return child_block;
1203 }
1204 }
1205 case BO_AndAssign:
1206 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign");
1207 return nullptr;
1208 case BO_XorAssign:
1209 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_XorAssign");
1210 return nullptr;
1211 case BO_OrAssign:
1212 emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_OrAssign");
1213 return nullptr;
1214 case BO_PtrMemD:
1215 case BO_PtrMemI:
1216 case BO_Assign:
1217 case BO_Mul:
1218 case BO_Div:
1219 case BO_Rem:
1220 case BO_Add:
1221 case BO_Sub:
1222 case BO_Shl:
1223 case BO_Shr:
1224 case BO_LT:
1225 case BO_GT:
1226 case BO_LE:
1227 case BO_GE:
1228 case BO_EQ:
1229 case BO_NE:
1230 case BO_And:
1231 case BO_Xor:
1232 case BO_Or:
1233 case BO_LAnd:
1234 case BO_LOr:
1235 case BO_Comma:
1236 zig_panic("compound assign expected to be handled by binary operator");
1237 }
1238
1239 zig_unreachable();
1240}
1241
8801242static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) {
8811243 switch (stmt->getCastKind()) {
8821244 case CK_LValueToRValue:
883 return trans_expr(c, block, stmt->getSubExpr());
1245 return trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
8841246 case CK_IntegralCast:
8851247 {
886 AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast");
887
888 AstNode *result_type_node = trans_qual_type(c, stmt->getType(), stmt->getExprLoc());
889 if (result_type_node == nullptr)
1248 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1249 if (target_node == nullptr)
8901250 return nullptr;
891
892 AstNode *target_node = trans_expr(c, block, stmt->getSubExpr());
1251 return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node);
1252 }
1253 case CK_FunctionToPointerDecay:
1254 case CK_ArrayToPointerDecay:
1255 {
1256 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
8931257 if (target_node == nullptr)
8941258 return nullptr;
1259 return target_node;
1260 }
1261 case CK_BitCast:
1262 {
1263 AstNode *target_node = trans_expr(c, true, block, stmt->getSubExpr(), TransRValue);
1264 if (target_node == nullptr)
1265 return nullptr;
1266
1267 AstNode *dest_type_node = trans_qual_type(c, stmt->getType(), stmt->getLocStart());
8951268
896 node->data.fn_call_expr.params.append(result_type_node);
1269 AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast");
1270 node->data.fn_call_expr.params.append(dest_type_node);
8971271 node->data.fn_call_expr.params.append(target_node);
8981272 return node;
8991273 }
9001274 case CK_Dependent:
9011275 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
9021276 return nullptr;
903 case CK_BitCast:
904 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_BitCast");
905 return nullptr;
9061277 case CK_LValueBitCast:
9071278 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_LValueBitCast");
9081279 return nullptr;
......@@ -924,12 +1295,6 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas
9241295 case CK_ToUnion:
9251296 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ToUnion");
9261297 return nullptr;
927 case CK_ArrayToPointerDecay:
928 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_ArrayToPointerDecay");
929 return nullptr;
930 case CK_FunctionToPointerDecay:
931 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_FunctionToPointerDecay");
932 return nullptr;
9331298 case CK_NullToPointer:
9341299 emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_NullToPointer");
9351300 return nullptr;
......@@ -1069,17 +1434,44 @@ static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCas
10691434 zig_unreachable();
10701435}
10711436
1072static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt) {
1437static AstNode *trans_decl_ref_expr(Context *c, DeclRefExpr *stmt, TransLRValue lrval) {
10731438 ValueDecl *value_decl = stmt->getDecl();
1074 const char *name = decl_name(value_decl);
1075 return trans_create_node_symbol_str(c, name);
1439 Buf *symbol_name = buf_create_from_str(decl_name(value_decl));
1440 if (lrval == TransLValue) {
1441 c->ptr_params.put(symbol_name, true);
1442 }
1443 return trans_create_node_symbol(c, symbol_name);
10761444}
10771445
1078static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *stmt) {
1446static AstNode *trans_unary_operator(Context *c, bool result_used, AstNode *block, UnaryOperator *stmt) {
10791447 switch (stmt->getOpcode()) {
1080 case UO_PostInc:
1081 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc");
1082 return nullptr;
1448 case UO_PostInc: {
1449 Expr *op_expr = stmt->getSubExpr();
1450 BinOpType bin_op = qual_type_has_wrapping_overflow(c, op_expr->getType())
1451 ? BinOpTypeAssignPlusWrap
1452 : BinOpTypeAssignPlus;
1453
1454 if (!result_used) {
1455 // common case
1456 // c: expr++
1457 // zig: expr += 1
1458 return trans_create_node_bin_op(c,
1459 trans_expr(c, true, block, op_expr, TransLValue),
1460 bin_op,
1461 trans_create_node_unsigned(c, 1));
1462 } else {
1463 // worst case
1464 // c: expr++
1465 // zig: {
1466 // zig: const _ref = &expr;
1467 // zig: const _tmp = *_ref;
1468 // zig: *_ref += 1;
1469 // zig: _tmp
1470 // zig: }
1471 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostInc with result_used");
1472 return nullptr;
1473 }
1474 }
10831475 case UO_PostDec:
10841476 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_PostDec");
10851477 return nullptr;
......@@ -1101,11 +1493,11 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *
11011493 case UO_Minus:
11021494 {
11031495 Expr *op_expr = stmt->getSubExpr();
1104 if (c_is_signed_integer(c, op_expr->getType()) || c_is_float(c, op_expr->getType())) {
1496 if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
11051497 AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
11061498 node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
11071499
1108 node->data.prefix_op_expr.primary_expr = trans_expr(c, block, op_expr);
1500 node->data.prefix_op_expr.primary_expr = trans_expr(c, true, block, op_expr, TransRValue);
11091501 if (node->data.prefix_op_expr.primary_expr == nullptr)
11101502 return nullptr;
11111503
......@@ -1115,7 +1507,7 @@ static AstNode *trans_unary_operator(Context *c, AstNode *block, UnaryOperator *
11151507 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
11161508 node->data.bin_op_expr.op1 = trans_create_node_unsigned(c, 0);
11171509
1118 node->data.bin_op_expr.op2 = trans_expr(c, block, op_expr);
1510 node->data.bin_op_expr.op2 = trans_expr(c, true, block, op_expr, TransRValue);
11191511 if (node->data.bin_op_expr.op2 == nullptr)
11201512 return nullptr;
11211513
......@@ -1157,7 +1549,7 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st
11571549 QualType qual_type = var_decl->getTypeSourceInfo()->getType();
11581550 AstNode *init_node = nullptr;
11591551 if (var_decl->hasInit()) {
1160 init_node = trans_expr(c, block, var_decl->getInit());
1552 init_node = trans_expr(c, true, block, var_decl->getInit(), TransRValue);
11611553 if (init_node == nullptr)
11621554 return nullptr;
11631555
......@@ -1166,8 +1558,10 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st
11661558 if (type_node == nullptr)
11671559 return nullptr;
11681560
1169 AstNode *node = trans_create_node_var_decl(c, qual_type.isConstQualified(),
1170 buf_create_from_str(decl_name(var_decl)), type_node, init_node);
1561 Buf *symbol_name = buf_create_from_str(decl_name(var_decl));
1562
1563 AstNode *node = trans_create_node_var_decl_local(c, qual_type.isConstQualified(),
1564 symbol_name, type_node, init_node);
11711565 block->data.block.statements.append(node);
11721566 continue;
11731567 }
......@@ -1398,18 +1792,112 @@ static AstNode *trans_local_declaration(Context *c, AstNode *block, DeclStmt *st
13981792static AstNode *trans_while_loop(Context *c, AstNode *block, WhileStmt *stmt) {
13991793 AstNode *while_node = trans_create_node(c, NodeTypeWhileExpr);
14001794
1401 while_node->data.while_expr.condition = trans_expr(c, block, stmt->getCond());
1795 while_node->data.while_expr.condition = trans_expr(c, true, block, stmt->getCond(), TransRValue);
14021796 if (while_node->data.while_expr.condition == nullptr)
14031797 return nullptr;
14041798
1405 while_node->data.while_expr.body = trans_stmt(c, block, stmt->getBody());
1799 while_node->data.while_expr.body = trans_stmt(c, false, block, stmt->getBody(), TransRValue);
14061800 if (while_node->data.while_expr.body == nullptr)
14071801 return nullptr;
14081802
14091803 return while_node;
14101804}
14111805
1412static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
1806static AstNode *trans_if_statement(Context *c, AstNode *block, IfStmt *stmt) {
1807 // if (c) t
1808 // if (c) t else e
1809 AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
1810
1811 // TODO: condition != 0
1812 AstNode *condition_node = trans_expr(c, true, block, stmt->getCond(), TransRValue);
1813 if (condition_node == nullptr)
1814 return nullptr;
1815 if_node->data.if_bool_expr.condition = condition_node;
1816
1817 if_node->data.if_bool_expr.then_block = trans_stmt(c, false, block, stmt->getThen(), TransRValue);
1818 if (if_node->data.if_bool_expr.then_block == nullptr)
1819 return nullptr;
1820
1821 if (stmt->getElse() != nullptr) {
1822 if_node->data.if_bool_expr.else_node = trans_stmt(c, false, block, stmt->getElse(), TransRValue);
1823 if (if_node->data.if_bool_expr.else_node == nullptr)
1824 return nullptr;
1825 }
1826
1827 return if_node;
1828}
1829
1830static AstNode *trans_call_expr(Context *c, bool result_used, AstNode *block, CallExpr *stmt) {
1831 AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
1832 node->data.fn_call_expr.fn_ref_expr = trans_expr(c, true, block, stmt->getCallee(), TransRValue);
1833 if (node->data.fn_call_expr.fn_ref_expr == nullptr)
1834 return nullptr;
1835
1836 unsigned num_args = stmt->getNumArgs();
1837 Expr **args = stmt->getArgs();
1838 for (unsigned i = 0; i < num_args; i += 1) {
1839 AstNode *arg_node = trans_expr(c, true, block, args[i], TransRValue);
1840 if (arg_node == nullptr)
1841 return nullptr;
1842
1843 node->data.fn_call_expr.params.append(arg_node);
1844 }
1845
1846 return node;
1847}
1848
1849static AstNode *trans_member_expr(Context *c, AstNode *block, MemberExpr *stmt) {
1850 AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue);
1851 if (container_node == nullptr)
1852 return nullptr;
1853
1854 if (stmt->isArrow()) {
1855 container_node = trans_create_node_unwrap_null(c, container_node);
1856 }
1857
1858 const char *name = decl_name(stmt->getMemberDecl());
1859
1860 AstNode *node = trans_create_node_field_access_str(c, container_node, name);
1861 return node;
1862}
1863
1864static AstNode *trans_array_subscript_expr(Context *c, AstNode *block, ArraySubscriptExpr *stmt) {
1865 AstNode *container_node = trans_expr(c, true, block, stmt->getBase(), TransRValue);
1866 if (container_node == nullptr)
1867 return nullptr;
1868
1869 AstNode *idx_node = trans_expr(c, true, block, stmt->getIdx(), TransRValue);
1870 if (idx_node == nullptr)
1871 return nullptr;
1872
1873
1874 AstNode *node = trans_create_node(c, NodeTypeArrayAccessExpr);
1875 node->data.array_access_expr.array_ref_expr = container_node;
1876 node->data.array_access_expr.subscript = idx_node;
1877 return node;
1878}
1879
1880static AstNode *trans_c_style_cast_expr(Context *c, bool result_used, AstNode *block,
1881 CStyleCastExpr *stmt, TransLRValue lrvalue)
1882{
1883 AstNode *sub_expr_node = trans_expr(c, result_used, block, stmt->getSubExpr(), lrvalue);
1884 if (sub_expr_node == nullptr)
1885 return nullptr;
1886
1887 return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), sub_expr_node);
1888}
1889
1890static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, AstNode *block, UnaryExprOrTypeTraitExpr *stmt) {
1891 AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart());
1892 if (type_node == nullptr)
1893 return nullptr;
1894
1895 AstNode *node = trans_create_node_builtin_fn_call_str(c, "sizeOf");
1896 node->data.fn_call_expr.params.append(type_node);
1897 return node;
1898}
1899
1900static AstNode *trans_stmt(Context *c, bool result_used, AstNode *block, Stmt *stmt, TransLRValue lrvalue) {
14131901 Stmt::StmtClass sc = stmt->getStmtClass();
14141902 switch (sc) {
14151903 case Stmt::ReturnStmtClass:
......@@ -1419,19 +1907,35 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
14191907 case Stmt::IntegerLiteralClass:
14201908 return trans_integer_literal(c, (IntegerLiteral *)stmt);
14211909 case Stmt::ConditionalOperatorClass:
1422 return trans_conditional_operator(c, block, (ConditionalOperator *)stmt);
1910 return trans_conditional_operator(c, result_used, block, (ConditionalOperator *)stmt);
14231911 case Stmt::BinaryOperatorClass:
1424 return trans_binary_operator(c, block, (BinaryOperator *)stmt);
1912 return trans_binary_operator(c, result_used, block, (BinaryOperator *)stmt);
1913 case Stmt::CompoundAssignOperatorClass:
1914 return trans_compound_assign_operator(c, result_used, block, (CompoundAssignOperator *)stmt);
14251915 case Stmt::ImplicitCastExprClass:
14261916 return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt);
14271917 case Stmt::DeclRefExprClass:
1428 return trans_decl_ref_expr(c, (DeclRefExpr *)stmt);
1918 return trans_decl_ref_expr(c, (DeclRefExpr *)stmt, lrvalue);
14291919 case Stmt::UnaryOperatorClass:
1430 return trans_unary_operator(c, block, (UnaryOperator *)stmt);
1920 return trans_unary_operator(c, result_used, block, (UnaryOperator *)stmt);
14311921 case Stmt::DeclStmtClass:
14321922 return trans_local_declaration(c, block, (DeclStmt *)stmt);
14331923 case Stmt::WhileStmtClass:
14341924 return trans_while_loop(c, block, (WhileStmt *)stmt);
1925 case Stmt::IfStmtClass:
1926 return trans_if_statement(c, block, (IfStmt *)stmt);
1927 case Stmt::CallExprClass:
1928 return trans_call_expr(c, result_used, block, (CallExpr *)stmt);
1929 case Stmt::NullStmtClass:
1930 return skip_add_to_block_node;
1931 case Stmt::MemberExprClass:
1932 return trans_member_expr(c, block, (MemberExpr *)stmt);
1933 case Stmt::ArraySubscriptExprClass:
1934 return trans_array_subscript_expr(c, block, (ArraySubscriptExpr *)stmt);
1935 case Stmt::CStyleCastExprClass:
1936 return trans_c_style_cast_expr(c, result_used, block, (CStyleCastExpr *)stmt, lrvalue);
1937 case Stmt::UnaryExprOrTypeTraitExprClass:
1938 return trans_unary_expr_or_type_trait_expr(c, block, (UnaryExprOrTypeTraitExpr *)stmt);
14351939 case Stmt::CaseStmtClass:
14361940 emit_warning(c, stmt->getLocStart(), "TODO handle C CaseStmtClass");
14371941 return nullptr;
......@@ -1492,9 +1996,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
14921996 case Stmt::ArrayInitLoopExprClass:
14931997 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayInitLoopExprClass");
14941998 return nullptr;
1495 case Stmt::ArraySubscriptExprClass:
1496 emit_warning(c, stmt->getLocStart(), "TODO handle C ArraySubscriptExprClass");
1497 return nullptr;
14981999 case Stmt::ArrayTypeTraitExprClass:
14992000 emit_warning(c, stmt->getLocStart(), "TODO handle C ArrayTypeTraitExprClass");
15002001 return nullptr;
......@@ -1504,9 +2005,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
15042005 case Stmt::AtomicExprClass:
15052006 emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");
15062007 return nullptr;
1507 case Stmt::CompoundAssignOperatorClass:
1508 emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundAssignOperatorClass");
1509 return nullptr;
15102008 case Stmt::BlockExprClass:
15112009 emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");
15122010 return nullptr;
......@@ -1573,13 +2071,11 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
15732071 case Stmt::CXXUuidofExprClass:
15742072 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXUuidofExprClass");
15752073 return nullptr;
1576 case Stmt::CallExprClass:
1577 emit_warning(c, stmt->getLocStart(), "TODO handle C CallExprClass");
1578 return nullptr;
15792074 case Stmt::CUDAKernelCallExprClass:
15802075 emit_warning(c, stmt->getLocStart(), "TODO handle C CUDAKernelCallExprClass");
15812076 return nullptr;
15822077 case Stmt::CXXMemberCallExprClass:
2078 (void)result_used;
15832079 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXMemberCallExprClass");
15842080 return nullptr;
15852081 case Stmt::CXXOperatorCallExprClass:
......@@ -1588,9 +2084,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
15882084 case Stmt::UserDefinedLiteralClass:
15892085 emit_warning(c, stmt->getLocStart(), "TODO handle C UserDefinedLiteralClass");
15902086 return nullptr;
1591 case Stmt::CStyleCastExprClass:
1592 emit_warning(c, stmt->getLocStart(), "TODO handle C CStyleCastExprClass");
1593 return nullptr;
15942087 case Stmt::CXXFunctionalCastExprClass:
15952088 emit_warning(c, stmt->getLocStart(), "TODO handle C CXXFunctionalCastExprClass");
15962089 return nullptr;
......@@ -1681,9 +2174,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
16812174 case Stmt::MaterializeTemporaryExprClass:
16822175 emit_warning(c, stmt->getLocStart(), "TODO handle C MaterializeTemporaryExprClass");
16832176 return nullptr;
1684 case Stmt::MemberExprClass:
1685 emit_warning(c, stmt->getLocStart(), "TODO handle C MemberExprClass");
1686 return nullptr;
16872177 case Stmt::NoInitExprClass:
16882178 emit_warning(c, stmt->getLocStart(), "TODO handle C NoInitExprClass");
16892179 return nullptr;
......@@ -1751,8 +2241,7 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
17512241 emit_warning(c, stmt->getLocStart(), "TODO handle C PackExpansionExprClass");
17522242 return nullptr;
17532243 case Stmt::ParenExprClass:
1754 emit_warning(c, stmt->getLocStart(), "TODO handle C ParenExprClass");
1755 return nullptr;
2244 return trans_expr(c, result_used, block, ((ParenExpr*)stmt)->getSubExpr(), lrvalue);
17562245 case Stmt::ParenListExprClass:
17572246 emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass");
17582247 return nullptr;
......@@ -1786,9 +2275,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
17862275 case Stmt::TypoExprClass:
17872276 emit_warning(c, stmt->getLocStart(), "TODO handle C TypoExprClass");
17882277 return nullptr;
1789 case Stmt::UnaryExprOrTypeTraitExprClass:
1790 emit_warning(c, stmt->getLocStart(), "TODO handle C UnaryExprOrTypeTraitExprClass");
1791 return nullptr;
17922278 case Stmt::VAArgExprClass:
17932279 emit_warning(c, stmt->getLocStart(), "TODO handle C VAArgExprClass");
17942280 return nullptr;
......@@ -1798,9 +2284,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
17982284 case Stmt::GotoStmtClass:
17992285 emit_warning(c, stmt->getLocStart(), "TODO handle C GotoStmtClass");
18002286 return nullptr;
1801 case Stmt::IfStmtClass:
1802 emit_warning(c, stmt->getLocStart(), "TODO handle C IfStmtClass");
1803 return nullptr;
18042287 case Stmt::IndirectGotoStmtClass:
18052288 emit_warning(c, stmt->getLocStart(), "TODO handle C IndirectGotoStmtClass");
18062289 return nullptr;
......@@ -1810,9 +2293,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
18102293 case Stmt::MSDependentExistsStmtClass:
18112294 emit_warning(c, stmt->getLocStart(), "TODO handle C MSDependentExistsStmtClass");
18122295 return nullptr;
1813 case Stmt::NullStmtClass:
1814 emit_warning(c, stmt->getLocStart(), "TODO handle C NullStmtClass");
1815 return nullptr;
18162296 case Stmt::OMPAtomicDirectiveClass:
18172297 emit_warning(c, stmt->getLocStart(), "TODO handle C OMPAtomicDirectiveClass");
18182298 return nullptr;
......@@ -2025,36 +2505,65 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
20252505 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
20262506 const ParmVarDecl *param = fn_decl->getParamDecl(i);
20272507 const char *name = decl_name(param);
2028 if (strlen(name) == 0) {
2029 Buf *proto_param_name = param_node->data.param_decl.name;
2508 Buf *proto_param_name;
2509 if (strlen(name) != 0) {
2510 proto_param_name = buf_create_from_str(name);
2511 } else {
2512 proto_param_name = param_node->data.param_decl.name;
20302513 if (proto_param_name == nullptr) {
2031 param_node->data.param_decl.name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
2032 } else {
2033 param_node->data.param_decl.name = proto_param_name;
2514 proto_param_name = buf_sprintf("arg%" ZIG_PRI_usize "", i);
20342515 }
2035 } else {
2036 param_node->data.param_decl.name = buf_create_from_str(name);
20372516 }
2517 param_node->data.param_decl.name = proto_param_name;
2518 }
2519
2520 if (!fn_decl->hasBody()) {
2521 // just a prototype
2522 c->root->data.root.top_level_decls.append(proto_node);
2523 return;
20382524 }
20392525
2040 if (fn_decl->hasBody()) {
2041 Stmt *body = fn_decl->getBody();
2526 // actual function definition with body
2527 c->ptr_params.clear();
2528 Stmt *body = fn_decl->getBody();
2529 AstNode *actual_body_node = trans_stmt(c, false, nullptr, body, TransRValue);
2530 assert(actual_body_node != skip_add_to_block_node);
2531 if (actual_body_node == nullptr) {
2532 emit_warning(c, fn_decl->getLocation(), "unable to translate function");
2533 return;
2534 }
20422535
2043 AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef);
2044 fn_def_node->data.fn_def.fn_proto = proto_node;
2045 fn_def_node->data.fn_def.body = trans_stmt(c, nullptr, body);
2046 assert(fn_def_node->data.fn_def.body != skip_add_to_block_node);
2047 if (fn_def_node->data.fn_def.body == nullptr) {
2048 emit_warning(c, fn_decl->getLocation(), "unable to translate function");
2049 return;
2536 // it worked
2537
2538 assert(actual_body_node->type == NodeTypeBlock);
2539 AstNode *body_node_with_param_inits = trans_create_node(c, NodeTypeBlock);
2540
2541 for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
2542 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
2543 Buf *good_name = param_node->data.param_decl.name;
2544
2545 if (c->ptr_params.maybe_get(good_name) != nullptr) {
2546 // TODO: avoid name collisions
2547 Buf *mangled_name = buf_sprintf("_arg_%s", buf_ptr(good_name));
2548 param_node->data.param_decl.name = mangled_name;
2549
2550 // var c_name = _mangled_name;
2551 AstNode *parameter_init = trans_create_node_var_decl_local(c, false, good_name, nullptr, trans_create_node_symbol(c, mangled_name));
2552
2553 body_node_with_param_inits->data.block.statements.append(parameter_init);
20502554 }
2555 }
20512556
2052 proto_node->data.fn_proto.fn_def_node = fn_def_node;
2053 c->root->data.root.top_level_decls.append(fn_def_node);
2054 return;
2557 for (size_t i = 0; i < actual_body_node->data.block.statements.length; i += 1) {
2558 body_node_with_param_inits->data.block.statements.append(actual_body_node->data.block.statements.at(i));
20552559 }
20562560
2057 c->root->data.root.top_level_decls.append(proto_node);
2561 AstNode *fn_def_node = trans_create_node(c, NodeTypeFnDef);
2562 fn_def_node->data.fn_def.fn_proto = proto_node;
2563 fn_def_node->data.fn_def.body = body_node_with_param_inits;
2564
2565 proto_node->data.fn_proto.fn_def_node = fn_def_node;
2566 c->root->data.root.top_level_decls.append(fn_def_node);
20582567}
20592568
20602569static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {
......@@ -2190,9 +2699,14 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
21902699
21912700 // in C each enum value is in the global namespace. so we put them there too.
21922701 // at this point we can rely on the enum emitting successfully
2193 AstNode *field_access_node = trans_create_node_field_access(c,
2194 trans_create_node_symbol(c, full_type_name), field_name);
2195 add_global_var(c, enum_val_name, field_access_node);
2702 if (is_anonymous) {
2703 AstNode *lit_node = trans_create_node_unsigned(c, i);
2704 add_global_var(c, enum_val_name, lit_node);
2705 } else {
2706 AstNode *field_access_node = trans_create_node_field_access(c,
2707 trans_create_node_symbol(c, full_type_name), field_name);
2708 add_global_var(c, enum_val_name, field_access_node);
2709 }
21962710 }
21972711
21982712 if (is_anonymous) {
......@@ -2376,7 +2890,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
23762890 init_node = trans_create_node_apint(c, ap_value->getInt());
23772891 break;
23782892 case APValue::Uninitialized:
2379 init_node = trans_create_node_symbol_str(c, "undefined");
2893 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
23802894 break;
23812895 case APValue::Float:
23822896 case APValue::ComplexInt:
......@@ -2393,16 +2907,16 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
23932907 return;
23942908 }
23952909 } else {
2396 init_node = trans_create_node_symbol_str(c, "undefined");
2910 init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
23972911 }
23982912
2399 AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, init_node);
2913 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, init_node);
24002914 c->root->data.root.top_level_decls.append(var_node);
24012915 return;
24022916 }
24032917
24042918 if (is_extern) {
2405 AstNode *var_node = trans_create_node_var_decl(c, is_const, name, var_type, nullptr);
2919 AstNode *var_node = trans_create_node_var_decl_global(c, is_const, name, var_type, nullptr);
24062920 var_node->data.variable_declaration.is_extern = true;
24072921 c->root->data.root.top_level_decls.append(var_node);
24082922 return;
......@@ -2663,6 +3177,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
26633177 c->visib_mod = VisibModPub;
26643178 c->decl_table.init(8);
26653179 c->macro_table.init(8);
3180 c->ptr_params.init(8);
26663181 c->codegen = codegen;
26673182 c->source_node = source_node;
26683183
src/util.hpp+4
......@@ -147,4 +147,8 @@ bool uint64_eq(uint64_t a, uint64_t b);
147147uint32_t ptr_hash(const void *ptr);
148148bool ptr_eq(const void *a, const void *b);
149149
150static inline uint8_t log2_u64(uint64_t x) {
151 return (63 - clzll(x));
152}
153
150154#endif
test/parsec.zig+295-1
......@@ -98,7 +98,7 @@ pub fn addCases(cases: &tests.ParseCContext) {
9898 ,
9999 \\pub const BarB = enum_Bar.B;
100100 ,
101 \\pub extern fn func(a: ?&struct_Foo, b: ?&?&enum_Bar);
101 \\pub extern fn func(a: ?&struct_Foo, b: ?&(?&enum_Bar));
102102 ,
103103 \\pub const Foo = struct_Foo;
104104 ,
......@@ -314,4 +314,298 @@ pub fn addCases(cases: &tests.ParseCContext) {
314314 ,
315315 \\pub const LUA_GLOBALSINDEX = -10002;
316316 );
317
318 cases.add("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.add("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.add("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.add("==, !=",
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.add("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.add("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.add("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.add("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.add("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.add("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.add("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.add("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.add("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.add("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.add("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.add("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.add("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 );
317599}
600
601
602
603
604// TODO
605//float *ptrcast(int *a) {
606// return (float *)a;
607//}
608// should translate to
609// fn ptrcast(a: ?&c_int) -> ?&f32 {
610// return @ptrCast(?&f32, a);
611// }
test/tests.zig+2-2
......@@ -780,7 +780,7 @@ pub const ParseCContext = struct {
780780 });
781781 }
782782
783 pub fn addExpectedError(self: &TestCase, text: []const u8) {
783 pub fn addExpectedLine(self: &TestCase, text: []const u8) {
784784 %%self.expected_lines.append(text);
785785 }
786786 };
......@@ -905,7 +905,7 @@ pub const ParseCContext = struct {
905905 tc.addSourceFile("source.h", source);
906906 comptime var arg_i = 0;
907907 inline while (arg_i < expected_lines.len) : (arg_i += 1) {
908 tc.addExpectedError(expected_lines[arg_i]);
908 tc.addExpectedLine(expected_lines[arg_i]);
909909 }
910910 return tc;
911911 }