Skip to content

Commit

Permalink
Correctly cast bool to signed int in translate-c
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
ehaas authored and Vexu committed Dec 25, 2020
1 parent 9f33984 commit 830bc41
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 24 deletions.
29 changes: 8 additions & 21 deletions src/translate_c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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");
_ = try appendToken(rp.c, .Comma, ",");
inner_cast_node.params()[1] = &builtin_node.base;
inner_cast_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);
const as_node = try rp.c.createBuiltinCall("@as", 2);
as_node.params()[0] = try transQualType(rp, dst_type, loc);
_ = try appendToken(rp.c, .Comma, ",");
as_node.params()[1] = &builtin_node.base;
as_node.rparen_token = try appendToken(rp.c, .RParen, ")");

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);
Expand Down
13 changes: 13 additions & 0 deletions test/run_translated_c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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;
\\}
, "");
}
6 changes: 3 additions & 3 deletions test/translate_c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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))));
\\}
});

Expand Down

0 comments on commit 830bc41

Please sign in to comment.