authorgravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-03-08 15:34:00+01:00
committergravatar for jhc@dismail.deJimmi Holst Christensen <jhc@dismail.de> 2018-03-08 15:34:00+01:00
log2e010c60ae006944ae20ab8b3445598471c9f1e8
treef80846ddeeac1ed46d1205ee067173ce7771ae9f
parentb2887620f39d756b9f73a93b8b0932b3e471d996

Translate C now correctly converts ints, floats, ptrs and enums to bools

* Boolean "and" and "or" should also work with these types. * This new method also simplifies to output code.

2 files changed, 339 insertions(+), 144 deletions(-)

src/translate_c.cpp+259-78
......@@ -119,7 +119,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
119119static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
120120static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
121121static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
122static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr);
122static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
123123
124124ATTRIBUTE_PRINTF(3, 4)
125125static 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) {
467467 return expr->getType();
468468}
469469
470static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {
471 if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
472 const ImplicitCastExpr *cast_expr = static_cast<const ImplicitCastExpr *>(expr);
473 return get_expr_qual_type(c, cast_expr->getSubExpr());
474 }
475 return expr->getType();
476}
477
470478static AstNode *get_expr_type(Context *c, const Expr *expr) {
471479 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
472480}
......@@ -1152,6 +1160,22 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi
11521160 return node;
11531161}
11541162
1163static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {
1164 assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
1165 AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
1166 node->data.bin_op_expr.bin_op = bin_op;
1167
1168 node->data.bin_op_expr.op1 = trans_bool_expr(c, ResultUsedYes, scope, lhs, TransRValue);
1169 if (node->data.bin_op_expr.op1 == nullptr)
1170 return nullptr;
1171
1172 node->data.bin_op_expr.op2 = trans_bool_expr(c, ResultUsedYes, scope, rhs, TransRValue);
1173 if (node->data.bin_op_expr.op2 == nullptr)
1174 return nullptr;
1175
1176 return node;
1177}
1178
11551179static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {
11561180 if (result_used == ResultUsedNo) {
11571181 // common case
......@@ -1293,10 +1317,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
12931317 case BO_Or:
12941318 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
12951319 case BO_LAnd:
1296 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
1320 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
12971321 case BO_LOr:
1298 // TODO: int vs bool
1299 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1322 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
13001323 case BO_Assign:
13011324 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
13021325 case BO_Comma:
......@@ -1924,7 +1947,6 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
19241947 return nullptr;
19251948 }
19261949 }
1927 case UO_LNot:
19281950 case UO_Not:
19291951 {
19301952 Expr *op_expr = stmt->getSubExpr();
......@@ -1932,14 +1954,16 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
19321954 if (sub_node == nullptr)
19331955 return nullptr;
19341956
1935 switch (stmt->getOpcode()) {
1936 case UO_LNot:
1937 return trans_create_node_prefix_op(c, PrefixOpBoolNot, trans_to_bool_expr(c, scope, sub_node));
1938 case UO_Not:
1939 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
1940 default:
1941 zig_unreachable();
1942 }
1957 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
1958 }
1959 case UO_LNot:
1960 {
1961 Expr *op_expr = stmt->getSubExpr();
1962 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
1963 if (sub_node == nullptr)
1964 return nullptr;
1965
1966 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
19431967 }
19441968 case UO_Real:
19451969 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
22202244 return ErrorNone;
22212245}
22222246
2223static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) {
2224 switch (expr->type) {
2247static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) {
2248 AstNode *tag_type = trans_create_node_builtin_fn_call_str(c, "TagType");
2249 tag_type->data.fn_call_expr.params.append(enum_type);
2250
2251 // @TagType(Enum)(0)
2252 AstNode *zero = trans_create_node_unsigned_negative(c, 0, false);
2253 AstNode *casted_zero = trans_create_node_fn_call_1(c, tag_type, zero);
2254
2255 // @bitCast(Enum, @TagType(Enum)(0))
2256 AstNode *bitcast = trans_create_node_builtin_fn_call_str(c, "bitCast");
2257 bitcast->data.fn_call_expr.params.append(enum_type);
2258 bitcast->data.fn_call_expr.params.append(casted_zero);
2259
2260 return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
2261}
2262
2263static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) {
2264 AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
2265 if (res == nullptr)
2266 return nullptr;
2267
2268 switch (res->type) {
22252269 case NodeTypeBinOpExpr:
2226 switch (expr->data.bin_op_expr.bin_op) {
2270 switch (res->data.bin_op_expr.bin_op) {
22272271 case BinOpTypeBoolOr:
22282272 case BinOpTypeBoolAnd:
22292273 case BinOpTypeCmpEq:
......@@ -2232,76 +2276,208 @@ static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr)
22322276 case BinOpTypeCmpGreaterThan:
22332277 case BinOpTypeCmpLessOrEq:
22342278 case BinOpTypeCmpGreaterOrEq:
2235 return expr;
2279 return res;
22362280 default:
2237 goto convert_to_bitcast;
2281 break;
22382282 }
22392283
22402284 case NodeTypePrefixOpExpr:
2241 switch (expr->data.prefix_op_expr.prefix_op) {
2285 switch (res->data.prefix_op_expr.prefix_op) {
22422286 case PrefixOpBoolNot:
2243 return expr;
2287 return res;
22442288 default:
2245 goto convert_to_bitcast;
2289 break;
22462290 }
22472291
22482292 case NodeTypeBoolLiteral:
2249 return expr;
2250
2251 default: {
2252 // In Zig, float, int and pointer does not implicitly cast to bool.
2253 // To make it work, we bitcast any value we get to an int of the right size
2254 // and comp it to 0
2255 // TODO: This doesn't work for pointers, as they become nullable on
2256 // translate
2257 // c: expr
2258 // zig: __to_bool_expr: {
2259 // zig: const _tmp = cond;
2260 // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
2261 // zig: }
2262 convert_to_bitcast:
2263 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);
2264 Buf *label_name = buf_create_from_str("__to_bool_expr");
2265 child_scope->node->data.block.name = label_name;
2266
2267 // const _tmp = cond;
2268 // TODO: avoid name collisions with generated variable names
2269 Buf *tmp_var_name = buf_create_from_str("_tmp");
2270 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr);
2271 child_scope->node->data.block.statements.append(tmp_var_decl);
2272
2273 // @sizeOf(@typeOf(_tmp)) * 8
2274 AstNode *typeof_tmp = trans_create_node_builtin_fn_call_str(c, "typeOf");
2275 typeof_tmp->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
2276 AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");
2277 sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);
2278 AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(
2279 c, sizeof_tmp, BinOpTypeMult,
2280 trans_create_node_unsigned_negative(c, 8, false));
2281
2282 // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)
2283 AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType");
2284 int_type->data.fn_call_expr.params.append(trans_create_node_bool(c, false));
2285 int_type->data.fn_call_expr.params.append(sizeof_tmp_in_bits);
2286
2287 // @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp)
2288 AstNode *bit_cast = trans_create_node_builtin_fn_call_str(c, "bitCast");
2289 bit_cast->data.fn_call_expr.params.append(int_type);
2290 bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));
2291
2292 // break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0
2293 AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2294 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero));
2295
2296 return child_scope->node;
2293 return res;
2294
2295 default:
2296 break;
2297 }
2298
2299
2300 const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
2301 auto classs = ty->getTypeClass();
2302 switch (classs) {
2303 case Type::Builtin:
2304 {
2305 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
2306 switch (builtin_ty->getKind()) {
2307 case BuiltinType::Bool:
2308 case BuiltinType::Char_U:
2309 case BuiltinType::UChar:
2310 case BuiltinType::Char_S:
2311 case BuiltinType::SChar:
2312 case BuiltinType::UShort:
2313 case BuiltinType::UInt:
2314 case BuiltinType::ULong:
2315 case BuiltinType::ULongLong:
2316 case BuiltinType::Short:
2317 case BuiltinType::Int:
2318 case BuiltinType::Long:
2319 case BuiltinType::LongLong:
2320 case BuiltinType::UInt128:
2321 case BuiltinType::Int128:
2322 case BuiltinType::Float:
2323 case BuiltinType::Double:
2324 case BuiltinType::Float128:
2325 case BuiltinType::LongDouble:
2326 case BuiltinType::WChar_U:
2327 case BuiltinType::Char16:
2328 case BuiltinType::Char32:
2329 case BuiltinType::WChar_S:
2330 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2331 case BuiltinType::NullPtr:
2332 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2333
2334 case BuiltinType::Void:
2335 case BuiltinType::Half:
2336 case BuiltinType::ObjCId:
2337 case BuiltinType::ObjCClass:
2338 case BuiltinType::ObjCSel:
2339 case BuiltinType::OMPArraySection:
2340 case BuiltinType::Dependent:
2341 case BuiltinType::Overload:
2342 case BuiltinType::BoundMember:
2343 case BuiltinType::PseudoObject:
2344 case BuiltinType::UnknownAny:
2345 case BuiltinType::BuiltinFn:
2346 case BuiltinType::ARCUnbridgedCast:
2347 case BuiltinType::OCLImage1dRO:
2348 case BuiltinType::OCLImage1dArrayRO:
2349 case BuiltinType::OCLImage1dBufferRO:
2350 case BuiltinType::OCLImage2dRO:
2351 case BuiltinType::OCLImage2dArrayRO:
2352 case BuiltinType::OCLImage2dDepthRO:
2353 case BuiltinType::OCLImage2dArrayDepthRO:
2354 case BuiltinType::OCLImage2dMSAARO:
2355 case BuiltinType::OCLImage2dArrayMSAARO:
2356 case BuiltinType::OCLImage2dMSAADepthRO:
2357 case BuiltinType::OCLImage2dArrayMSAADepthRO:
2358 case BuiltinType::OCLImage3dRO:
2359 case BuiltinType::OCLImage1dWO:
2360 case BuiltinType::OCLImage1dArrayWO:
2361 case BuiltinType::OCLImage1dBufferWO:
2362 case BuiltinType::OCLImage2dWO:
2363 case BuiltinType::OCLImage2dArrayWO:
2364 case BuiltinType::OCLImage2dDepthWO:
2365 case BuiltinType::OCLImage2dArrayDepthWO:
2366 case BuiltinType::OCLImage2dMSAAWO:
2367 case BuiltinType::OCLImage2dArrayMSAAWO:
2368 case BuiltinType::OCLImage2dMSAADepthWO:
2369 case BuiltinType::OCLImage2dArrayMSAADepthWO:
2370 case BuiltinType::OCLImage3dWO:
2371 case BuiltinType::OCLImage1dRW:
2372 case BuiltinType::OCLImage1dArrayRW:
2373 case BuiltinType::OCLImage1dBufferRW:
2374 case BuiltinType::OCLImage2dRW:
2375 case BuiltinType::OCLImage2dArrayRW:
2376 case BuiltinType::OCLImage2dDepthRW:
2377 case BuiltinType::OCLImage2dArrayDepthRW:
2378 case BuiltinType::OCLImage2dMSAARW:
2379 case BuiltinType::OCLImage2dArrayMSAARW:
2380 case BuiltinType::OCLImage2dMSAADepthRW:
2381 case BuiltinType::OCLImage2dArrayMSAADepthRW:
2382 case BuiltinType::OCLImage3dRW:
2383 case BuiltinType::OCLSampler:
2384 case BuiltinType::OCLEvent:
2385 case BuiltinType::OCLClkEvent:
2386 case BuiltinType::OCLQueue:
2387 case BuiltinType::OCLReserveID:
2388 return res;
2389 }
2390 break;
2391 }
2392 case Type::Pointer:
2393 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2394
2395 case Type::Typedef:
2396 {
2397 const TypedefType *typedef_ty = static_cast<const TypedefType*>(ty);
2398 const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
2399 auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
2400 if (existing_entry) {
2401 return existing_entry->value;
2402 }
2403
2404 return res;
22972405 }
2406
2407 case Type::Enum:
2408 {
2409 const EnumType *enum_ty = static_cast<const EnumType*>(ty);
2410 AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
2411 return to_enum_zero_cmp(c, res, enum_type);
2412 }
2413
2414 case Type::Elaborated:
2415 {
2416 const ElaboratedType *elaborated_ty = static_cast<const ElaboratedType*>(ty);
2417 switch (elaborated_ty->getKeyword()) {
2418 case ETK_Enum: {
2419 AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getLocStart());
2420 return to_enum_zero_cmp(c, res, enum_type);
2421 }
2422 case ETK_Struct:
2423 case ETK_Union:
2424 case ETK_Interface:
2425 case ETK_Class:
2426 case ETK_Typename:
2427 case ETK_None:
2428 return res;
2429 }
2430 }
2431
2432 case Type::FunctionProto:
2433 case Type::Record:
2434 case Type::ConstantArray:
2435 case Type::Paren:
2436 case Type::Decayed:
2437 case Type::Attributed:
2438 case Type::IncompleteArray:
2439 case Type::BlockPointer:
2440 case Type::LValueReference:
2441 case Type::RValueReference:
2442 case Type::MemberPointer:
2443 case Type::VariableArray:
2444 case Type::DependentSizedArray:
2445 case Type::DependentSizedExtVector:
2446 case Type::Vector:
2447 case Type::ExtVector:
2448 case Type::FunctionNoProto:
2449 case Type::UnresolvedUsing:
2450 case Type::Adjusted:
2451 case Type::TypeOfExpr:
2452 case Type::TypeOf:
2453 case Type::Decltype:
2454 case Type::UnaryTransform:
2455 case Type::TemplateTypeParm:
2456 case Type::SubstTemplateTypeParm:
2457 case Type::SubstTemplateTypeParmPack:
2458 case Type::TemplateSpecialization:
2459 case Type::Auto:
2460 case Type::InjectedClassName:
2461 case Type::DependentName:
2462 case Type::DependentTemplateSpecialization:
2463 case Type::PackExpansion:
2464 case Type::ObjCObject:
2465 case Type::ObjCInterface:
2466 case Type::Complex:
2467 case Type::ObjCObjectPointer:
2468 case Type::Atomic:
2469 case Type::Pipe:
2470 case Type::ObjCTypeParam:
2471 case Type::DeducedTemplateSpecialization:
2472 return res;
22982473 }
2474 zig_unreachable();
22992475}
23002476
23012477static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
23022478 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
23032479
2304 while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, scope, trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue));
2480 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
23052481 if (while_scope->node->data.while_expr.condition == nullptr)
23062482 return nullptr;
23072483
......@@ -2328,11 +2504,10 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
23282504 return nullptr;
23292505 }
23302506
2331 AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2332 if (condition_node == nullptr)
2507 if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2508 if (if_node->data.if_bool_expr.condition == nullptr)
23332509 return nullptr;
23342510
2335 if_node->data.if_bool_expr.condition = trans_to_bool_expr(c, scope, condition_node);
23362511 return if_node;
23372512}
23382513
......@@ -2524,12 +2699,18 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
25242699 if (cond_stmt == nullptr) {
25252700 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
25262701 } else {
2527 TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,
2528 &while_scope->node->data.while_expr.condition);
2529 if (end_cond_scope == nullptr)
2530 return nullptr;
2702 if (Expr::classof(cond_stmt)) {
2703 const Expr *cond_expr = static_cast<const Expr*>(cond_stmt);
2704 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
25312705
2532 while_scope->node->data.while_expr.condition = trans_to_bool_expr(c, cond_scope, while_scope->node->data.while_expr.condition);
2706 if (while_scope->node->data.while_expr.condition == nullptr)
2707 return nullptr;
2708 } else {
2709 TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,
2710 &while_scope->node->data.while_expr.condition);
2711 if (end_cond_scope == nullptr)
2712 return nullptr;
2713 }
25332714 }
25342715
25352716 const Stmt *inc_stmt = stmt->getInc();
test/translate_c.zig+80-66
......@@ -451,6 +451,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
451451 \\}
452452 );
453453
454 cases.addC("logical and, logical or on none bool values",
455 \\int and_or_none_bool(int a, float b, void *c) {
456 \\ if (a && b) return 0;
457 \\ if (b && c) return 1;
458 \\ if (a && c) return 2;
459 \\ if (a || b) return 3;
460 \\ if (b || c) return 4;
461 \\ if (a || c) return 5;
462 \\ return 6;
463 \\}
464 ,
465 \\pub export fn and_or_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
466 \\ if ((a != 0) and (b != 0)) return 0;
467 \\ if ((b != 0) and (c != null)) return 1;
468 \\ if ((a != 0) and (c != null)) return 2;
469 \\ if ((a != 0) or (b != 0)) return 3;
470 \\ if ((b != 0) or (c != null)) return 4;
471 \\ if ((a != 0) or (c != null)) return 5;
472 \\ return 6;
473 \\}
474 );
475
454476 cases.addC("assign",
455477 \\int max(int a) {
456478 \\ int tmp;
......@@ -1102,17 +1124,18 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
11021124 );
11031125
11041126 cases.add("bool not",
1105 \\int foo(int x) {
1106 \\ return !(x == 0);
1107 \\ return !x;
1127 \\int foo(int a, float b, void *c) {
1128 \\ return !(a == 0);
1129 \\ return !a;
1130 \\ return !b;
1131 \\ return !c;
11081132 \\}
11091133 ,
1110 \\pub fn foo(x: c_int) c_int {
1111 \\ return !(x == 0);
1112 \\ return !__to_bool_expr: {
1113 \\ const _tmp = x;
1114 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1115 \\ };
1134 \\pub fn foo(a: c_int, b: f32, c: ?&c_void) c_int {
1135 \\ return !(a == 0);
1136 \\ return !(a != 0);
1137 \\ return !(b != 0);
1138 \\ return !(c != null);
11161139 \\}
11171140 );
11181141
......@@ -1148,75 +1171,66 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
11481171 \\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);
11491172 );
11501173
1151 cases.add("if on int",
1152 \\int if_int(int i) {
1153 \\ if (i) {
1154 \\ return 0;
1155 \\ } else {
1156 \\ return 1;
1157 \\ }
1174 cases.add("if on none bool",
1175 \\enum SomeEnum { A, B, C };
1176 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
1177 \\ if (a) return 0;
1178 \\ if (b) return 1;
1179 \\ if (c) return 2;
1180 \\ if (d) return 3;
1181 \\ return 4;
11581182 \\}
11591183 ,
1160 \\pub fn if_int(i: c_int) c_int {
1161 \\ if (__to_bool_expr: {
1162 \\ const _tmp = i;
1163 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1164 \\ }) {
1165 \\ return 0;
1166 \\ } else {
1167 \\ return 1;
1168 \\ }
1169 \\}
1184 \\pub const A = enum_SomeEnum.A;
1185 \\pub const B = enum_SomeEnum.B;
1186 \\pub const C = enum_SomeEnum.C;
1187 \\pub const enum_SomeEnum = extern enum {
1188 \\ A,
1189 \\ B,
1190 \\ C,
1191 \\};
1192 \\pub fn if_none_bool(a: c_int, b: f32, c: ?&c_void, d: enum_SomeEnum) c_int {
1193 \\ if (a != 0) return 0;
1194 \\ if (b != 0) return 1;
1195 \\ if (c != null) return 2;
1196 \\ if (d != @bitCast(enum_SomeEnum, @TagType(enum_SomeEnum)(0))) return 3;
1197 \\ return 4;
1198 \\}
11701199 );
11711200
1172 cases.add("while on int",
1173 \\int while_int(int i) {
1174 \\ while (i) {
1175 \\ return 0;
1176 \\ }
1201 cases.add("while on none bool",
1202 \\int while_none_bool(int a, float b, void *c) {
1203 \\ while (a) return 0;
1204 \\ while (b) return 1;
1205 \\ while (c) return 2;
1206 \\ return 3;
11771207 \\}
11781208 ,
1179 \\pub fn while_int(i: c_int) c_int {
1180 \\ while (__to_bool_expr: {
1181 \\ const _tmp = i;
1182 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1183 \\ }) {
1184 \\ return 0;
1185 \\ }
1186 \\}
1209 \\pub fn while_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
1210 \\ while (a != 0) return 0;
1211 \\ while (b != 0) return 1;
1212 \\ while (c != null) return 2;
1213 \\ return 3;
1214 \\}
11871215 );
11881216
1189 cases.add("for on int",
1190 \\int for_int(int i) {
1191 \\ for (;i;) {
1192 \\ return 0;
1193 \\ }
1194 \\
1195 \\ for (int j = 4;j;j--) {
1196 \\ return 0;
1197 \\ }
1217 cases.add("for on none bool",
1218 \\int for_none_bool(int a, float b, void *c) {
1219 \\ for (;a;) return 0;
1220 \\ for (;b;) return 1;
1221 \\ for (;c;) return 2;
1222 \\ return 3;
11981223 \\}
11991224 ,
1200 \\pub fn for_int(i: c_int) c_int {
1201 \\ while (__to_bool_expr: {
1202 \\ const _tmp = i;
1203 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1204 \\ }) {
1205 \\ return 0;
1206 \\ }
1207 \\ {
1208 \\ var j: c_int = 4;
1209 \\ while (__to_bool_expr: {
1210 \\ const _tmp = j;
1211 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;
1212 \\ }) : (j -= 1) {
1213 \\ return 0;
1214 \\ }
1215 \\ }
1216 \\}
1225 \\pub fn for_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
1226 \\ while (a != 0) return 0;
1227 \\ while (b != 0) return 1;
1228 \\ while (c != null) return 2;
1229 \\ return 3;
1230 \\}
12171231 );
12181232
1219 cases.add("for on int",
1233 cases.add("switch on int",
12201234 \\int switch_fn(int i) {
12211235 \\ int res = 0;
12221236 \\ switch (i) {