diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2022-11-30 13:13:51 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2022-12-07 12:18:35 +0100 |
commit | aa9849ba06cb99a5b0917a2e7b33406fe6f76d0c (patch) | |
tree | 440eefac38dcec287ec1cdfd2ee2a2719279b88b | |
parent | a9d41985313f2f4e35a15fe1a94724fb373d051c (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.
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 { |