Skip to content

Commit

Permalink
Always add repr(C) to rustified enums
Browse files Browse the repository at this point in the history
If we don't, then eddyb's recent layout optimizations will do unexpected things
to them.

We also need to handle empty `enum`s without variants. When `repr(C)` is on a
Rust `enum`, it cannot be empty, so we need to add a dummy.
  • Loading branch information
fitzgen committed Dec 12, 2017
1 parent d9950d4 commit 43c43ba
Show file tree
Hide file tree
Showing 46 changed files with 171 additions and 22 deletions.
43 changes: 26 additions & 17 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2148,7 +2148,10 @@ impl EnumVariation {

/// A helper type to construct different enum variations.
enum EnumBuilder<'a> {
Rust(quote::Tokens),
Rust {
tokens: quote::Tokens,
emitted_any_variants: bool,
},
Bitfield {
canonical_name: &'a str,
tokens: quote::Tokens,
Expand Down Expand Up @@ -2188,7 +2191,10 @@ impl<'a> EnumBuilder<'a> {
pub enum #ident
};
tokens.append("{");
EnumBuilder::Rust(tokens)
EnumBuilder::Rust {
tokens,
emitted_any_variants: false,
}
}

EnumVariation::Consts => {
Expand Down Expand Up @@ -2229,12 +2235,15 @@ impl<'a> EnumBuilder<'a> {
};

match self {
EnumBuilder::Rust(tokens) => {
EnumBuilder::Rust { tokens, emitted_any_variants: _ } => {
let name = ctx.rust_ident(variant_name);
EnumBuilder::Rust(quote! {
#tokens
#name = #expr,
})
EnumBuilder::Rust {
tokens: quote! {
#tokens
#name = #expr,
},
emitted_any_variants: true,
}
}

EnumBuilder::Bitfield { .. } => {
Expand Down Expand Up @@ -2295,9 +2304,12 @@ impl<'a> EnumBuilder<'a> {
result: &mut CodegenResult<'b>,
) -> quote::Tokens {
match self {
EnumBuilder::Rust(mut t) => {
t.append("}");
t
EnumBuilder::Rust { mut tokens, emitted_any_variants } => {
if !emitted_any_variants {
tokens.append(quote! { __bindgen_cannot_repr_c_on_empty_enum = 0 });
}
tokens.append("}");
tokens
}
EnumBuilder::Bitfield {
canonical_name,
Expand Down Expand Up @@ -2432,15 +2444,12 @@ impl CodeGenerator for Enum {

let mut attrs = vec![];

// FIXME: Rust forbids repr with empty enums. Remove this condition when
// this is allowed.
//
// TODO(emilio): Delegate this to the builders?
if variation.is_rust() {
if !self.variants().is_empty() {
attrs.push(attributes::repr(repr_name));
}
} else if variation.is_bitfield() {
attrs.push(attributes::repr(repr_name));
}

if variation.is_bitfield() || variation.is_rust() {
attrs.push(attributes::repr("C"));
}

Expand Down
2 changes: 2 additions & 0 deletions tests/expectations/tests/anon_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub struct Test {
}
pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Test__bindgen_ty_1 {
T_NONE = 0,
Expand Down Expand Up @@ -40,6 +41,7 @@ fn bindgen_test_layout_Test() {
);
}
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Baz {
Foo = 0,
Expand Down
2 changes: 2 additions & 0 deletions tests/expectations/tests/anon_enum_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub const DataType_channels: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::ge
pub const DataType_fmt: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type;
pub const DataType_type_: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type;
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum DataType__bindgen_ty_1 {
generic_type = 0,
Expand All @@ -31,6 +32,7 @@ pub struct Foo {
pub const Foo_Bar: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar;
pub const Foo_Baz: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo__bindgen_ty_1 {
Bar = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/anon_enum_whitelist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO;
pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
NODE_FLAG_FOO = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/anon_union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub struct TErrorResult {
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
TErrorResult_UnionState::HasMessage;
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TErrorResult_UnionState {
HasMessage = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/anon_union_1_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub struct TErrorResult {
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
TErrorResult_UnionState::HasMessage;
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TErrorResult_UnionState {
HasMessage = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/bitfield_align_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ where
}
}
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MyEnum {
ONE = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/class_with_inner_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ fn bindgen_test_layout_B() {
);
}
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StepSyntax {
Keyword = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/class_with_inner_struct_1_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ impl Clone for B {
}
}
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StepSyntax {
Keyword = 0,
Expand Down
2 changes: 2 additions & 0 deletions tests/expectations/tests/const_enum_unnamed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR;
pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
FOO_BAR = 0,
Expand All @@ -19,6 +20,7 @@ pub struct Foo {
}
pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo__bindgen_ty_1 {
FOO_BAR = 10,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/constify-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub const nsCSSPropertyID_eCSSProperty_COUNT_unexistingVariantValue: nsCSSProper
pub const nsCSSPropertyID_eCSSProperty_COUNT: nsCSSPropertyID =
nsCSSPropertyID::eCSSPropertyAlias_aa;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsCSSPropertyID {
eCSSProperty_a = 0,
Expand Down
36 changes: 36 additions & 0 deletions tests/expectations/tests/empty-enum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


pub type EmptyConstified = ::std::os::raw::c_uint;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum EmptyRustified {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
pub mod EmptyModule {
pub type Type = ::std::os::raw::c_uint;
}
#[repr(i8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum EmptyClassRustified {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
pub type EmptyClassConstified = ::std::os::raw::c_char;
pub mod EmptyClassModule {
pub type Type = ::std::os::raw::c_char;
}
#[repr(i8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ForwardClassRustified {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
pub type ForwardClassConstified = ::std::os::raw::c_char;
pub mod ForwardClassModule {
pub type Type = ::std::os::raw::c_char;
}
2 changes: 2 additions & 0 deletions tests/expectations/tests/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@


#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/enum_alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@


#[repr(u8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bar {
VAL = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/enum_and_vtable_mangling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
pub const match_: _bindgen_ty_1 = _bindgen_ty_1::match_;
pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
match_ = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/enum_dupe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

pub const Foo_Dupe: Foo = Foo::Bar;
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 1,
Expand Down
6 changes: 6 additions & 0 deletions tests/expectations/tests/enum_explicit_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,40 @@


#[repr(u8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
One = 1,
}
#[repr(u16)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bigger {
Much = 255,
Larger = 256,
}
#[repr(i64)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchLong {
MuchLow = -4294967296,
}
#[repr(i64)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchLongLong {
I64_MIN = -9223372036854775808,
}
#[repr(u64)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchULongLong {
MuchHigh = 4294967296,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/enum_in_template_with_typedef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub type std_fbstring_core_category_type = u8;
pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category =
std_fbstring_core_Category::Foo;
#[repr(u8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum std_fbstring_core_Category {
Foo = 0,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/enum_negative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@


#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = -2,
Expand Down
3 changes: 3 additions & 0 deletions tests/expectations/tests/enum_packed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,21 @@


#[repr(u8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i8)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
One = 1,
}
#[repr(u16)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bigger {
Much = 255,
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/forward-enum-decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@


#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CSSPseudoClassType {
empty = 0,
Expand Down
6 changes: 5 additions & 1 deletion tests/expectations/tests/func_ptr_in_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum baz {}
pub enum baz {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Foo {
Expand Down
1 change: 1 addition & 0 deletions tests/expectations/tests/issue-372.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ pub mod root {
}
}
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum n {
o = 0,
Expand Down
6 changes: 5 additions & 1 deletion tests/expectations/tests/issue-410.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ pub mod root {
}
}
}
#[repr(u32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSWhyMagic {}
pub enum JSWhyMagic {
__bindgen_cannot_repr_c_on_empty_enum = 0,
}
}
2 changes: 2 additions & 0 deletions tests/expectations/tests/issue-493.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ impl Default for basic_string___long {
pub const basic_string___min_cap: basic_string__bindgen_ty_1 =
basic_string__bindgen_ty_1::__min_cap;
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum basic_string__bindgen_ty_1 {
__min_cap = 0,
Expand Down Expand Up @@ -109,6 +110,7 @@ impl Default for basic_string___ulx {
pub const basic_string___n_words: basic_string__bindgen_ty_2 =
basic_string__bindgen_ty_2::__n_words;
#[repr(i32)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum basic_string__bindgen_ty_2 {
__n_words = 0,
Expand Down
Loading

0 comments on commit 43c43ba

Please sign in to comment.