Skip to content

Commit

Permalink
Handle empty enums without variants
Browse files Browse the repository at this point in the history
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 6b4718a commit 978f221
Show file tree
Hide file tree
Showing 44 changed files with 222 additions and 279 deletions.
44 changes: 26 additions & 18 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 @@ -2185,11 +2188,13 @@ impl<'a> EnumBuilder<'a> {
EnumVariation::Rust => {
let mut tokens = quote! {
#( #attrs )*
#[repr(C)]
pub enum #ident
};
tokens.append("{");
EnumBuilder::Rust(tokens)
EnumBuilder::Rust {
tokens,
emitted_any_variants: false,
}
}

EnumVariation::Consts => {
Expand Down Expand Up @@ -2230,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 @@ -2296,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 @@ -2433,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
4 changes: 2 additions & 2 deletions tests/expectations/tests/anon_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ pub struct Test {
}
pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Test__bindgen_ty_1 {
T_NONE = 0,
}
Expand Down Expand Up @@ -41,8 +41,8 @@ fn bindgen_test_layout_Test() {
);
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Baz {
Foo = 0,
Bar = 1,
Expand Down
4 changes: 2 additions & 2 deletions tests/expectations/tests/anon_enum_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ 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)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum DataType__bindgen_ty_1 {
generic_type = 0,
}
Expand All @@ -32,8 +32,8 @@ 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)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo__bindgen_ty_1 {
Bar = 0,
}
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/anon_enum_whitelist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
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)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
NODE_FLAG_FOO = 0,
NODE_FLAG_BAR = 1,
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/anon_union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ pub struct TErrorResult {
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
TErrorResult_UnionState::HasMessage;
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TErrorResult_UnionState {
HasMessage = 0,
}
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/anon_union_1_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ pub struct TErrorResult {
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
TErrorResult_UnionState::HasMessage;
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TErrorResult_UnionState {
HasMessage = 0,
}
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/bitfield_align_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ where
}
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MyEnum {
ONE = 0,
TWO = 1,
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/class_with_inner_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,8 @@ fn bindgen_test_layout_B() {
);
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StepSyntax {
Keyword = 0,
FunctionalWithoutKeyword = 1,
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/class_with_inner_struct_1_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,8 @@ impl Clone for B {
}
}
#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StepSyntax {
Keyword = 0,
FunctionalWithoutKeyword = 1,
Expand Down
4 changes: 2 additions & 2 deletions tests/expectations/tests/const_enum_unnamed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
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)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
FOO_BAR = 0,
FOO_BAZ = 1,
Expand All @@ -20,8 +20,8 @@ pub struct Foo {
}
pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo__bindgen_ty_1 {
FOO_BAR = 10,
}
Expand Down
2 changes: 1 addition & 1 deletion tests/expectations/tests/constify-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ pub const nsCSSPropertyID_eCSSProperty_COUNT_unexistingVariantValue: nsCSSProper
pub const nsCSSPropertyID_eCSSProperty_COUNT: nsCSSPropertyID =
nsCSSPropertyID::eCSSPropertyAlias_aa;
#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsCSSPropertyID {
eCSSProperty_a = 0,
eCSSProperty_b = 1,
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;
}
4 changes: 2 additions & 2 deletions tests/expectations/tests/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@


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


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

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


#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
One = 1,
}
#[repr(u16)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bigger {
Much = 255,
Larger = 256,
}
#[repr(i64)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchLong {
MuchLow = -4294967296,
}
#[repr(i64)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchLongLong {
I64_MIN = -9223372036854775808,
}
#[repr(u64)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchULongLong {
MuchHigh = 4294967296,
}
2 changes: 1 addition & 1 deletion tests/expectations/tests/enum_in_template_with_typedef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ 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)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum std_fbstring_core_Category {
Foo = 0,
}
2 changes: 1 addition & 1 deletion tests/expectations/tests/enum_negative.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@


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


#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i8)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
One = 1,
}
#[repr(u16)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bigger {
Much = 255,
Larger = 256,
Expand Down
Loading

0 comments on commit 978f221

Please sign in to comment.