Commit 2e010c60ae
Changed files (2)
test
src/translate_c.cpp
@@ -119,7 +119,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
-static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr);
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
ATTRIBUTE_PRINTF(3, 4)
static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {
@@ -467,6 +467,14 @@ static QualType get_expr_qual_type(Context *c, const Expr *expr) {
return expr->getType();
}
+static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {
+ if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
+ const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
+ return get_expr_qual_type(c, cast_expr->getSubExpr());
+ }
+ return expr->getType();
+}
+
static AstNode *get_expr_type(Context *c, const Expr *expr) {
return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
}
@@ -1152,6 +1160,22 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi
return node;
}
+static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {
+ assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
+ AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
+ node->data.bin_op_expr.bin_op = bin_op;
+
+ node->data.bin_op_expr.op1 = trans_bool_expr(c, ResultUsedYes, scope, lhs, TransRValue);
+ if (node->data.bin_op_expr.op1 == nullptr)
+ return nullptr;
+
+ node->data.bin_op_expr.op2 = trans_bool_expr(c, ResultUsedYes, scope, rhs, TransRValue);
+ if (node->data.bin_op_expr.op2 == nullptr)
+ return nullptr;
+
+ return node;
+}
+
static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {
if (result_used == ResultUsedNo) {
// common case
@@ -1293,10 +1317,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
case BO_Or:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
case BO_LAnd:
- return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
+ return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
case BO_LOr:
- // TODO: int vs bool
- return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
+ return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
case BO_Assign:
return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
case BO_Comma:
@@ -1924,7 +1947,6 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
return nullptr;
}
}
- case UO_LNot:
case UO_Not:
{
Expr *op_expr = stmt->getSubExpr();
@@ -1932,14 +1954,16 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
if (sub_node == nullptr)
return nullptr;
- switch (stmt->getOpcode()) {
- case UO_LNot:
- return trans_create_node_prefix_op(c, PrefixOpBoolNot, trans_to_bool_expr(c, scope, sub_node));
- case UO_Not:
- return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
- default:
- zig_unreachable();
- }
+ return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
+ }
+ case UO_LNot:
+ {
+ Expr *op_expr = stmt->getSubExpr();
+ AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
+ if (sub_node == nullptr)
+ return nullptr;
+
+ return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
}
case UO_Real:
emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real");
@@ -2220,10 +2244,30 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
return ErrorNone;
}
-static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) {
- switch (expr->type) {
+static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) {
+ AstNode *tag_type = trans_create_node_builtin_fn_call_str(c, "TagType");
+ tag_type->data.fn_call_expr.params.append(enum_type);
+
+ // @TagType(Enum)(0)
+ AstNode *zero = trans_create_node_unsigned_negative(c, 0, false);
+ AstNode *casted_zero = trans_create_node_fn_call_1(c, tag_type, zero);
+
+ // @bitCast(Enum, @TagType(Enum)(0))
+ AstNode *bitcast = trans_create_node_builtin_fn_call_str(c, "bitCast");
+ bitcast->data.fn_call_expr.params.append(enum_type);
+ bitcast->data.fn_call_expr.params.append(casted_zero);
+
+ return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
+}
+
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) {
+ AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
+ if (res == nullptr)
+ return nullptr;
+
+ switch (res->type) {
case NodeTypeBinOpExpr:
- switch (expr->data.bin_op_expr.bin_op) {
+ switch (res->data.bin_op_expr.bin_op) {
case BinOpTypeBoolOr:
case BinOpTypeBoolAnd:
case BinOpTypeCmpEq:
@@ -2232,76 +2276,208 @@ static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr)
case BinOpTypeCmpGreaterThan:
case BinOpTypeCmpLessOrEq:
case BinOpTypeCmpGreaterOrEq:
- return expr;
+ return res;
default:
- goto convert_to_bitcast;
+ break;
}
case NodeTypePrefixOpExpr:
- switch (expr->data.prefix_op_expr.prefix_op) {
+ switch (res->data.prefix_op_expr.prefix_op) {
case PrefixOpBoolNot:
- return expr;
+ return res;
default:
- goto convert_to_bitcast;
+ break;
}
case NodeTypeBoolLiteral:
- return expr;
-
- default: {
- // In Zig, float, int and pointer does not implicitly cast to bool.
- // To make it work, we bitcast any value we get to an int of the right size
- // and comp it to 0
- // TODO: This doesn't work for pointers, as they become nullable on
- // translate
- // c: expr
- // zig: __to_bool_expr: {
- // zig: const _tmp = cond;
- // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
- // zig: }
- convert_to_bitcast:
- TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
- Buf *label_name = buf_create_from_str("__to_bool_expr");
- child_scope->node->data.block.name = label_name;
-
- // const _tmp = cond;
- // TODO: avoid name collisions with generated variable names
- Buf *tmp_var_name = buf_create_from_str("_tmp");
- AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr);
- child_scope->node->data.block.statements.append(tmp_var_decl);
-
- // @sizeOf(@typeOf(_tmp)) * 8
- AstNode *typeof_tmp = trans_create_node_builtin_fn_call_str(c, "typeOf");
- typeof_tmp->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
- AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");
- sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);
- AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(
- c, sizeof_tmp, BinOpTypeMult,
- trans_create_node_unsigned_negative(c, 8, false));
-
- // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)
- AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType");
- int_type->data.fn_call_expr.params.append(trans_create_node_bool(c, false));
- int_type->data.fn_call_expr.params.append(sizeof_tmp_in_bits);
-
- // @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp)
- AstNode *bit_cast = trans_create_node_builtin_fn_call_str(c, "bitCast");
- bit_cast->data.fn_call_expr.params.append(int_type);
- bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
-
- // break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0
- AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
- child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero));
-
- return child_scope->node;
+ return res;
+
+ default:
+ break;
+ }
+
+
+ const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
+ auto classs = ty->getTypeClass();
+ switch (classs) {
+ case Type::Builtin:
+ {
+ const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
+ switch (builtin_ty->getKind()) {
+ case BuiltinType::Bool:
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ case BuiltinType::LongLong:
+ case BuiltinType::UInt128:
+ case BuiltinType::Int128:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::Float128:
+ case BuiltinType::LongDouble:
+ case BuiltinType::WChar_U:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::WChar_S:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
+ case BuiltinType::NullPtr:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
+
+ case BuiltinType::Void:
+ case BuiltinType::Half:
+ case BuiltinType::ObjCId:
+ case BuiltinType::ObjCClass:
+ case BuiltinType::ObjCSel:
+ case BuiltinType::OMPArraySection:
+ case BuiltinType::Dependent:
+ case BuiltinType::Overload:
+ case BuiltinType::BoundMember:
+ case BuiltinType::PseudoObject:
+ case BuiltinType::UnknownAny:
+ case BuiltinType::BuiltinFn:
+ case BuiltinType::ARCUnbridgedCast:
+ case BuiltinType::OCLImage1dRO:
+ case BuiltinType::OCLImage1dArrayRO:
+ case BuiltinType::OCLImage1dBufferRO:
+ case BuiltinType::OCLImage2dRO:
+ case BuiltinType::OCLImage2dArrayRO:
+ case BuiltinType::OCLImage2dDepthRO:
+ case BuiltinType::OCLImage2dArrayDepthRO:
+ case BuiltinType::OCLImage2dMSAARO:
+ case BuiltinType::OCLImage2dArrayMSAARO:
+ case BuiltinType::OCLImage2dMSAADepthRO:
+ case BuiltinType::OCLImage2dArrayMSAADepthRO:
+ case BuiltinType::OCLImage3dRO:
+ case BuiltinType::OCLImage1dWO:
+ case BuiltinType::OCLImage1dArrayWO:
+ case BuiltinType::OCLImage1dBufferWO:
+ case BuiltinType::OCLImage2dWO:
+ case BuiltinType::OCLImage2dArrayWO:
+ case BuiltinType::OCLImage2dDepthWO:
+ case BuiltinType::OCLImage2dArrayDepthWO:
+ case BuiltinType::OCLImage2dMSAAWO:
+ case BuiltinType::OCLImage2dArrayMSAAWO:
+ case BuiltinType::OCLImage2dMSAADepthWO:
+ case BuiltinType::OCLImage2dArrayMSAADepthWO:
+ case BuiltinType::OCLImage3dWO:
+ case BuiltinType::OCLImage1dRW:
+ case BuiltinType::OCLImage1dArrayRW:
+ case BuiltinType::OCLImage1dBufferRW:
+ case BuiltinType::OCLImage2dRW:
+ case BuiltinType::OCLImage2dArrayRW:
+ case BuiltinType::OCLImage2dDepthRW:
+ case BuiltinType::OCLImage2dArrayDepthRW:
+ case BuiltinType::OCLImage2dMSAARW:
+ case BuiltinType::OCLImage2dArrayMSAARW:
+ case BuiltinType::OCLImage2dMSAADepthRW:
+ case BuiltinType::OCLImage2dArrayMSAADepthRW:
+ case BuiltinType::OCLImage3dRW:
+ case BuiltinType::OCLSampler:
+ case BuiltinType::OCLEvent:
+ case BuiltinType::OCLClkEvent:
+ case BuiltinType::OCLQueue:
+ case BuiltinType::OCLReserveID:
+ return res;
+ }
+ break;
+ }
+ case Type::Pointer:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
+
+ case Type::Typedef:
+ {
+ const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
+ const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
+ if (existing_entry) {
+ return existing_entry->value;
+ }
+
+ return res;
}
+
+ case Type::Enum:
+ {
+ const EnumType *enum_ty = static_cast<const EnumType*>(ty);
+ AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
+ return to_enum_zero_cmp(c, res, enum_type);
+ }
+
+ case Type::Elaborated:
+ {
+ const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
+ switch (elaborated_ty->getKeyword()) {
+ case ETK_Enum: {
+ AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart());
+ return to_enum_zero_cmp(c, res, enum_type);
+ }
+ case ETK_Struct:
+ case ETK_Union:
+ case ETK_Interface:
+ case ETK_Class:
+ case ETK_Typename:
+ case ETK_None:
+ return res;
+ }
+ }
+
+ case Type::FunctionProto:
+ case Type::Record:
+ case Type::ConstantArray:
+ case Type::Paren:
+ case Type::Decayed:
+ case Type::Attributed:
+ case Type::IncompleteArray:
+ case Type::BlockPointer:
+ case Type::LValueReference:
+ case Type::RValueReference:
+ case Type::MemberPointer:
+ case Type::VariableArray:
+ case Type::DependentSizedArray:
+ case Type::DependentSizedExtVector:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::FunctionNoProto:
+ case Type::UnresolvedUsing:
+ case Type::Adjusted:
+ case Type::TypeOfExpr:
+ case Type::TypeOf:
+ case Type::Decltype:
+ case Type::UnaryTransform:
+ case Type::TemplateTypeParm:
+ case Type::SubstTemplateTypeParm:
+ case Type::SubstTemplateTypeParmPack:
+ case Type::TemplateSpecialization:
+ case Type::Auto:
+ case Type::InjectedClassName:
+ case Type::DependentName:
+ case Type::DependentTemplateSpecialization:
+ case Type::PackExpansion:
+ case Type::ObjCObject:
+ case Type::ObjCInterface:
+ case Type::Complex:
+ case Type::ObjCObjectPointer:
+ case Type::Atomic:
+ case Type::Pipe:
+ case Type::ObjCTypeParam:
+ case Type::DeducedTemplateSpecialization:
+ return res;
}
+ zig_unreachable();
}
static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
- while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, scope, trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue));
+ while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
if (while_scope->node->data.while_expr.condition == nullptr)
return nullptr;
@@ -2328,11 +2504,10 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
return nullptr;
}
- AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
- if (condition_node == nullptr)
+ if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
+ if (if_node->data.if_bool_expr.condition == nullptr)
return nullptr;
- if_node->data.if_bool_expr.condition = trans_to_bool_expr(c, scope, condition_node);
return if_node;
}
@@ -2524,12 +2699,18 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
if (cond_stmt == nullptr) {
while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
} else {
- TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,
- &while_scope->node->data.while_expr.condition);
- if (end_cond_scope == nullptr)
- return nullptr;
+ if (Expr::classof(cond_stmt)) {
+ const Expr *cond_expr = static_cast<const Expr*>(cond_stmt);
+ while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
- while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, cond_scope, while_scope->node->data.while_expr.condition);
+ if (while_scope->node->data.while_expr.condition == nullptr)
+ return nullptr;
+ } else {
+ TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,
+ &while_scope->node->data.while_expr.condition);
+ if (end_cond_scope == nullptr)
+ return nullptr;
+ }
}
const Stmt *inc_stmt = stmt->getInc();
test/translate_c.zig
@@ -451,6 +451,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\}
);
+ cases.addC("logical and, logical or on none bool values",
+ \\int and_or_none_bool(int a, float b, void *c) {
+ \\ if (a && b) return 0;
+ \\ if (b && c) return 1;
+ \\ if (a && c) return 2;
+ \\ if (a || b) return 3;
+ \\ if (b || c) return 4;
+ \\ if (a || c) return 5;
+ \\ return 6;
+ \\}
+ ,
+ \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
+ \\ if ((a != 0) and (b != 0)) return 0;
+ \\ if ((b != 0) and (c != null)) return 1;
+ \\ if ((a != 0) and (c != null)) return 2;
+ \\ if ((a != 0) or (b != 0)) return 3;
+ \\ if ((b != 0) or (c != null)) return 4;
+ \\ if ((a != 0) or (c != null)) return 5;
+ \\ return 6;
+ \\}
+ );
+
cases.addC("assign",
\\int max(int a) {
\\ int tmp;
@@ -1102,17 +1124,18 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
);
cases.add("bool not",
- \\int foo(int x) {
- \\ return !(x == 0);
- \\ return !x;
+ \\int foo(int a, float b, void *c) {
+ \\ return !(a == 0);
+ \\ return !a;
+ \\ return !b;
+ \\ return !c;
\\}
,
- \\pub fn foo(x: c_int) c_int {
- \\ return !(x == 0);
- \\ return !__to_bool_expr: {
- \\ const _tmp = x;
- \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
- \\ };
+ \\pub fn foo(a: c_int, b: f32, c: ?&c_void) c_int {
+ \\ return !(a == 0);
+ \\ return !(a != 0);
+ \\ return !(b != 0);
+ \\ return !(c != null);
\\}
);
@@ -1148,75 +1171,66 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
\\pub const NRF_GPIO = if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Pointer) @ptrCast(&NRF_GPIO_Type, NRF_GPIO_BASE) else if (@typeId(@typeOf(NRF_GPIO_BASE)) == @import("builtin").TypeId.Int) @intToPtr(&NRF_GPIO_Type, NRF_GPIO_BASE) else (&NRF_GPIO_Type)(NRF_GPIO_BASE);
);
- cases.add("if on int",
- \\int if_int(int i) {
- \\ if (i) {
- \\ return 0;
- \\ } else {
- \\ return 1;
- \\ }
+ cases.add("if on none bool",
+ \\enum SomeEnum { A, B, C };
+ \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
+ \\ if (a) return 0;
+ \\ if (b) return 1;
+ \\ if (c) return 2;
+ \\ if (d) return 3;
+ \\ return 4;
\\}
,
- \\pub fn if_int(i: c_int) c_int {
- \\ if (__to_bool_expr: {
- \\ const _tmp = i;
- \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
- \\ }) {
- \\ return 0;
- \\ } else {
- \\ return 1;
- \\ }
- \\}
+ \\pub const A = enum_SomeEnum.A;
+ \\pub const B = enum_SomeEnum.B;
+ \\pub const C = enum_SomeEnum.C;
+ \\pub const enum_SomeEnum = extern enum {
+ \\ A,
+ \\ B,
+ \\ C,
+ \\};
+ \\pub fn if_none_bool(a: c_int, b: f32, c: ?&c_void, d: enum_SomeEnum) c_int {
+ \\ if (a != 0) return 0;
+ \\ if (b != 0) return 1;
+ \\ if (c != null) return 2;
+ \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
+ \\ return 4;
+ \\}
);
- cases.add("while on int",
- \\int while_int(int i) {
- \\ while (i) {
- \\ return 0;
- \\ }
+ cases.add("while on none bool",
+ \\int while_none_bool(int a, float b, void *c) {
+ \\ while (a) return 0;
+ \\ while (b) return 1;
+ \\ while (c) return 2;
+ \\ return 3;
\\}
,
- \\pub fn while_int(i: c_int) c_int {
- \\ while (__to_bool_expr: {
- \\ const _tmp = i;
- \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
- \\ }) {
- \\ return 0;
- \\ }
- \\}
+ \\pub fn while_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
+ \\ while (a != 0) return 0;
+ \\ while (b != 0) return 1;
+ \\ while (c != null) return 2;
+ \\ return 3;
+ \\}
);
- cases.add("for on int",
- \\int for_int(int i) {
- \\ for (;i;) {
- \\ return 0;
- \\ }
- \\
- \\ for (int j = 4;j;j--) {
- \\ return 0;
- \\ }
+ cases.add("for on none bool",
+ \\int for_none_bool(int a, float b, void *c) {
+ \\ for (;a;) return 0;
+ \\ for (;b;) return 1;
+ \\ for (;c;) return 2;
+ \\ return 3;
\\}
,
- \\pub fn for_int(i: c_int) c_int {
- \\ while (__to_bool_expr: {
- \\ const _tmp = i;
- \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
- \\ }) {
- \\ return 0;
- \\ }
- \\ {
- \\ var j: c_int = 4;
- \\ while (__to_bool_expr: {
- \\ const _tmp = j;
- \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
- \\ }) : (j -= 1) {
- \\ return 0;
- \\ }
- \\ }
- \\}
+ \\pub fn for_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
+ \\ while (a != 0) return 0;
+ \\ while (b != 0) return 1;
+ \\ while (c != null) return 2;
+ \\ return 3;
+ \\}
);
- cases.add("for on int",
+ cases.add("switch on int",
\\int switch_fn(int i) {
\\ int res = 0;
\\ switch (i) {