Commit cf5932b236

Vexu <git@vexu.eu>
2020-08-09 18:24:30
translate-c: convert int to bool if bool is expected
1 parent dfcac3c
Changed files (5)
src/zig_clang.cpp
@@ -2510,6 +2510,19 @@ struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct Zi
     return bitcast(casted->getBeginLoc());
 }
 
+bool ZigClangIntegerLiteral_isZero(const struct ZigClangIntegerLiteral *self, bool *result, const struct ZigClangASTContext *ctx) {
+    auto casted_self = reinterpret_cast<const clang::IntegerLiteral *>(self);
+    auto casted_ctx = reinterpret_cast<const clang::ASTContext *>(ctx);
+    clang::Expr::EvalResult eval_result;
+    if (!casted_self->EvaluateAsInt(eval_result, *casted_ctx)) {
+        return false;
+    }
+    const llvm::APSInt result_int = eval_result.Val.getInt();
+    const llvm::APSInt zero(result_int.getBitWidth(), result_int.isUnsigned());
+    *result = zero == result_int;
+    return true;
+}
+
 const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *self) {
     auto casted = reinterpret_cast<const clang::ReturnStmt *>(self);
     return reinterpret_cast<const struct ZigClangExpr *>(casted->getRetValue());
src/zig_clang.h
@@ -1086,6 +1086,7 @@ ZIG_EXTERN_C struct ZigClangQualType ZigClangCStyleCastExpr_getType(const struct
 
 ZIG_EXTERN_C bool ZigClangIntegerLiteral_EvaluateAsInt(const struct ZigClangIntegerLiteral *, struct ZigClangExprEvalResult *, const struct ZigClangASTContext *);
 ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangIntegerLiteral_getBeginLoc(const struct ZigClangIntegerLiteral *);
+ZIG_EXTERN_C bool ZigClangIntegerLiteral_isZero(const struct ZigClangIntegerLiteral *, bool *, const struct ZigClangASTContext *);
 
 ZIG_EXTERN_C const struct ZigClangExpr *ZigClangReturnStmt_getRetValue(const struct ZigClangReturnStmt *);
 
src-self-hosted/clang.zig
@@ -1086,6 +1086,7 @@ pub extern fn ZigClangVarDecl_getTypeSourceInfo_getType(self: *const struct_ZigC
 
 pub extern fn ZigClangIntegerLiteral_EvaluateAsInt(*const ZigClangIntegerLiteral, *ZigClangExprEvalResult, *const ZigClangASTContext) bool;
 pub extern fn ZigClangIntegerLiteral_getBeginLoc(*const ZigClangIntegerLiteral) ZigClangSourceLocation;
+pub extern fn ZigClangIntegerLiteral_isZero(*const ZigClangIntegerLiteral, *bool, *const ZigClangASTContext) bool;
 
 pub extern fn ZigClangReturnStmt_getRetValue(*const ZigClangReturnStmt) ?*const ZigClangExpr;
 
src-self-hosted/translate_c.zig
@@ -1684,6 +1684,14 @@ fn transBoolExpr(
     lrvalue: LRValue,
     grouped: bool,
 ) TransError!*ast.Node {
+    if (ZigClangStmt_getStmtClass(@ptrCast(*const ZigClangStmt, expr)) == .IntegerLiteralClass) {
+        var is_zero: bool = undefined;
+        if (!ZigClangIntegerLiteral_isZero(@ptrCast(*const ZigClangIntegerLiteral, expr), &is_zero, rp.c.clang_context)) {
+            return revertAndWarn(rp, error.UnsupportedTranslation, ZigClangExpr_getBeginLoc(expr), "invalid integer literal", .{});
+        }
+        return try transCreateNodeBoolLiteral(rp.c, !is_zero);
+    }
+
     const lparen = if (grouped)
         try appendToken(rp.c, .LParen, "(")
     else
test/translate_c.zig
@@ -99,10 +99,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     , &[_][]const u8{
         \\pub export fn foo() void {
-        \\    while (@as(c_int, 0) != 0) while (@as(c_int, 0) != 0) {};
-        \\    while (true) while (@as(c_int, 0) != 0) {};
+        \\    while (false) while (false) {};
+        \\    while (true) while (false) {};
         \\    while (true) while (true) {
-        \\        if (!(@as(c_int, 0) != 0)) break;
+        \\        if (!false) break;
         \\    };
         \\}
     });
@@ -1634,8 +1634,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
     , &[_][]const u8{
         \\pub export fn foo() c_int {
         \\    var a: c_int = 5;
-        \\    while (@as(c_int, 2) != 0) a = 2;
-        \\    while (@as(c_int, 4) != 0) {
+        \\    while (true) a = 2;
+        \\    while (true) {
         \\        var a_1: c_int = 4;
         \\        a_1 = 9;
         \\        _ = @as(c_int, 6);
@@ -1644,11 +1644,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\    while (true) {
         \\        var a_1: c_int = 2;
         \\        a_1 = 12;
-        \\        if (!(@as(c_int, 4) != 0)) break;
+        \\        if (!true) break;
         \\    }
         \\    while (true) {
         \\        a = 7;
-        \\        if (!(@as(c_int, 4) != 0)) break;
+        \\        if (!true) break;
         \\    }
         \\}
     });
@@ -1702,8 +1702,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     , &[_][]const u8{
         \\pub export fn bar() c_int {
-        \\    if ((if (@as(c_int, 2) != 0) @as(c_int, 5) else (if (@as(c_int, 5) != 0) @as(c_int, 4) else @as(c_int, 6))) != 0) _ = @as(c_int, 2);
-        \\    return if (@as(c_int, 2) != 0) @as(c_int, 5) else if (@as(c_int, 5) != 0) @as(c_int, 4) else @as(c_int, 6);
+        \\    if ((if (true) @as(c_int, 5) else (if (true) @as(c_int, 4) else @as(c_int, 6))) != 0) _ = @as(c_int, 2);
+        \\    return if (true) @as(c_int, 5) else if (true) @as(c_int, 4) else @as(c_int, 6);
         \\}
     });
 
@@ -2214,7 +2214,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     , &[_][]const u8{
         \\pub export fn foo() c_int {
-        \\    if (@as(c_int, 2) != 0) {
+        \\    if (true) {
         \\        var a: c_int = 2;
         \\    }
         \\    if ((blk: {
@@ -2748,8 +2748,8 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
         \\}
     , &[_][]const u8{
         \\pub fn foo() callconv(.C) void {
-        \\    if (@as(c_int, 1) != 0) while (true) {
-        \\        if (!(@as(c_int, 0) != 0)) break;
+        \\    if (true) while (true) {
+        \\        if (!false) break;
         \\    };
         \\}
     });