summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-07-09 15:48:10 +0200
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-07-09 16:02:44 +0200
commitcb0ef01b167976d6c5447e123c96af4109af7d16 (patch)
treecb5f39a7ec6ab95bbbc17b997aaa83745b54d3ba
parentf19e576961d2e3832760ca22a8e62f8ab4f7f078 (diff)
codegen: Fix some sloppiness in our handling of opaque types.
Fixes #801
-rw-r--r--src/codegen/mod.rs24
-rw-r--r--tests/expectations/tests/issue-801-opaque-sloppiness.rs40
-rw-r--r--tests/headers/issue-801-opaque-sloppiness.hpp11
3 files changed, 68 insertions, 7 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 50ebebf2..0621ea62 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1571,7 +1571,8 @@ impl CodeGenerator for CompInfo {
}
// Yeah, sorry about that.
- if item.is_opaque(ctx, &()) {
+ let is_opaque = item.is_opaque(ctx, &());
+ if is_opaque {
fields.clear();
methods.clear();
@@ -1613,7 +1614,14 @@ impl CodeGenerator for CompInfo {
// NOTE: This check is conveniently here to avoid the dummy fields we
// may add for unused template parameters.
if self.is_unsized(ctx) {
- let has_address = layout.map_or(true, |l| l.size != 0);
+ let has_address = if is_opaque {
+ // Generate the address field if it's an opaque type and
+ // couldn't determine the layout of the blob.
+ layout.is_none()
+ } else {
+ layout.map_or(true, |l| l.size != 0)
+ };
+
if has_address {
let ty = BlobTyBuilder::new(Layout::new(1, 1)).build();
let field = StructFieldBuilder::named("_address")
@@ -1670,9 +1678,11 @@ impl CodeGenerator for CompInfo {
}
if used_template_params.is_none() {
- for var in self.inner_vars() {
- ctx.resolve_item(*var)
- .codegen(ctx, result, whitelisted_items, &());
+ if !is_opaque {
+ for var in self.inner_vars() {
+ ctx.resolve_item(*var)
+ .codegen(ctx, result, whitelisted_items, &());
+ }
}
if ctx.options().layout_tests {
@@ -1707,8 +1717,8 @@ impl CodeGenerator for CompInfo {
})
.count() > 1;
- let should_skip_field_offset_checks = item.is_opaque(ctx, &()) ||
- too_many_base_vtables;
+ let should_skip_field_offset_checks =
+ is_opaque || too_many_base_vtables;
let check_field_offset = if should_skip_field_offset_checks {
None
diff --git a/tests/expectations/tests/issue-801-opaque-sloppiness.rs b/tests/expectations/tests/issue-801-opaque-sloppiness.rs
new file mode 100644
index 00000000..29ec7795
--- /dev/null
+++ b/tests/expectations/tests/issue-801-opaque-sloppiness.rs
@@ -0,0 +1,40 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct B {
+ pub _bindgen_opaque_blob: u8,
+}
+#[test]
+fn bindgen_test_layout_B() {
+ assert_eq!(::std::mem::size_of::<B>() , 1usize , concat ! (
+ "Size of: " , stringify ! ( B ) ));
+ assert_eq! (::std::mem::align_of::<B>() , 1usize , concat ! (
+ "Alignment of " , stringify ! ( B ) ));
+}
+impl Clone for B {
+ fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct C {
+ pub b: B,
+}
+#[test]
+fn bindgen_test_layout_C() {
+ assert_eq!(::std::mem::size_of::<C>() , 1usize , concat ! (
+ "Size of: " , stringify ! ( C ) ));
+ assert_eq! (::std::mem::align_of::<C>() , 1usize , concat ! (
+ "Alignment of " , stringify ! ( C ) ));
+ assert_eq! (unsafe { & ( * ( 0 as * const C ) ) . b as * const _ as usize
+ } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( C ) , "::" , stringify
+ ! ( b ) ));
+}
+impl Clone for C {
+ fn clone(&self) -> Self { *self }
+}
diff --git a/tests/headers/issue-801-opaque-sloppiness.hpp b/tests/headers/issue-801-opaque-sloppiness.hpp
new file mode 100644
index 00000000..503bba39
--- /dev/null
+++ b/tests/headers/issue-801-opaque-sloppiness.hpp
@@ -0,0 +1,11 @@
+// bindgen-flags: --opaque-type "B" --whitelist-type "C"
+
+class A;
+
+class B {
+ static A a;
+};
+
+class C {
+ B b;
+};