diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index af202a0204..79e63de61d 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1419,23 +1419,6 @@ impl CodeGenerator for CompInfo { let layout = ty.layout(ctx); let mut packed = self.is_packed(ctx, &layout); - // generate tuple struct if struct or union is a forward declaration, - // skip for now if template parameters are needed. - // - // NB: We generate a proper struct to avoid struct/function name - // collisions. - if self.is_forward_declaration() && used_template_params.is_none() { - let struct_name = item.canonical_name(ctx); - let struct_name = ctx.rust_ident_raw(struct_name); - let tuple_struct = quote! { - #[repr(C)] - #[derive(Debug, Copy, Clone)] - pub struct #struct_name { _unused: [u8; 0] } - }; - result.push(tuple_struct); - return; - } - let canonical_name = item.canonical_name(ctx); let canonical_ident = ctx.rust_ident(&canonical_name); @@ -1491,14 +1474,6 @@ impl CodeGenerator for CompInfo { } } - let is_union = self.kind() == CompKind::Union; - if is_union { - result.saw_union(); - if !self.can_be_rust_union(ctx) { - result.saw_bindgen_union(); - } - } - let mut methods = vec![]; if !is_opaque { let codegen_depth = item.codegen_depth(ctx); @@ -1523,8 +1498,14 @@ impl CodeGenerator for CompInfo { } } + let is_union = self.kind() == CompKind::Union; let layout = item.kind().expect_type().layout(ctx); - if is_union && !is_opaque { + if is_union && !is_opaque && !self.is_forward_declaration() { + result.saw_union(); + if !self.can_be_rust_union(ctx) { + result.saw_bindgen_union(); + } + let layout = layout.expect("Unable to get layout information?"); let ty = helpers::blob(layout); @@ -1588,7 +1569,11 @@ impl CodeGenerator for CompInfo { // // NOTE: This check is conveniently here to avoid the dummy fields we // may add for unused template parameters. - if item.is_zero_sized(ctx) { + if self.is_forward_declaration() { + fields.push(quote! { + _unused: [u8; 0], + }); + } else if item.is_zero_sized(ctx) { 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. @@ -1658,12 +1643,11 @@ impl CodeGenerator for CompInfo { if item.can_derive_default(ctx) { derives.push("Default"); } else { - needs_default_impl = ctx.options().derive_default; + needs_default_impl = + ctx.options().derive_default && !self.is_forward_declaration(); } - if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() && - ctx.options().derive_copy - { + if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() { derives.push("Copy"); if ctx.options().rust_features().builtin_clone_impls() || @@ -1756,7 +1740,7 @@ impl CodeGenerator for CompInfo { } } - if ctx.options().layout_tests { + if ctx.options().layout_tests && !self.is_forward_declaration() { if let Some(layout) = layout { let fn_name = format!("bindgen_test_layout_{}", canonical_ident.as_str()); diff --git a/src/ir/analysis/derive_copy.rs b/src/ir/analysis/derive_copy.rs index 8da47a7f3a..94d457d543 100644 --- a/src/ir/analysis/derive_copy.rs +++ b/src/ir/analysis/derive_copy.rs @@ -235,9 +235,10 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> { if info.kind() == CompKind::Union { if !self.ctx.options().rust_features().untagged_union() { - // NOTE: If there's no template parameters we can derive copy - // unconditionally, since arrays are magical for rustc, and - // __BindgenUnionField always implements copy. + // NOTE: If there's no template parameters we can derive + // copy unconditionally, since arrays are magical for + // rustc, and __BindgenUnionField always implements + // copy. trace!( " comp can always derive debug if it's a Union and no template parameters" ); diff --git a/src/ir/analysis/derive_default.rs b/src/ir/analysis/derive_default.rs index f8f02df75d..2c79a4377f 100644 --- a/src/ir/analysis/derive_default.rs +++ b/src/ir/analysis/derive_default.rs @@ -265,6 +265,11 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> { "The early ty.is_opaque check should have handled this case" ); + if info.is_forward_declaration() { + trace!(" cannot derive Default for forward decls"); + return self.insert(id); + } + if info.kind() == CompKind::Union { if self.ctx.options().rust_features().untagged_union() { trace!(" cannot derive Default for Rust unions"); diff --git a/src/ir/analysis/derive_hash.rs b/src/ir/analysis/derive_hash.rs index 4679023242..3fc31b3968 100644 --- a/src/ir/analysis/derive_hash.rs +++ b/src/ir/analysis/derive_hash.rs @@ -251,6 +251,11 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> { "The early ty.is_opaque check should have handled this case" ); + if info.is_forward_declaration() { + trace!(" cannot derive Hash for forward decls"); + return self.insert(id); + } + if info.kind() == CompKind::Union { if self.ctx.options().rust_features().untagged_union() { trace!(" cannot derive Hash for Rust unions"); diff --git a/src/ir/analysis/derive_partialeq_or_partialord.rs b/src/ir/analysis/derive_partialeq_or_partialord.rs index 92861341b2..2641d2b3f3 100644 --- a/src/ir/analysis/derive_partialeq_or_partialord.rs +++ b/src/ir/analysis/derive_partialeq_or_partialord.rs @@ -236,6 +236,11 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> { "The early ty.is_opaque check should have handled this case" ); + if info.is_forward_declaration() { + trace!(" cannot derive for forward decls"); + return CanDerive::No; + } + if info.kind() == CompKind::Union { if self.ctx.options().rust_features().untagged_union() { trace!( diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 5008dcfd70..50d0ddb16e 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1543,13 +1543,20 @@ impl CompInfo { /// 1. Current RustTarget allows for `untagged_union` /// 2. Each field can derive `Copy` pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool { - ctx.options().rust_features().untagged_union() && - self.fields().iter().all(|f| match *f { - Field::DataMember(ref field_data) => { - field_data.ty().can_derive_copy(ctx) - } - Field::Bitfields(_) => true, - }) + if !ctx.options().rust_features().untagged_union() { + return false; + } + + if self.is_forward_declaration() { + return false; + } + + self.fields().iter().all(|f| match *f { + Field::DataMember(ref field_data) => { + field_data.ty().can_derive_copy(ctx) + } + Field::Bitfields(_) => true, + }) } } diff --git a/src/ir/context.rs b/src/ir/context.rs index cddbeb2d13..21801c9f71 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -222,8 +222,7 @@ where T: Copy + Into { fn can_derive_default(&self, ctx: &BindgenContext) -> bool { - ctx.options().derive_default && - ctx.lookup_can_derive_default(*self) + ctx.options().derive_default && ctx.lookup_can_derive_default(*self) } } @@ -232,7 +231,7 @@ where T: Copy + Into { fn can_derive_copy(&self, ctx: &BindgenContext) -> bool { - ctx.lookup_can_derive_copy(*self) + ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self) } } @@ -2452,6 +2451,7 @@ impl BindgenContext { // Look up the computed value for whether the item with `id` can // derive `Copy` or not. let id = id.into(); + !self.lookup_has_type_param_in_array(id) && !self.cannot_derive_copy.as_ref().unwrap().contains(&id) } diff --git a/tests/expectations/tests/anon_union.rs b/tests/expectations/tests/anon_union.rs index 689279142f..446cd58962 100644 --- a/tests/expectations/tests/anon_union.rs +++ b/tests/expectations/tests/anon_union.rs @@ -17,14 +17,14 @@ pub enum TErrorResult_UnionState { HasMessage = 0, } #[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone)] pub struct TErrorResult_Message { - pub _address: u8, + _unused: [u8; 0], } #[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone)] pub struct TErrorResult_DOMExceptionInfo { - pub _address: u8, + _unused: [u8; 0], } #[repr(C)] pub union TErrorResult__bindgen_ty_1 { diff --git a/tests/expectations/tests/anon_union_1_0.rs b/tests/expectations/tests/anon_union_1_0.rs index 80111b9044..60e2e0c5cc 100644 --- a/tests/expectations/tests/anon_union_1_0.rs +++ b/tests/expectations/tests/anon_union_1_0.rs @@ -61,14 +61,14 @@ pub enum TErrorResult_UnionState { HasMessage = 0, } #[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone)] pub struct TErrorResult_Message { - pub _address: u8, + _unused: [u8; 0], } #[repr(C)] -#[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] +#[derive(Debug, Copy, Clone)] pub struct TErrorResult_DOMExceptionInfo { - pub _address: u8, + _unused: [u8; 0], } #[repr(C)] #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)] diff --git a/tests/expectations/tests/forward-declaration-autoptr.rs b/tests/expectations/tests/forward-declaration-autoptr.rs index b465836d2f..5d3c3eaafb 100644 --- a/tests/expectations/tests/forward-declaration-autoptr.rs +++ b/tests/expectations/tests/forward-declaration-autoptr.rs @@ -1,9 +1,7 @@ /* 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 { diff --git a/tests/expectations/tests/forward_declared_complex_types.rs b/tests/expectations/tests/forward_declared_complex_types.rs index 970d6d59df..1132bfbe89 100644 --- a/tests/expectations/tests/forward_declared_complex_types.rs +++ b/tests/expectations/tests/forward_declared_complex_types.rs @@ -1,9 +1,7 @@ /* 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, Clone)] pub struct Foo_empty { @@ -60,7 +58,7 @@ extern "C" { pub fn baz_struct(f: *mut Foo); } #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Copy, Clone)] pub struct Union { _unused: [u8; 0], } diff --git a/tests/expectations/tests/forward_declared_complex_types_1_0.rs b/tests/expectations/tests/forward_declared_complex_types_1_0.rs index 04fe9a3c7e..0a6a32be81 100644 --- a/tests/expectations/tests/forward_declared_complex_types_1_0.rs +++ b/tests/expectations/tests/forward_declared_complex_types_1_0.rs @@ -1,9 +1,7 @@ /* 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 Foo_empty { @@ -28,10 +26,15 @@ impl Clone for Foo_empty { } } #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy)] pub struct Foo { _unused: [u8; 0], } +impl Clone for Foo { + fn clone(&self) -> Self { + *self + } +} #[repr(C)] #[derive(Debug, Copy)] pub struct Bar { @@ -70,19 +73,29 @@ extern "C" { pub fn baz_struct(f: *mut Foo); } #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Copy)] pub struct Union { _unused: [u8; 0], } +impl Clone for Union { + fn clone(&self) -> Self { + *self + } +} extern "C" { #[link_name = "\u{1}_Z9baz_unionP5Union"] pub fn baz_union(u: *mut Union); } #[repr(C)] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy)] pub struct Quux { _unused: [u8; 0], } +impl Clone for Quux { + fn clone(&self) -> Self { + *self + } +} extern "C" { #[link_name = "\u{1}_Z9baz_classP4Quux"] pub fn baz_class(q: *mut Quux); diff --git a/tests/expectations/tests/issue-1238-fwd-no-copy.rs b/tests/expectations/tests/issue-1238-fwd-no-copy.rs new file mode 100644 index 0000000000..f2156dfb5a --- /dev/null +++ b/tests/expectations/tests/issue-1238-fwd-no-copy.rs @@ -0,0 +1,10 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + +#[repr(C)] +#[derive(Debug)] +pub struct MyType { + _unused: [u8; 0], +} +pub type MyTypeT = MyType; diff --git a/tests/expectations/tests/issue-654-struct-fn-collision.rs b/tests/expectations/tests/issue-654-struct-fn-collision.rs index 8b2bb533a8..fbd8cca3ec 100644 --- a/tests/expectations/tests/issue-654-struct-fn-collision.rs +++ b/tests/expectations/tests/issue-654-struct-fn-collision.rs @@ -1,9 +1,7 @@ /* 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 { diff --git a/tests/expectations/tests/issue-801-opaque-sloppiness.rs b/tests/expectations/tests/issue-801-opaque-sloppiness.rs index b3ad9d05a9..76deebbaa5 100644 --- a/tests/expectations/tests/issue-801-opaque-sloppiness.rs +++ b/tests/expectations/tests/issue-801-opaque-sloppiness.rs @@ -1,9 +1,7 @@ /* 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 A { diff --git a/tests/expectations/tests/layout_array.rs b/tests/expectations/tests/layout_array.rs index 51676999d2..8429c4d4b5 100644 --- a/tests/expectations/tests/layout_array.rs +++ b/tests/expectations/tests/layout_array.rs @@ -1,9 +1,7 @@ /* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - pub const RTE_CACHE_LINE_SIZE: ::std::os::raw::c_uint = 64; pub const RTE_MEMPOOL_OPS_NAMESIZE: ::std::os::raw::c_uint = 32; pub const RTE_MEMPOOL_MAX_OPS_IDX: ::std::os::raw::c_uint = 16; @@ -21,9 +19,8 @@ pub struct rte_mempool { /// it will most likely point to a different type of data structure, and /// will be transparent to the application programmer. /// This function should set mp->pool_data. -pub type rte_mempool_alloc_t = ::std::option::Option< - unsafe extern "C" fn(mp: *mut rte_mempool) -> ::std::os::raw::c_int, ->; +pub type rte_mempool_alloc_t = + ::std::option::Option ::std::os::raw::c_int>; /// Free the opaque private data pointed to by mp->pool_data pointer. pub type rte_mempool_free_t = ::std::option::Option; /// Enqueue an object into the external pool. @@ -43,10 +40,8 @@ pub type rte_mempool_dequeue_t = ::std::option::Option< ) -> ::std::os::raw::c_int, >; /// Return the number of available objects in the external pool. -pub type rte_mempool_get_count = ::std::option::Option< - unsafe extern "C" fn(mp: *const rte_mempool) - -> ::std::os::raw::c_uint, ->; +pub type rte_mempool_get_count = + ::std::option::Option ::std::os::raw::c_uint>; /// Structure defining mempool operations structure #[repr(C)] #[derive(Copy, Clone)] diff --git a/tests/expectations/tests/same_struct_name_in_different_namespaces.rs b/tests/expectations/tests/same_struct_name_in_different_namespaces.rs index 03ac70b8ae..9a8c1efa14 100644 --- a/tests/expectations/tests/same_struct_name_in_different_namespaces.rs +++ b/tests/expectations/tests/same_struct_name_in_different_namespaces.rs @@ -1,9 +1,7 @@ /* 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 JS_Zone { diff --git a/tests/expectations/tests/template.rs b/tests/expectations/tests/template.rs index 70c1cdcb3d..6083265cf5 100644 --- a/tests/expectations/tests/template.rs +++ b/tests/expectations/tests/template.rs @@ -1,9 +1,7 @@ /* automatically generated by rust-bindgen */ - #![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] - #[repr(C)] #[derive(Debug, Hash, PartialEq, Eq)] pub struct Foo { diff --git a/tests/headers/issue-1238-fwd-no-copy.h b/tests/headers/issue-1238-fwd-no-copy.h new file mode 100644 index 0000000000..150bbbeb77 --- /dev/null +++ b/tests/headers/issue-1238-fwd-no-copy.h @@ -0,0 +1,3 @@ +// bindgen-flags: --no-copy MyType + +typedef struct MyType MyTypeT;