From a77b2a0810bd835aa1adcfc18d32bc66ba8f1914 Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Fri, 15 Mar 2019 16:12:41 +0100 Subject: [PATCH] Implemented enough of translate-c to translate assert This required the following * __extention__ * ({}) * Fixing if (0) ; else ; --- src/translate_c.cpp | 51 +++++++++++++++++++---- test/translate_c.zig | 97 +++++++++++++++++++++++++------------------- 2 files changed, 99 insertions(+), 49 deletions(-) diff --git a/src/translate_c.cpp b/src/translate_c.cpp index c56d31eb2..90aa9c746 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -684,6 +684,13 @@ static bool qual_type_child_is_fn_proto(const clang::QualType &qt) { static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type, clang::QualType src_type, AstNode *expr) { + // The only way void pointer casts are valid C code, is if + // the value of the expression is ignored. We therefore just + // return the expr, and let the system that ignores values + // translate this correctly. + if (qual_type_canon(dest_type)->isVoidType()) { + return expr; + } if (qual_types_equal(dest_type, src_type)) { return expr; } @@ -1219,6 +1226,31 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang:: return child_scope_block->node; } +static AstNode *trans_stmt_expr(Context *c, TransScope *scope, const clang::StmtExpr *stmt, + TransScope **out_node_scope) +{ + AstNode *block = trans_compound_stmt(c, scope, stmt->getSubStmt(), out_node_scope); + if (block == nullptr) + return block; + assert(block->type == NodeTypeBlock); + if (block->data.block.statements.length == 0) + return block; + + Buf *label = buf_create_from_str("x"); + block->data.block.name = label; + AstNode *return_expr = block->data.block.statements.pop(); + if (return_expr->type == NodeTypeBinOpExpr && + return_expr->data.bin_op_expr.bin_op == BinOpTypeAssign && + return_expr->data.bin_op_expr.op1->type == NodeTypeSymbol) + { + Buf *symbol_buf = return_expr->data.bin_op_expr.op1->data.symbol_expr.symbol; + if (strcmp("_", buf_ptr(symbol_buf)) == 0) + return_expr = return_expr->data.bin_op_expr.op2; + } + block->data.block.statements.append(trans_create_node_break(c, label, return_expr)); + return block; +} + static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) { const clang::Expr *value_expr = stmt->getRetValue(); if (value_expr == nullptr) { @@ -1459,7 +1491,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue); if (rhs == nullptr) return nullptr; - scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs))); + scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, rhs)); return scope_block->node; } case clang::BO_MulAssign: @@ -2097,8 +2129,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Imag"); return nullptr; case clang::UO_Extension: - emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Extension"); - return nullptr; + return trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue); case clang::UO_Coawait: emit_warning(c, stmt->getLocStart(), "TODO handle C translation clang::UO_Coawait"); return nullptr; @@ -3079,6 +3110,10 @@ static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang:: return trans_create_node(c, NodeTypeContinue); } +static AstNode *trans_predefined_expr(Context *c, TransScope *scope, const clang::PredefinedExpr *expr) { + return trans_string_literal(c, scope, expr->getFunctionName()); +} + static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_scope, AstNode *result_node) { if (result_node == nullptr) return ErrorUnexpected; @@ -3146,7 +3181,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st return wrap_stmt(out_node, out_child_scope, scope, trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt)); case clang::Stmt::NullStmtClass: - *out_node = nullptr; + *out_node = trans_create_node(c, NodeTypeBlock); *out_child_scope = scope; return ErrorNone; case clang::Stmt::MemberExprClass: @@ -3473,8 +3508,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st emit_warning(c, stmt->getLocStart(), "TODO handle C ParenListExprClass"); return ErrorUnexpected; case clang::Stmt::PredefinedExprClass: - emit_warning(c, stmt->getLocStart(), "TODO handle C PredefinedExprClass"); - return ErrorUnexpected; + return wrap_stmt(out_node, out_child_scope, scope, + trans_predefined_expr(c, scope, (const clang::PredefinedExpr *)stmt)); case clang::Stmt::PseudoObjectExprClass: emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass"); return ErrorUnexpected; @@ -3485,8 +3520,8 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st emit_warning(c, stmt->getLocStart(), "TODO handle C SizeOfPackExprClass"); return ErrorUnexpected; case clang::Stmt::StmtExprClass: - emit_warning(c, stmt->getLocStart(), "TODO handle C StmtExprClass"); - return ErrorUnexpected; + return wrap_stmt(out_node, out_child_scope, scope, + trans_stmt_expr(c, scope, (const clang::StmtExpr *)stmt, out_node_scope)); case clang::Stmt::SubstNonTypeTemplateParmExprClass: emit_warning(c, stmt->getLocStart(), "TODO handle C SubstNonTypeTemplateParmExprClass"); return ErrorUnexpected; diff --git a/test/translate_c.zig b/test/translate_c.zig index e83ca7478..394da0ece 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -59,6 +59,20 @@ pub fn addCases(cases: *tests.TranslateCContext) void { ); } + cases.add("for loop with var init but empty body", + \\void foo(void) { + \\ __func__; + \\ __FUNCTION__; + \\ __PRETTY_FUNCTION__; + \\} + , + \\pub fn foo() void { + \\ c"foo"; + \\ c"foo"; + \\ c"void foo(void)"; + \\} + ); + cases.add("for loop with var init but empty body", \\void foo(void) { \\ for (int x = 0; x < 10; x++); @@ -79,6 +93,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { , // TODO this should be if (1 != 0) break \\pub fn foo() void { \\ while (true) { + \\ {} \\ if (!1) break; \\ } \\} @@ -720,7 +735,13 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ ;;;;; \\} , - \\pub export fn foo() void {} + \\pub export fn foo() void { + \\ {} + \\ {} + \\ {} + \\ {} + \\ {} + \\} ); cases.add("undefined array global", @@ -795,6 +816,32 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} ); + cases.addC("statement expression", + \\int foo(void) { + \\ return ({ + \\ int a = 1; + \\ a; + \\ }); + \\} + , + \\pub export fn foo() c_int { + \\ return x: { + \\ var a: c_int = 1; + \\ break :x a; + \\ }; + \\} + ); + + cases.addC("__extension__ cast", + \\int foo(void) { + \\ return __extension__ 1; + \\} + , + \\pub export fn foo() c_int { + \\ return 1; + \\} + ); + cases.addC("bitshift", \\int foo(void) { \\ return (1 << 2) >> 1; @@ -1425,53 +1472,21 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\pub export fn bar() void {} ); - cases.addC("u integer suffix after 0 (zero) in macro definition", - "#define ZERO 0U" - , - "pub const ZERO = c_uint(0);" - ); + cases.addC("u integer suffix after 0 (zero) in macro definition", "#define ZERO 0U", "pub const ZERO = c_uint(0);"); - cases.addC("l integer suffix after 0 (zero) in macro definition", - "#define ZERO 0L" - , - "pub const ZERO = c_long(0);" - ); + cases.addC("l integer suffix after 0 (zero) in macro definition", "#define ZERO 0L", "pub const ZERO = c_long(0);"); - cases.addC("ul integer suffix after 0 (zero) in macro definition", - "#define ZERO 0UL" - , - "pub const ZERO = c_ulong(0);" - ); + cases.addC("ul integer suffix after 0 (zero) in macro definition", "#define ZERO 0UL", "pub const ZERO = c_ulong(0);"); - cases.addC("lu integer suffix after 0 (zero) in macro definition", - "#define ZERO 0LU" - , - "pub const ZERO = c_ulong(0);" - ); + cases.addC("lu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LU", "pub const ZERO = c_ulong(0);"); - cases.addC("ll integer suffix after 0 (zero) in macro definition", - "#define ZERO 0LL" - , - "pub const ZERO = c_longlong(0);" - ); + cases.addC("ll integer suffix after 0 (zero) in macro definition", "#define ZERO 0LL", "pub const ZERO = c_longlong(0);"); - cases.addC("ull integer suffix after 0 (zero) in macro definition", - "#define ZERO 0ULL" - , - "pub const ZERO = c_ulonglong(0);" - ); + cases.addC("ull integer suffix after 0 (zero) in macro definition", "#define ZERO 0ULL", "pub const ZERO = c_ulonglong(0);"); - cases.addC("llu integer suffix after 0 (zero) in macro definition", - "#define ZERO 0LLU" - , - "pub const ZERO = c_ulonglong(0);" - ); + cases.addC("llu integer suffix after 0 (zero) in macro definition", "#define ZERO 0LLU", "pub const ZERO = c_ulonglong(0);"); - cases.addC("bitwise not on u-suffixed 0 (zero) in macro definition", - "#define NOT_ZERO (~0U)" - , - "pub const NOT_ZERO = ~c_uint(0);" - ); + cases.addC("bitwise not on u-suffixed 0 (zero) in macro definition", "#define NOT_ZERO (~0U)", "pub const NOT_ZERO = ~c_uint(0);"); // cases.add("empty array with initializer", // "int a[4] = {};"