diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 659007397c..a656c2c13a 100755 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -14,11 +14,11 @@ use ir::item_kind::ItemKind; use ir::comp::{CompKind, CompInfo, Field, Method}; use ir::layout::Layout; use ir::annotations::FieldAccessorKind; +use ir::type_collector::{ItemSet, TypeCollector}; use std::ops; use std::borrow::Cow; use std::mem; -use std::collections::BTreeSet; use std::collections::HashSet; use std::collections::hash_map::{HashMap, Entry}; @@ -1584,133 +1584,6 @@ impl CodeGenerator for Function { } } -type ItemSet = BTreeSet; - -trait TypeCollector { - type Extra; - - fn collect_types(&self, - context: &BindgenContext, - types: &mut ItemSet, - extra: &Self::Extra); -} - -impl TypeCollector for ItemId { - type Extra = (); - - fn collect_types(&self, - context: &BindgenContext, - types: &mut ItemSet, - extra: &()) { - context.resolve_item(*self).collect_types(context, types, extra); - } -} - -impl TypeCollector for Item { - type Extra = (); - - fn collect_types(&self, - context: &BindgenContext, - types: &mut ItemSet, - _extra: &()) { - if self.is_hidden(context) || types.contains(&self.id()) { - return; - } - - match *self.kind() { - ItemKind::Type(ref ty) => { - types.insert(self.id()); - if !self.is_opaque(context) { - ty.collect_types(context, types, self); - } - } - _ => {}, // FIXME. - } - } -} - -impl TypeCollector for Type { - type Extra = Item; - - fn collect_types(&self, - context: &BindgenContext, - types: &mut ItemSet, - item: &Item) { - match *self.kind() { - TypeKind::Pointer(inner) | - TypeKind::Reference(inner) | - TypeKind::Array(inner, _) | - TypeKind::TemplateAlias(inner, _) | - TypeKind::Alias(_, inner) | - TypeKind::Named(_, Some(inner)) | - TypeKind::ResolvedTypeRef(inner) - => inner.collect_types(context, types, &()), - - TypeKind::TemplateRef(inner, ref template_args) => { - inner.collect_types(context, types, &()); - for item in template_args { - item.collect_types(context, types, &()); - } - } - TypeKind::Comp(ref ci) => ci.collect_types(context, types, item), - TypeKind::Function(ref sig) => { - sig.collect_types(context, types, item) - } - // FIXME: Pending types! - ref other @ _ => { - debug!("Ignoring: {:?}", other); - }, - } - } -} - -impl TypeCollector for FunctionSig { - type Extra = Item; - - fn collect_types(&self, - context: &BindgenContext, - types: &mut ItemSet, - _item: &Item) { - self.return_type().collect_types(context, types, &()); - - for &(_, ty) in self.argument_types() { - ty.collect_types(context, types, &()); - } - } -} - -impl TypeCollector for CompInfo { - type Extra = Item; - - fn collect_types(&self, - context: &BindgenContext, - types: &mut ItemSet, - item: &Item) { - if let Some(template) = self.specialized_template() { - template.collect_types(context, types, &()); - } - - let applicable_template_args = item.applicable_template_args(context); - for arg in applicable_template_args { - arg.collect_types(context, types, &()); - } - - for base in self.base_members() { - base.collect_types(context, types, &()); - } - - for field in self.fields() { - field.ty().collect_types(context, types, &()); - } - - for ty in self.inner_types() { - ty.collect_types(context, types, &()); - } - - // FIXME(emilio): Methods, VTable? - } -} - pub fn codegen(context: &mut BindgenContext) -> Vec> { context.gen(|context| { let mut result = CodegenResult::new(); diff --git a/src/ir/comp.rs b/src/ir/comp.rs index b9e9ec8b66..13eaa6db0c 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -5,6 +5,7 @@ use super::context::BindgenContext; use super::layout::Layout; use super::item::{Item, ItemId}; use super::ty::{Type, RUST_DERIVE_IN_ARRAY_LIMIT}; +use super::type_collector::{ItemSet, TypeCollector}; use std::cell::Cell; use std::cmp; use parse::{ClangItemParser, ParseError}; @@ -804,3 +805,35 @@ impl CompInfo { }) } } + +impl TypeCollector for CompInfo { + type Extra = Item; + + fn collect_types(&self, + context: &BindgenContext, + types: &mut ItemSet, + item: &Item) { + if let Some(template) = self.specialized_template() { + template.collect_types(context, types, &()); + } + + let applicable_template_args = item.applicable_template_args(context); + for arg in applicable_template_args { + arg.collect_types(context, types, &()); + } + + for base in self.base_members() { + base.collect_types(context, types, &()); + } + + for field in self.fields() { + field.ty().collect_types(context, types, &()); + } + + for ty in self.inner_types() { + ty.collect_types(context, types, &()); + } + + // FIXME(emilio): Methods, VTable? + } +} diff --git a/src/ir/context.rs b/src/ir/context.rs index 65c628171e..729a1c02b5 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -32,7 +32,7 @@ enum TypeKey { // context. struct GenContext<'ctx>(ExtCtxt<'ctx>); -impl<'ctx> fmt::Debug for GenContext <'ctx> { +impl<'ctx> fmt::Debug for GenContext<'ctx> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "GenContext {{ ... }}") } diff --git a/src/ir/function.rs b/src/ir/function.rs index 0cf23f43b0..fc2a7110c3 100644 --- a/src/ir/function.rs +++ b/src/ir/function.rs @@ -1,8 +1,9 @@ //! Intermediate representation for C/C++ functions and methods. +use super::context::BindgenContext; use super::item::{Item, ItemId}; use super::ty::TypeKind; -use super::context::BindgenContext; +use super::type_collector::{ItemSet, TypeCollector}; use syntax::abi; use clang; use clangll::Enum_CXCallingConv; @@ -246,3 +247,18 @@ impl ClangSubItemParser for Function { Ok(ParseResult::New(function, Some(cursor))) } } + +impl TypeCollector for FunctionSig { + type Extra = Item; + + fn collect_types(&self, + context: &BindgenContext, + types: &mut ItemSet, + _item: &Item) { + self.return_type().collect_types(context, types, &()); + + for &(_, ty) in self.argument_types() { + ty.collect_types(context, types, &()); + } + } +} diff --git a/src/ir/item.rs b/src/ir/item.rs index 0d409f0401..b262b825a6 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -4,6 +4,7 @@ use regex::Regex; use super::context::BindgenContext; use super::item_kind::ItemKind; use super::ty::{Type, TypeKind}; +use super::type_collector::{ItemSet, TypeCollector}; use super::function::Function; use super::module::Module; use super::annotations::Annotations; @@ -76,6 +77,40 @@ impl ItemCanonicalPath for ItemId { } } +impl TypeCollector for ItemId { + type Extra = (); + + fn collect_types(&self, + context: &BindgenContext, + types: &mut ItemSet, + extra: &()) { + context.resolve_item(*self).collect_types(context, types, extra); + } +} + +impl TypeCollector for Item { + type Extra = (); + + fn collect_types(&self, + context: &BindgenContext, + types: &mut ItemSet, + _extra: &()) { + if self.is_hidden(context) || types.contains(&self.id()) { + return; + } + + match *self.kind() { + ItemKind::Type(ref ty) => { + types.insert(self.id()); + if !self.is_opaque(context) { + ty.collect_types(context, types, self); + } + } + _ => {}, // FIXME. + } + } +} + /// An item is the base of the bindgen representation, it can be either a /// module, a type, a function, or a variable (see `ItemKind` for more /// information). @@ -566,12 +601,12 @@ impl Item { static ref RE_ENDS_WITH_BINDGEN_TY: Regex = Regex::new(r"_bindgen_ty(_\d+)+$").unwrap(); static ref RE_ENDS_WITH_BINDGEN_MOD: Regex = Regex::new(r"_bindgen_mod(_\d+)+$").unwrap(); } - + let (re, kind) = match *self.kind() { ItemKind::Module(..) => (&*RE_ENDS_WITH_BINDGEN_MOD, "mod"), _ => (&*RE_ENDS_WITH_BINDGEN_TY, "ty"), }; - + let parent_name = parent_name.and_then(|n| if n.is_empty() { None } else { Some(n) }); match (parent_name, base_name) { (Some(parent), Some(base)) => format!("{}_{}", parent, base), diff --git a/src/ir/mod.rs b/src/ir/mod.rs index 01f388b806..3c658a4aad 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -14,4 +14,5 @@ pub mod item_kind; pub mod layout; pub mod module; pub mod ty; +pub mod type_collector; pub mod var; diff --git a/src/ir/ty.rs b/src/ir/ty.rs index b9816f6ee1..b2f20ddee8 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -7,6 +7,7 @@ use super::item::{Item, ItemId}; use super::int::IntKind; use super::layout::Layout; use super::context::BindgenContext; +use super::type_collector::{ItemSet, TypeCollector}; use parse::{ClangItemParser, ParseResult, ParseError}; use clang::{self, Cursor}; @@ -709,3 +710,38 @@ impl Type { Ok(ParseResult::New(ty, Some(cursor.canonical()))) } } + +impl TypeCollector for Type { + type Extra = Item; + + fn collect_types(&self, + context: &BindgenContext, + types: &mut ItemSet, + item: &Item) { + match *self.kind() { + TypeKind::Pointer(inner) | + TypeKind::Reference(inner) | + TypeKind::Array(inner, _) | + TypeKind::TemplateAlias(inner, _) | + TypeKind::Alias(_, inner) | + TypeKind::Named(_, Some(inner)) | + TypeKind::ResolvedTypeRef(inner) + => inner.collect_types(context, types, &()), + + TypeKind::TemplateRef(inner, ref template_args) => { + inner.collect_types(context, types, &()); + for item in template_args { + item.collect_types(context, types, &()); + } + } + TypeKind::Comp(ref ci) => ci.collect_types(context, types, item), + TypeKind::Function(ref sig) => { + sig.collect_types(context, types, item) + } + // FIXME: Pending types! + ref other @ _ => { + debug!("Ignoring: {:?}", other); + }, + } + } +} diff --git a/src/ir/type_collector.rs b/src/ir/type_collector.rs new file mode 100644 index 0000000000..a829b165ba --- /dev/null +++ b/src/ir/type_collector.rs @@ -0,0 +1,23 @@ +//! Collecting type items. + +use std::collections::BTreeSet; +use super::context::BindgenContext; +use super::item::ItemId; + +/// A set of items. +pub type ItemSet = BTreeSet; + +/// Collect all the type items referenced by this item. +pub trait TypeCollector { + /// If a particular type needs extra information beyond what it has in + /// `self` and `context` to find its referenced type items, its + /// implementation can define this associated type, forcing callers to pass + /// the needed information through. + type Extra; + + /// Add each type item referenced by `self` into the `types` set. + fn collect_types(&self, + context: &BindgenContext, + types: &mut ItemSet, + extra: &Self::Extra); +}