diff --git a/src-self-hosted/clang.zig b/src-self-hosted/clang.zig index 6222f3d8e4..2551829084 100644 --- a/src-self-hosted/clang.zig +++ b/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; diff --git a/src-self-hosted/translate_c.zig b/src-self-hosted/translate_c.zig index 9b5ad2644b..a6b5862fae 100644 --- a/src-self-hosted/translate_c.zig +++ b/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 diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index f333a6b7a0..21d0c5c0ca 100644 --- a/src/zig_clang.cpp +++ b/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(self); + auto casted_ctx = reinterpret_cast(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(self); return reinterpret_cast(casted->getRetValue()); diff --git a/src/zig_clang.h b/src/zig_clang.h index 94a37d98c7..2c358d880e 100644 --- a/src/zig_clang.h +++ b/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 *); diff --git a/test/translate_c.zig b/test/translate_c.zig index 7e94798efb..ac549695aa 100644 --- a/test/translate_c.zig +++ b/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; \\ }; \\} });