Skip to content

repr(C) on enums #1183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions csmith-fuzzing/predicate.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
default=BINDGEN_ARGS,
help="An argument string that `bindgen` should be invoked with. By default, all traits are derived. Note that the input header and output bindings file will automatically be provided by this script, and you should not manually specify them.")

parser.add_argument(
"--save-temp-files",
action="store_true",
help="Do not delete temporary files.")

parser.add_argument(
"input",
type=str,
Expand Down Expand Up @@ -144,11 +149,12 @@ def main():
exit_code = 2
print("Unexpected exception:", e)

for path in TEMP_FILES:
try:
os.remove(path)
except Exception as e:
print("Unexpected exception:", e)
if not args.save_temp_files:
for path in TEMP_FILES:
try:
os.remove(path)
except Exception as e:
print("Unexpected exception:", e)

sys.exit(exit_code)

Expand Down
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
Loading