Skip to content

Redeclaration with incompatible signature may use unexpected signature #123

Open
@TheDan64

Description

@TheDan64

Newlib does a little bit more complicated version of this:

#include <limits.h>

double __exp10(unsigned x);

int main(void) {
  __exp10(1U);

  return 0;
}

Where double __exp10(unsigned x) is defined in another local file.

When translating this code you get a warning from C:

/home/dkolsoi/repos/c2rust/test.c:3:8: warning: incompatible redeclaration of library function
      '__exp10' [-Wincompatible-library-redeclaration]
double __exp10(unsigned x);
       ^
/home/dkolsoi/repos/c2rust/test.c:3:8: note: '__exp10' is a builtin with type 'double (double)'

But the translated code:

extern "C" {
    #[no_mangle]
    fn __exp10(_: libc::c_double) -> libc::c_double;
}
unsafe fn main_0() -> libc::c_int { __exp10(1u32); return 0i32; }

Will fail to compile because it uses the builtin signature which takes a double and not an int.

Interestingly (but maybe not totally surprising), passing the -ffreestanding flag to clang via the transpiler will bypass this issue and use the correct signature:

extern "C" {
    #[no_mangle]
    fn __exp10(x: libc::c_uint) -> libc::c_double;
}
#[export_name = "main"]
pub unsafe extern "C" fn main_0() -> libc::c_int {
    __exp10(1u32);
    return 0i32;
}

(also interesting, but not problematic, note that it's using x not _ in the param sig)

This can be seen in newlib when configuring with --disable-newlib-fno-builtin

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions