summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-01-11 04:13:47 -0800
committerGitHub <noreply@github.com>2017-01-11 04:13:47 -0800
commit54aba18b3808f07de607137a6aee1a625b076784 (patch)
tree8155da9285d21e72a8510cdb0428d7763c0f566a
parent6bfeae155155a12849033e1c5199ca6e48e8b22c (diff)
parent66447ff277181073d14bb04c7947eec805cd0623 (diff)
Auto merge of #387 - emilio:trace-improvements, r=fitzgen
Improve tracing so it doesn't ignore opaque stuff when it shouldn't Concretely, trace through functions, pointers, arrays, references, resolved type references, and template references, which are the types for which either: * There's no special meaning to be opaque, or * They're just placeholders that point to other types.
-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;
+};