From 4eaca743b257ae51f5f80aa279a8faaefc98ffac Mon Sep 17 00:00:00 2001 From: Christian Legnitto Date: Thu, 3 Jan 2019 13:57:45 -0800 Subject: [PATCH] Bitfield enums use #[repr(transparent)] on Rust 1.28+ Fixes https://github.com/rust-lang/rust-bindgen/issues/1474. --- src/codegen/mod.rs | 6 ++- src/features.rs | 6 +++ .../expectations/tests/bitfield-enum-basic.rs | 7 ++- .../tests/bitfield-enum-repr-c.rs | 50 +++++++++++++++++++ .../tests/bitfield-enum-repr-transparent.rs | 50 +++++++++++++++++++ tests/headers/bitfield-enum-repr-c.hpp | 8 +++ .../bitfield-enum-repr-transparent.hpp | 8 +++ 7 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 tests/expectations/tests/bitfield-enum-repr-c.rs create mode 100644 tests/expectations/tests/bitfield-enum-repr-transparent.rs create mode 100644 tests/headers/bitfield-enum-repr-c.hpp create mode 100644 tests/headers/bitfield-enum-repr-transparent.hpp diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 898df16771..6fd7e7d35f 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2573,7 +2573,11 @@ impl CodeGenerator for Enum { if variation.is_rust() { attrs.push(attributes::repr(repr_name)); } else if variation.is_bitfield() { - attrs.push(attributes::repr("C")); + if ctx.options().rust_features.repr_transparent { + attrs.push(attributes::repr("transparent")); + } else { + attrs.push(attributes::repr("C")); + } } if let Some(comment) = item.comment(ctx) { diff --git a/src/features.rs b/src/features.rs index 6f10f11bab..1f70003931 100644 --- a/src/features.rs +++ b/src/features.rs @@ -100,6 +100,8 @@ macro_rules! rust_target_base { => Stable_1_26 => 1.26; /// Rust stable 1.27 => Stable_1_27 => 1.27; + /// Rust stable 1.28 + => Stable_1_28 => 1.28; /// Nightly rust => Nightly => nightly; ); @@ -184,6 +186,10 @@ rust_feature_def!( /// `must_use` attribute on functions ([PR](https://github.com/rust-lang/rust/pull/48925)) => must_use_function; } + Stable_1_28 { + /// repr(transparent) ([PR](https://github.com/rust-lang/rust/pull/51562)) + => repr_transparent; + } Nightly { /// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202)) => thiscall_abi; diff --git a/tests/expectations/tests/bitfield-enum-basic.rs b/tests/expectations/tests/bitfield-enum-basic.rs index a8140b2eb0..2142776e65 100644 --- a/tests/expectations/tests/bitfield-enum-basic.rs +++ b/tests/expectations/tests/bitfield-enum-basic.rs @@ -1,6 +1,11 @@ /* automatically generated by rust-bindgen */ -#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] impl Foo { pub const Bar: Foo = Foo(2); diff --git a/tests/expectations/tests/bitfield-enum-repr-c.rs b/tests/expectations/tests/bitfield-enum-repr-c.rs new file mode 100644 index 0000000000..33103c17c2 --- /dev/null +++ b/tests/expectations/tests/bitfield-enum-repr-c.rs @@ -0,0 +1,50 @@ +/* automatically generated by rust-bindgen */ + +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +impl Foo { + pub const Bar: Foo = Foo(2); +} +impl Foo { + pub const Baz: Foo = Foo(4); +} +impl Foo { + pub const Duplicated: Foo = Foo(4); +} +impl Foo { + pub const Negative: Foo = Foo(-3); +} +impl ::std::ops::BitOr for Foo { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + Foo(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for Foo { + #[inline] + fn bitor_assign(&mut self, rhs: Foo) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for Foo { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + Foo(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for Foo { + #[inline] + fn bitand_assign(&mut self, rhs: Foo) { + self.0 &= rhs.0; + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Foo(pub i32); diff --git a/tests/expectations/tests/bitfield-enum-repr-transparent.rs b/tests/expectations/tests/bitfield-enum-repr-transparent.rs new file mode 100644 index 0000000000..6d0c541593 --- /dev/null +++ b/tests/expectations/tests/bitfield-enum-repr-transparent.rs @@ -0,0 +1,50 @@ +/* automatically generated by rust-bindgen */ + +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +impl Foo { + pub const Bar: Foo = Foo(2); +} +impl Foo { + pub const Baz: Foo = Foo(4); +} +impl Foo { + pub const Duplicated: Foo = Foo(4); +} +impl Foo { + pub const Negative: Foo = Foo(-3); +} +impl ::std::ops::BitOr for Foo { + type Output = Self; + #[inline] + fn bitor(self, other: Self) -> Self { + Foo(self.0 | other.0) + } +} +impl ::std::ops::BitOrAssign for Foo { + #[inline] + fn bitor_assign(&mut self, rhs: Foo) { + self.0 |= rhs.0; + } +} +impl ::std::ops::BitAnd for Foo { + type Output = Self; + #[inline] + fn bitand(self, other: Self) -> Self { + Foo(self.0 & other.0) + } +} +impl ::std::ops::BitAndAssign for Foo { + #[inline] + fn bitand_assign(&mut self, rhs: Foo) { + self.0 &= rhs.0; + } +} +#[repr(transparent)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Foo(pub i32); diff --git a/tests/headers/bitfield-enum-repr-c.hpp b/tests/headers/bitfield-enum-repr-c.hpp new file mode 100644 index 0000000000..20a3f9dbbe --- /dev/null +++ b/tests/headers/bitfield-enum-repr-c.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --bitfield-enum "Foo" --rust-target 1.27 -- -std=c++11 + +enum Foo { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +}; diff --git a/tests/headers/bitfield-enum-repr-transparent.hpp b/tests/headers/bitfield-enum-repr-transparent.hpp new file mode 100644 index 0000000000..e53bb0753c --- /dev/null +++ b/tests/headers/bitfield-enum-repr-transparent.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --bitfield-enum "Foo" --rust-target 1.28 -- -std=c++11 + +enum Foo { + Bar = 1 << 1, + Baz = 1 << 2, + Duplicated = 1 << 2, + Negative = -3, +};