diff options
Diffstat (limited to 'libbindgen/src')
-rw-r--r-- | libbindgen/src/codegen/mod.rs | 54 | ||||
-rw-r--r-- | libbindgen/src/ir/context.rs | 4 | ||||
-rw-r--r-- | libbindgen/src/ir/function.rs | 3 | ||||
-rw-r--r-- | libbindgen/src/ir/item.rs | 97 | ||||
-rw-r--r-- | libbindgen/src/ir/ty.rs | 33 |
5 files changed, 131 insertions, 60 deletions
diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs index 6c8a36f7..c8cd4cdf 100644 --- a/libbindgen/src/codegen/mod.rs +++ b/libbindgen/src/codegen/mod.rs @@ -33,7 +33,8 @@ fn root_import(ctx: &BindgenContext) -> P<ast::Item> { assert!(ctx.options().enable_cxx_namespaces, "Somebody messed it up"); let root = ctx.root_module().canonical_name(ctx); let root_ident = ctx.rust_ident(&root); - quote_item!(ctx.ext_cx(), use $root_ident;).unwrap() + quote_item!(ctx.ext_cx(), #[allow(unused_imports)] use $root_ident;) + .unwrap() } struct CodegenResult { @@ -217,6 +218,7 @@ trait CodeGenerator { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + whitelisted_items: &ItemSet, extra: &Self::Extra); } @@ -226,6 +228,7 @@ impl CodeGenerator for Item { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + whitelisted_items: &ItemSet, _extra: &()) { if self.is_hidden(ctx) || result.seen(self.id()) { debug!("<Item as CodeGenerator>::codegen: Ignoring hidden or seen: \ @@ -244,18 +247,18 @@ impl CodeGenerator for Item { return; } - module.codegen(ctx, result, self); + module.codegen(ctx, result, whitelisted_items, self); } ItemKind::Function(ref fun) => { if !ctx.options().ignore_functions { - fun.codegen(ctx, result, self); + fun.codegen(ctx, result, whitelisted_items, self); } } ItemKind::Var(ref var) => { - var.codegen(ctx, result, self); + var.codegen(ctx, result, whitelisted_items, self); } ItemKind::Type(ref ty) => { - ty.codegen(ctx, result, self); + ty.codegen(ctx, result, whitelisted_items, self); } } } @@ -267,12 +270,14 @@ impl CodeGenerator for Module { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + whitelisted_items: &ItemSet, item: &Item) { debug!("<Module as CodeGenerator>::codegen: item = {:?}", item); if !ctx.options().enable_cxx_namespaces { for child in self.children() { - ctx.resolve_item(*child).codegen(ctx, result, &()); + ctx.resolve_item(*child) + .codegen(ctx, result, whitelisted_items, &()); } return; } @@ -280,7 +285,10 @@ impl CodeGenerator for Module { let inner_items = result.inner(|result| { result.push(root_import(ctx)); for child in self.children() { - ctx.resolve_item(*child).codegen(ctx, result, &()); + if whitelisted_items.contains(child) { + ctx.resolve_item(*child) + .codegen(ctx, result, whitelisted_items, &()); + } } }); @@ -304,6 +312,7 @@ impl CodeGenerator for Var { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + _whitelisted_items: &ItemSet, item: &Item) { use ir::var::VarType; debug!("<Var as CodeGenerator>::codegen: item = {:?}", item); @@ -394,6 +403,7 @@ impl CodeGenerator for Type { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + whitelisted_items: &ItemSet, item: &Item) { debug!("<Type as CodeGenerator>::codegen: item = {:?}", item); @@ -415,12 +425,15 @@ impl CodeGenerator for Type { // converted to rust types in fields, arguments, and such. return; } - TypeKind::Comp(ref ci) => ci.codegen(ctx, result, item), + TypeKind::Comp(ref ci) => { + ci.codegen(ctx, result, whitelisted_items, item) + } TypeKind::TemplateAlias(inner, _) => { // NB: The inner Alias will pick the correct // applicable_template_args. let inner_item = ctx.resolve_item(inner); - inner_item.expect_type().codegen(ctx, result, inner_item); + inner_item.expect_type() + .codegen(ctx, result, whitelisted_items, inner_item); } TypeKind::Alias(ref spelling, inner) => { let inner_item = ctx.resolve_item(inner); @@ -478,7 +491,9 @@ impl CodeGenerator for Type { let typedef = generics.build().build_ty(inner_rust_type); result.push(typedef) } - TypeKind::Enum(ref ei) => ei.codegen(ctx, result, item), + TypeKind::Enum(ref ei) => { + ei.codegen(ctx, result, whitelisted_items, item) + } ref u @ TypeKind::UnresolvedTypeRef(..) => { unreachable!("Should have been resolved after parsing {:?}!", u) } @@ -513,6 +528,7 @@ impl<'a> CodeGenerator for Vtable<'a> { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + _whitelisted_items: &ItemSet, item: &Item) { assert_eq!(item.id(), self.item_id); // For now, generate an empty struct, later we should generate function @@ -646,6 +662,7 @@ impl CodeGenerator for CompInfo { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + whitelisted_items: &ItemSet, item: &Item) { use aster::struct_field::StructFieldBuilder; @@ -732,7 +749,7 @@ impl CodeGenerator for CompInfo { if self.needs_explicit_vtable(ctx) { let vtable = Vtable::new(item.id(), self.methods(), self.base_members()); - vtable.codegen(ctx, result, item); + vtable.codegen(ctx, result, whitelisted_items, item); let vtable_type = vtable.to_rust_ty(ctx).to_ptr(true, ctx.span()); @@ -1051,7 +1068,7 @@ impl CodeGenerator for CompInfo { for ty in self.inner_types() { let child_item = ctx.resolve_item(*ty); // assert_eq!(child_item.parent_id(), item.id()); - child_item.codegen(ctx, result, &()); + child_item.codegen(ctx, result, whitelisted_items, &()); } // NOTE: Some unexposed attributes (like alignment attributes) may @@ -1064,7 +1081,8 @@ impl CodeGenerator for CompInfo { if applicable_template_args.is_empty() && !self.found_unknown_attr() { for var in self.inner_vars() { - ctx.resolve_item(*var).codegen(ctx, result, &()); + ctx.resolve_item(*var) + .codegen(ctx, result, whitelisted_items, &()); } if let Some(layout) = layout { @@ -1094,6 +1112,7 @@ impl CodeGenerator for CompInfo { &mut methods, &mut method_names, result, + whitelisted_items, item); } } @@ -1145,6 +1164,7 @@ trait MethodCodegen { methods: &mut Vec<ast::ImplItem>, method_names: &mut HashMap<String, usize>, result: &mut CodegenResult, + whitelisted_items: &ItemSet, parent: &Item); } @@ -1154,6 +1174,7 @@ impl MethodCodegen for Method { methods: &mut Vec<ast::ImplItem>, method_names: &mut HashMap<String, usize>, result: &mut CodegenResult, + whitelisted_items: &ItemSet, _parent: &Item) { if ctx.options().ignore_methods { return; @@ -1163,7 +1184,8 @@ impl MethodCodegen for Method { return; // FIXME } // First of all, output the actual function. - ctx.resolve_item(self.signature()).codegen(ctx, result, &()); + ctx.resolve_item(self.signature()) + .codegen(ctx, result, whitelisted_items, &()); let function_item = ctx.resolve_item(self.signature()); let function = function_item.expect_function(); @@ -1411,6 +1433,7 @@ impl CodeGenerator for Enum { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + _whitelisted_items: &ItemSet, item: &Item) { debug!("<Enum as CodeGenerator>::codegen: item = {:?}", item); @@ -1852,6 +1875,7 @@ impl CodeGenerator for Function { fn codegen(&self, ctx: &BindgenContext, result: &mut CodegenResult, + _whitelisted_items: &ItemSet, item: &Item) { debug!("<Function as CodeGenerator>::codegen: item = {:?}", item); @@ -1963,7 +1987,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { // need to take responsibility for generating it. if item.is_toplevel(context) || !ancestor_is_whitelisted(context, &whitelisted_items, id) { - item.codegen(context, &mut result, &()); + item.codegen(context, &mut result, &whitelisted_items, &()); } } diff --git a/libbindgen/src/ir/context.rs b/libbindgen/src/ir/context.rs index bda3e3c8..7c643f04 100644 --- a/libbindgen/src/ir/context.rs +++ b/libbindgen/src/ir/context.rs @@ -938,7 +938,9 @@ impl<'ctx> BindgenContext<'ctx> { let name = item.canonical_name(self); match *item.kind() { - ItemKind::Module(..) => false, + ItemKind::Module(..) => { + self.options().enable_cxx_namespaces + } ItemKind::Function(_) => { self.options().whitelisted_functions.matches(&name) } diff --git a/libbindgen/src/ir/function.rs b/libbindgen/src/ir/function.rs index 60bd1e5b..5a864cfc 100644 --- a/libbindgen/src/ir/function.rs +++ b/libbindgen/src/ir/function.rs @@ -150,7 +150,8 @@ impl FunctionSig { CXCursor_CXXMethod => { // For CXCursor_FunctionDecl, cursor.args() is the reliable way // to get parameter names and types. - cursor.args().expect("It cannot be None because we are in a method/function") + cursor.args() + .unwrap() .iter() .map(|arg| { let arg_ty = arg.cur_type(); diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs index 176eca14..32e3c4c5 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -1,6 +1,7 @@ //! Bindgen's core intermediate representation type. use clang; +use clangll; use parse::{ClangItemParser, ClangSubItemParser, ParseError, ParseResult}; use std::cell::{Cell, RefCell}; use std::fmt::Write; @@ -527,7 +528,10 @@ impl Item { } /// Get the target item id for name generation. - fn name_target(&self, ctx: &BindgenContext, for_name_checking: bool) -> ItemId { + fn name_target(&self, + ctx: &BindgenContext, + for_name_checking: bool) + -> ItemId { let mut item = self; loop { match *item.kind() { @@ -535,24 +539,31 @@ impl Item { match *ty.kind() { // If we're a template specialization, our name is our // parent's name. - TypeKind::Comp(ref ci) if ci.is_template_specialization() => { - item = ctx.resolve_item(ci.specialized_template().unwrap()); - }, + TypeKind::Comp(ref ci) + if ci.is_template_specialization() => { + let specialized = + ci.specialized_template().unwrap(); + item = ctx.resolve_item(specialized); + } // Same as above. TypeKind::ResolvedTypeRef(inner) | TypeKind::TemplateRef(inner, _) => { item = ctx.resolve_item(inner); } - // Template aliases use their inner alias type's name if we - // are checking names for whitelisting/replacement/etc. - TypeKind::TemplateAlias(inner, _) if for_name_checking => { + // Template aliases use their inner alias type's name if + // we are checking names for + // whitelisting/replacement/etc. + TypeKind::TemplateAlias(inner, _) + if for_name_checking => { item = ctx.resolve_item(inner); - assert_eq!(item.id(), item.name_target(ctx, for_name_checking)); + assert_eq!(item.id(), + item.name_target(ctx, + for_name_checking)); return item.id(); } _ => return item.id(), } - }, + } _ => return item.id(), } } @@ -580,9 +591,7 @@ impl Item { let func = item.expect_function(); func.name() == func_name }) - .enumerate() - .find(|&(_, ref method)| method.signature() == self.id()) - .map(|(idx, _)| idx); + .position(|method| method.signature() == self.id()); } } @@ -595,24 +604,33 @@ impl Item { /// The `for_name_checking` boolean parameter informs us whether we are /// asking for the name in order to do a whitelisting/replacement/etc check /// or if we are instead using it for code generation. - fn base_name(&self, ctx: &BindgenContext, for_name_checking: bool) -> String { + fn base_name(&self, + ctx: &BindgenContext, + for_name_checking: bool) + -> String { match *self.kind() { ItemKind::Var(ref var) => var.name().to_owned(), ItemKind::Module(ref module) => { module.name() .map(ToOwned::to_owned) - .unwrap_or_else(|| format!("_bindgen_mod_{}", self.exposed_id(ctx))) - }, + .unwrap_or_else(|| { + format!("_bindgen_mod_{}", self.exposed_id(ctx)) + }) + } ItemKind::Type(ref ty) => { let name = match *ty.kind() { - TypeKind::ResolvedTypeRef(..) => - panic!("should have resolved this in name_target()"), - TypeKind::TemplateAlias(..) if !for_name_checking => Some(""), - TypeKind::TemplateAlias(..) => None, + TypeKind::ResolvedTypeRef(..) => { + panic!("should have resolved this in name_target()") + } + TypeKind::TemplateAlias(..) => { + if for_name_checking { None } else { Some("") } + } _ => ty.name(), }; name.map(ToOwned::to_owned) - .unwrap_or_else(|| format!("_bindgen_ty_{}", self.exposed_id(ctx))) + .unwrap_or_else(|| { + format!("_bindgen_ty_{}", self.exposed_id(ctx)) + }) } ItemKind::Function(ref fun) => { let mut name = fun.name().to_owned(); @@ -624,7 +642,7 @@ impl Item { } name - }, + } } } @@ -716,6 +734,31 @@ impl Item { } } +// An utility function to handle recursing inside nested types. +fn visit_child(cur: clang::Cursor, + id: ItemId, + ty: &clang::Type, + parent_id: Option<ItemId>, + ctx: &mut BindgenContext, + result: &mut Result<ItemId, ParseError>) + -> clangll::Enum_CXChildVisitResult { + use clangll::*; + if result.is_ok() { + return CXChildVisit_Break; + } + + *result = Item::from_ty_with_id(id, ty, Some(cur), parent_id, ctx); + + match *result { + Ok(..) => CXChildVisit_Break, + Err(ParseError::Recurse) => { + cur.visit(|c| visit_child(c, id, ty, parent_id, ctx, result)); + CXChildVisit_Continue + } + Err(ParseError::Continue) => CXChildVisit_Continue, + } +} + impl ClangItemParser for Item { fn builtin_type(kind: TypeKind, is_const: bool, @@ -1005,17 +1048,7 @@ impl ClangItemParser for Item { } location.visit(|cur| { - use clangll::*; - result = Item::from_ty_with_id(id, - ty, - Some(cur), - parent_id, - ctx); - match result { - Ok(..) => CXChildVisit_Break, - Err(ParseError::Recurse) => CXChildVisit_Recurse, - Err(ParseError::Continue) => CXChildVisit_Continue, - } + visit_child(cur, id, ty, parent_id, ctx, &mut result) }); if valid_decl { diff --git a/libbindgen/src/ir/ty.rs b/libbindgen/src/ir/ty.rs index 60611b8d..7f01e388 100644 --- a/libbindgen/src/ir/ty.rs +++ b/libbindgen/src/ir/ty.rs @@ -685,30 +685,41 @@ impl Type { CXCursor_TemplateRef => { let referenced = location.referenced().unwrap(); let referenced_ty = referenced.cur_type(); - let referenced_declaration = - Some(referenced_ty.declaration()); + + debug!("TemplateRef: location = {:?}; referenced = \ + {:?}; referenced_ty = {:?}", + location, + referenced, + referenced_ty); return Self::from_clang_ty(potential_id, &referenced_ty, - referenced_declaration, + Some(referenced), parent_id, ctx); } CXCursor_TypeRef => { let referenced = location.referenced().unwrap(); let referenced_ty = referenced.cur_type(); - let referenced_declaration = - Some(referenced_ty.declaration()); + let declaration = referenced_ty.declaration(); + + debug!("TypeRef: location = {:?}; referenced = \ + {:?}; referenced_ty = {:?}", + location, + referenced, + referenced_ty); let item = - Item::from_ty_or_ref_with_id( - potential_id, - referenced_ty, - referenced_declaration, - parent_id, - ctx); + Item::from_ty_or_ref_with_id(potential_id, + referenced_ty, + Some(declaration), + parent_id, + ctx); return Ok(ParseResult::AlreadyResolved(item)); } + CXCursor_NamespaceRef => { + return Err(ParseError::Continue); + } _ => { if ty.kind() == CXType_Unexposed { warn!("Unexposed type {:?}, recursing inside, \ |