c2rust icon indicating copy to clipboard operation
c2rust copied to clipboard

`|=` operator on `bool` results in invalid Rust being generated

Open nyanpasu64 opened this issue 4 years ago • 2 comments

I tried running c2rust on BRRtools as an example of a small but nontrivial C project. However the generated Rust fails to compile. The input C in question is:

https://github.com/Optiroc/BRRtools/blob/9f6c4708150120284102f9899632d7f5f0b0638a/src/brr_encoder.c#L596-L598

I minified this example to the following C code (x can be either bool or int):

#include <stdbool.h>

// both bool and int reproduce the bug
extern bool x;

int main() {
	bool initial_block = false;
	initial_block |= x;
}

Running the latest c2rust 030df665741bb9d1b29fe41cdbfd7223a67c5995 produces the following Rust code:

#![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case,
         non_upper_case_globals, unused_assignments, unused_mut)]
#![register_tool(c2rust)]
#![feature(main, register_tool)]
use ::c2rust_out::*;
extern "C" {
    // both bool and int reproduce the bug
    #[no_mangle]
    static mut x: bool;
}
unsafe fn main_0() -> libc::c_int {
    let mut initial_block: bool = 0 as libc::c_int != 0;
    initial_block = (initial_block as libc::c_int | x as libc::c_int) as bool;
    return 0;
}
#[main]
pub fn main() { unsafe { ::std::process::exit(main_0() as i32) } }

which produces an error when compiling on both cargo +nightly-2019-12-05 and stable:

error[E0054]: cannot cast as `bool`
  --> src/brr_encoder.rs:13:21
   |
13 |     initial_block = (initial_block as libc::c_int | x as libc::c_int) as bool;
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: compare with zero instead: `(initial_block as libc::c_int | x as libc::c_int) != 0`

I've uploaded at repo at https://github.com/nyanpasu64/c2rust-bug. Steps to reproduce:

c2rust transpile --binary brr_encoder --overwrite-existing compile_commands.json
cargo build

nyanpasu64 avatar Jul 01 '21 09:07 nyanpasu64

The same problem also occurs with &=. c2rust also generates invalid code when casting bool directly to a pointer type (because boolean as *mut T is invalid). https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=44a0720a276e962309baf54ba59f759b

Dante-Broggi avatar Jan 11 '23 05:01 Dante-Broggi

I'm guessing this is also the same issue:

	_Bool q = 1;
	q += 1;
    let mut q: bool = 1 as libc::c_int != 0;
    q = (q as libc::c_int + 1 as libc::c_int) as bool;
error[E0054]: cannot cast as `bool`
   --> src/binary.rs:245:9
    |
245 |     q = (q as libc::c_int + 1 as libc::c_int) as bool;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: compare with zero instead: `(q as libc::c_int + 1 as libc::c_int) != 0`

GPHemsley avatar Sep 29 '24 16:09 GPHemsley