Commit b7f18164f9

Vexu <git@vexu.eu>
2019-12-19 20:30:51
translate-c-2 add missing casts
1 parent 61482be
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -1210,10 +1210,10 @@ fn transImplicitCastExpr(
     const c = rp.c;
     const sub_expr = ZigClangImplicitCastExpr_getSubExpr(expr);
     const sub_expr_node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value);
+    const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr));
+    const src_type = getExprQualType(c, sub_expr);
     switch (ZigClangImplicitCastExpr_getCastKind(expr)) {
         .BitCast, .FloatingCast, .FloatingToIntegral, .IntegralToFloating, .IntegralCast => {
-            const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr));
-            const src_type = getExprQualType(c, sub_expr);
             return transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, sub_expr_node);
         },
         .LValueToRValue, .NoOp, .FunctionToPointerDecay, .ArrayToPointerDecay => {
@@ -1222,6 +1222,47 @@ fn transImplicitCastExpr(
         .NullToPointer => {
             return try transCreateNodeNullLiteral(rp.c);
         },
+        .PointerToBoolean => {
+            // @ptrToInt(val) != 0
+            const ptr_to_int = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
+            try ptr_to_int.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value));
+            ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")");
+
+            const op_token = try appendToken(rp.c, .BangEqual, "!=");
+            const rhs_node = try transCreateNodeInt(rp.c, 0);
+            return transCreateNodeInfixOp(rp, scope, &ptr_to_int.base, .BangEqual, op_token, rhs_node, result_used, false);
+        },
+        .IntegralToBoolean => {
+            // val != 0
+            const node = try transExpr(rp, scope, sub_expr, .used, .r_value);
+
+            const op_token = try appendToken(rp.c, .BangEqual, "!=");
+            const rhs_node = try transCreateNodeInt(rp.c, 0);
+            return transCreateNodeInfixOp(rp, scope, node, .BangEqual, op_token, rhs_node, result_used, false);
+        },
+        .PointerToIntegral => {
+            // @intCast(dest_type, @ptrToInt(val))
+            const cast_node = try transCreateNodeBuiltinFnCall(rp.c, "@intCast");
+            try cast_node.params.push(try transQualType(rp, dest_type, ZigClangImplicitCastExpr_getBeginLoc(expr)));
+            _ = try appendToken(rp.c, .Comma, ",");
+
+            const ptr_to_int = try transCreateNodeBuiltinFnCall(rp.c, "@ptrToInt");
+            try ptr_to_int.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value));
+            ptr_to_int.rparen_token = try appendToken(rp.c, .RParen, ")");
+            try cast_node.params.push(&ptr_to_int.base);
+            cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+            return maybeSuppressResult(rp, scope, result_used, &cast_node.base);
+        },
+        .IntegralToPointer => {
+            // @intToPtr(dest_type, val)
+            const int_to_ptr = try transCreateNodeBuiltinFnCall(rp.c, "@intToPtr");
+            try int_to_ptr.params.push(try transQualType(rp, dest_type, ZigClangImplicitCastExpr_getBeginLoc(expr)));
+            _ = try appendToken(rp.c, .Comma, ",");
+
+            try int_to_ptr.params.push(try transExpr(rp, scope, sub_expr, .used, .r_value));
+            int_to_ptr.rparen_token = try appendToken(rp.c, .RParen, ")");
+            return maybeSuppressResult(rp, scope, result_used, &int_to_ptr.base);
+        },
         else => |kind| return revertAndWarn(
             rp,
             error.UnsupportedTranslation,
@@ -2224,6 +2265,9 @@ fn transUnaryOperator(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangUnar
             op_node.rhs = try transBoolExpr(rp, scope, op_expr, .used, .r_value, true);
             return &op_node.base;
         },
+        .Extension => {
+            return transExpr(rp, scope, ZigClangUnaryOperator_getSubExpr(stmt), used, .l_value);
+        },
         else => return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangUnaryOperator_getBeginLoc(stmt), "unsupported C translation {}", .{ZigClangUnaryOperator_getOpcode(stmt)}),
     }
 }
test/translate_c.zig
@@ -819,6 +819,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
+    cases.addC("__extension__ cast",
+        \\int foo(void) {
+        \\    return __extension__ 1;
+        \\}
+    , &[_][]const u8{
+        \\pub export fn foo() c_int {
+        \\    return 1;
+        \\}
+    });
+
     /////////////// Cases that pass for only stage2 ////////////////
 
     cases.add_2("Parameterless function prototypes",
@@ -2031,43 +2041,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     });
 
-    /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
-
-    cases.add("macro defines string literal with hex",
-        \\#define FOO "aoeu\xab derp"
-        \\#define FOO2 "aoeu\x0007a derp"
-        \\#define FOO_CHAR '\xfF'
-    , &[_][]const u8{
-        \\pub const FOO = "aoeu\xab derp";
-    ,
-        \\pub const FOO2 = "aoeuz derp";
-    ,
-        \\pub const FOO_CHAR = 255;
-    });
-
-    cases.add("macro defines string literal with octal",
-        \\#define FOO "aoeu\023 derp"
-        \\#define FOO2 "aoeu\0234 derp"
-        \\#define FOO_CHAR '\077'
-    , &[_][]const u8{
-        \\pub const FOO = "aoeu\x13 derp";
-    ,
-        \\pub const FOO2 = "aoeu\x134 derp";
-    ,
-        \\pub const FOO_CHAR = 63;
-    });
-
-    cases.addC("__extension__ cast",
-        \\int foo(void) {
-        \\    return __extension__ 1;
-        \\}
-    , &[_][]const u8{
-        \\pub export fn foo() c_int {
-        \\    return 1;
-        \\}
-    });
-
-    cases.addC("implicit casts",
+    cases.add_2("implicit casts",
         \\#include <stdbool.h>
         \\
         \\void fn_int(int x);
@@ -2103,25 +2077,51 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\pub extern fn fn_bool(x: bool) void;
         \\pub extern fn fn_ptr(x: ?*c_void) void;
         \\pub export fn call(q: c_int) void {
-        \\    fn_int(@floatToInt(c_int, 3.000000));
-        \\    fn_int(@floatToInt(c_int, 3.000000));
-        \\    fn_int(@floatToInt(c_int, 3.000000));
+        \\    fn_int(@floatToInt(c_int, 3));
+        \\    fn_int(@floatToInt(c_int, 3));
+        \\    fn_int(@floatToInt(c_int, 3));
         \\    fn_int(1094861636);
         \\    fn_f32(@intToFloat(f32, 3));
         \\    fn_f64(@intToFloat(f64, 3));
         \\    fn_char(@as(u8, '3'));
         \\    fn_char(@as(u8, '\x01'));
         \\    fn_char(@as(u8, 0));
-        \\    fn_f32(3.000000);
-        \\    fn_f64(3.000000);
-        \\    fn_bool(true);
-        \\    fn_bool(false);
+        \\    fn_f32(3);
+        \\    fn_f64(3);
+        \\    fn_bool(123 != 0);
+        \\    fn_bool(0 != 0);
         \\    fn_bool(@ptrToInt(&fn_int) != 0);
         \\    fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
         \\    fn_ptr(@intToPtr(?*c_void, 42));
         \\}
     });
 
+    /////////////// Cases for only stage1 which are TODO items for stage2 ////////////////
+
+    cases.add("macro defines string literal with hex",
+        \\#define FOO "aoeu\xab derp"
+        \\#define FOO2 "aoeu\x0007a derp"
+        \\#define FOO_CHAR '\xfF'
+    , &[_][]const u8{
+        \\pub const FOO = "aoeu\xab derp";
+    ,
+        \\pub const FOO2 = "aoeuz derp";
+    ,
+        \\pub const FOO_CHAR = 255;
+    });
+
+    cases.add("macro defines string literal with octal",
+        \\#define FOO "aoeu\023 derp"
+        \\#define FOO2 "aoeu\0234 derp"
+        \\#define FOO_CHAR '\077'
+    , &[_][]const u8{
+        \\pub const FOO = "aoeu\x13 derp";
+    ,
+        \\pub const FOO2 = "aoeu\x134 derp";
+    ,
+        \\pub const FOO_CHAR = 63;
+    });
+
     if (builtin.os != builtin.Os.windows) {
         // sysv_abi not currently supported on windows
         cases.add("Macro qualified functions",
@@ -2990,4 +2990,59 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    });
         \\}
     });
+
+    cases.addC("implicit casts",
+        \\#include <stdbool.h>
+        \\
+        \\void fn_int(int x);
+        \\void fn_f32(float x);
+        \\void fn_f64(double x);
+        \\void fn_char(char x);
+        \\void fn_bool(bool x);
+        \\void fn_ptr(void *x);
+        \\
+        \\void call(int q) {
+        \\    fn_int(3.0f);
+        \\    fn_int(3.0);
+        \\    fn_int(3.0L);
+        \\    fn_int('ABCD');
+        \\    fn_f32(3);
+        \\    fn_f64(3);
+        \\    fn_char('3');
+        \\    fn_char('\x1');
+        \\    fn_char(0);
+        \\    fn_f32(3.0f);
+        \\    fn_f64(3.0);
+        \\    fn_bool(123);
+        \\    fn_bool(0);
+        \\    fn_bool(&fn_int);
+        \\    fn_int(&fn_int);
+        \\    fn_ptr(42);
+        \\}
+    , &[_][]const u8{
+        \\pub extern fn fn_int(x: c_int) void;
+        \\pub extern fn fn_f32(x: f32) void;
+        \\pub extern fn fn_f64(x: f64) void;
+        \\pub extern fn fn_char(x: u8) void;
+        \\pub extern fn fn_bool(x: bool) void;
+        \\pub extern fn fn_ptr(x: ?*c_void) void;
+        \\pub export fn call(q: c_int) void {
+        \\    fn_int(@floatToInt(c_int, 3.000000));
+        \\    fn_int(@floatToInt(c_int, 3.000000));
+        \\    fn_int(@floatToInt(c_int, 3.000000));
+        \\    fn_int(1094861636);
+        \\    fn_f32(@intToFloat(f32, 3));
+        \\    fn_f64(@intToFloat(f64, 3));
+        \\    fn_char(@as(u8, '3'));
+        \\    fn_char(@as(u8, '\x01'));
+        \\    fn_char(@as(u8, 0));
+        \\    fn_f32(3.000000);
+        \\    fn_f64(3.000000);
+        \\    fn_bool(true);
+        \\    fn_bool(false);
+        \\    fn_bool(@ptrToInt(&fn_int) != 0);
+        \\    fn_int(@intCast(c_int, @ptrToInt(&fn_int)));
+        \\    fn_ptr(@intToPtr(?*c_void, 42));
+        \\}
+    });
 }