Skip to content

codegen: Make forward declarations go through the more generic path. #1241

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 16 additions & 32 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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() ||
Expand Down Expand Up @@ -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());
Expand Down
7 changes: 4 additions & 3 deletions src/ir/analysis/derive_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
);
Expand Down
5 changes: 5 additions & 0 deletions src/ir/analysis/derive_default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
5 changes: 5 additions & 0 deletions src/ir/analysis/derive_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
5 changes: 5 additions & 0 deletions src/ir/analysis/derive_partialeq_or_partialord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!(
Expand Down
21 changes: 14 additions & 7 deletions src/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,7 @@ where
T: Copy + Into<ItemId>
{
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)
}
}

Expand All @@ -232,7 +231,7 @@ where
T: Copy + Into<ItemId>
{
fn can_derive_copy(&self, ctx: &BindgenContext) -> bool {
ctx.lookup_can_derive_copy(*self)
ctx.options().derive_copy && ctx.lookup_can_derive_copy(*self)
}
}

Expand Down Expand Up @@ -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)
}
Expand Down
8 changes: 4 additions & 4 deletions tests/expectations/tests/anon_union.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions tests/expectations/tests/anon_union_1_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
2 changes: 0 additions & 2 deletions tests/expectations/tests/forward-declaration-autoptr.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
4 changes: 1 addition & 3 deletions tests/expectations/tests/forward_declared_complex_types.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down Expand Up @@ -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],
}
Expand Down
23 changes: 18 additions & 5 deletions tests/expectations/tests/forward_declared_complex_types_1_0.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions tests/expectations/tests/issue-1238-fwd-no-copy.rs
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 0 additions & 2 deletions tests/expectations/tests/issue-654-struct-fn-collision.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
2 changes: 0 additions & 2 deletions tests/expectations/tests/issue-801-opaque-sloppiness.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
13 changes: 4 additions & 9 deletions tests/expectations/tests/layout_array.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<unsafe extern "C" fn(mp: *mut rte_mempool) -> ::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<unsafe extern "C" fn(mp: *mut rte_mempool)>;
/// Enqueue an object into the external pool.
Expand All @@ -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<unsafe extern "C" fn(mp: *const rte_mempool) -> ::std::os::raw::c_uint>;
/// Structure defining mempool operations structure
#[repr(C)]
#[derive(Copy, Clone)]
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
Loading