Commit 1702b413f7
Changed files (2)
src/translate_c.zig
@@ -2082,13 +2082,20 @@ fn transCCast(
// 3. Bit-cast to correct signed-ness
const src_type_is_signed = cIsSignedInteger(src_type) or cIsEnum(src_type);
const src_int_type = if (cIsInteger(src_type)) src_type else cIntTypeForEnum(src_type);
- const src_int_expr = if (cIsInteger(src_type)) expr else try transEnumToInt(rp.c, expr);
+ var src_int_expr = if (cIsInteger(src_type)) expr else try transEnumToInt(rp.c, expr);
// @bitCast(dest_type, intermediate_value)
const cast_node = try rp.c.createBuiltinCall("@bitCast", 2);
cast_node.params()[0] = try transQualType(rp, dst_type, loc);
_ = try appendToken(rp.c, .Comma, ",");
+ if (isBoolRes(src_int_expr)) {
+ const bool_to_int_node = try rp.c.createBuiltinCall("@boolToInt", 1);
+ bool_to_int_node.params()[0] = src_int_expr;
+ bool_to_int_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ src_int_expr = &bool_to_int_node.base;
+ }
+
switch (cIntTypeCmp(dst_type, src_int_type)) {
.lt => {
// @truncate(SameSignSmallerInt, src_int_expr)
@@ -3113,7 +3120,26 @@ fn transCallExpr(rp: RestorePoint, scope: *Scope, stmt: *const clang.CallExpr, r
if (i != 0) {
_ = try appendToken(rp.c, .Comma, ",");
}
- call_params[i] = try transExpr(rp, scope, args[i], .used, .r_value);
+ var call_param = try transExpr(rp, scope, args[i], .used, .r_value);
+
+ // In C the result type of a boolean expression is int. If this result is passed as
+ // an argument to a function whose parameter is also int, there is no cast. Therefore
+ // in Zig we'll need to cast it from bool to u1 (which will safely coerce to c_int).
+ if (fn_ty) |ty| {
+ switch (ty) {
+ .Proto => |fn_proto| {
+ const param_qt = fn_proto.getParamType(@intCast(c_uint, i));
+ if (isBoolRes(call_param) and cIsNativeInt(param_qt)) {
+ const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);
+ builtin_node.params()[0] = call_param;
+ builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
+ call_param = &builtin_node.base;
+ }
+ },
+ else => {},
+ }
+ }
+ call_params[i] = call_param;
}
node.rtoken = try appendToken(rp.c, .RParen, ")");
@@ -4125,6 +4151,13 @@ fn cIsSignedInteger(qt: clang.QualType) bool {
};
}
+fn cIsNativeInt(qt: clang.QualType) bool {
+ const c_type = qualTypeCanon(qt);
+ if (c_type.getTypeClass() != .Builtin) return false;
+ const builtin_ty = @ptrCast(*const clang.BuiltinType, c_type);
+ return builtin_ty.getKind() == .Int;
+}
+
fn cIsFloating(qt: clang.QualType) bool {
const c_type = qualTypeCanon(qt);
if (c_type.getTypeClass() != .Builtin) return false;
test/run_translated_c.zig
@@ -703,4 +703,20 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
\\ return 0;
\\}
, "");
+
+ cases.add("Cast boolean expression result to int",
+ \\#include <stdlib.h>
+ \\char foo(char c) { return c; }
+ \\int bar(int i) { return i; }
+ \\long baz(long l) { return l; }
+ \\int main() {
+ \\ if (foo(1 == 2)) abort();
+ \\ if (!foo(1 == 1)) abort();
+ \\ if (bar(1 == 2)) abort();
+ \\ if (!bar(1 == 1)) abort();
+ \\ if (baz(1 == 2)) abort();
+ \\ if (!baz(1 == 1)) abort();
+ \\ return 0;
+ \\}
+ , "");
}