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

Translate-c incorrectly translates address-of operator with fn ptr and obscure fn calls #4124

Closed
Rocknest opened this issue Jan 9, 2020 · 1 comment · Fixed by #7965
Closed
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. frontend Tokenization, parsing, AstGen, Sema, and Liveness. translate-c C to Zig source translation feature (@cImport)
Milestone

Comments

@Rocknest
Copy link
Contributor

Rocknest commented Jan 9, 2020

This c source

#include <stdlib.h>
#include <stdint.h>

static int add(int a, int b) {
    return a + b;
}

int main(int argc, char **argv) {
    if ((&add)(1, 2) != 3) abort();
    if (add(3, 1) != 4) abort();
    if ((*add)(2, 3) != 5) abort();
    if ((**add)(7, -1) != 6) abort();
    if ((***add)(-2, 9) != 7) abort();

    int (*ptr)(int a, int b);
    ptr = add;
    
    if (ptr(1, 2) != 3) abort();
    if ((*ptr)(3, 1) != 4) abort();
    if ((**ptr)(2, 3) != 5) abort();
    if ((***ptr)(7, -1) != 6) abort();
    if ((****ptr(-2, 9) != 7) abort();

    uintptr_t addr1 = (uintptr_t) (add);
    uintptr_t addr2 = (uintptr_t) (&add);
    
    if (addr1 != addr2) abort();
    return 0;
}

incorrectly translated as

pub fn add(arg_a: c_int, arg_b: c_int) callconv(.C) c_int {
    var a = arg_a;
    var b = arg_b;
    return (a + b);
}
pub export fn main(arg_argc: c_int, arg_argv: [*c][*c]u8) c_int {
    var argc = arg_argc;
    var argv = arg_argv;
!   if ((&add).?(@as(c_int, 1), @as(c_int, 2)) != @as(c_int, 3)) abort();
    if (add(@as(c_int, 3), @as(c_int, 1)) != @as(c_int, 4)) abort();
!   if ((add).?(@as(c_int, 2), @as(c_int, 3)) != @as(c_int, 5)) abort();
!   if ((add).?(@as(c_int, 7), -@as(c_int, 1)) != @as(c_int, 6)) abort();
!   if ((add).?(-@as(c_int, 2), @as(c_int, 9)) != @as(c_int, 7)) abort();
    var ptr: ?fn (c_int, c_int) callconv(.C) c_int = undefined;
    ptr = add;
    if (ptr.?(@as(c_int, 1), @as(c_int, 2)) != @as(c_int, 3)) abort();
    if ((ptr).?(@as(c_int, 3), @as(c_int, 1)) != @as(c_int, 4)) abort();
    if ((ptr).?(@as(c_int, 2), @as(c_int, 3)) != @as(c_int, 5)) abort();
    if ((ptr).?(@as(c_int, 7), -@as(c_int, 1)) != @as(c_int, 6)) abort();
    if ((ptr).?(-@as(c_int, 2), @as(c_int, 9)) != @as(c_int, 7)) abort();
    var addr1: usize = @intCast(usize, @ptrToInt((add)));
!   var addr2: usize = @intCast(usize, @ptrToInt((&add)));
    if (addr1 != addr2) abort();
    return 0;
}
  1. In C address-of operator on function name is ignored.
    (uintptr_t) (add) and (uintptr_t) (&add) are equivalent. This is a footgun protection against footgun of pointer casting a double pointer to a single pointer #1890

  2. C allows to call functions in obscure ways. In addition to the default way name(args) there are:
    (&name)(args) and ( '*' n times name)(args).

Similarly to this dereference operator (n times) is ignored on function pointers.

@daurnimator daurnimator added the translate-c C to Zig source translation feature (@cImport) label Jan 9, 2020
@andrewrk andrewrk added contributor friendly This issue is limited in scope and/or knowledge of Zig internals. frontend Tokenization, parsing, AstGen, Sema, and Liveness. labels Jan 17, 2020
@andrewrk andrewrk added this to the 0.7.0 milestone Jan 17, 2020
@zuntrax
Copy link

zuntrax commented Apr 11, 2020

I'm looking into this.

@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Aug 13, 2020
ehaas added a commit to ehaas/zig that referenced this issue Feb 7, 2021
Omit address-of operator if operand is a function.

Improve handling of function-call translation when using function pointers

Fixes ziglang#4124
ehaas added a commit to ehaas/zig that referenced this issue Feb 7, 2021
Omit address-of operator if operand is a function.

Improve handling of function-call translation when using function pointers

Fixes ziglang#4124
ehaas added a commit to ehaas/zig that referenced this issue Feb 8, 2021
Omit address-of operator if operand is a function.

Improve handling of function-call translation when using function pointers

Fixes ziglang#4124
@Vexu Vexu closed this as completed in #7965 Feb 8, 2021
Vexu pushed a commit that referenced this issue Feb 8, 2021
Omit address-of operator if operand is a function.

Improve handling of function-call translation when using function pointers

Fixes #4124
dgbuckley pushed a commit to dgbuckley/zig that referenced this issue Mar 9, 2021
Omit address-of operator if operand is a function.

Improve handling of function-call translation when using function pointers

Fixes ziglang#4124
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. frontend Tokenization, parsing, AstGen, Sema, and Liveness. translate-c C to Zig source translation feature (@cImport)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants