diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/clang.rs | 6 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/parser.rs | 45 | ||||
-rw-r--r-- | src/types.rs | 20 |
4 files changed, 67 insertions, 5 deletions
diff --git a/src/clang.rs b/src/clang.rs index b7d6b5c7..1d738def 100644 --- a/src/clang.rs +++ b/src/clang.rs @@ -43,6 +43,12 @@ impl Cursor { mangling } + pub fn lexical_parent(&self) -> Cursor { + unsafe { + Cursor { x: clang_getCursorLexicalParent(self.x) } + } + } + pub fn semantic_parent(&self) -> Cursor { unsafe { Cursor { x: clang_getCursorSemanticParent(self.x) } @@ -1,6 +1,7 @@ #![crate_name = "bindgen"] #![crate_type = "dylib"] #![feature(quote)] +#![feature(borrow_state)] #![cfg_attr(feature = "clippy", feature(plugin))] #![cfg_attr(feature = "clippy", plugin(clippy))] diff --git a/src/parser.rs b/src/parser.rs index 774ebbbb..86240eb2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -124,6 +124,7 @@ fn decl_name(ctx: &mut ClangParserCtx, cursor: &Cursor) -> Global { }; let mut ci = CompInfo::new(spelling, ctx.current_module_id, filename, comment, kind, vec![], layout); + ci.parser_cursor = Some(cursor); // If it's an instantiation of another template, // find the canonical declaration to find the module @@ -367,18 +368,18 @@ fn conv_decl_ty_resolving_typedefs(ctx: &mut ClangParserCtx, // it's important not to override if !args.is_empty() { ci.borrow_mut().args = args; + // XXX: This is a super-dumb way to get the spesialisation, // but it seems to be the only one that'd work here... cursor.visit(|c, _: &Cursor| { if c.kind() == CXCursor_TemplateRef { - let decl = decl_name(ctx, &c.referenced()); + let decl = decl_name(ctx, &c.referenced()); ci.borrow_mut().ref_template = Some(decl.to_type()); } CXChildVisit_Continue }); } - TComp(ci) } CXCursor_EnumDecl => { @@ -458,7 +459,9 @@ fn conv_ty_resolving_typedefs(ctx: &mut ClangParserCtx, CXType_Pointer => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, false, layout, resolve_typedefs), CXType_LValueReference => conv_ptr_ty_resolving_typedefs(ctx, &ty.pointee_type(), cursor, true, layout, resolve_typedefs), // XXX DependentSizedArray is wrong - CXType_VariableArray | CXType_DependentSizedArray | CXType_IncompleteArray => { + CXType_VariableArray | + CXType_DependentSizedArray | + CXType_IncompleteArray => { conv_ptr_ty_resolving_typedefs(ctx, &ty.elem_type(), cursor, false, layout, resolve_typedefs) } CXType_FunctionProto => TFuncProto(mk_fn_sig(ctx, ty, cursor)), @@ -537,6 +540,7 @@ impl Annotations { fn visit_composite(cursor: &Cursor, parent: &Cursor, ctx: &mut ClangParserCtx, ci: &mut CompInfo) -> Enum_CXVisitorResult { + assert!(ci.parser_cursor.is_some()); fn is_bitfield_continuation(field: &il::FieldInfo, _ty: &il::Type, width: u32) -> bool { match (&field.bitfields, field.ty.layout()) { (&Some(ref bitfields), Some(layout)) => { @@ -560,8 +564,41 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor, let is_class_typedef = cursor.cur_type().sanitized_spelling_in(&ci.typedefs); let mutable = cursor.is_mutable_field(); + let cursor_ty = cursor.cur_type(); + // NB: Overwritten in the case of non-integer bitfield - let mut ty = conv_ty_resolving_typedefs(ctx, &cursor.cur_type(), cursor, is_class_typedef); + let mut ty = conv_ty_resolving_typedefs(ctx, + &cursor.cur_type(), + cursor, + is_class_typedef); + + use std::cell::BorrowState; + if let Some(child_ci) = ty.get_outermost_composite() { + if let BorrowState::Unused = child_ci.borrow_state() { + let mut child_ci = child_ci.borrow_mut(); + let child_cursor = child_ci.parser_cursor.unwrap(); + + // TODO: This is lame, ideally we should use cursors. + // The problem this is trying to solve is + // tests/headers/inner_template_self.hpp. + // + // The problem with this is that clang treats the *prev* + // field as a Class Declaration instead of a Class Template, + // so we have to check now for the name and the module id. + // + // Ideally, some method like `semantic_parent` or + // `lexical_parent` should return the reference to the + // class, but I've tried everything I could think about and + // failed miserably. + if child_cursor.kind() == CXCursor_ClassDecl && + child_ci.args.is_empty() && + child_ci.name == ci.name && + child_ci.module_id == ci.module_id { + child_ci.args = ci.args.clone(); + } + } + } + let comment = cursor.raw_comment(); let (name, bitfields) = match (cursor.bit_width(), ci.members.last_mut()) { diff --git a/src/types.rs b/src/types.rs index c7b9e530..c0180cd6 100644 --- a/src/types.rs +++ b/src/types.rs @@ -10,6 +10,7 @@ pub use self::Global::*; pub use self::Type::*; pub use self::IKind::*; pub use self::FKind::*; +use clang::Cursor; static NEXT_MODULE_ID: AtomicUsize = ATOMIC_USIZE_INIT; @@ -200,6 +201,15 @@ impl Type { } } + pub fn get_outermost_composite(&self) -> Option<Rc<RefCell<CompInfo>>> { + match *self { + TComp(ref ci) => Some(ci.clone()), + TArray(ref t, _, _) => t.get_outermost_composite(), + TPtr(ref t, _, _, _) => t.get_outermost_composite(), + _ => None, + } + } + pub fn size(&self) -> usize { self.layout().map(|l| l.size).unwrap_or(0) } @@ -401,6 +411,7 @@ pub struct CompInfo { pub has_destructor: bool, pub has_nonempty_base: bool, pub hide: bool, + pub parser_cursor: Option<Cursor>, /// If this struct should be replaced by an opaque blob. /// /// This is useful if for some reason we can't generate @@ -431,7 +442,13 @@ fn unnamed_name(name: String, filename: &String) -> String { } impl CompInfo { - pub fn new(name: String, module_id: ModuleId, filename: String, comment: String, kind: CompKind, members: Vec<CompMember>, layout: Layout) -> CompInfo { + pub fn new(name: String, + module_id: ModuleId, + filename: String, + comment: String, + kind: CompKind, + members: Vec<CompMember>, + layout: Layout) -> CompInfo { let was_unnamed = name.is_empty(); CompInfo { kind: kind, @@ -448,6 +465,7 @@ impl CompInfo { has_destructor: false, has_nonempty_base: false, hide: false, + parser_cursor: None, opaque: false, base_members: 0, layout: layout, |