summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-03-01 14:57:19 +0100
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-03-01 15:53:16 +0100
commit0ce79c3ed392e5f0bcf459c24a2ba7f0cb6136dc (patch)
tree7eb49b2f186d0b36d49628afa6b65590ee72a6a6
parent56021b28a5150d2f7f7b662a261956d9eff8fe9d (diff)
Follow proper derive rules for function pointers.
-rw-r--r--src/ir/function.rs24
-rw-r--r--src/ir/ty.rs8
-rw-r--r--tests/expectations/tests/call-conv-field.rs12
-rw-r--r--tests/expectations/tests/derive-fn-ptr.rs46
-rw-r--r--tests/headers/call-conv-field.h2
-rw-r--r--tests/headers/derive-fn-ptr.h8
6 files changed, 97 insertions, 3 deletions
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 5864bbf8..ad336c4b 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -5,6 +5,7 @@ use super::dot::DotAttributes;
use super::item::Item;
use super::traversal::{EdgeKind, Trace, Tracer};
use super::ty::TypeKind;
+use ir::derive::CanDeriveDebug;
use clang;
use clang_sys::CXCallingConv;
use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult};
@@ -349,3 +350,26 @@ impl Trace for FunctionSig {
}
}
}
+
+// Function pointers follow special rules, see:
+//
+// https://github.com/servo/rust-bindgen/issues/547,
+// https://github.com/rust-lang/rust/issues/38848,
+// and https://github.com/rust-lang/rust/issues/40158
+//
+// Note that copy is always derived, so we don't need to implement it.
+impl CanDeriveDebug for FunctionSig {
+ type Extra = ();
+
+ fn can_derive_debug(&self, _ctx: &BindgenContext, _: ()) -> bool {
+ const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
+ if self.argument_types.len() > RUST_DERIVE_FUNPTR_LIMIT {
+ return false;
+ }
+
+ match self.abi {
+ Some(abi::Abi::C) | None => true,
+ _ => false,
+ }
+ }
+}
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index a664fa79..329f4f54 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -605,6 +605,13 @@ impl CanDeriveDebug for Type {
TypeKind::Comp(ref info) => {
info.can_derive_debug(ctx, self.layout(ctx))
}
+ TypeKind::Pointer(inner) => {
+ let inner = ctx.resolve_type(inner);
+ if let TypeKind::Function(ref sig) = *inner.canonical_type(ctx).kind() {
+ return sig.can_derive_debug(ctx, ());
+ }
+ return true;
+ }
_ => true,
}
}
@@ -636,6 +643,7 @@ impl CanDeriveDefault for Type {
TypeKind::ObjCSel |
TypeKind::ObjCInterface(..) |
TypeKind::Enum(..) => false,
+
TypeKind::Function(..) |
TypeKind::Int(..) |
TypeKind::Float(..) |
diff --git a/tests/expectations/tests/call-conv-field.rs b/tests/expectations/tests/call-conv-field.rs
index e9a4d873..d6aa9e4e 100644
--- a/tests/expectations/tests/call-conv-field.rs
+++ b/tests/expectations/tests/call-conv-field.rs
@@ -5,17 +5,18 @@
#[repr(C)]
-#[derive(Debug, Copy)]
+#[derive(Copy)]
pub struct JNINativeInterface_ {
pub GetVersion: ::std::option::Option<unsafe extern "stdcall" fn(env:
*mut ::std::os::raw::c_void)
-> ::std::os::raw::c_int>,
+ pub __hack: ::std::os::raw::c_ulonglong,
}
#[test]
fn bindgen_test_layout_JNINativeInterface_() {
- assert_eq!(::std::mem::size_of::<JNINativeInterface_>() , 4usize , concat
+ assert_eq!(::std::mem::size_of::<JNINativeInterface_>() , 16usize , concat
! ( "Size of: " , stringify ! ( JNINativeInterface_ ) ));
- assert_eq! (::std::mem::align_of::<JNINativeInterface_>() , 4usize ,
+ assert_eq! (::std::mem::align_of::<JNINativeInterface_>() , 8usize ,
concat ! (
"Alignment of " , stringify ! ( JNINativeInterface_ ) ));
assert_eq! (unsafe {
@@ -23,6 +24,11 @@ fn bindgen_test_layout_JNINativeInterface_() {
const _ as usize } , 0usize , concat ! (
"Alignment of field: " , stringify ! ( JNINativeInterface_ ) ,
"::" , stringify ! ( GetVersion ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const JNINativeInterface_ ) ) . __hack as *
+ const _ as usize } , 8usize , concat ! (
+ "Alignment of field: " , stringify ! ( JNINativeInterface_ ) ,
+ "::" , stringify ! ( __hack ) ));
}
impl Clone for JNINativeInterface_ {
fn clone(&self) -> Self { *self }
diff --git a/tests/expectations/tests/derive-fn-ptr.rs b/tests/expectations/tests/derive-fn-ptr.rs
new file mode 100644
index 00000000..b6a4f351
--- /dev/null
+++ b/tests/expectations/tests/derive-fn-ptr.rs
@@ -0,0 +1,46 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+pub type my_fun_t =
+ ::std::option::Option<unsafe extern "C" fn(arg1: ::std::os::raw::c_int,
+ arg2: ::std::os::raw::c_int,
+ arg3: ::std::os::raw::c_int,
+ arg4: ::std::os::raw::c_int,
+ arg5: ::std::os::raw::c_int,
+ arg6: ::std::os::raw::c_int,
+ arg7: ::std::os::raw::c_int,
+ arg8: ::std::os::raw::c_int,
+ arg9: ::std::os::raw::c_int,
+ arg10: ::std::os::raw::c_int,
+ arg11: ::std::os::raw::c_int,
+ arg12: ::std::os::raw::c_int,
+ arg13: ::std::os::raw::c_int,
+ arg14: ::std::os::raw::c_int,
+ arg15: ::std::os::raw::c_int,
+ arg16: ::std::os::raw::c_int)>;
+#[repr(C)]
+#[derive(Copy)]
+pub struct Foo {
+ pub callback: my_fun_t,
+}
+#[test]
+fn bindgen_test_layout_Foo() {
+ assert_eq!(::std::mem::size_of::<Foo>() , 8usize , concat ! (
+ "Size of: " , stringify ! ( Foo ) ));
+ assert_eq! (::std::mem::align_of::<Foo>() , 8usize , concat ! (
+ "Alignment of " , stringify ! ( Foo ) ));
+ assert_eq! (unsafe {
+ & ( * ( 0 as * const Foo ) ) . callback as * const _ as usize
+ } , 0usize , concat ! (
+ "Alignment of field: " , stringify ! ( Foo ) , "::" ,
+ stringify ! ( callback ) ));
+}
+impl Clone for Foo {
+ fn clone(&self) -> Self { *self }
+}
+impl Default for Foo {
+ fn default() -> Self { unsafe { ::std::mem::zeroed() } }
+}
diff --git a/tests/headers/call-conv-field.h b/tests/headers/call-conv-field.h
index b6d306eb..5702a09a 100644
--- a/tests/headers/call-conv-field.h
+++ b/tests/headers/call-conv-field.h
@@ -2,6 +2,8 @@
struct JNINativeInterface_ {
int (__stdcall *GetVersion)(void *env);
+ unsigned long long __hack; // A hack so the field alignment is the same than
+ // for 64-bit, where we run CI.
};
__stdcall void bar();
diff --git a/tests/headers/derive-fn-ptr.h b/tests/headers/derive-fn-ptr.h
new file mode 100644
index 00000000..39ff76d6
--- /dev/null
+++ b/tests/headers/derive-fn-ptr.h
@@ -0,0 +1,8 @@
+typedef void (*my_fun_t)(int, int, int, int,
+ int, int, int, int,
+ int, int, int, int,
+ int, int, int, int);
+
+struct Foo {
+ my_fun_t callback;
+};