summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libbindgen/src/codegen/mod.rs38
-rw-r--r--libbindgen/src/ir/item.rs11
-rw-r--r--libbindgen/src/ir/ty.rs14
-rw-r--r--libbindgen/tests/expectations/tests/opaque-tracing.rs23
-rw-r--r--libbindgen/tests/expectations/tests/opaque_in_struct.rs2
-rw-r--r--libbindgen/tests/expectations/tests/opaque_pointer.rs2
-rw-r--r--libbindgen/tests/headers/opaque-tracing.hpp21
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;
+};