c2rust icon indicating copy to clipboard operation
c2rust copied to clipboard

Translation of union with bit field is not correct

Open Air111 opened this issue 2 years ago • 1 comments

Please consider this testcase:

#include <stdio.h>
union U0 {
   unsigned int f0;
   int f1 : 2;
} g;

int main() {
    printf("%d\n", g.f1);
}

Transpile successed:

$ intercept-build sh -c "clang-15 testcase.c"
$ c2rust --version
C2Rust 0.17.0 (2023-04-02)
$ c2rust transpile --binary testcase compile_commands.json --output-dir generated
$ cd generated && cargo build --release
   Compiling generated v0.0.0 (/home/x/creducetest/rusttest/generated)
warning: unused import: `::generated::*`
 --> src/testcase.rs:2:5
  |
2 | use ::generated::*;
  |     ^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0599]: no method named `f1` found for union `U0` in the current scope
  --> src/testcase.rs:15:61
   |
8  | pub union U0 {
   | ------------ method `f1` not found for this union
...
15 |     printf(b"%d\n\0" as *const u8 as *const libc::c_char, g.f1());
   |                                                             ^^-- help: remove the arguments
   |                                                             |
   |                                                             field, not a method

For more information about this error, try `rustc --explain E0599`.
warning: `generated` (bin "testcase") generated 1 warning
error: could not compile `generated` due to previous error; 1 warning emitted

testcase.rs:

#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)]
use ::generated::*;
extern "C" {
    fn printf(_: *const libc::c_char, _: ...) -> libc::c_int;
}
#[derive(Copy, Clone)]
#[repr(C)]
pub union U0 {
    pub f0: libc::c_uint,
    pub f1: libc::c_int,
}
#[no_mangle]
pub static mut g: U0 = U0 { f0: 0 };
unsafe fn main_0() -> libc::c_int {
    printf(b"%d\n\0" as *const u8 as *const libc::c_char, g.f1());
    return 0;
}
pub fn main() {
    unsafe { ::std::process::exit(main_0() as i32) }
}

It got the value of f1 through the getter method. But unlike transpilation of struct with bit field, f1 is just a common member in union U0, without using something like "bitfield(padding)" or "BitfieldStruct".

Air111 avatar Apr 03 '23 08:04 Air111

I think it may belong to what the translator can't handle, but I cannot find it on Known Limitations of Translation.

Air111 avatar Apr 27 '23 14:04 Air111