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,...@@ -119,7 +119,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
119static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);119static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
120static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);120static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
121static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);121static 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
124ATTRIBUTE_PRINTF(3, 4)124ATTRIBUTE_PRINTF(3, 4)
125static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {125static 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) {...@@ -467,6 +467,14 @@ static QualType get_expr_qual_type(Context *c, const Expr *expr) {
467 return expr->getType();467 return expr->getType();
468}468}
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
470static AstNode *get_expr_type(Context *c, const Expr *expr) {478static AstNode *get_expr_type(Context *c, const Expr *expr) {
471 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());479 return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getLocStart());
472}480}
...@@ -1152,6 +1160,22 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi...@@ -1152,6 +1160,22 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi
1152 return node;1160 return node;
1153}1161}
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
1155static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {1179static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {
1156 if (result_used == ResultUsedNo) {1180 if (result_used == ResultUsedNo) {
1157 // common case1181 // common case
...@@ -1293,10 +1317,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS...@@ -1293,10 +1317,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
1293 case BO_Or:1317 case BO_Or:
1294 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());1318 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
1295 case BO_LAnd:1319 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());
1297 case BO_LOr:1321 case BO_LOr:
1298 // TODO: int vs bool1322 return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1299 return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
1300 case BO_Assign:1323 case BO_Assign:
1301 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());1324 return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
1302 case BO_Comma:1325 case BO_Comma:
...@@ -1924,7 +1947,6 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -1924,7 +1947,6 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
1924 return nullptr;1947 return nullptr;
1925 }1948 }
1926 }1949 }
1927 case UO_LNot:
1928 case UO_Not:1950 case UO_Not:
1929 {1951 {
1930 Expr *op_expr = stmt->getSubExpr();1952 Expr *op_expr = stmt->getSubExpr();
...@@ -1932,14 +1954,16 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc...@@ -1932,14 +1954,16 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
1932 if (sub_node == nullptr)1954 if (sub_node == nullptr)
1933 return nullptr;1955 return nullptr;
19341956
1935 switch (stmt->getOpcode()) {1957 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
1936 case UO_LNot:1958 }
1937 return trans_create_node_prefix_op(c, PrefixOpBoolNot, trans_to_bool_expr(c, scope, sub_node));1959 case UO_LNot:
1938 case UO_Not:1960 {
1939 return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);1961 Expr *op_expr = stmt->getSubExpr();
1940 default:1962 AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
1941 zig_unreachable();1963 if (sub_node == nullptr)
1942 }1964 return nullptr;
1965
1966 return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
1943 }1967 }
1944 case UO_Real:1968 case UO_Real:
1945 emit_warning(c, stmt->getLocStart(), "TODO handle C translation UO_Real");1969 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...@@ -2220,10 +2244,30 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
2220 return ErrorNone;2244 return ErrorNone;
2221}2245}
22222246
2223static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr) {2247static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type) {
2224 switch (expr->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) {
2225 case NodeTypeBinOpExpr:2269 case NodeTypeBinOpExpr:
2226 switch (expr->data.bin_op_expr.bin_op) {2270 switch (res->data.bin_op_expr.bin_op) {
2227 case BinOpTypeBoolOr:2271 case BinOpTypeBoolOr:
2228 case BinOpTypeBoolAnd:2272 case BinOpTypeBoolAnd:
2229 case BinOpTypeCmpEq:2273 case BinOpTypeCmpEq:
...@@ -2232,76 +2276,208 @@ static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr)...@@ -2232,76 +2276,208 @@ static AstNode *trans_to_bool_expr(Context *c, TransScope *scope, AstNode *expr)
2232 case BinOpTypeCmpGreaterThan:2276 case BinOpTypeCmpGreaterThan:
2233 case BinOpTypeCmpLessOrEq:2277 case BinOpTypeCmpLessOrEq:
2234 case BinOpTypeCmpGreaterOrEq:2278 case BinOpTypeCmpGreaterOrEq:
2235 return expr;2279 return res;
2236 default:2280 default:
2237 goto convert_to_bitcast;2281 break;
2238 }2282 }
22392283
2240 case NodeTypePrefixOpExpr:2284 case NodeTypePrefixOpExpr:
2241 switch (expr->data.prefix_op_expr.prefix_op) {2285 switch (res->data.prefix_op_expr.prefix_op) {
2242 case PrefixOpBoolNot:2286 case PrefixOpBoolNot:
2243 return expr;2287 return res;
2244 default:2288 default:
2245 goto convert_to_bitcast;2289 break;
2246 }2290 }
22472291
2248 case NodeTypeBoolLiteral:2292 case NodeTypeBoolLiteral:
2249 return expr;2293 return res;
22502294
2251 default: {2295 default:
2252 // In Zig, float, int and pointer does not implicitly cast to bool.2296 break;
2253 // To make it work, we bitcast any value we get to an int of the right size2297 }
2254 // and comp it to 02298
2255 // TODO: This doesn't work for pointers, as they become nullable on2299
2256 // translate2300 const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
2257 // c: expr2301 auto classs = ty->getTypeClass();
2258 // zig: __to_bool_expr: {2302 switch (classs) {
2259 // zig: const _tmp = cond;2303 case Type::Builtin:
2260 // zig: break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;2304 {
2261 // zig: }2305 const BuiltinType *builtin_ty = static_cast<const BuiltinType*>(ty);
2262 convert_to_bitcast:2306 switch (builtin_ty->getKind()) {
2263 TransScopeBlock *child_scope = trans_scope_block_create(c, scope);2307 case BuiltinType::Bool:
2264 Buf *label_name = buf_create_from_str("__to_bool_expr");2308 case BuiltinType::Char_U:
2265 child_scope->node->data.block.name = label_name;2309 case BuiltinType::UChar:
22662310 case BuiltinType::Char_S:
2267 // const _tmp = cond;2311 case BuiltinType::SChar:
2268 // TODO: avoid name collisions with generated variable names2312 case BuiltinType::UShort:
2269 Buf *tmp_var_name = buf_create_from_str("_tmp");2313 case BuiltinType::UInt:
2270 AstNode *tmp_var_decl = trans_create_node_var_decl_local(c, true, tmp_var_name, nullptr, expr);2314 case BuiltinType::ULong:
2271 child_scope->node->data.block.statements.append(tmp_var_decl);2315 case BuiltinType::ULongLong:
22722316 case BuiltinType::Short:
2273 // @sizeOf(@typeOf(_tmp)) * 82317 case BuiltinType::Int:
2274 AstNode *typeof_tmp = trans_create_node_builtin_fn_call_str(c, "typeOf");2318 case BuiltinType::Long:
2275 typeof_tmp->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));2319 case BuiltinType::LongLong:
2276 AstNode *sizeof_tmp = trans_create_node_builtin_fn_call_str(c, "sizeOf");2320 case BuiltinType::UInt128:
2277 sizeof_tmp->data.fn_call_expr.params.append(typeof_tmp);2321 case BuiltinType::Int128:
2278 AstNode *sizeof_tmp_in_bits = trans_create_node_bin_op(2322 case BuiltinType::Float:
2279 c, sizeof_tmp, BinOpTypeMult,2323 case BuiltinType::Double:
2280 trans_create_node_unsigned_negative(c, 8, false));2324 case BuiltinType::Float128:
22812325 case BuiltinType::LongDouble:
2282 // @IntType(false, @sizeOf(@typeOf(_tmp)) * 8)2326 case BuiltinType::WChar_U:
2283 AstNode *int_type = trans_create_node_builtin_fn_call_str(c, "IntType");2327 case BuiltinType::Char16:
2284 int_type->data.fn_call_expr.params.append(trans_create_node_bool(c, false));2328 case BuiltinType::Char32:
2285 int_type->data.fn_call_expr.params.append(sizeof_tmp_in_bits);2329 case BuiltinType::WChar_S:
22862330 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
2287 // @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp)2331 case BuiltinType::NullPtr:
2288 AstNode *bit_cast = trans_create_node_builtin_fn_call_str(c, "bitCast");2332 return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
2289 bit_cast->data.fn_call_expr.params.append(int_type);2333
2290 bit_cast->data.fn_call_expr.params.append(trans_create_node_symbol(c, tmp_var_name));2334 case BuiltinType::Void:
22912335 case BuiltinType::Half:
2292 // break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 02336 case BuiltinType::ObjCId:
2293 AstNode *not_eql_zero = trans_create_node_bin_op(c, bit_cast, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));2337 case BuiltinType::ObjCClass:
2294 child_scope->node->data.block.statements.append(trans_create_node_break(c, label_name, not_eql_zero));2338 case BuiltinType::ObjCSel:
22952339 case BuiltinType::OMPArraySection:
2296 return child_scope->node;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;
2297 }2405 }
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;
2298 }2473 }
2474 zig_unreachable();
2299}2475}
23002476
2301static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {2477static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
2302 TransScopeWhile *while_scope = trans_scope_while_create(c, scope);2478 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);
2305 if (while_scope->node->data.while_expr.condition == nullptr)2481 if (while_scope->node->data.while_expr.condition == nullptr)
2306 return nullptr;2482 return nullptr;
23072483
...@@ -2328,11 +2504,10 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *...@@ -2328,11 +2504,10 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
2328 return nullptr;2504 return nullptr;
2329 }2505 }
23302506
2331 AstNode *condition_node = trans_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);2507 if_node->data.if_bool_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
2332 if (condition_node == nullptr)2508 if (if_node->data.if_bool_expr.condition == nullptr)
2333 return nullptr;2509 return nullptr;
23342510
2335 if_node->data.if_bool_expr.condition = trans_to_bool_expr(c, scope, condition_node);
2336 return if_node;2511 return if_node;
2337}2512}
23382513
...@@ -2524,12 +2699,18 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt...@@ -2524,12 +2699,18 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
2524 if (cond_stmt == nullptr) {2699 if (cond_stmt == nullptr) {
2525 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);2700 while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
2526 } else {2701 } else {
2527 TransScope *end_cond_scope = trans_stmt(c, cond_scope, cond_stmt,2702 if (Expr::classof(cond_stmt)) {
2528 &while_scope->node->data.while_expr.condition);2703 const Expr *cond_expr = static_cast<const Expr*>(cond_stmt);
2529 if (end_cond_scope == nullptr)2704 while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
2530 return nullptr;
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 }
2533 }2714 }
25342715
2535 const Stmt *inc_stmt = stmt->getInc();2716 const Stmt *inc_stmt = stmt->getInc();
test/translate_c.zig+80-66
...@@ -451,6 +451,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -451,6 +451,28 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
451 \\}451 \\}
452 );452 );
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
454 cases.addC("assign",476 cases.addC("assign",
455 \\int max(int a) {477 \\int max(int a) {
456 \\ int tmp;478 \\ int tmp;
...@@ -1102,17 +1124,18 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -1102,17 +1124,18 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
1102 );1124 );
11031125
1104 cases.add("bool not",1126 cases.add("bool not",
1105 \\int foo(int x) {1127 \\int foo(int a, float b, void *c) {
1106 \\ return !(x == 0);1128 \\ return !(a == 0);
1107 \\ return !x;1129 \\ return !a;
1130 \\ return !b;
1131 \\ return !c;
1108 \\}1132 \\}
1109 ,1133 ,
1110 \\pub fn foo(x: c_int) c_int {1134 \\pub fn foo(a: c_int, b: f32, c: ?&c_void) c_int {
1111 \\ return !(x == 0);1135 \\ return !(a == 0);
1112 \\ return !__to_bool_expr: {1136 \\ return !(a != 0);
1113 \\ const _tmp = x;1137 \\ return !(b != 0);
1114 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;1138 \\ return !(c != null);
1115 \\ };
1116 \\}1139 \\}
1117 );1140 );
11181141
...@@ -1148,75 +1171,66 @@ pub fn addCases(cases: &tests.TranslateCContext) void {...@@ -1148,75 +1171,66 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
1148 \\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);1171 \\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);
1149 );1172 );
11501173
1151 cases.add("if on int",1174 cases.add("if on none bool",
1152 \\int if_int(int i) {1175 \\enum SomeEnum { A, B, C };
1153 \\ if (i) {1176 \\int if_none_bool(int a, float b, void *c, enum SomeEnum d) {
1154 \\ return 0;1177 \\ if (a) return 0;
1155 \\ } else {1178 \\ if (b) return 1;
1156 \\ return 1;1179 \\ if (c) return 2;
1157 \\ }1180 \\ if (d) return 3;
1181 \\ return 4;
1158 \\}1182 \\}
1159 ,1183 ,
1160 \\pub fn if_int(i: c_int) c_int {1184 \\pub const A = enum_SomeEnum.A;
1161 \\ if (__to_bool_expr: {1185 \\pub const B = enum_SomeEnum.B;
1162 \\ const _tmp = i;1186 \\pub const C = enum_SomeEnum.C;
1163 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;1187 \\pub const enum_SomeEnum = extern enum {
1164 \\ }) {1188 \\ A,
1165 \\ return 0;1189 \\ B,
1166 \\ } else {1190 \\ C,
1167 \\ return 1;1191 \\};
1168 \\ }1192 \\pub fn if_none_bool(a: c_int, b: f32, c: ?&c_void, d: enum_SomeEnum) c_int {
1169 \\}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 \\}
1170 );1199 );
11711200
1172 cases.add("while on int",1201 cases.add("while on none bool",
1173 \\int while_int(int i) {1202 \\int while_none_bool(int a, float b, void *c) {
1174 \\ while (i) {1203 \\ while (a) return 0;
1175 \\ return 0;1204 \\ while (b) return 1;
1176 \\ }1205 \\ while (c) return 2;
1206 \\ return 3;
1177 \\}1207 \\}
1178 ,1208 ,
1179 \\pub fn while_int(i: c_int) c_int {1209 \\pub fn while_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
1180 \\ while (__to_bool_expr: {1210 \\ while (a != 0) return 0;
1181 \\ const _tmp = i;1211 \\ while (b != 0) return 1;
1182 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;1212 \\ while (c != null) return 2;
1183 \\ }) {1213 \\ return 3;
1184 \\ return 0;1214 \\}
1185 \\ }
1186 \\}
1187 );1215 );
11881216
1189 cases.add("for on int",1217 cases.add("for on none bool",
1190 \\int for_int(int i) {1218 \\int for_none_bool(int a, float b, void *c) {
1191 \\ for (;i;) {1219 \\ for (;a;) return 0;
1192 \\ return 0;1220 \\ for (;b;) return 1;
1193 \\ }1221 \\ for (;c;) return 2;
1194 \\1222 \\ return 3;
1195 \\ for (int j = 4;j;j--) {
1196 \\ return 0;
1197 \\ }
1198 \\}1223 \\}
1199 ,1224 ,
1200 \\pub fn for_int(i: c_int) c_int {1225 \\pub fn for_none_bool(a: c_int, b: f32, c: ?&c_void) c_int {
1201 \\ while (__to_bool_expr: {1226 \\ while (a != 0) return 0;
1202 \\ const _tmp = i;1227 \\ while (b != 0) return 1;
1203 \\ break :__to_bool_expr @bitCast(@IntType(false, @sizeOf(@typeOf(_tmp)) * 8), _tmp) != 0;1228 \\ while (c != null) return 2;
1204 \\ }) {1229 \\ return 3;
1205 \\ return 0;1230 \\}
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 \\}
1217 );1231 );
12181232
1219 cases.add("for on int",1233 cases.add("switch on int",
1220 \\int switch_fn(int i) {1234 \\int switch_fn(int i) {
1221 \\ int res = 0;1235 \\ int res = 0;
1222 \\ switch (i) {1236 \\ switch (i) {