Skip to content
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

zig translate-c Type Propagation Error for Nullable Pointer ([*c]) Dereferencing and Address Calculation in Zig #22045

Open
Yeaseen opened this issue Nov 22, 2024 · 2 comments
Labels
bug Observed behavior contradicts documented or intended behavior translate-c C to Zig source translation feature (@cImport)

Comments

@Yeaseen
Copy link

Yeaseen commented Nov 22, 2024

Zig Version

0.14.0-dev.2064+b5cafe223

Steps to Reproduce and Observed Behavior

Input C Code

typedef int (*myarr)[2];

void main() {
    // Define an array and set `a` to point to it
    int array[2] = {10, 20};
    int (*a)[2] = &array;  // `a` points to `array`

    // Set `b` to point to the same array, casted to `myarr`
    myarr b = (myarr)a;

    // Modify array elements through `b`
    (*b)[0] = 30;
}

Translated zig code

pub const myarr = [*c][2]c_int;
pub export fn main() void {
    var array: [2]c_int = [2]c_int{
        10,
        20,
    };
    _ = &array;
    var a: [*c][2]c_int = &array;
    _ = &a;
    var b: myarr = @as(myarr, @ptrCast(@alignCast(a)));
    _ = &b;
    b.*[@as(c_uint, @intCast(@as(c_int, 0)))] = 30;
}

zig build failure

runner.zig:68:49: error: expected type '[2]c_int', found 'comptime_int'
    b.*[@as(c_uint, @intCast(@as(c_int, 0)))] = 30;
                                                ^~

The generated zig code incorrectly uses a cast that results in a comptime_int type mismatch, making it impossible to modify the array elements as intended.

Expected Behavior

The zig translate-c tool should generate the correct zig code that allows accessing and modifying array elements through a pointer. For example, the output zig code should correctly handle the array pointer and allow the assignment.

@Yeaseen Yeaseen added the bug Observed behavior contradicts documented or intended behavior label Nov 22, 2024
@rohlem
Copy link
Contributor

rohlem commented Nov 22, 2024

I don't see the issue in the generated code, rather something in the type check / access pattern of b.*[n] = x might be wrong in the compiler:

  • @TypeOf(b.*[0]) == @TypeOf(b.*[1]) == c_int (imo correct)
  • @TypeOf(&(b.*[1])) == *[2]c_int (imo wrong)
    It seems like taking the address of the double-dereference [*c]-Pointer access somehow moves us up two layers / to the root?
    If myarray is declared as *[2]c_int, the issue doesn't happen.
  • @TypeOf(&(b.*[0])) == *allowzero [2]c_int, which I also can't explain - maybe we're incorrectly reinterpreting (uninitialized?) memory in some way?
    This also doesn't happen for myarray = *[2]c_int.

@Yeaseen Yeaseen changed the title zig translate-c Produces Incorrect Zig Code for Array Pointer Access zig translate-c Type Propagation Error for Nullable Pointer ([*c]) Dereferencing and Address Calculation in Zig Nov 23, 2024
@Yeaseen
Copy link
Author

Yeaseen commented Nov 23, 2024

Thank you for your detailed analysis @rohlem

It does seem zig translate-c is correctly mimicking C code's intent here. I updated the title. The issue indeed seems to stem from an inconsistency in how the Zig compiler handles [*c] pointers during dereferencing and address-of operations.

The issue with @TypeOf(&(b.*[0])) producing *allowzero [2]c_int instead of *c_int seems to require a deeper analysis of how the Zig compiler handles the following:

  1. Dereferencing Nullable Pointers ([*c]):

    • Specifically, how the compiler propagates types during dereferencing and indexing for nullable pointers pointing to arrays.
  2. Array Indexing and Address Calculation:

    • The unexpected type suggests the compiler might be treating the operation as taking the address of the entire array rather than a specific element. This could be related to how indexing (b.*[n]) interacts with nullable pointer semantics.
  3. Role of allowzero:

    • The presence of allowzero in the result type might indicate additional complexity in how nullable pointers are being interpreted. This could involve an incorrect reinterpretation of memory during address-of operations.

Further investigation into these areas could help clarify why the compiler produces *allowzero [2]c_int and resolve the unexpected type propagation.

@Vexu Vexu added the translate-c C to Zig source translation feature (@cImport) label Feb 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior translate-c C to Zig source translation feature (@cImport)
Projects
None yet
Development

No branches or pull requests

3 participants