mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 22:33:08 +00:00
translate-c: ensure bools are cast to int when necessary
Fixes two scenarios where @boolToInt() calls were missing: 1. Boolean expression cast to different-size int (char, long, etc) 2. Boolean expression used as parameter for function with int argument
This commit is contained in:
parent
35686262f5
commit
1702b413f7
@ -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;
|
||||
|
||||
@ -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;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user