summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ir/context.rs86
-rw-r--r--src/ir/item.rs28
-rw-r--r--src/ir/ty.rs2
3 files changed, 98 insertions, 18 deletions
diff --git a/src/ir/context.rs b/src/ir/context.rs
index edf42ec8..a2277b39 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -120,9 +120,7 @@ pub struct BindgenContext<'ctx> {
/// We could also use the `types` HashMap, but my intention with it is that
/// only valid types and declarations end up there, and this could
/// potentially break that assumption.
- ///
- /// FIXME: Should not be public, though... meh.
- pub currently_parsed_types: Vec<(Cursor, ItemId)>,
+ currently_parsed_types: Vec<PartialType>,
/// A HashSet with all the already parsed macro names. This is done to avoid
/// hard errors while parsing duplicated macros, as well to allow macro
@@ -193,6 +191,26 @@ impl<'ctx> BindgenContext<'ctx> {
me
}
+ /// Get the stack of partially parsed types that we are in the middle of
+ /// parsing.
+ pub fn currently_parsed_types(&self) -> &[PartialType] {
+ &self.currently_parsed_types[..]
+ }
+
+ /// Begin parsing the given partial type, and push it onto the
+ /// `currently_parsed_types` stack so that we won't infinite recurse if we
+ /// run into a reference to it while parsing it.
+ pub fn begin_parsing(&mut self, partial_ty: PartialType) {
+ self.currently_parsed_types.push(partial_ty);
+ }
+
+ /// Finish parsing the current partial type, pop it off the
+ /// `currently_parsed_types` stack, and return it.
+ pub fn finish_parsing(&mut self) -> PartialType {
+ self.currently_parsed_types.pop()
+ .expect("should have been parsing a type, if we finished parsing a type")
+ }
+
/// Get the user-provided type chooser by reference, if any.
pub fn type_chooser(&self) -> Option<&TypeChooser> {
self.options().type_chooser.as_ref().map(|t| &**t)
@@ -1156,6 +1174,68 @@ impl<'ctx> BindgenContext<'ctx> {
}
}
+/// A type that we are in the middle of parsing.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct PartialType {
+ decl: Cursor,
+ id: ItemId,
+}
+
+impl PartialType {
+ /// Construct a new `PartialType`.
+ pub fn new(decl: Cursor, id: ItemId) -> PartialType {
+ // assert!(decl == decl.canonical());
+ PartialType {
+ decl: decl,
+ id: id,
+ }
+ }
+
+ /// The cursor pointing to this partial type's declaration location.
+ pub fn decl(&self) -> &Cursor {
+ &self.decl
+ }
+
+ /// The item ID allocated for this type. This is *NOT* a key for an entry in
+ /// the context's item set yet!
+ pub fn id(&self) -> ItemId {
+ self.id
+ }
+}
+
+impl TemplateDeclaration for PartialType {
+ fn template_params(&self, _ctx: &BindgenContext) -> Option<Vec<ItemId>> {
+ // Maybe at some point we will eagerly parse named types, but for now we
+ // don't and this information is unavailable.
+ None
+ }
+
+ fn num_template_params(&self, _ctx: &BindgenContext) -> Option<usize> {
+ // Wouldn't it be nice if libclang would reliably give us this
+ // information‽
+ match self.decl().kind() {
+ clang_sys::CXCursor_ClassTemplate |
+ clang_sys::CXCursor_FunctionTemplate |
+ clang_sys::CXCursor_TypeAliasTemplateDecl => {
+ let mut num_params = 0;
+ self.decl().visit(|c| {
+ match c.kind() {
+ clang_sys::CXCursor_TemplateTypeParameter |
+ clang_sys::CXCursor_TemplateTemplateParameter |
+ clang_sys::CXCursor_NonTypeTemplateParameter => {
+ num_params += 1;
+ }
+ _ => {}
+ };
+ clang_sys::CXChildVisit_Continue
+ });
+ Some(num_params)
+ }
+ _ => None,
+ }
+ }
+}
+
/// An iterator over whitelisted items.
///
/// See `BindgenContext::whitelisted_items` for more information.
diff --git a/src/ir/item.rs b/src/ir/item.rs
index 3ce228b6..83e2a41f 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -1,7 +1,7 @@
//! Bindgen's core intermediate representation type.
use super::annotations::Annotations;
-use super::context::{BindgenContext, ItemId};
+use super::context::{BindgenContext, ItemId, PartialType};
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
use super::function::Function;
use super::item_kind::ItemKind;
@@ -1202,18 +1202,18 @@ impl ClangItemParser for Item {
};
if valid_decl {
- if let Some(&(_, item_id)) =
- ctx.currently_parsed_types
- .iter()
- .find(|&&(d, _)| d == declaration_to_look_for) {
+ if let Some(partial) = ctx.currently_parsed_types()
+ .iter()
+ .find(|ty| *ty.decl() == declaration_to_look_for) {
debug!("Avoiding recursion parsing type: {:?}", ty);
- return Ok(item_id);
+ return Ok(partial.id());
}
}
let current_module = ctx.current_module();
+ let partial_ty = PartialType::new(declaration_to_look_for, id);
if valid_decl {
- ctx.currently_parsed_types.push((declaration_to_look_for, id));
+ ctx.begin_parsing(partial_ty);
}
let result = Type::from_clang_ty(id, ty, location, parent_id, ctx);
@@ -1241,9 +1241,8 @@ impl ClangItemParser for Item {
// declaration_to_look_for suspiciously shares a lot of
// logic with ir::context, so we should refactor that.
if valid_decl {
- let (popped_decl, _) =
- ctx.currently_parsed_types.pop().unwrap();
- assert_eq!(popped_decl, declaration_to_look_for);
+ let finished = ctx.finish_parsing();
+ assert_eq!(*finished.decl(), declaration_to_look_for);
}
location.visit(|cur| {
@@ -1251,8 +1250,9 @@ impl ClangItemParser for Item {
});
if valid_decl {
- ctx.currently_parsed_types
- .push((declaration_to_look_for, id));
+ let partial_ty =
+ PartialType::new(declaration_to_look_for, id);
+ ctx.begin_parsing(partial_ty);
}
}
// If we have recursed into the AST all we know, and we still
@@ -1279,8 +1279,8 @@ impl ClangItemParser for Item {
};
if valid_decl {
- let (popped_decl, _) = ctx.currently_parsed_types.pop().unwrap();
- assert_eq!(popped_decl, declaration_to_look_for);
+ let partial_ty = ctx.finish_parsing();
+ assert_eq!(*partial_ty.decl(), declaration_to_look_for);
}
ret
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 0c90547e..a98ca446 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -755,7 +755,7 @@ impl Type {
potential_id,
ty,
location);
- debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types);
+ debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types());
let canonical_ty = ty.canonical_type();