generate type alias for the block type

This commit is contained in:
Flier Lu 2018-09-01 00:55:43 +08:00 committed by Emilio Cobos Álvarez
parent f5368b3b7d
commit 83751c8789
19 changed files with 177 additions and 52 deletions

View File

@ -940,6 +940,7 @@ impl Type {
CXType_RValueReference |
CXType_LValueReference |
CXType_MemberPointer |
CXType_BlockPointer |
CXType_ObjCObjectPointer => {
let ret = Type {
x: unsafe { clang_getPointeeType(self.x) },

View File

@ -156,7 +156,6 @@ impl<'a> ImplDebug<'a> for Item {
TypeKind::Function(..) |
TypeKind::Enum(..) |
TypeKind::Reference(..) |
TypeKind::BlockPointer |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
@ -227,7 +226,8 @@ impl<'a> ImplDebug<'a> for Item {
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
// We follow the aliases
ctx.resolve_item(t).impl_debug(ctx, name)
}

View File

@ -88,7 +88,6 @@ fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens
TypeKind::Enum(..) |
TypeKind::TypeParam |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::BlockPointer |
TypeKind::Reference(..) |
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
@ -125,7 +124,8 @@ fn gen_field(ctx: &BindgenContext, ty_item: &Item, name: &str) -> quote::Tokens
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
let inner_item = ctx.resolve_item(t);
gen_field(ctx, inner_item, name)
}

View File

@ -103,6 +103,9 @@ struct CodegenResult<'a> {
/// Whether Objective C types have been seen at least once.
saw_objc: bool,
/// Whether Apple block types have been seen at least once.
saw_block: bool,
/// Whether a bitfield allocation unit has been seen at least once.
saw_bitfield_unit: bool,
@ -140,6 +143,7 @@ impl<'a> CodegenResult<'a> {
saw_bindgen_union: false,
saw_incomplete_array: false,
saw_objc: false,
saw_block: false,
saw_bitfield_unit: false,
codegen_id: codegen_id,
items_seen: Default::default(),
@ -166,6 +170,10 @@ impl<'a> CodegenResult<'a> {
self.saw_objc = true;
}
fn saw_block(&mut self) {
self.saw_block = true;
}
fn saw_bitfield_unit(&mut self) {
self.saw_bitfield_unit = true;
}
@ -215,6 +223,7 @@ impl<'a> CodegenResult<'a> {
self.saw_union |= new.saw_union;
self.saw_incomplete_array |= new.saw_incomplete_array;
self.saw_objc |= new.saw_objc;
self.saw_block |= new.saw_block;
self.saw_bitfield_unit |= new.saw_bitfield_unit;
new.items
@ -293,7 +302,6 @@ impl AppendImplicitTemplateParams for quote::Tokens {
TypeKind::Opaque |
TypeKind::Function(..) |
TypeKind::Enum(..) |
TypeKind::BlockPointer |
TypeKind::ObjCId |
TypeKind::ObjCSel |
TypeKind::TemplateInstantiation(..) => return,
@ -394,6 +402,9 @@ impl CodeGenerator for Module {
}
if item.id() == ctx.root_module() {
if result.saw_block {
utils::prepend_block_header(ctx, &mut *result);
}
if result.saw_bindgen_union {
utils::prepend_union_types(ctx, &mut *result);
}
@ -597,7 +608,6 @@ impl CodeGenerator for Type {
TypeKind::Array(..) |
TypeKind::Vector(..) |
TypeKind::Pointer(..) |
TypeKind::BlockPointer |
TypeKind::Reference(..) |
TypeKind::Function(..) |
TypeKind::ResolvedTypeRef(..) |
@ -610,6 +620,35 @@ impl CodeGenerator for Type {
TypeKind::TemplateInstantiation(ref inst) => {
inst.codegen(ctx, result, item)
}
TypeKind::BlockPointer(inner) => {
let inner_item = inner.into_resolver()
.through_type_refs()
.resolve(ctx);
let name = item.canonical_name(ctx);
let inner_rust_type = {
if let TypeKind::Function(fnsig) = inner_item.kind().expect_type().kind() {
utils::fnsig_block(ctx, fnsig)
} else {
panic!("invalid block typedef: {:?}", inner_item)
}
};
let rust_name = ctx.rust_ident(&name);
let mut tokens = if let Some(comment) = item.comment(ctx) {
attributes::doc(comment)
} else {
quote! {}
};
tokens.append_all(quote! {
pub type #rust_name = #inner_rust_type ;
});
result.push(tokens);
result.saw_block();
}
TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item),
TypeKind::TemplateAlias(inner, _) |
TypeKind::Alias(inner) => {
@ -3071,20 +3110,16 @@ impl TryToRustTy for Type {
}
TypeKind::ResolvedTypeRef(inner) => inner.try_to_rust_ty(ctx, &()),
TypeKind::TemplateAlias(..) |
TypeKind::Alias(..) => {
TypeKind::Alias(..) |
TypeKind::BlockPointer(..) => {
let template_params = item.used_template_params(ctx)
.into_iter()
.filter(|param| param.is_template_param(ctx, &()))
.collect::<Vec<_>>();
let spelling = self.name().expect("Unnamed alias?");
if item.is_opaque(ctx, &()) && !template_params.is_empty() {
self.try_to_opaque(ctx, item)
} else if let Some(ty) = utils::type_from_named(
ctx,
spelling,
)
{
} else if let Some(ty) = self.name().and_then(|name| utils::type_from_named(ctx, name)) {
Ok(ty)
} else {
utils::build_path(item, ctx)
@ -3101,13 +3136,6 @@ impl TryToRustTy for Type {
utils::build_path(item, ctx)
}
TypeKind::Opaque => self.try_to_opaque(ctx, item),
TypeKind::BlockPointer => {
let void = raw_type(ctx, "c_void");
Ok(void.to_ptr(
/* is_const = */
false
))
}
TypeKind::Pointer(inner) |
TypeKind::Reference(inner) => {
let is_const = ctx.resolve_type(inner).is_const();
@ -3560,6 +3588,25 @@ mod utils {
result.extend(old_items.into_iter());
}
pub fn prepend_block_header(
ctx: &BindgenContext,
result: &mut Vec<quote::Tokens>,
) {
let use_block = if ctx.options().block_extern_crate {
quote! {
extern crate block;
}
} else {
quote! {
use block;
}
};
let items = vec![use_block];
let old_items = mem::replace(result, items);
result.extend(old_items.into_iter());
}
pub fn prepend_union_types(
ctx: &BindgenContext,
result: &mut Vec<quote::Tokens>,
@ -3871,4 +3918,26 @@ mod utils {
args
}
pub fn fnsig_block(
ctx: &BindgenContext,
sig: &FunctionSig,
) -> quote::Tokens {
let args = sig.argument_types().iter().map(|&(_, ty)| {
let arg_item = ctx.resolve_item(ty);
arg_item.to_rust_ty_or_opaque(ctx, &())
});
let return_item = ctx.resolve_item(sig.return_type());
let ret_ty = if let TypeKind::Void = *return_item.kind().expect_type().kind() {
quote! { () }
} else {
return_item.to_rust_ty_or_opaque(ctx, &())
};
quote! {
*const ::block::Block<(#(#args),*), #ret_ty>
}
}
}

View File

@ -173,7 +173,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
TypeKind::Enum(..) |
TypeKind::Reference(..) |
TypeKind::TypeParam |
TypeKind::BlockPointer |
TypeKind::Pointer(..) |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::ObjCInterface(..) |
@ -204,7 +203,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveCopy<'ctx> {
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
let cant_derive_copy = self.is_not_copy(t);
if cant_derive_copy {
trace!(

View File

@ -183,7 +183,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
TypeKind::Enum(..) |
TypeKind::Reference(..) |
TypeKind::Vector(..) |
TypeKind::BlockPointer |
TypeKind::TypeParam |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::ObjCInterface(..) |
@ -213,7 +212,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveDebug<'ctx> {
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
if self.is_not_debug(t) {
trace!(
" aliases and type refs to T which cannot derive \

View File

@ -215,7 +215,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
TypeKind::Reference(..) |
TypeKind::NullPtr |
TypeKind::Pointer(..) |
TypeKind::BlockPointer |
TypeKind::ObjCId |
TypeKind::ObjCSel |
TypeKind::ObjCInterface(..) |
@ -244,7 +243,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveDefault<'ctx> {
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
if self.is_not_default(t) {
trace!(
" aliases and type refs to T which cannot derive \

View File

@ -167,7 +167,6 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
TypeKind::Enum(..) |
TypeKind::TypeParam |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::BlockPointer |
TypeKind::Reference(..) |
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
@ -241,7 +240,8 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> {
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
if self.cannot_derive_hash.contains(&t.into()) {
trace!(
" aliases and type refs to T which cannot derive \

View File

@ -43,7 +43,7 @@ use std::collections::hash_map::Entry;
pub struct CannotDerivePartialEqOrPartialOrd<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation.
// The incremental result of this analysis's computation.
// Contains information whether particular item can derive `PartialEq`/`PartialOrd`.
can_derive_partialeq_or_partialord: HashMap<ItemId, CanDerive>,
@ -158,7 +158,6 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
TypeKind::Enum(..) |
TypeKind::TypeParam |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::BlockPointer |
TypeKind::Reference(..) |
TypeKind::ObjCInterface(..) |
TypeKind::ObjCId |
@ -281,6 +280,7 @@ impl<'ctx> CannotDerivePartialEqOrPartialOrd<'ctx> {
TypeKind::ResolvedTypeRef(..) |
TypeKind::TemplateAlias(..) |
TypeKind::Alias(..) |
TypeKind::BlockPointer(..) |
TypeKind::TemplateInstantiation(..) => {
return self.constrain_join(item);
}

View File

@ -122,7 +122,6 @@ impl<'ctx> MonotoneFramework for HasFloat<'ctx> {
TypeKind::Function(..) |
TypeKind::Enum(..) |
TypeKind::Reference(..) |
TypeKind::BlockPointer |
TypeKind::TypeParam |
TypeKind::Opaque |
TypeKind::Pointer(..) |
@ -159,7 +158,8 @@ impl<'ctx> MonotoneFramework for HasFloat<'ctx> {
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
if self.has_float.contains(&t.into()) {
trace!(" aliases and type refs to T which have float \
also have float");

View File

@ -135,7 +135,6 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> {
TypeKind::Function(..) |
TypeKind::Enum(..) |
TypeKind::Reference(..) |
TypeKind::BlockPointer |
TypeKind::TypeParam |
TypeKind::Opaque |
TypeKind::Pointer(..) |
@ -166,7 +165,8 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> {
TypeKind::ResolvedTypeRef(t) |
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) => {
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) => {
if self.has_type_parameter_in_array.contains(&t.into()) {
trace!(
" aliases and type refs to T which have array \

View File

@ -261,7 +261,6 @@ impl<'ctx> MonotoneFramework for SizednessAnalysis<'ctx> {
TypeKind::Enum(..) |
TypeKind::Reference(..) |
TypeKind::NullPtr |
TypeKind::BlockPointer |
TypeKind::ObjCId |
TypeKind::ObjCSel |
TypeKind::Pointer(..) => {
@ -276,6 +275,7 @@ impl<'ctx> MonotoneFramework for SizednessAnalysis<'ctx> {
TypeKind::TemplateAlias(t, _) |
TypeKind::Alias(t) |
TypeKind::BlockPointer(t) |
TypeKind::ResolvedTypeRef(t) => {
trace!(" aliases and type refs forward to their inner type");
self.forward(t, id)

View File

@ -155,7 +155,6 @@ impl Type {
TypeKind::Array(..) |
TypeKind::Reference(..) |
TypeKind::Pointer(..) |
TypeKind::BlockPointer |
TypeKind::Int(..) |
TypeKind::Float(..) |
TypeKind::TypeParam => true,
@ -244,8 +243,7 @@ impl Type {
TypeKind::Comp(ref ci) => ci.layout(ctx),
// FIXME(emilio): This is a hack for anonymous union templates.
// Use the actual pointer size!
TypeKind::Pointer(..) |
TypeKind::BlockPointer => {
TypeKind::Pointer(..) => {
Some(Layout::new(
ctx.target_pointer_size(),
ctx.target_pointer_size(),
@ -339,7 +337,6 @@ impl Type {
TypeKind::Reference(..) |
TypeKind::Void |
TypeKind::NullPtr |
TypeKind::BlockPointer |
TypeKind::Pointer(..) |
TypeKind::ObjCId |
TypeKind::ObjCSel |
@ -347,6 +344,7 @@ impl Type {
TypeKind::ResolvedTypeRef(inner) |
TypeKind::Alias(inner) |
TypeKind::BlockPointer(inner) |
TypeKind::TemplateAlias(inner, _) => {
ctx.resolve_type(inner).safe_canonical_type(ctx)
}
@ -485,7 +483,7 @@ impl TypeKind {
TypeKind::Function(..) => "Function",
TypeKind::Enum(..) => "Enum",
TypeKind::Pointer(..) => "Pointer",
TypeKind::BlockPointer => "BlockPointer",
TypeKind::BlockPointer(..) => "BlockPointer",
TypeKind::Reference(..) => "Reference",
TypeKind::TemplateInstantiation(..) => "TemplateInstantiation",
TypeKind::UnresolvedTypeRef(..) => "UnresolvedTypeRef",
@ -579,7 +577,7 @@ impl TemplateParameters for TypeKind {
TypeKind::Function(_) |
TypeKind::Enum(_) |
TypeKind::Pointer(_) |
TypeKind::BlockPointer |
TypeKind::BlockPointer(_) |
TypeKind::Reference(_) |
TypeKind::UnresolvedTypeRef(..) |
TypeKind::TypeParam |
@ -655,7 +653,7 @@ pub enum TypeKind {
Pointer(TypeId),
/// A pointer to an Apple block.
BlockPointer,
BlockPointer(TypeId),
/// A reference to a type, as in: int& foo().
Reference(TypeId),
@ -1086,7 +1084,12 @@ impl Type {
Item::from_ty_or_ref(pointee, location, None, ctx);
TypeKind::Pointer(inner)
}
CXType_BlockPointer => TypeKind::BlockPointer,
CXType_BlockPointer => {
let pointee = ty.pointee_type().expect("Not valid Type?");
let inner =
Item::from_ty_or_ref(pointee, location, None, ctx);
TypeKind::BlockPointer(inner)
},
// XXX: RValueReference is most likely wrong, but I don't think we
// can even add bindings for that, so huh.
CXType_RValueReference |
@ -1232,6 +1235,7 @@ impl Trace for Type {
TypeKind::Reference(inner) |
TypeKind::Array(inner, _) |
TypeKind::Vector(inner, _) |
TypeKind::BlockPointer(inner) |
TypeKind::Alias(inner) |
TypeKind::ResolvedTypeRef(inner) => {
tracer.visit_kind(inner.into(), EdgeKind::TypeReference);
@ -1273,8 +1277,7 @@ impl Trace for Type {
TypeKind::Float(_) |
TypeKind::Complex(_) |
TypeKind::ObjCId |
TypeKind::ObjCSel |
TypeKind::BlockPointer => {}
TypeKind::ObjCSel => {}
}
}
}

View File

@ -373,6 +373,10 @@ impl Builder {
output_vector.push("--objc-extern-crate".into());
}
if self.options.block_extern_crate {
output_vector.push("--block-extern-crate".into());
}
if self.options.builtins {
output_vector.push("--builtins".into());
}
@ -700,6 +704,13 @@ impl Builder {
self
}
/// Generate `#[macro_use] extern crate block;` instead of `use block;`
/// in the prologue of the files generated from apple block files
pub fn block_extern_crate(mut self, doit: bool) -> Self {
self.options.block_extern_crate = doit;
self
}
/// Whether to use the clang-provided name mangling. This is true by default
/// and probably needed for C++ features.
///
@ -1454,6 +1465,10 @@ struct BindgenOptions {
/// generate '#[macro_use] extern crate objc;'
objc_extern_crate: bool,
/// Instead of emitting 'use block;' to files generated from objective c files,
/// generate '#[macro_use] extern crate block;'
block_extern_crate: bool,
/// Whether to use the clang-provided name mangling. This is true and
/// probably needed for C++ features.
///
@ -1579,6 +1594,7 @@ impl Default for BindgenOptions {
generate_inline_functions: false,
whitelist_recursively: true,
objc_extern_crate: false,
block_extern_crate: false,
enable_mangling: true,
prepend_enum_name: true,
time_phases: false,

View File

@ -132,6 +132,9 @@ where
Arg::with_name("objc-extern-crate")
.long("objc-extern-crate")
.help("Use extern crate instead of use for objc."),
Arg::with_name("block-extern-crate")
.long("block-extern-crate")
.help("Use extern crate instead of use for block."),
Arg::with_name("distrust-clang-mangling")
.long("distrust-clang-mangling")
.help("Do not trust the libclang-provided mangling"),
@ -493,6 +496,10 @@ where
builder = builder.objc_extern_crate(true);
}
if matches.is_present("block-extern-crate") {
builder = builder.block_extern_crate(true);
}
if let Some(opaque_types) = matches.values_of("opaque-type") {
for ty in opaque_types {
builder = builder.opaque_type(ty);

View File

@ -10,3 +10,4 @@ authors = [
[dependencies]
objc = "0.2"
block = "0.1"

View File

@ -1,9 +1,24 @@
/* automatically generated by rust-bindgen */
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]
#![cfg(target_os = "macos")]
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
extern crate block;
extern "C" {
pub fn atexit_b(arg1: *mut ::std::os::raw::c_void);
#[link_name = "\u{1}_Z8atexit_bU13block_pointerFvvE"]
pub fn atexit_b(arg1: _bindgen_ty_id_19);
}
pub type dispatch_data_t = *mut ::std::os::raw::c_void;
pub type dispatch_data_applier_t = _bindgen_ty_id_26;
extern "C" {
#[link_name = "\u{1}_Z19dispatch_data_applyPvU13block_pointerFbS_yPKvyE"]
pub fn dispatch_data_apply(data: dispatch_data_t, applier: dispatch_data_applier_t) -> bool;
}
pub type _bindgen_ty_id_19 = *const ::block::Block<(), ()>;
pub type _bindgen_ty_id_26 =
*const ::block::Block<(dispatch_data_t, usize, *const ::std::os::raw::c_void, usize), bool>;

View File

@ -1,3 +0,0 @@
// bindgen-flags: -- -fblocks
void atexit_b(void (^)(void));

16
tests/headers/blocks.hpp Normal file
View File

@ -0,0 +1,16 @@
// bindgen-flags: --block-extern-crate -- -fblocks
// bindgen-osx-only
typedef unsigned long long size_t;
void atexit_b(void (^)(void));
typedef void *dispatch_data_t;
typedef bool (^dispatch_data_applier_t)(dispatch_data_t region,
size_t offset,
const void *buffer,
size_t size);
bool dispatch_data_apply(dispatch_data_t data,
dispatch_data_applier_t applier);