mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Correctly cast bool to signed int in translate-c
Previously casting a bool to an int would result in the following Zig code:
@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b))));
This is incorrect if `b` is true, since bitcasting a `u1` with the value 1
to an `i1` will result in the value -1. Instead, generate the following code:
@as(c_int, @boolToInt(b));
Since @boolToInt returns a `u1`, this is only disallowed if the destination
type is one-bit and signed, which can only happen if it's a bitfield
(currently not supported by translate-c)
This commit is contained in:
parent
9f33984119
commit
830bc41b1f
@ -2160,33 +2160,20 @@ fn transCCast(
|
||||
}
|
||||
if (qualTypeIsBoolean(src_type) and !qualTypeIsBoolean(dst_type)) {
|
||||
// @boolToInt returns either a comptime_int or a u1
|
||||
// TODO: if dst_type is 1 bit & signed (bitfield) we need @bitCast
|
||||
// instead of @as
|
||||
|
||||
const builtin_node = try rp.c.createBuiltinCall("@boolToInt", 1);
|
||||
builtin_node.params()[0] = expr;
|
||||
builtin_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
|
||||
const inner_cast_node = try rp.c.createBuiltinCall("@intCast", 2);
|
||||
inner_cast_node.params()[0] = try transCreateNodeIdentifier(rp.c, "u1");
|
||||
const as_node = try rp.c.createBuiltinCall("@as", 2);
|
||||
as_node.params()[0] = try transQualType(rp, dst_type, loc);
|
||||
_ = try appendToken(rp.c, .Comma, ",");
|
||||
inner_cast_node.params()[1] = &builtin_node.base;
|
||||
inner_cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
as_node.params()[1] = &builtin_node.base;
|
||||
as_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
|
||||
const cast_node = try rp.c.createBuiltinCall("@intCast", 2);
|
||||
cast_node.params()[0] = try transQualType(rp, dst_type, loc);
|
||||
_ = try appendToken(rp.c, .Comma, ",");
|
||||
|
||||
if (cIsSignedInteger(dst_type)) {
|
||||
const bitcast_node = try rp.c.createBuiltinCall("@bitCast", 2);
|
||||
bitcast_node.params()[0] = try transCreateNodeIdentifier(rp.c, "i1");
|
||||
_ = try appendToken(rp.c, .Comma, ",");
|
||||
bitcast_node.params()[1] = &inner_cast_node.base;
|
||||
bitcast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
cast_node.params()[1] = &bitcast_node.base;
|
||||
} else {
|
||||
cast_node.params()[1] = &inner_cast_node.base;
|
||||
}
|
||||
cast_node.rparen_token = try appendToken(rp.c, .RParen, ")");
|
||||
|
||||
return &cast_node.base;
|
||||
return &as_node.base;
|
||||
}
|
||||
if (cIsEnum(dst_type)) {
|
||||
const builtin_node = try rp.c.createBuiltinCall("@intToEnum", 2);
|
||||
|
||||
@ -644,4 +644,17 @@ pub fn addCases(cases: *tests.RunTranslatedCContext) void {
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
|
||||
cases.add("assign bool result to int or char",
|
||||
\\#include <stdlib.h>
|
||||
\\#include <stdbool.h>
|
||||
\\bool foo() { return true; }
|
||||
\\int main() {
|
||||
\\ int x = foo();
|
||||
\\ if (x != 1) abort();
|
||||
\\ signed char c = foo();
|
||||
\\ if (c != 1) abort();
|
||||
\\ return 0;
|
||||
\\}
|
||||
, "");
|
||||
}
|
||||
|
||||
@ -2964,10 +2964,10 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
|
||||
, &[_][]const u8{
|
||||
\\pub export fn foo(arg_x: bool) bool {
|
||||
\\ var x = arg_x;
|
||||
\\ var a: bool = (@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(x)))) != @as(c_int, 1));
|
||||
\\ var b: bool = (@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(a)))) != @as(c_int, 0));
|
||||
\\ var a: bool = (@as(c_int, @boolToInt(x)) != @as(c_int, 1));
|
||||
\\ var b: bool = (@as(c_int, @boolToInt(a)) != @as(c_int, 0));
|
||||
\\ var c: bool = @ptrToInt(foo) != 0;
|
||||
\\ return foo((@intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(c)))) != @intCast(c_int, @bitCast(i1, @intCast(u1, @boolToInt(b))))));
|
||||
\\ return foo((@as(c_int, @boolToInt(c)) != @as(c_int, @boolToInt(b))));
|
||||
\\}
|
||||
});
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user