diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2019-03-06 14:16:22 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-06 14:16:22 +0100 |
commit | 185a5f322e973b60f8d0986672f9a88e5d9a07bd (patch) | |
tree | 4fa6d49cb0270b3e1c55ef27b74838f2a1569814 | |
parent | 3a6864cf9a76916c002c41a8ae813d9f8bd9853e (diff) | |
parent | 9b6d0e84b432d95b3bfdf5a19b8abadde768489c (diff) |
Merge pull request #1531 from emilio/ref-layoutv0.48.1
Work around a libclang bug / limitation.
-rw-r--r-- | CHANGELOG.md | 11 | ||||
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | src/clang.rs | 50 | ||||
-rw-r--r-- | src/ir/context.rs | 10 | ||||
-rw-r--r-- | src/ir/item.rs | 2 | ||||
-rw-r--r-- | src/ir/layout.rs | 4 | ||||
-rw-r--r-- | src/ir/ty.rs | 6 | ||||
-rw-r--r-- | tests/expectations/tests/issue-1443.rs | 150 | ||||
-rw-r--r-- | tests/headers/issue-1443.hpp | 21 |
10 files changed, 225 insertions, 33 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index fbbf29c1..fe3dff50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -92,6 +92,17 @@ Released YYYY/MM/DD * TODO (or remove section if none) +-------------------------------------------------------------------------------- + +# 0.48.1 + +Released 2019/03/06 + +## Fixed + +* Bindgen will properly lay out types that use reference members. [#1531][] + +[#1531]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1531 -------------------------------------------------------------------------------- @@ -49,7 +49,7 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.48.0" +version = "0.48.1" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cexpr 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -14,7 +14,7 @@ readme = "README.md" repository = "https://github.com/rust-lang/rust-bindgen" documentation = "https://docs.rs/bindgen" homepage = "https://rust-lang.github.io/rust-bindgen/" -version = "0.48.0" +version = "0.48.1" build = "build.rs" include = [ diff --git a/src/clang.rs b/src/clang.rs index 40ba60e8..e02d363f 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -7,6 +7,7 @@ use cexpr; use clang_sys::*; use regex; +use ir::context::BindgenContext; use std::{mem, ptr, slice}; use std::ffi::{CStr, CString}; use std::fmt; @@ -933,35 +934,44 @@ impl Type { #[inline] fn is_non_deductible_auto_type(&self) -> bool { - self.kind() == CXType_Auto && self.canonical_type() == *self + debug_assert_eq!(self.kind(), CXType_Auto); + self.canonical_type() == *self } #[inline] - fn clang_size_of(&self) -> c_longlong { - if self.is_non_deductible_auto_type() { - return -6; // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813 + fn clang_size_of(&self, ctx: &BindgenContext) -> c_longlong { + match self.kind() { + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975 + CXType_RValueReference | + CXType_LValueReference => ctx.target_pointer_size() as c_longlong, + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813 + CXType_Auto if self.is_non_deductible_auto_type() => return -6, + _ => unsafe { clang_Type_getSizeOf(self.x) }, } - unsafe { clang_Type_getSizeOf(self.x) } } #[inline] - fn clang_align_of(&self) -> c_longlong { - if self.is_non_deductible_auto_type() { - return -6; // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813 + fn clang_align_of(&self, ctx: &BindgenContext) -> c_longlong { + match self.kind() { + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40975 + CXType_RValueReference | + CXType_LValueReference => ctx.target_pointer_size() as c_longlong, + // Work-around https://bugs.llvm.org/show_bug.cgi?id=40813 + CXType_Auto if self.is_non_deductible_auto_type() => return -6, + _ => unsafe { clang_Type_getAlignOf(self.x) }, } - unsafe { clang_Type_getAlignOf(self.x) } } /// What is the size of this type? Paper over invalid types by returning `0` /// for them. - pub fn size(&self) -> usize { - let val = self.clang_size_of(); + pub fn size(&self, ctx: &BindgenContext) -> usize { + let val = self.clang_size_of(ctx); if val < 0 { 0 } else { val as usize } } /// What is the size of this type? - pub fn fallible_size(&self) -> Result<usize, LayoutError> { - let val = self.clang_size_of(); + pub fn fallible_size(&self, ctx: &BindgenContext) -> Result<usize, LayoutError> { + let val = self.clang_size_of(ctx); if val < 0 { Err(LayoutError::from(val as i32)) } else { @@ -971,14 +981,14 @@ impl Type { /// What is the alignment of this type? Paper over invalid types by /// returning `0`. - pub fn align(&self) -> usize { - let val = self.clang_align_of(); + pub fn align(&self, ctx: &BindgenContext) -> usize { + let val = self.clang_align_of(ctx); if val < 0 { 0 } else { val as usize } } /// What is the alignment of this type? - pub fn fallible_align(&self) -> Result<usize, LayoutError> { - let val = self.clang_align_of(); + pub fn fallible_align(&self, ctx: &BindgenContext) -> Result<usize, LayoutError> { + let val = self.clang_align_of(ctx); if val < 0 { Err(LayoutError::from(val as i32)) } else { @@ -988,10 +998,10 @@ impl Type { /// Get the layout for this type, or an error describing why it does not /// have a valid layout. - pub fn fallible_layout(&self) -> Result<::ir::layout::Layout, LayoutError> { + pub fn fallible_layout(&self, ctx: &BindgenContext) -> Result<::ir::layout::Layout, LayoutError> { use ir::layout::Layout; - let size = self.fallible_size()?; - let align = self.fallible_align()?; + let size = self.fallible_size(ctx)?; + let align = self.fallible_align(ctx)?; Ok(Layout::new(size, align)) } diff --git a/src/ir/context.rs b/src/ir/context.rs index f9cd53f3..2626b3e5 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -1755,7 +1755,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" sub_name, template_decl_cursor .cur_type() - .fallible_layout() + .fallible_layout(self) .ok(), sub_kind, false, @@ -1821,7 +1821,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" let name = if name.is_empty() { None } else { Some(name) }; let ty = Type::new( name, - ty.fallible_layout().ok(), + ty.fallible_layout(self).ok(), type_kind, ty.is_const(), ); @@ -1977,7 +1977,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" is_const: bool, ) -> TypeId { let spelling = ty.spelling(); - let layout = ty.fallible_layout().ok(); + let layout = ty.fallible_layout(self).ok(); let type_kind = TypeKind::ResolvedTypeRef(wrapped_id); let ty = Type::new(Some(spelling), layout, type_kind, is_const); let item = Item::new( @@ -2018,7 +2018,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" CXType_UShort => TypeKind::Int(IntKind::UShort), CXType_WChar => { TypeKind::Int(IntKind::WChar { - size: ty.fallible_size().expect("Couldn't compute size of wchar_t?"), + size: ty.fallible_size(self).expect("Couldn't compute size of wchar_t?"), }) }, CXType_Char16 => TypeKind::Int(IntKind::U16), @@ -2056,7 +2056,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" let spelling = ty.spelling(); let is_const = ty.is_const(); - let layout = ty.fallible_layout().ok(); + let layout = ty.fallible_layout(self).ok(); let ty = Type::new(Some(spelling), layout, type_kind, is_const); let id = self.next_item_id(); let item = diff --git a/src/ir/item.rs b/src/ir/item.rs index eec64695..6df19be8 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -454,7 +454,7 @@ impl Item { ty: &clang::Type, ctx: &mut BindgenContext, ) -> TypeId { - let ty = Opaque::from_clang_ty(ty); + let ty = Opaque::from_clang_ty(ty, ctx); let kind = ItemKind::Type(ty); let parent = ctx.root_module().into(); ctx.add_item(Item::new(with_id, None, None, parent, kind), None, None); diff --git a/src/ir/layout.rs b/src/ir/layout.rs index c34da0e1..c70d2884 100644 --- a/src/ir/layout.rs +++ b/src/ir/layout.rs @@ -100,8 +100,8 @@ pub struct Opaque(pub Layout); impl Opaque { /// Construct a new opaque type from the given clang type. - pub fn from_clang_ty(ty: &clang::Type) -> Type { - let layout = Layout::new(ty.size(), ty.align()); + pub fn from_clang_ty(ty: &clang::Type, ctx: &BindgenContext) -> Type { + let layout = Layout::new(ty.size(ctx), ty.align(ctx)); let ty_kind = TypeKind::Opaque; let is_const = ty.is_const(); Type::new(None, Some(layout), ty_kind, is_const) diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 922146ea..73309330 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -730,7 +730,7 @@ impl Type { } } - let layout = ty.fallible_layout().ok(); + let layout = ty.fallible_layout(ctx).ok(); let cursor = ty.declaration(); let mut name = cursor.spelling(); @@ -780,7 +780,7 @@ impl Type { opaque type instead." ); return Ok( - ParseResult::New(Opaque::from_clang_ty(&canonical_ty), None), + ParseResult::New(Opaque::from_clang_ty(&canonical_ty, ctx), None), ); } @@ -912,7 +912,7 @@ impl Type { from class template or base \ specifier, using opaque blob" ); - let opaque = Opaque::from_clang_ty(ty); + let opaque = Opaque::from_clang_ty(ty, ctx); return Ok( ParseResult::New(opaque, None), ); diff --git a/tests/expectations/tests/issue-1443.rs b/tests/expectations/tests/issue-1443.rs new file mode 100644 index 00000000..54045ef3 --- /dev/null +++ b/tests/expectations/tests/issue-1443.rs @@ -0,0 +1,150 @@ +/* automatically generated by rust-bindgen */ + +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Foo { + _unused: [u8; 0], +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Bar { + pub f: *const Foo, + pub m: ::std::os::raw::c_uint, +} +#[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>(), + 8usize, + concat!("Alignment of ", stringify!(Bar)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Bar>())).f as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Bar), "::", stringify!(f)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Bar>())).m as *const _ as usize }, + 8usize, + concat!("Offset of field: ", stringify!(Bar), "::", stringify!(m)) + ); +} +impl Default for Bar { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Baz { + pub f: *mut Foo, + pub m: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_Baz() { + assert_eq!( + ::std::mem::size_of::<Baz>(), + 16usize, + concat!("Size of: ", stringify!(Baz)) + ); + assert_eq!( + ::std::mem::align_of::<Baz>(), + 8usize, + concat!("Alignment of ", stringify!(Baz)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Baz>())).f as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Baz), "::", stringify!(f)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Baz>())).m as *const _ as usize }, + 8usize, + concat!("Offset of field: ", stringify!(Baz), "::", stringify!(m)) + ); +} +impl Default for Baz { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Tar { + pub f: *const Foo, + pub m: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_Tar() { + assert_eq!( + ::std::mem::size_of::<Tar>(), + 16usize, + concat!("Size of: ", stringify!(Tar)) + ); + assert_eq!( + ::std::mem::align_of::<Tar>(), + 8usize, + concat!("Alignment of ", stringify!(Tar)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Tar>())).f as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Tar), "::", stringify!(f)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Tar>())).m as *const _ as usize }, + 8usize, + concat!("Offset of field: ", stringify!(Tar), "::", stringify!(m)) + ); +} +impl Default for Tar { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct Taz { + pub f: *mut Foo, + pub m: ::std::os::raw::c_uint, +} +#[test] +fn bindgen_test_layout_Taz() { + assert_eq!( + ::std::mem::size_of::<Taz>(), + 16usize, + concat!("Size of: ", stringify!(Taz)) + ); + assert_eq!( + ::std::mem::align_of::<Taz>(), + 8usize, + concat!("Alignment of ", stringify!(Taz)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Taz>())).f as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(Taz), "::", stringify!(f)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<Taz>())).m as *const _ as usize }, + 8usize, + concat!("Offset of field: ", stringify!(Taz), "::", stringify!(m)) + ); +} +impl Default for Taz { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} diff --git a/tests/headers/issue-1443.hpp b/tests/headers/issue-1443.hpp new file mode 100644 index 00000000..9b637ba7 --- /dev/null +++ b/tests/headers/issue-1443.hpp @@ -0,0 +1,21 @@ +struct Foo; + +struct Bar { + const Foo& f; + unsigned m; +}; + +struct Baz { + Foo& f; + unsigned m; +}; + +struct Tar { + const Foo&& f; + unsigned m; +}; + +struct Taz { + Foo&& f; + unsigned m; +}; |