summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2022-11-30 13:13:51 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2022-12-07 12:18:35 +0100
commitaa9849ba06cb99a5b0917a2e7b33406fe6f76d0c (patch)
tree440eefac38dcec287ec1cdfd2ee2a2719279b88b
parenta9d41985313f2f4e35a15fe1a94724fb373d051c (diff)
codegen: Do generate field offset checks for classes with multiple bases.
The bug only affects virtual inheritance, so instead disable layout tests in the test that we know is broken. Not generating layout tests is wrong anyways, because the offset would be wrong.
-rw-r--r--bindgen-tests/tests/expectations/tests/inherit_multiple_interfaces.rs130
-rw-r--r--bindgen-tests/tests/expectations/tests/virtual_inheritance.rs76
-rw-r--r--bindgen-tests/tests/headers/inherit_multiple_interfaces.hpp15
-rw-r--r--bindgen-tests/tests/headers/virtual_inheritance.hpp3
-rw-r--r--bindgen/codegen/mod.rs11
5 files changed, 148 insertions, 87 deletions
diff --git a/bindgen-tests/tests/expectations/tests/inherit_multiple_interfaces.rs b/bindgen-tests/tests/expectations/tests/inherit_multiple_interfaces.rs
new file mode 100644
index 00000000..46aa15db
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/inherit_multiple_interfaces.rs
@@ -0,0 +1,130 @@
+#![allow(
+ dead_code,
+ non_snake_case,
+ non_camel_case_types,
+ non_upper_case_globals
+)]
+
+#[repr(C)]
+pub struct A__bindgen_vtable {}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct A {
+ pub vtable_: *const A__bindgen_vtable,
+ pub member: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_A() {
+ const UNINIT: ::std::mem::MaybeUninit<A> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<A>(),
+ 16usize,
+ concat!("Size of: ", stringify!(A))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<A>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(A))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).member) as usize - ptr as usize },
+ 8usize,
+ concat!("Offset of field: ", stringify!(A), "::", stringify!(member))
+ );
+}
+impl Default for A {
+ fn default() -> Self {
+ let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
+ unsafe {
+ ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+#[repr(C)]
+pub struct B__bindgen_vtable {}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct B {
+ pub vtable_: *const B__bindgen_vtable,
+ pub member2: *mut ::std::os::raw::c_void,
+}
+#[test]
+fn bindgen_test_layout_B() {
+ const UNINIT: ::std::mem::MaybeUninit<B> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<B>(),
+ 16usize,
+ concat!("Size of: ", stringify!(B))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<B>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(B))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).member2) as usize - ptr as usize },
+ 8usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(B),
+ "::",
+ stringify!(member2)
+ )
+ );
+}
+impl Default for B {
+ fn default() -> Self {
+ let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
+ unsafe {
+ ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct C {
+ pub _base: A,
+ pub _base_1: B,
+ pub member3: f32,
+}
+#[test]
+fn bindgen_test_layout_C() {
+ const UNINIT: ::std::mem::MaybeUninit<C> =
+ ::std::mem::MaybeUninit::uninit();
+ let ptr = UNINIT.as_ptr();
+ assert_eq!(
+ ::std::mem::size_of::<C>(),
+ 40usize,
+ concat!("Size of: ", stringify!(C))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<C>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(C))
+ );
+ assert_eq!(
+ unsafe { ::std::ptr::addr_of!((*ptr).member3) as usize - ptr as usize },
+ 32usize,
+ concat!(
+ "Offset of field: ",
+ stringify!(C),
+ "::",
+ stringify!(member3)
+ )
+ );
+}
+impl Default for C {
+ fn default() -> Self {
+ let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
+ unsafe {
+ ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+ s.assume_init()
+ }
+ }
+}
diff --git a/bindgen-tests/tests/expectations/tests/virtual_inheritance.rs b/bindgen-tests/tests/expectations/tests/virtual_inheritance.rs
index 2c15b428..07b94ec8 100644
--- a/bindgen-tests/tests/expectations/tests/virtual_inheritance.rs
+++ b/bindgen-tests/tests/expectations/tests/virtual_inheritance.rs
@@ -10,27 +10,6 @@
pub struct A {
pub foo: ::std::os::raw::c_int,
}
-#[test]
-fn bindgen_test_layout_A() {
- const UNINIT: ::std::mem::MaybeUninit<A> =
- ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<A>(),
- 4usize,
- concat!("Size of: ", stringify!(A))
- );
- assert_eq!(
- ::std::mem::align_of::<A>(),
- 4usize,
- concat!("Alignment of ", stringify!(A))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).foo) as usize - ptr as usize },
- 0usize,
- concat!("Offset of field: ", stringify!(A), "::", stringify!(foo))
- );
-}
#[repr(C)]
pub struct B__bindgen_vtable(::std::os::raw::c_void);
#[repr(C)]
@@ -39,27 +18,6 @@ pub struct B {
pub vtable_: *const B__bindgen_vtable,
pub bar: ::std::os::raw::c_int,
}
-#[test]
-fn bindgen_test_layout_B() {
- const UNINIT: ::std::mem::MaybeUninit<B> =
- ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<B>(),
- 16usize,
- concat!("Size of: ", stringify!(B))
- );
- assert_eq!(
- ::std::mem::align_of::<B>(),
- 8usize,
- concat!("Alignment of ", stringify!(B))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).bar) as usize - ptr as usize },
- 8usize,
- concat!("Offset of field: ", stringify!(B), "::", stringify!(bar))
- );
-}
impl Default for B {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
@@ -77,27 +35,6 @@ pub struct C {
pub vtable_: *const C__bindgen_vtable,
pub baz: ::std::os::raw::c_int,
}
-#[test]
-fn bindgen_test_layout_C() {
- const UNINIT: ::std::mem::MaybeUninit<C> =
- ::std::mem::MaybeUninit::uninit();
- let ptr = UNINIT.as_ptr();
- assert_eq!(
- ::std::mem::size_of::<C>(),
- 16usize,
- concat!("Size of: ", stringify!(C))
- );
- assert_eq!(
- ::std::mem::align_of::<C>(),
- 8usize,
- concat!("Alignment of ", stringify!(C))
- );
- assert_eq!(
- unsafe { ::std::ptr::addr_of!((*ptr).baz) as usize - ptr as usize },
- 8usize,
- concat!("Offset of field: ", stringify!(C), "::", stringify!(baz))
- );
-}
impl Default for C {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
@@ -114,19 +51,6 @@ pub struct D {
pub _base_1: B,
pub bazz: ::std::os::raw::c_int,
}
-#[test]
-fn bindgen_test_layout_D() {
- assert_eq!(
- ::std::mem::size_of::<D>(),
- 40usize,
- concat!("Size of: ", stringify!(D))
- );
- assert_eq!(
- ::std::mem::align_of::<D>(),
- 8usize,
- concat!("Alignment of ", stringify!(D))
- );
-}
impl Default for D {
fn default() -> Self {
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
diff --git a/bindgen-tests/tests/headers/inherit_multiple_interfaces.hpp b/bindgen-tests/tests/headers/inherit_multiple_interfaces.hpp
new file mode 100644
index 00000000..725992c7
--- /dev/null
+++ b/bindgen-tests/tests/headers/inherit_multiple_interfaces.hpp
@@ -0,0 +1,15 @@
+class A {
+ virtual void Foo();
+
+ int member;
+};
+
+class B {
+ virtual void Bar();
+
+ void* member2;
+};
+
+class C : public A, public B {
+ float member3;
+};
diff --git a/bindgen-tests/tests/headers/virtual_inheritance.hpp b/bindgen-tests/tests/headers/virtual_inheritance.hpp
index 5198c51e..b35378d8 100644
--- a/bindgen-tests/tests/headers/virtual_inheritance.hpp
+++ b/bindgen-tests/tests/headers/virtual_inheritance.hpp
@@ -1,4 +1,5 @@
-
+// bindgen-flags: --no-layout-tests
+// FIXME: Enable layout tests when #465 is fixed.
class A {
int foo;
};
diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs
index 154d7fd1..c297aaab 100644
--- a/bindgen/codegen/mod.rs
+++ b/bindgen/codegen/mod.rs
@@ -2193,16 +2193,7 @@ impl CodeGenerator for CompInfo {
})
};
- // FIXME when [issue #465](https://github.com/rust-lang/rust-bindgen/issues/465) ready
- let too_many_base_vtables = self
- .base_members()
- .iter()
- .filter(|base| base.ty.has_vtable(ctx))
- .count() >
- 1;
-
- let should_skip_field_offset_checks =
- is_opaque || too_many_base_vtables;
+ let should_skip_field_offset_checks = is_opaque;
let check_field_offset = if should_skip_field_offset_checks
{