| author | |
| committer | |
| log | a77b2a0810bd835aa1adcfc18d32bc66ba8f1914 |
| tree | 5daae184b1dd50cd4674d9f84c665c3a22492524 |
| parent | 761356209bd64ed655be96c0cf11869f2ff5f530 |
This required the following
* __extention__
* ({})
* Fixing if (0) ; else ;2 files changed, 99 insertions(+), 49 deletions(-)
src/translate_c.cpp+43-8| ... | ... | @@ -684,6 +684,13 @@ static bool qual_type_child_is_fn_proto(const clang::QualType &qt) { |
| 684 | 684 | static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type, |
| 685 | 685 | clang::QualType src_type, AstNode *expr) |
| 686 | 686 | { |
| 687 | // The only way void pointer casts are valid C code, is if | |
| 688 | // the value of the expression is ignored. We therefore just | |
| 689 | // return the expr, and let the system that ignores values | |
| 690 | // translate this correctly. | |
| 691 | if (qual_type_canon(dest_type)->isVoidType()) { | |
| 692 | return expr; | |
| 693 | } | |
| 687 | 694 | if (qual_types_equal(dest_type, src_type)) { |
| 688 | 695 | return expr; |
| 689 | 696 | } |
| ... | ... | @@ -1219,6 +1226,31 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang:: |
| 1219 | 1226 | return child_scope_block->node; |
| 1220 | 1227 | } |
| 1221 | 1228 | |
| 1229 | static AstNode *trans_stmt_expr(Context *c, TransScope *scope, const clang::StmtExpr *stmt, | |
| 1230 | TransScope **out_node_scope) | |
| 1231 | { | |
| 1232 | AstNode *block = trans_compound_stmt(c, scope, stmt->getSubStmt(), out_node_scope); | |
| 1233 | if (block == nullptr) | |
| 1234 | return block; | |
| 1235 | assert(block->type == NodeTypeBlock); | |
| 1236 | if (block->data.block.statements.length == 0) | |
| 1237 | return block; | |
| 1238 | ||
| 1239 | Buf *label = buf_create_from_str("x"); | |
| 1240 | block->data.block.name = label; | |
| 1241 | AstNode *return_expr = block->data.block.statements.pop(); | |
| 1242 | if (return_expr->type == NodeTypeBinOpExpr && | |
| 1243 | return_expr->data.bin_op_expr.bin_op == BinOpTypeAssign && | |
| 1244 | return_expr->data.bin_op_expr.op1->type == NodeTypeSymbol) | |
| 1245 | { | |
| 1246 | Buf *symbol_buf = return_expr->data.bin_op_expr.op1->data.symbol_expr.symbol; | |
| 1247 | if (strcmp("_", buf_ptr(symbol_buf)) == 0) | |
| 1248 | return_expr = return_expr->data.bin_op_expr.op2; | |
| 1249 | } | |
| 1250 | block->data.block.statements.append(trans_create_node_break(c, label, return_expr)); | |
| 1251 | return block; | |
| 1252 | } | |
| 1253 | ||
| 1222 | 1254 | static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) { |
| 1223 | 1255 | const clang::Expr *value_expr = stmt->getRetValue(); |
| 1224 | 1256 | if (value_expr == nullptr) { |
| ... | ... | @@ -1459,7 +1491,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS |
| 1459 | 1491 | AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue); |
| 1460 | 1492 | if (rhs == nullptr) |
| 1461 | 1493 | return nullptr; |
| 1462 | scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs))); | |
| 1494 | scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, rhs)); | |
| 1463 | 1495 | return scope_block->node; |
| 1464 | 1496 | } |
| 1465 | 1497 | case clang::BO_MulAssign: |
| ... | ... | @@ -2097,8 +2129,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc |
| 2097 | 2129 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Imag"); |
| 2098 | 2130 | return nullptr; |
| 2099 | 2131 | case clang::UO_Extension: |
| 2100 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Extension"); | |
| 2101 | return nullptr; | |
| 2132 | return trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); | |
| 2102 | 2133 | case clang::UO_Coawait: |
| 2103 | 2134 | emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Coawait"); |
| 2104 | 2135 | return nullptr; |
| ... | ... | @@ -3079,6 +3110,10 @@ static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang:: |
| 3079 | 3110 | return trans_create_node(c, NodeTypeContinue); |
| 3080 | 3111 | } |
| 3081 | 3112 | |
| 3113 | static AstNode *trans_predefined_expr(Context *c, TransScope *scope, const clang::PredefinedExpr *expr) { | |
| 3114 | return trans_string_literal(c, scope, expr->getFunctionName()); | |
| 3115 | } | |
| 3116 | ||
| 3082 | 3117 | static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_scope, AstNode *result_node) { |
| 3083 | 3118 | if (result_node == nullptr) |
| 3084 | 3119 | return ErrorUnexpected; |
| ... | ... | @@ -3146,7 +3181,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st |
| 3146 | 3181 | return wrap_stmt(out_node, out_child_scope, scope, |
| 3147 | 3182 | trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt)); |
| 3148 | 3183 | case clang::Stmt::NullStmtClass: |
| 3149 | *out_node = nullptr; | |
| 3184 | *out_node = trans_create_node(c, NodeTypeBlock); | |
| 3150 | 3185 | *out_child_scope = scope; |
| 3151 | 3186 | return ErrorNone; |
| 3152 | 3187 | case clang::Stmt::MemberExprClass: |
| ... | ... | @@ -3473,8 +3508,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st |
| 3473 | 3508 | emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); |
| 3474 | 3509 | return ErrorUnexpected; |
| 3475 | 3510 | case clang::Stmt::PredefinedExprClass: |
| 3476 | emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass"); | |
| 3477 | return ErrorUnexpected; | |
| 3511 | return wrap_stmt(out_node, out_child_scope, scope, | |
| 3512 | trans_predefined_expr(c, scope, (const clang::PredefinedExpr *)stmt)); | |
| 3478 | 3513 | case clang::Stmt::PseudoObjectExprClass: |
| 3479 | 3514 | emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass"); |
| 3480 | 3515 | return ErrorUnexpected; |
| ... | ... | @@ -3485,8 +3520,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st |
| 3485 | 3520 | emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass"); |
| 3486 | 3521 | return ErrorUnexpected; |
| 3487 | 3522 | case clang::Stmt::StmtExprClass: |
| 3488 | emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass"); | |
| 3489 | return ErrorUnexpected; | |
| 3523 | return wrap_stmt(out_node, out_child_scope, scope, | |
| 3524 | trans_stmt_expr(c, scope, (const clang::StmtExpr *)stmt, out_node_scope)); | |
| 3490 | 3525 | case clang::Stmt::SubstNonTypeTemplateParmExprClass: |
| 3491 | 3526 | emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass"); |
| 3492 | 3527 | return ErrorUnexpected; |
test/translate_c.zig+56-41| ... | ... | @@ -59,6 +59,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 59 | 59 | ); |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | cases.add("for loop with var init but empty body", | |
| 63 | \\void foo(void) { | |
| 64 | \\ __func__; | |
| 65 | \\ __FUNCTION__; | |
| 66 | \\ __PRETTY_FUNCTION__; | |
| 67 | \\} | |
| 68 | , | |
| 69 | \\pub fn foo() void { | |
| 70 | \\ c"foo"; | |
| 71 | \\ c"foo"; | |
| 72 | \\ c"void foo(void)"; | |
| 73 | \\} | |
| 74 | ); | |
| 75 | ||
| 62 | 76 | cases.add("for loop with var init but empty body", |
| 63 | 77 | \\void foo(void) { |
| 64 | 78 | \\ for (int x = 0; x < 10; x++); |
| ... | ... | @@ -79,6 +93,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 79 | 93 | , // TODO this should be if (1 != 0) break |
| 80 | 94 | \\pub fn foo() void { |
| 81 | 95 | \\ while (true) { |
| 96 | \\ {} | |
| 82 | 97 | \\ if (!1) break; |
| 83 | 98 | \\ } |
| 84 | 99 | \\} |
| ... | ... | @@ -720,7 +735,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 720 | 735 | \\ ;;;;; |
| 721 | 736 | \\} |
| 722 | 737 | , |
| 723 | \\pub export fn foo() void {} | |
| 738 | \\pub export fn foo() void { | |
| 739 | \\ {} | |
| 740 | \\ {} | |
| 741 | \\ {} | |
| 742 | \\ {} | |
| 743 | \\ {} | |
| 744 | \\} | |
| 724 | 745 | ); |
| 725 | 746 | |
| 726 | 747 | cases.add("undefined array global", |
| ... | ... | @@ -795,6 +816,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 795 | 816 | \\} |
| 796 | 817 | ); |
| 797 | 818 | |
| 819 | cases.addC("statement expression", | |
| 820 | \\int foo(void) { | |
| 821 | \\ return ({ | |
| 822 | \\ int a = 1; | |
| 823 | \\ a; | |
| 824 | \\ }); | |
| 825 | \\} | |
| 826 | , | |
| 827 | \\pub export fn foo() c_int { | |
| 828 | \\ return x: { | |
| 829 | \\ var a: c_int = 1; | |
| 830 | \\ break :x a; | |
| 831 | \\ }; | |
| 832 | \\} | |
| 833 | ); | |
| 834 | ||
| 835 | cases.addC("__extension__ cast", | |
| 836 | \\int foo(void) { | |
| 837 | \\ return __extension__ 1; | |
| 838 | \\} | |
| 839 | , | |
| 840 | \\pub export fn foo() c_int { | |
| 841 | \\ return 1; | |
| 842 | \\} | |
| 843 | ); | |
| 844 | ||
| 798 | 845 | cases.addC("bitshift", |
| 799 | 846 | \\int foo(void) { |
| 800 | 847 | \\ return (1 << 2) >> 1; |
| ... | ... | @@ -1425,53 +1472,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void { |
| 1425 | 1472 | \\pub export fn bar() void {} |
| 1426 | 1473 | ); |
| 1427 | 1474 | |
| 1428 | cases.addC("u integer suffix after 0 (zero) in macro definition", | |
| 1429 | "#define ZERO 0U" | |
| 1430 | , | |
| 1431 | "pub const ZERO = c_uint(0);" | |
| 1432 | ); | |
| 1475 | cases.addC("u integer suffix after 0 (zero) in macro definition", "#define ZERO 0U", "pub const ZERO = c_uint(0);"); | |
| 1433 | 1476 | |
| 1434 | cases.addC("l integer suffix after 0 (zero) in macro definition", | |
| 1435 | "#define ZERO 0L" | |
| 1436 | , | |
| 1437 | "pub const ZERO = c_long(0);" | |
| 1438 | ); | |
| 1477 | cases.addC("l integer suffix after 0 (zero) in macro definition", "#define ZERO 0L", "pub const ZERO = c_long(0);"); | |
| 1439 | 1478 | |
| 1440 | cases.addC("ul integer suffix after 0 (zero) in macro definition", | |
| 1441 | "#define ZERO 0UL" | |
| 1442 | , | |
| 1443 | "pub const ZERO = c_ulong(0);" | |
| 1444 | ); | |
| 1479 | cases.addC("ul integer suffix after 0 (zero) in macro definition", "#define ZERO 0UL", "pub const ZERO = c_ulong(0);"); | |
| 1445 | 1480 | |
| 1446 | cases.addC("lu integer suffix after 0 (zero) in macro definition", | |
| 1447 | "#define ZERO 0LU" | |
| 1448 | , | |
| 1449 | "pub const ZERO = c_ulong(0);" | |
| 1450 | ); | |
| 1481 | cases.addC("lu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LU", "pub const ZERO = c_ulong(0);"); | |
| 1451 | 1482 | |
| 1452 | cases.addC("ll integer suffix after 0 (zero) in macro definition", | |
| 1453 | "#define ZERO 0LL" | |
| 1454 | , | |
| 1455 | "pub const ZERO = c_longlong(0);" | |
| 1456 | ); | |
| 1483 | cases.addC("ll integer suffix after 0 (zero) in macro definition", "#define ZERO 0LL", "pub const ZERO = c_longlong(0);"); | |
| 1457 | 1484 | |
| 1458 | cases.addC("ull integer suffix after 0 (zero) in macro definition", | |
| 1459 | "#define ZERO 0ULL" | |
| 1460 | , | |
| 1461 | "pub const ZERO = c_ulonglong(0);" | |
| 1462 | ); | |
| 1485 | cases.addC("ull integer suffix after 0 (zero) in macro definition", "#define ZERO 0ULL", "pub const ZERO = c_ulonglong(0);"); | |
| 1463 | 1486 | |
| 1464 | cases.addC("llu integer suffix after 0 (zero) in macro definition", | |
| 1465 | "#define ZERO 0LLU" | |
| 1466 | , | |
| 1467 | "pub const ZERO = c_ulonglong(0);" | |
| 1468 | ); | |
| 1487 | cases.addC("llu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LLU", "pub const ZERO = c_ulonglong(0);"); | |
| 1469 | 1488 | |
| 1470 | cases.addC("bitwise not on u-suffixed 0 (zero) in macro definition", | |
| 1471 | "#define NOT_ZERO (~0U)" | |
| 1472 | , | |
| 1473 | "pub const NOT_ZERO = ~c_uint(0);" | |
| 1474 | ); | |
| 1489 | cases.addC("bitwise not on u-suffixed 0 (zero) in macro definition", "#define NOT_ZERO (~0U)", "pub const NOT_ZERO = ~c_uint(0);"); | |
| 1475 | 1490 | |
| 1476 | 1491 | // cases.add("empty array with initializer", |
| 1477 | 1492 | // "int a[4] = {};" |