summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs47
-rw-r--r--tests/expectations/tests/union-align.rs39
-rw-r--r--tests/headers/long_double.h5
-rw-r--r--tests/headers/union-align.h5
4 files changed, 75 insertions, 21 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 67d6b6d5..1bff1e26 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1540,27 +1540,6 @@ impl CodeGenerator for CompInfo {
let is_union = self.kind() == CompKind::Union;
let layout = item.kind().expect_type().layout(ctx);
- if is_union && !is_opaque && !self.is_forward_declaration() {
- result.saw_union();
- if !self.can_be_rust_union(ctx) {
- result.saw_bindgen_union();
- }
-
- let layout = layout.expect("Unable to get layout information?");
- let ty = helpers::blob(ctx, layout);
-
- fields.push(if self.can_be_rust_union(ctx) {
- quote! {
- _bindgen_union_align: #ty ,
- }
- } else {
- struct_layout.saw_union(layout);
-
- quote! {
- pub bindgen_union_field: #ty ,
- }
- });
- }
let mut explicit_align = None;
if is_opaque {
@@ -1603,6 +1582,32 @@ 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?");
+
+ if struct_layout.requires_explicit_align(layout) {
+ explicit_align = Some(layout.align);
+ }
+
+ let ty = helpers::blob(ctx, layout);
+ fields.push(if self.can_be_rust_union(ctx) {
+ quote! {
+ _bindgen_union_align: #ty ,
+ }
+ } else {
+ struct_layout.saw_union(layout);
+
+ quote! {
+ pub bindgen_union_field: #ty ,
+ }
+ });
}
// C++ requires every struct to be addressable, so what C++ compilers do
diff --git a/tests/expectations/tests/union-align.rs b/tests/expectations/tests/union-align.rs
new file mode 100644
index 00000000..01eb78b7
--- /dev/null
+++ b/tests/expectations/tests/union-align.rs
@@ -0,0 +1,39 @@
+/* automatically generated by rust-bindgen */
+
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+#[repr(C)]
+#[repr(align(16))]
+#[derive(Copy, Clone)]
+pub union Bar {
+ pub foo: ::std::os::raw::c_uchar,
+ _bindgen_union_align: u128,
+}
+#[test]
+fn bindgen_test_layout_Bar() {
+ assert_eq!(
+ ::std::mem::size_of::<Bar>(),
+ 16usize,
+ concat!("Size of: ", stringify!(Bar))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Bar>(),
+ 16usize,
+ 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))
+ );
+}
+impl Default for Bar {
+ fn default() -> Self {
+ unsafe { ::std::mem::zeroed() }
+ }
+}
diff --git a/tests/headers/long_double.h b/tests/headers/long_double.h
new file mode 100644
index 00000000..91c4ed6c
--- /dev/null
+++ b/tests/headers/long_double.h
@@ -0,0 +1,5 @@
+// bindgen-flags: --rust-target 1.26
+
+struct foo {
+ long double bar;
+};
diff --git a/tests/headers/union-align.h b/tests/headers/union-align.h
new file mode 100644
index 00000000..94e60ef1
--- /dev/null
+++ b/tests/headers/union-align.h
@@ -0,0 +1,5 @@
+// bindgen-flags: --rust-target 1.26
+
+union Bar {
+ unsigned char foo;
+} __attribute__ ((__aligned__ (16)));