zig icon indicating copy to clipboard operation
zig copied to clipboard

C translation issue with boolean expression

Open eknkc opened this issue 1 year ago • 5 comments

Zig Version

0.12.0

Steps to Reproduce and Observed Behavior

Given the C header file:

typedef struct
{
  int a;
} bar;

bar test_bool(int b)
{
  return (bar){.a = b != 0};
}

Zig translates this to:

pub export fn test_bool(arg_b: c_int) bar {
    var b = arg_b;
    _ = &b;
    return bar{
        .a = b != @as(c_int, 0),
    };
}

Which in turn results in

cimport.zig:64:12: error: expected type 'c_int', found 'bool'
        .a = b != @as(c_int, 0),
        ~~~^~~~~~~~~~~~~~~~~~~~

Expected Behavior

Translation shold probably use @intFromBool while assigning the int variable.

eknkc avatar May 19 '24 18:05 eknkc

Relevant quote from the c99 standard

Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false.92) The result has type int

6.5.8.6

The translation to zig needs to depend on how the result is used, since in other situations the bool result is correct and int would be wrong:

_Bool test(int a)
{
  return a != 0 && a != 4;
}

translates correctly to

pub export fn t(arg_a: c_int) bool {
    var a = arg_a;
    _ = &a;
    return (a != @as(c_int, 0)) and (a != @as(c_int, 4));
}

ProkopRandacek avatar May 21 '24 13:05 ProkopRandacek

I can successfully reproduce the issue on master. It looks like it's specifically a bug for implicit casting for a record field. The translation is correct for variables.

silver-signal avatar May 21 '24 17:05 silver-signal

I can successfully reproduce the issue on master. It looks like it's specifically a bug for implicit casting for a record field. The translation is correct for variables.

Can confirm. I was trying to come up with the absolute minimal repro sample but could not trigger it on variables. Just with a struct field.

eknkc avatar May 21 '24 19:05 eknkc

I've been testing this a bit, and I'm pretty sure this is a bug in Clang. Clang is identifying the init expression class as BinaryOperator instead of ImplicitCastExpr. The expression is correctly identified as an implicit cast in every other situation (such as struct field access). I'll file an upstream bug.

silver-signal avatar May 26 '24 03:05 silver-signal

Upstream issue is here: llvm/llvm-project#93393

@Vexu Would you mind adding labels to this issue? Probably translate-c and upstream.

silver-signal avatar May 26 '24 19:05 silver-signal