Skip to content

Add a run-make test that checks our core::ffi::c_* types against Clang #133058

Open
@tgross35

Description

@tgross35

It would be good to have a test that our C interop types are always compatible with C (c_char, c_long, c_longlong all vary to some extent). This will more or less be what @taiki-e did at #129945, just rolled into a run-make test rather than a shell script.

The test will basically need to do the following:

  1. Loop through each target string in the output of rustc --print target-list

  2. Map the rust target to a LLVM target if they aren't the same

  3. Loop through a list of each c_* type available in core::ffi

  4. Query clang -E -dM -x c /dev/null -target LLVM_TARGET to get a list of builtin definitions. Of note will be something like the following (comments added by me)

    #define __CHAR_BIT__ 8 // c_char
    #define __CHAR_UNSIGNED__ 1 // char signedness
    
    #define __SIZEOF_DOUBLE__ 8 // c_double
    #define __SIZEOF_FLOAT__ 4 // c_float
    #define __SIZEOF_INT__ 4 // c_int
    #define __SIZEOF_LONG_DOUBLE__ 16 // c_longdouble
    #define __SIZEOF_LONG_LONG__ 8 // c_longlong
    #define __SIZEOF_LONG__ 4 // c_long
    #define __SIZEOF_POINTER__ 4 // *const c_void
    #define __SIZEOF_PTRDIFF_T__ 4 // c_ptrdiff_t
    #define __SIZEOF_SHORT__ 2 // c_short
    #define __SIZEOF_SIZE_T__ 4 // c_size_t
    
    #define __BOOL_WIDTH__ 8 // bool
    #define __INTPTR_WIDTH__ 32 // isize
    #define __INT_WIDTH__ 32 // c_int
    #define __LLONG_WIDTH__ 64 // c_longlong
    #define __LONG_WIDTH__ 32 // c_long
    #define __POINTER_WIDTH__ 32 // *const c_void
    #define __PTRDIFF_WIDTH__ 32 // c_ptrdiff_t
    #define __SHRT_WIDTH__ 16 // c_short
    #define __SIZE_WIDTH__ 32 // c_size_t
    #define __UINTPTR_WIDTH__ 32 // usize
  5. Use the above to construct a simple Rust program that can verify the sizes and (when applicable) signedness line up at compile time. Probably do an assignment that will catch mismatched types plus a const assert for anything that doesn't have literals.

    // input to check `c_short`
    const C_SHORT: u{c_sizeof_short} = 0;
    const RUST_SHORT: core::ffi::c_short = C_SHORT;
    
    ```rust
    // input to check pointer width
    const _: () = assert!(size_of::<*const core::ffi::c_void>() * 8 == {c_pointer_width});
  6. Run rustc -Z no-codegen and check success/failure against a list of xfail targets.

run_make_support has clang available, example usage: https://github.com/rust-lang/rust/blob/e84902d35a4d3039c794e139eb12fba3624c5ff1/tests/run-make/cross-lang-lto-clang/rmake.rs. There is probably some way we could check this on MSVC targets too.

Metadata

Metadata

Assignees

Labels

A-FFIArea: Foreign function interface (FFI)A-testsuiteArea: The testsuite used to check the correctness of rustcE-hardCall for participation: Hard difficulty. Experience needed to fix: A lot.E-needs-designThis issue needs exploration and design to see how and if we can fix/implement itE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-libsRelevant to the library team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions