diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-12-02 07:52:17 -0600 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2018-12-02 08:03:39 -0600 |
commit | c7b28dbcd27656a03d18008f282668b84b234bf6 (patch) | |
tree | 9c63ae6ef4679be04bf68c21f9d1dabd8d570b16 | |
parent | 7b1406dc90f67fafca61dba915ac57b9d2d7d2d4 (diff) |
codegen: Properly detect bindgen unions.
The root cause of the issue was the missing:
```
self.saw_bindgen_union |= new.saw_bindgen_union;
```
But I also cleaned up a bit more and removed the unused saw_union.
Fixes #1457
-rw-r--r-- | src/codegen/mod.rs | 18 | ||||
-rw-r--r-- | tests/expectations/tests/bindgen-union-inside-namespace.rs | 96 | ||||
-rw-r--r-- | tests/headers/bindgen-union-inside-namespace.hpp | 8 |
3 files changed, 107 insertions, 15 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index d2b77d6a..9a7bf897 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -95,9 +95,6 @@ struct CodegenResult<'a> { /// Whether a bindgen union has been generated at least once. saw_bindgen_union: bool, - /// Whether an union has been generated at least once. - saw_union: bool, - /// Whether an incomplete array has been generated at least once. saw_incomplete_array: bool, @@ -140,7 +137,6 @@ impl<'a> CodegenResult<'a> { fn new(codegen_id: &'a Cell<usize>) -> Self { CodegenResult { items: vec![], - saw_union: false, saw_bindgen_union: false, saw_incomplete_array: false, saw_objc: false, @@ -154,12 +150,7 @@ impl<'a> CodegenResult<'a> { } } - fn saw_union(&mut self) { - self.saw_union = true; - } - fn saw_bindgen_union(&mut self) { - self.saw_union(); self.saw_bindgen_union = true; } @@ -221,11 +212,11 @@ impl<'a> CodegenResult<'a> { cb(&mut new); - self.saw_union |= new.saw_union; self.saw_incomplete_array |= new.saw_incomplete_array; self.saw_objc |= new.saw_objc; self.saw_block |= new.saw_block; self.saw_bitfield_unit |= new.saw_bitfield_unit; + self.saw_bindgen_union |= new.saw_bindgen_union; new.items } @@ -1047,6 +1038,7 @@ impl<'a> FieldCodegen<'a> for FieldData { // NB: If supported, we use proper `union` types. let ty = if parent.is_union() && !parent.can_be_rust_union(ctx) { + result.saw_bindgen_union(); if ctx.options().enable_cxx_namespaces { quote! { root::__BindgenUnionField<#ty> @@ -1241,6 +1233,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { let field_ty = { let ty = helpers::bitfield_unit(ctx, self.layout()); if parent.is_union() && !parent.can_be_rust_union(ctx) { + result.saw_bindgen_union(); if ctx.options().enable_cxx_namespaces { quote! { root::__BindgenUnionField<#ty> @@ -1592,11 +1585,6 @@ impl CodeGenerator for CompInfo { } } } else if is_union && !self.is_forward_declaration() { - result.saw_union(); - if !self.can_be_rust_union(ctx) { - result.saw_bindgen_union(); - } - // TODO(emilio): It'd be nice to unify this with the struct path // above somehow. let layout = layout.expect("Unable to get layout information?"); diff --git a/tests/expectations/tests/bindgen-union-inside-namespace.rs b/tests/expectations/tests/bindgen-union-inside-namespace.rs new file mode 100644 index 00000000..b2e6226c --- /dev/null +++ b/tests/expectations/tests/bindgen-union-inside-namespace.rs @@ -0,0 +1,96 @@ +/* automatically generated by rust-bindgen */ + +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)] +pub mod root { + #[repr(C)] + pub struct __BindgenUnionField<T>(::std::marker::PhantomData<T>); + impl<T> __BindgenUnionField<T> { + #[inline] + pub fn new() -> Self { + __BindgenUnionField(::std::marker::PhantomData) + } + #[inline] + pub unsafe fn as_ref(&self) -> &T { + ::std::mem::transmute(self) + } + #[inline] + pub unsafe fn as_mut(&mut self) -> &mut T { + ::std::mem::transmute(self) + } + } + impl<T> ::std::default::Default for __BindgenUnionField<T> { + #[inline] + fn default() -> Self { + Self::new() + } + } + impl<T> ::std::clone::Clone for __BindgenUnionField<T> { + #[inline] + fn clone(&self) -> Self { + Self::new() + } + } + impl<T> ::std::marker::Copy for __BindgenUnionField<T> {} + impl<T> ::std::fmt::Debug for __BindgenUnionField<T> { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__BindgenUnionField") + } + } + impl<T> ::std::hash::Hash for __BindgenUnionField<T> { + fn hash<H: ::std::hash::Hasher>(&self, _state: &mut H) {} + } + impl<T> ::std::cmp::PartialEq for __BindgenUnionField<T> { + fn eq(&self, _other: &__BindgenUnionField<T>) -> bool { + true + } + } + impl<T> ::std::cmp::Eq for __BindgenUnionField<T> {} + #[allow(unused_imports)] + use self::super::root; + pub mod foo { + #[allow(unused_imports)] + use self::super::super::root; + #[repr(C)] + #[derive(Debug, Default, Copy)] + pub struct Bar { + pub foo: root::__BindgenUnionField<::std::os::raw::c_int>, + pub bar: root::__BindgenUnionField<::std::os::raw::c_int>, + pub bindgen_union_field: u32, + } + #[test] + fn bindgen_test_layout_Bar() { + assert_eq!( + ::std::mem::size_of::<Bar>(), + 4usize, + concat!("Size of: ", stringify!(Bar)) + ); + assert_eq!( + ::std::mem::align_of::<Bar>(), + 4usize, + concat!("Alignment of ", stringify!(Bar)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Bar>())).foo as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Bar), "::", stringify!(foo)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Bar>())).bar as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Bar), "::", stringify!(bar)) + ); + } + impl Clone for Bar { + fn clone(&self) -> Self { + *self + } + } + } +} diff --git a/tests/headers/bindgen-union-inside-namespace.hpp b/tests/headers/bindgen-union-inside-namespace.hpp new file mode 100644 index 00000000..6a7d3a30 --- /dev/null +++ b/tests/headers/bindgen-union-inside-namespace.hpp @@ -0,0 +1,8 @@ +// bindgen-flags: --rust-target 1.0 --enable-cxx-namespaces + +namespace foo { + union Bar { + int foo; + int bar; + }; +} |