diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2017-03-09 13:53:20 -0800 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2017-03-09 13:56:53 -0800 |
commit | b662443c1bf0c6c0103b91aec30e6b95ea5c4ff4 (patch) | |
tree | bdfbbbf4bec63ade4956837fbf09ed01a5667374 | |
parent | 72ab471539fcf2809f82e2dd980c59352a67eba4 (diff) |
Generate better opaque blobs in the face of non-type parameters
When instantiating templates whose definitions have non-type generic parameters,
prefer the layout of the instantiation type to the garbage we get from the
definition's layout. In general, an instantiation's layout will always be a
better choice than the definition's layout, regardless of non-type parameters.
Fixes #569
-rw-r--r-- | src/codegen/mod.rs | 16 | ||||
-rw-r--r-- | tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs | 42 | ||||
-rw-r--r-- | tests/expectations/tests/non-type-params.rs | 48 | ||||
-rw-r--r-- | tests/expectations/tests/opaque_pointer.rs | 2 | ||||
-rw-r--r-- | tests/expectations/tests/type_alias_empty.rs | 2 | ||||
-rw-r--r-- | tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp | 27 | ||||
-rw-r--r-- | tests/headers/non-type-params.hpp | 17 |
7 files changed, 148 insertions, 6 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 49b320ae..fe93783f 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -561,7 +561,13 @@ impl CodeGenerator for Type { let layout = self.layout(ctx).unwrap_or_else(Layout::zero); BlobTyBuilder::new(layout).build() } else { - inner_item.to_rust_ty(ctx) + let inner_rust_ty = inner_item.to_rust_ty(ctx); + if inner_rust_ty == aster::AstBuilder::new().ty().unit() { + let layout = self.layout(ctx).unwrap_or_else(|| Layout::for_size(1)); + BlobTyBuilder::new(layout).build() + } else { + inner_rust_ty + } }; { @@ -2356,12 +2362,14 @@ impl ToRustTy for TemplateInstantiation { let decl = self.template_definition(); let mut ty = decl.to_rust_ty(ctx).unwrap(); - // If we gave up when making a type for the template definition, - // check if maybe we can make a better opaque blob for the - // instantiation. if ty == aster::AstBuilder::new().ty().unit().unwrap() { + // If we gave up when making a type for the template definition, + // check if maybe we can make a better opaque blob for the + // instantiation. If not, at least don't use a zero-sized type. if let Some(layout) = self_ty.layout(ctx) { return BlobTyBuilder::new(layout).build(); + } else { + return quote_ty!(ctx.ext_cx(), u8); } } diff --git a/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs b/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs new file mode 100644 index 00000000..6cf2ba16 --- /dev/null +++ b/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs @@ -0,0 +1,42 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub const ENUM_VARIANT_1: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_1; +pub const ENUM_VARIANT_2: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_2; +#[repr(u32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum _bindgen_ty_1 { ENUM_VARIANT_1 = 0, ENUM_VARIANT_2 = 1, } +pub type JS_Alias = u8; +#[repr(C)] +pub struct JS_Base { + pub f: JS_Alias, +} +impl Default for JS_Base { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[repr(C)] +pub struct JS_AutoIdVector { + pub _base: JS_Base, +} +#[test] +fn bindgen_test_layout_JS_AutoIdVector() { + assert_eq!(::std::mem::size_of::<JS_AutoIdVector>() , 1usize , concat ! ( + "Size of: " , stringify ! ( JS_AutoIdVector ) )); + assert_eq! (::std::mem::align_of::<JS_AutoIdVector>() , 1usize , concat ! + ( "Alignment of " , stringify ! ( JS_AutoIdVector ) )); +} +impl Default for JS_AutoIdVector { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[test] +fn __bindgen_test_layout_JS_Base_instantiation_16() { + assert_eq!(::std::mem::size_of::<JS_Base>() , 1usize , concat ! ( + "Size of template specialization: " , stringify ! ( JS_Base ) + )); + assert_eq!(::std::mem::align_of::<JS_Base>() , 1usize , concat ! ( + "Alignment of template specialization: " , stringify ! ( + JS_Base ) )); +} diff --git a/tests/expectations/tests/non-type-params.rs b/tests/expectations/tests/non-type-params.rs new file mode 100644 index 00000000..039aa711 --- /dev/null +++ b/tests/expectations/tests/non-type-params.rs @@ -0,0 +1,48 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub type Array16 = u8; +pub type ArrayInt4 = [u32; 4usize]; +#[repr(C)] +pub struct UsesArray { + pub array_char_16: [u8; 16usize], + pub array_bool_8: [u8; 8usize], + pub array_int_4: ArrayInt4, +} +#[test] +fn bindgen_test_layout_UsesArray() { + assert_eq!(::std::mem::size_of::<UsesArray>() , 40usize , concat ! ( + "Size of: " , stringify ! ( UsesArray ) )); + assert_eq! (::std::mem::align_of::<UsesArray>() , 4usize , concat ! ( + "Alignment of " , stringify ! ( UsesArray ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const UsesArray ) ) . array_char_16 as * const + _ as usize } , 0usize , concat ! ( + "Alignment of field: " , stringify ! ( UsesArray ) , "::" , + stringify ! ( array_char_16 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const UsesArray ) ) . array_bool_8 as * const _ + as usize } , 16usize , concat ! ( + "Alignment of field: " , stringify ! ( UsesArray ) , "::" , + stringify ! ( array_bool_8 ) )); + assert_eq! (unsafe { + & ( * ( 0 as * const UsesArray ) ) . array_int_4 as * const _ + as usize } , 24usize , concat ! ( + "Alignment of field: " , stringify ! ( UsesArray ) , "::" , + stringify ! ( array_int_4 ) )); +} +impl Default for UsesArray { + fn default() -> Self { unsafe { ::std::mem::zeroed() } } +} +#[test] +fn __bindgen_test_layout_Array_instantiation_18() { + assert_eq!(::std::mem::size_of::<[u32; 4usize]>() , 16usize , concat ! ( + "Size of template specialization: " , stringify ! ( + [u32; 4usize] ) )); + assert_eq!(::std::mem::align_of::<[u32; 4usize]>() , 4usize , concat ! ( + "Alignment of template specialization: " , stringify ! ( + [u32; 4usize] ) )); +} diff --git a/tests/expectations/tests/opaque_pointer.rs b/tests/expectations/tests/opaque_pointer.rs index 2e1890a8..1a2da431 100644 --- a/tests/expectations/tests/opaque_pointer.rs +++ b/tests/expectations/tests/opaque_pointer.rs @@ -35,7 +35,7 @@ impl Default for Opaque { #[repr(C)] #[derive(Debug, Copy)] pub struct WithOpaquePtr { - pub whatever: *mut (), + pub whatever: *mut u8, pub other: u32, pub t: OtherOpaque, } diff --git a/tests/expectations/tests/type_alias_empty.rs b/tests/expectations/tests/type_alias_empty.rs index 47e36006..c455b8ae 100644 --- a/tests/expectations/tests/type_alias_empty.rs +++ b/tests/expectations/tests/type_alias_empty.rs @@ -4,4 +4,4 @@ #![allow(non_snake_case)] -pub type bool_constant = (); +pub type bool_constant = u8; diff --git a/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp b/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp new file mode 100644 index 00000000..7f8c2d8a --- /dev/null +++ b/tests/headers/issue-569-non-type-template-params-causing-layout-test-failures.hpp @@ -0,0 +1,27 @@ +// bindgen-flags: -- -std=c++14 + +// Generated by C-Reduce, cleaned up and given names for readability. + +template <int, typename> +struct HasNonTypeTemplateParam { + // But doesn't use the non-type template param nor its type param... +}; + +enum { + ENUM_VARIANT_1, + ENUM_VARIANT_2 +}; + +namespace JS { + +template <typename T> +using Alias = HasNonTypeTemplateParam<ENUM_VARIANT_1, T>; + +template <typename U> +class Base { + Alias<U> f; +}; + +class AutoIdVector : Base<int> {}; + +} diff --git a/tests/headers/non-type-params.hpp b/tests/headers/non-type-params.hpp new file mode 100644 index 00000000..3e2ccf8e --- /dev/null +++ b/tests/headers/non-type-params.hpp @@ -0,0 +1,17 @@ +// bindgen-flags: -- -std=c++14 + +template <typename T, unsigned int Capacity> +struct Array { + T elements[Capacity]; +}; + +template <typename T> +using Array16 = Array<T, 16>; + +using ArrayInt4 = Array<int, 4>; + +struct UsesArray { + Array16<char> array_char_16; + Array<bool, 8> array_bool_8; + ArrayInt4 array_int_4; +}; |