Commit b2887620f3

Jimmi Holst Christensen <jhc@liab.dk>
2018-03-08 13:15:30
Translate C will now handle ignored return values
1 parent 689e241
Changed files (2)
src/translate_c.cpp
@@ -500,15 +500,31 @@ static bool qual_type_is_ptr(QualType qt) {
     return ty->getTypeClass() == Type::Pointer;
 }
 
-static bool qual_type_is_fn_ptr(Context *c, QualType qt) {
+static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {
     const Type *ty = qual_type_canon(qt);
-    if (ty->getTypeClass() != Type::Pointer) {
-        return false;
+    *is_ptr = false;
+
+    if (ty->getTypeClass() == Type::Pointer) {
+        *is_ptr = true;
+        const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
+        QualType child_qt = pointer_ty->getPointeeType();
+        ty = child_qt.getTypePtr();
+    }
+
+    if (ty->getTypeClass() == Type::FunctionProto) {
+        return static_cast<const FunctionProtoType*>(ty);
     }
-    const PointerType *pointer_ty = static_cast<const PointerType*>(ty);
-    QualType child_qt = pointer_ty->getPointeeType();
-    const Type *child_ty = child_qt.getTypePtr();
-    return child_ty->getTypeClass() == Type::FunctionProto;
+
+    return nullptr;
+}
+
+static bool qual_type_is_fn_ptr(QualType qt) {
+    bool is_ptr;
+    if (qual_type_get_fn_proto(qt, &is_ptr)) {
+        return is_ptr;
+    }
+
+    return false;
 }
 
 static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
@@ -1871,7 +1887,7 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
                 AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
                 if (value_node == nullptr)
                     return nullptr;
-                bool is_fn_ptr = qual_type_is_fn_ptr(c, stmt->getSubExpr()->getType());
+                bool is_fn_ptr = qual_type_is_fn_ptr(stmt->getSubExpr()->getType());
                 if (is_fn_ptr)
                     return value_node;
                 AstNode *unwrapped = trans_create_node_prefix_op(c, PrefixOpUnwrapMaybe, value_node);
@@ -2327,8 +2343,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
     if (callee_raw_node == nullptr)
         return nullptr;
 
+    bool is_ptr = false;
+    const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
     AstNode *callee_node = nullptr;
-    if (qual_type_is_fn_ptr(c, stmt->getCallee()->getType())) {
+    if (is_ptr && fn_ty) {
         if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {
             const ImplicitCastExpr *implicit_cast = static_cast<const ImplicitCastExpr *>(stmt->getCallee());
             if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {
@@ -2360,6 +2378,10 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
         node->data.fn_call_expr.params.append(arg_node);
     }
 
+    if (result_used == ResultUsedNo && fn_ty && !qual_type_canon(fn_ty->getReturnType())->isVoidType()) {
+        node = trans_create_node_bin_op(c, trans_create_node_symbol_str(c, "_"), BinOpTypeAssign, node);
+    }
+
     return node;
 }
 
test/translate_c.zig
@@ -515,11 +515,19 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
 
     cases.addC("function call",
         \\static void bar(void) { }
-        \\void foo(void) { bar(); }
+        \\static int baz(void) { return 0; }
+        \\void foo(void) {
+        \\    bar();
+        \\    baz();
+        \\}
     ,
         \\pub fn bar() void {}
+        \\pub fn baz() c_int {
+        \\    return 0;
+        \\}
         \\pub export fn foo() void {
         \\    bar();
+        \\    _ = baz();
         \\}
     );
 
@@ -878,21 +886,31 @@ pub fn addCases(cases: &tests.TranslateCContext) void {
 
     cases.addC("deref function pointer",
         \\void foo(void) {}
-        \\void baz(void) {}
+        \\int baz(void) { return 0; }
         \\void bar(void) {
         \\    void(*f)(void) = foo;
+        \\    int(*b)(void) = baz;
         \\    f();
         \\    (*(f))();
+        \\    foo();
+        \\    b();
+        \\    (*(b))();
         \\    baz();
         \\}
     ,
         \\pub export fn foo() void {}
-        \\pub export fn baz() void {}
+        \\pub export fn baz() c_int {
+        \\    return 0;
+        \\}
         \\pub export fn bar() void {
         \\    var f: ?extern fn() void = foo;
+        \\    var b: ?extern fn() c_int = baz;
         \\    (??f)();
         \\    (??f)();
-        \\    baz();
+        \\    foo();
+        \\    _ = (??b)();
+        \\    _ = (??b)();
+        \\    _ = baz();
         \\}
     );