Skip to content

translate-c: char always converted to u8, even on platforms where char is signed #9154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
ehaas opened this issue Jun 18, 2021 · 6 comments
Labels
translate-c C to Zig source translation feature (@cImport)
Milestone

Comments

@ehaas
Copy link
Contributor

ehaas commented Jun 18, 2021

The following C code on x86_64-macos-gnu does not call abort; but when run via translate-c it does call abort:

#include <stdlib.h>
int main(void) {
    char c = -1;
    if (c != -1) abort();
}

In transType, .Char_S is translated as u8, but it means 'char' for targets where it's signed

Treating .Char_S as signed will break string literal -> char * implicit casts on those platforms; perhaps the proper thing to do is to special-case char * in transType ?

@xackus
Copy link
Contributor

xackus commented Jun 20, 2021

#875

@nektro
Copy link
Contributor

nektro commented Jul 14, 2021

https://www.cs.swarthmore.edu/~newhall/unixhelp/C_chars.html

In C, char values are stored in 1 byte, and are encoded as numbers using the ASCII encoding.

This is perfectly compatible with the u8 number type.

@nektro
Copy link
Contributor

nektro commented Jul 14, 2021

but when run via translate-c it does call abort:

what does translate-c generate for you?

@ehaas
Copy link
Contributor Author

ehaas commented Jul 14, 2021

pub export fn main() c_int {
    var c: u8 = @bitCast(u8, @truncate(i8, -@as(c_int, 1)));
    if (@bitCast(c_int, @as(c_uint, c)) != -@as(c_int, 1)) {
        abort();
    }
    return 0;
}

c is signed in the original C code on my platform but translate-c converts it to unsigned. In the C if statement if (c != -1), c is promoted from a signed char to a signed int; in the Zig code 255 is promoted to an unsigned int and then bitcasted to a signed int. So it compares the c_int values 255 and -1 and ultimately calls abort, which is incorrect behavior.

@Vexu Vexu added the translate-c C to Zig source translation feature (@cImport) label Aug 6, 2021
@Vexu Vexu added this to the 0.10.0 milestone Aug 6, 2021
@Mouvedia
Copy link

c_char type is currently always signed.

Concerning signedness detection see the discussion starting with this comment.

@Vexu
Copy link
Member

Vexu commented Apr 13, 2023

Here's the function Aro uses to determine char signedness:
https://github.com/Vexu/arocc/blob/c1955a474270562a4640217e62c888b52c79d39e/src/target.zig#L7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
translate-c C to Zig source translation feature (@cImport)
Projects
None yet
Development

No branches or pull requests

5 participants