From a77b2a0810bd835aa1adcfc18d32bc66ba8f1914 Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Fri, 15 Mar 2019 16:12:41 +0100 Subject: [PATCH 1/3] 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 c56d31eb2d..90aa9c7463 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 e83ca74786..394da0ece4 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] = {};" From 5ae400fb393b4a7fb4af15b89a4101de9255b26d Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Fri, 15 Mar 2019 19:11:46 +0100 Subject: [PATCH 2/3] fixed void cast and added the last tests --- src/translate_c.cpp | 6 ++++- test/translate_c.zig | 63 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 90aa9c7463..fcc050bc2d 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -2784,7 +2784,11 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran if (sub_expr_node == nullptr) return nullptr; - return trans_c_cast(c, stmt->getLocStart(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node); + AstNode *cast = trans_c_cast(c, stmt->getLocStart(), stmt->getType(), stmt->getSubExpr()->getType(), sub_expr_node); + if (cast == nullptr) + return nullptr; + + return maybe_suppress_result(c, result_used, cast); } static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, diff --git a/test/translate_c.zig b/test/translate_c.zig index 394da0ece4..39b2858cd9 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -59,7 +59,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void { ); } - cases.add("for loop with var init but empty body", + cases.add("predefined expressions", \\void foo(void) { \\ __func__; \\ __FUNCTION__; @@ -526,11 +526,14 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\ return b; \\ else \\ return a; + \\ + \\ if (a < b) ; else ; \\} , \\pub export fn max(a: c_int, b: c_int) c_int { \\ if (a < b) return b; \\ if (a < b) return b else return a; + \\ if (a < b) {} else {} \\} ); @@ -772,6 +775,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} ); + cases.addC("void cast", + \\void foo(int a) { + \\ (void) a; + \\} + , + \\pub export fn foo(a: c_int) void { + \\ _ = a; + \\} + ); + cases.addC("implicit cast to void *", \\void *foo(unsigned short *x) { \\ return x; @@ -1472,21 +1485,53 @@ 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] = {};" From 9171e7a7c11d2f5623a30683e1a0f510fe30b4de Mon Sep 17 00:00:00 2001 From: Jimmi Holst Christensen Date: Mon, 18 Mar 2019 14:55:57 +0100 Subject: [PATCH 3/3] More work on ignoring values correctly --- src/translate_c.cpp | 185 +++++++++++++++++++++++++++---------------- test/translate_c.zig | 26 +++++- 2 files changed, 138 insertions(+), 73 deletions(-) diff --git a/src/translate_c.cpp b/src/translate_c.cpp index fcc050bc2d..db3b8ba0e2 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -1226,8 +1226,8 @@ 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) +static AstNode *trans_stmt_expr(Context *c, ResultUsed result_used, 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) @@ -1248,7 +1248,7 @@ static AstNode *trans_stmt_expr(Context *c, TransScope *scope, const clang::Stmt return_expr = return_expr->data.bin_op_expr.op2; } block->data.block.statements.append(trans_create_node_break(c, label, return_expr)); - return block; + return maybe_suppress_result(c, result_used, block); } static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) { @@ -1264,13 +1264,15 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::Re } } -static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) { +static AstNode *trans_integer_literal(Context *c, ResultUsed result_used, const clang::IntegerLiteral *stmt) { llvm::APSInt result; if (!stmt->EvaluateAsInt(result, *reinterpret_cast(c->ctx))) { emit_warning(c, stmt->getLocStart(), "invalid integer literal"); return nullptr; } - return trans_create_node_apint(c, result); + + AstNode *node = trans_create_node_apint(c, result); + return maybe_suppress_result(c, result_used, node); } static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope, @@ -1407,14 +1409,17 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS case clang::BO_Cmp: emit_warning(c, stmt->getLocStart(), "TODO handle more C binary operators: clang::BO_Cmp"); return nullptr; - case clang::BO_Mul: - return trans_create_bin_op(c, scope, stmt->getLHS(), + case clang::BO_Mul: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } case clang::BO_Div: if (qual_type_has_wrapping_overflow(c, stmt->getType())) { // unsigned/float division uses the operator - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); } else { // signed integer division uses @divTrunc AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "divTrunc"); @@ -1424,12 +1429,13 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue); if (rhs == nullptr) return nullptr; fn_call->data.fn_call_expr.params.append(rhs); - return fn_call; + return maybe_suppress_result(c, result_used, fn_call); } case clang::BO_Rem: if (qual_type_has_wrapping_overflow(c, stmt->getType())) { // unsigned/float division uses the operator - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); } else { // signed integer division uses @rem AstNode *fn_call = trans_create_node_builtin_fn_call_str(c, "rem"); @@ -1439,42 +1445,72 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS AstNode *rhs = trans_expr(c, ResultUsedYes, scope, stmt->getRHS(), TransLValue); if (rhs == nullptr) return nullptr; fn_call->data.fn_call_expr.params.append(rhs); - return fn_call; + return maybe_suppress_result(c, result_used, fn_call); } - case clang::BO_Add: - return trans_create_bin_op(c, scope, stmt->getLHS(), + case clang::BO_Add: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd, stmt->getRHS()); - case clang::BO_Sub: - return trans_create_bin_op(c, scope, stmt->getLHS(), + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_Sub: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub, stmt->getRHS()); - case clang::BO_Shl: - return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); - case clang::BO_Shr: - return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); - case clang::BO_LT: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); - case clang::BO_GT: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); - case clang::BO_LE: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); - case clang::BO_GE: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); - case clang::BO_EQ: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); - case clang::BO_NE: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); - case clang::BO_And: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); - case clang::BO_Xor: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); - case clang::BO_Or: - return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); - case clang::BO_LAnd: - return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); - case clang::BO_LOr: - return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_Shl: { + AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_Shr: { + AstNode *node = trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_LT: { + AstNode *node =trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_GT: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_LE: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_GE: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_EQ: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_NE: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_And: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_Xor: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_Or: { + AstNode *node = trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_LAnd: { + AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } + case clang::BO_LOr: { + AstNode *node = trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS()); + return maybe_suppress_result(c, result_used, node); + } case clang::BO_Assign: return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS()); case clang::BO_Comma: @@ -1486,13 +1522,15 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS AstNode *lhs = trans_expr(c, ResultUsedNo, &scope_block->base, stmt->getLHS(), TransRValue); if (lhs == nullptr) return nullptr; - scope_block->node->data.block.statements.append(maybe_suppress_result(c, ResultUsedNo, lhs)); + scope_block->node->data.block.statements.append(lhs); - AstNode *rhs = trans_expr(c, result_used, &scope_block->base, stmt->getRHS(), TransRValue); + AstNode *rhs = trans_expr(c, ResultUsedYes, &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, rhs)); - return scope_block->node; + + rhs = trans_create_node_break(c, label_name, rhs); + scope_block->node->data.block.statements.append(rhs); + return maybe_suppress_result(c, result_used, scope_block->node); } case clang::BO_MulAssign: case clang::BO_DivAssign: @@ -1718,7 +1756,7 @@ static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_use zig_unreachable(); } -static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) { +static AstNode *trans_implicit_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ImplicitCastExpr *stmt) { switch (stmt->getCastKind()) { case clang::CK_LValueToRValue: return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); @@ -1727,8 +1765,9 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const cl AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); if (target_node == nullptr) return nullptr; - return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), + AstNode *node = trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), stmt->getSubExpr()->getType(), target_node); + return maybe_suppress_result(c, result_used, node); } case clang::CK_FunctionToPointerDecay: case clang::CK_ArrayToPointerDecay: @@ -1736,7 +1775,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const cl AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue); if (target_node == nullptr) return nullptr; - return target_node; + return maybe_suppress_result(c, result_used, target_node); } case clang::CK_BitCast: { @@ -1753,7 +1792,7 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const cl AstNode *node = trans_create_node_builtin_fn_call_str(c, "ptrCast"); node->data.fn_call_expr.params.append(dest_type_node); node->data.fn_call_expr.params.append(target_node); - return node; + return maybe_suppress_result(c, result_used, node); } case clang::CK_NullToPointer: return trans_create_node_unsigned(c, 0); @@ -2746,7 +2785,9 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope * return node; } -static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) { +static AstNode *trans_member_expr(Context *c, ResultUsed result_used, TransScope *scope, + const clang::MemberExpr *stmt) +{ AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); if (container_node == nullptr) return nullptr; @@ -2758,10 +2799,10 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::Me const char *name = decl_name(stmt->getMemberDecl()); AstNode *node = trans_create_node_field_access_str(c, container_node, name); - return node; + return maybe_suppress_result(c, result_used, node); } -static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) { +static AstNode *trans_array_subscript_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::ArraySubscriptExpr *stmt) { AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue); if (container_node == nullptr) return nullptr; @@ -2774,13 +2815,13 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const AstNode *node = trans_create_node(c, NodeTypeArrayAccessExpr); node->data.array_access_expr.array_ref_expr = container_node; node->data.array_access_expr.subscript = idx_node; - return node; + return maybe_suppress_result(c, result_used, node); } static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CStyleCastExpr *stmt, TransLRValue lrvalue) { - AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue); + AstNode *sub_expr_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), lrvalue); if (sub_expr_node == nullptr) return nullptr; @@ -2791,8 +2832,8 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran return maybe_suppress_result(c, result_used, cast); } -static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope, - const clang::UnaryExprOrTypeTraitExpr *stmt) +static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, ResultUsed result_used, + TransScope *scope, const clang::UnaryExprOrTypeTraitExpr *stmt) { AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getLocStart()); if (type_node == nullptr) @@ -2800,7 +2841,7 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop AstNode *node = trans_create_node_builtin_fn_call_str(c, "sizeOf"); node->data.fn_call_expr.params.append(type_node); - return node; + return maybe_suppress_result(c, result_used, node); } static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) { @@ -3078,11 +3119,13 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const clan return ErrorNone; } -static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) { +static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransScope *scope, const clang::StringLiteral *stmt) { switch (stmt->getKind()) { case clang::StringLiteral::Ascii: - case clang::StringLiteral::UTF8: - return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString())); + case clang::StringLiteral::UTF8: { + AstNode *node = trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString())); + return maybe_suppress_result(c, result_used, node); + } case clang::StringLiteral::UTF16: emit_warning(c, stmt->getLocStart(), "TODO support UTF16 string literals"); return nullptr; @@ -3114,8 +3157,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 AstNode *trans_predefined_expr(Context *c, ResultUsed result_used, TransScope *scope, + const clang::PredefinedExpr *expr) +{ + return trans_string_literal(c, result_used, scope, expr->getFunctionName()); } static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_scope, AstNode *result_node) { @@ -3142,7 +3187,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope)); case clang::Stmt::IntegerLiteralClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_integer_literal(c, (const clang::IntegerLiteral *)stmt)); + trans_integer_literal(c, result_used, (const clang::IntegerLiteral *)stmt)); case clang::Stmt::ConditionalOperatorClass: return wrap_stmt(out_node, out_child_scope, scope, trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt)); @@ -3154,7 +3199,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt)); case clang::Stmt::ImplicitCastExprClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt)); + trans_implicit_cast_expr(c, result_used, scope, (const clang::ImplicitCastExpr *)stmt)); case clang::Stmt::DeclRefExprClass: return wrap_stmt(out_node, out_child_scope, scope, trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue)); @@ -3190,23 +3235,23 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st return ErrorNone; case clang::Stmt::MemberExprClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_member_expr(c, scope, (const clang::MemberExpr *)stmt)); + trans_member_expr(c, result_used, scope, (const clang::MemberExpr *)stmt)); case clang::Stmt::ArraySubscriptExprClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt)); + trans_array_subscript_expr(c, result_used, scope, (const clang::ArraySubscriptExpr *)stmt)); case clang::Stmt::CStyleCastExprClass: return wrap_stmt(out_node, out_child_scope, scope, trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue)); case clang::Stmt::UnaryExprOrTypeTraitExprClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt)); + trans_unary_expr_or_type_trait_expr(c, result_used, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt)); case clang::Stmt::ForStmtClass: { AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt); return wrap_stmt(out_node, out_child_scope, scope, node); } case clang::Stmt::StringLiteralClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_string_literal(c, scope, (const clang::StringLiteral *)stmt)); + trans_string_literal(c, result_used, scope, (const clang::StringLiteral *)stmt)); case clang::Stmt::BreakStmtClass: return wrap_stmt(out_node, out_child_scope, scope, trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt)); @@ -3513,7 +3558,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st return ErrorUnexpected; case clang::Stmt::PredefinedExprClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_predefined_expr(c, scope, (const clang::PredefinedExpr *)stmt)); + trans_predefined_expr(c, result_used, scope, (const clang::PredefinedExpr *)stmt)); case clang::Stmt::PseudoObjectExprClass: emit_warning(c, stmt->getLocStart(), "TODO handle C PseudoObjectExprClass"); return ErrorUnexpected; @@ -3525,7 +3570,7 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *st return ErrorUnexpected; case clang::Stmt::StmtExprClass: return wrap_stmt(out_node, out_child_scope, scope, - trans_stmt_expr(c, scope, (const clang::StmtExpr *)stmt, out_node_scope)); + trans_stmt_expr(c, result_used, 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 39b2858cd9..b5a6d28e8c 100644 --- a/test/translate_c.zig +++ b/test/translate_c.zig @@ -67,9 +67,29 @@ pub fn addCases(cases: *tests.TranslateCContext) void { \\} , \\pub fn foo() void { - \\ c"foo"; - \\ c"foo"; - \\ c"void foo(void)"; + \\ _ = c"foo"; + \\ _ = c"foo"; + \\ _ = c"void foo(void)"; + \\} + ); + + cases.add("ignore result", + \\void foo() { + \\ int a; + \\ 1; + \\ "hey"; + \\ 1 + 1; + \\ 1 - 1; + \\ a = 1; + \\} + , + \\pub fn foo() void { + \\ var a: c_int = undefined; + \\ _ = 1; + \\ _ = c"hey"; + \\ _ = (1 + 1); + \\ _ = (1 - 1); + \\ a = 1; \\} );