summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2018-12-02 07:52:17 -0600
committerEmilio Cobos Álvarez <emilio@crisal.io>2018-12-02 08:03:39 -0600
commitc7b28dbcd27656a03d18008f282668b84b234bf6 (patch)
tree9c63ae6ef4679be04bf68c21f9d1dabd8d570b16
parent7b1406dc90f67fafca61dba915ac57b9d2d7d2d4 (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.rs18
-rw-r--r--tests/expectations/tests/bindgen-union-inside-namespace.rs96
-rw-r--r--tests/headers/bindgen-union-inside-namespace.hpp8
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;
+ };
+}