rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

Bitfield enums in return position violate the Linux 32-bit ABI

Open jryans opened this issue 8 years ago • 2 comments

Input C/C++ Header

enum class OriginFlags : char {
  UserAgent = 0x01,
  User      = 0x02,
  Author    = 0x04,
  All       = 0x07,
};

OriginFlags GetFlags();

Bindgen Invocation

$ bindgen origin-flags.h -o origin_flags_bindings_32.rs --bitfield-enum OriginFlags -- -x c++ -std=c++14 -m32

Actual Results

/* automatically generated by rust-bindgen */

pub const OriginFlags_UserAgent: OriginFlags = OriginFlags(1);
pub const OriginFlags_User: OriginFlags = OriginFlags(2);
pub const OriginFlags_Author: OriginFlags = OriginFlags(4);
pub const OriginFlags_All: OriginFlags = OriginFlags(7);
impl ::std::ops::BitOr<OriginFlags> for OriginFlags {
    type
    Output
    =
    Self;
    #[inline]
    fn bitor(self, other: Self) -> Self { OriginFlags(self.0 | other.0) }
}
impl ::std::ops::BitOrAssign for OriginFlags {
    #[inline]
    fn bitor_assign(&mut self, rhs: OriginFlags) { self.0 |= rhs.0; }
}
impl ::std::ops::BitAnd<OriginFlags> for OriginFlags {
    type
    Output
    =
    Self;
    #[inline]
    fn bitand(self, other: Self) -> Self { OriginFlags(self.0 & other.0) }
}
impl ::std::ops::BitAndAssign for OriginFlags {
    #[inline]
    fn bitand_assign(&mut self, rhs: OriginFlags) { self.0 &= rhs.0; }
}
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct OriginFlags(pub ::std::os::raw::c_char);
extern "C" {
    #[link_name = "_Z8GetFlagsv"]
    pub fn GetFlags() -> OriginFlags;
}

Expected Results

Bitfield enum mode uses a struct on the Rust side, but C++ treats this as a primitive type. Since the Linux 32-bit ABI treats structs vs. primitives in return position differently, this leads to nonsense behavior.

I encountered this in several places while working on Stylo. As a workaround, we lied to bindgen about the return type and replaced it with the primitive value:

http://searchfox.org/mozilla-central/search?q=bitfield+enums&case=true&regexp=false&path=

jryans avatar Sep 02 '17 00:09 jryans

Thanks for reporting, this is pretty much known, and depending on https://github.com/rust-lang/rust/issues/43036, mostly.

emilio avatar Sep 02 '17 00:09 emilio

#[repr(transparent)] has been stable for a while, and OriginFlags is tagged as such. Do we need to do anything else here?

pvdrz avatar Sep 19 '22 19:09 pvdrz