diff options
-rw-r--r-- | libbindgen/src/codegen/mod.rs | 38 | ||||
-rw-r--r-- | libbindgen/src/ir/item.rs | 11 | ||||
-rw-r--r-- | libbindgen/src/ir/ty.rs | 14 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/opaque-tracing.rs | 23 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/opaque_in_struct.rs | 2 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/opaque_pointer.rs | 2 | ||||
-rw-r--r-- | libbindgen/tests/headers/opaque-tracing.hpp | 21 |
7 files changed, 87 insertions, 24 deletions
diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs index 6e63a791..d12c3d2a 100644 --- a/libbindgen/src/codegen/mod.rs +++ b/libbindgen/src/codegen/mod.rs @@ -1879,7 +1879,13 @@ impl ToRustTy for Type { TypeKind::ResolvedTypeRef(inner) => inner.to_rust_ty(ctx), TypeKind::TemplateAlias(ref spelling, inner, _) | TypeKind::Alias(ref spelling, inner) => { - if item.is_opaque(ctx) { + let applicable_named_args = + item.applicable_template_args(ctx) + .into_iter() + .filter(|arg| ctx.resolve_type(*arg).is_named()) + .collect::<Vec<_>>(); + + if item.is_opaque(ctx) && !applicable_named_args.is_empty() { // Pray if there's no available layout. let layout = self.layout(ctx).unwrap_or_else(Layout::zero); BlobTyBuilder::new(layout).build() @@ -1888,11 +1894,15 @@ impl ToRustTy for Type { inner) { ty } else { - utils::build_templated_path(item, ctx, true) + utils::build_templated_path(item, + ctx, + applicable_named_args) } } TypeKind::Comp(ref info) => { - if item.is_opaque(ctx) || info.has_non_type_template_params() { + let template_args = item.applicable_template_args(ctx); + if info.has_non_type_template_params() || + (item.is_opaque(ctx) && !template_args.is_empty()) { return match self.layout(ctx) { Some(layout) => BlobTyBuilder::new(layout).build(), None => { @@ -1904,7 +1914,7 @@ impl ToRustTy for Type { }; } - utils::build_templated_path(item, ctx, false) + utils::build_templated_path(item, ctx, template_args) } TypeKind::BlockPointer => { let void = raw_type(ctx, "c_void"); @@ -2215,23 +2225,15 @@ mod utils { pub fn build_templated_path(item: &Item, ctx: &BindgenContext, - only_named: bool) + template_args: Vec<ItemId>) -> P<ast::Ty> { let path = item.namespace_aware_canonical_path(ctx); - let builder = aster::AstBuilder::new().ty().path(); - let template_args = if only_named { - item.applicable_template_args(ctx) - .iter() - .filter(|arg| ctx.resolve_type(**arg).is_named()) - .map(|arg| arg.to_rust_ty(ctx)) - .collect::<Vec<_>>() - } else { - item.applicable_template_args(ctx) - .iter() - .map(|arg| arg.to_rust_ty(ctx)) - .collect::<Vec<_>>() - }; + + let template_args = template_args + .iter() + .map(|arg| arg.to_rust_ty(ctx)) + .collect::<Vec<_>>(); // XXX: I suck at aster. if path.len() == 1 { diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs index f4598654..e9960166 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -190,14 +190,17 @@ impl TypeCollector for Item { match *self.kind() { ItemKind::Type(ref ty) => { - if !self.is_opaque(ctx) { + // There are some types, like resolved type references, where we + // don't want to stop collecting types even though they may be + // opaque. + if ty.should_be_traced_unconditionally() || !self.is_opaque(ctx) { ty.collect_types(ctx, types, self); } } ItemKind::Function(ref fun) => { - if !self.is_opaque(ctx) { - types.insert(fun.signature()); - } + // Just the same way, it has not real meaning for a function to + // be opaque, so we trace across it. + types.insert(fun.signature()); } _ => {} // FIXME. } diff --git a/libbindgen/src/ir/ty.rs b/libbindgen/src/ir/ty.rs index df3baf91..e83ef4fd 100644 --- a/libbindgen/src/ir/ty.rs +++ b/libbindgen/src/ir/ty.rs @@ -316,6 +316,20 @@ impl Type { TypeKind::UnresolvedTypeRef(..) => None, } } + + /// There are some types we don't want to stop at when finding an opaque + /// item, so we can arrive to the proper item that needs to be generated. + pub fn should_be_traced_unconditionally(&self) -> bool { + match self.kind { + TypeKind::Function(..) | + TypeKind::Pointer(..) | + TypeKind::Array(..) | + TypeKind::Reference(..) | + TypeKind::TemplateRef(..) | + TypeKind::ResolvedTypeRef(..) => true, + _ => false, + } + } } impl CanDeriveDebug for Type { diff --git a/libbindgen/tests/expectations/tests/opaque-tracing.rs b/libbindgen/tests/expectations/tests/opaque-tracing.rs new file mode 100644 index 00000000..7dcc4eef --- /dev/null +++ b/libbindgen/tests/expectations/tests/opaque-tracing.rs @@ -0,0 +1,23 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Container { + pub _bindgen_opaque_blob: [u32; 2usize], +} +#[test] +fn bindgen_test_layout_Container() { + assert_eq!(::std::mem::size_of::<Container>() , 8usize); + assert_eq!(::std::mem::align_of::<Container>() , 4usize); +} +impl Clone for Container { + fn clone(&self) -> Self { *self } +} +extern "C" { + #[link_name = "_Z3fooP9Container"] + pub fn foo(c: *mut Container); +} diff --git a/libbindgen/tests/expectations/tests/opaque_in_struct.rs b/libbindgen/tests/expectations/tests/opaque_in_struct.rs index d537f5c7..c94caa1f 100644 --- a/libbindgen/tests/expectations/tests/opaque_in_struct.rs +++ b/libbindgen/tests/expectations/tests/opaque_in_struct.rs @@ -21,7 +21,7 @@ impl Clone for opaque { #[repr(C)] #[derive(Debug, Copy)] pub struct container { - pub contained: u32, + pub contained: opaque, } #[test] fn bindgen_test_layout_container() { diff --git a/libbindgen/tests/expectations/tests/opaque_pointer.rs b/libbindgen/tests/expectations/tests/opaque_pointer.rs index 067f55bd..118a1782 100644 --- a/libbindgen/tests/expectations/tests/opaque_pointer.rs +++ b/libbindgen/tests/expectations/tests/opaque_pointer.rs @@ -33,7 +33,7 @@ pub struct Opaque<T> { pub struct WithOpaquePtr { pub whatever: *mut Opaque<::std::os::raw::c_int>, pub other: u32, - pub t: u32, + pub t: OtherOpaque, } #[test] fn bindgen_test_layout_WithOpaquePtr() { diff --git a/libbindgen/tests/headers/opaque-tracing.hpp b/libbindgen/tests/headers/opaque-tracing.hpp new file mode 100644 index 00000000..7356245e --- /dev/null +++ b/libbindgen/tests/headers/opaque-tracing.hpp @@ -0,0 +1,21 @@ +// bindgen-flags: --opaque-type=.* --whitelist-function=foo + +class Container; + +// The whitelist tracing should reach the Container type, even though it's +// marked as opaque. +void foo(Container* c); + +template<typename T> +class Wat { + T foo; +}; + +class OtherOpaque { + int bar; +}; + +class Container { + Wat<int> bar; + OtherOpaque baz; +}; |