diff options
-rw-r--r-- | rustfmt.toml | 1 | ||||
-rwxr-xr-x | src/clang.rs | 7 | ||||
-rwxr-xr-x | src/codegen/mod.rs | 104 | ||||
-rw-r--r-- | src/ir/comp.rs | 112 | ||||
-rw-r--r-- | src/ir/context.rs | 14 | ||||
-rw-r--r-- | src/ir/item.rs | 169 | ||||
-rw-r--r-- | src/ir/ty.rs | 155 | ||||
-rw-r--r-- | src/ir/var.rs | 38 |
8 files changed, 340 insertions, 260 deletions
diff --git a/rustfmt.toml b/rustfmt.toml index 6677939b..96d4ae47 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,6 +1,5 @@ max_width = 80 format_strings = false -wrap_comments = true fn_brace_style = "SameLineWhere" item_brace_style = "SameLineWhere" struct_lit_multiline_style = "ForceMulti" diff --git a/src/clang.rs b/src/clang.rs index 24d9e45e..e1bb1059 100755 --- a/src/clang.rs +++ b/src/clang.rs @@ -1259,7 +1259,12 @@ pub fn kind_to_str(x: Enum_CXCursorKind) -> &'static str { CXCursor_TemplateTemplateParameter => "TemplateTemplateParameter", CXCursor_FunctionTemplate => "FunctionTemplate", CXCursor_ClassTemplate => "ClassTemplate", - CXCursor_ClassTemplatePartialSpecialization => "ClassTemplatePartialSpecialization", + CXCursor_ClassTemplatePartialSpecialization => { + // FIXME: Ugly hack for rustfmt, should go away! + // + // I plan to convert this into an enum right away anyway, though. + return "ClassTemplatePartialSpecialization"; + } CXCursor_NamespaceAlias => "NamespaceAlias", CXCursor_UsingDirective => "UsingDirective", CXCursor_UsingDeclaration => "UsingDeclaration", diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index a4d717d3..57173904 100755 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1,9 +1,10 @@ mod helpers; + use aster; + use ir::annotations::FieldAccessorKind; use ir::comp::{CompInfo, CompKind, Field, Method}; - use ir::context::BindgenContext; use ir::enum_ty::Enum; use ir::function::{Function, FunctionSig}; @@ -16,13 +17,12 @@ use ir::ty::{Type, TypeKind}; use ir::type_collector::{ItemSet, TypeCollector}; use ir::var::Var; use self::helpers::{BlobTyBuilder, attributes}; + use std::borrow::Cow; use std::collections::HashSet; use std::collections::hash_map::{Entry, HashMap}; use std::mem; - use std::ops; - use syntax::abi::Abi; use syntax::ast; use syntax::codemap::{Span, respan}; @@ -40,8 +40,7 @@ struct CodegenResult { saw_union: bool, items_seen: HashSet<ItemId>, /// The set of generated function/var names, needed because in C/C++ is - /// legal to - /// do something like: + /// legal to do something like: /// /// ```c++ /// extern "C" { @@ -400,7 +399,8 @@ impl CodeGenerator for Type { if template_arg.is_named() { let name = template_arg.name().unwrap(); if name.contains("typename ") { - error!("Item contained `typename`'d template param: {:?}", item); + error!("Item contained `typename`'d template \ + parameter: {:?}", item); return; } generics = @@ -541,18 +541,25 @@ impl<'a> Bitfield<'a> { pub fn $getter_name(&self) -> $field_type { unsafe { ::std::mem::transmute( - ((self.$field_ident & ($mask as $bitfield_type)) >> $offset) - as $int_type) + ( + (self.$field_ident & + ($mask as $bitfield_type)) + >> $offset + ) as $int_type + ) } } #[inline] pub fn $setter_name(&mut self, val: $field_type) { self.$field_ident &= !($mask as $bitfield_type); - self.$field_ident |= (val as $int_type as $bitfield_type << $offset) & ($mask as $bitfield_type); + self.$field_ident |= + (val as $int_type as $bitfield_type << $offset) & + ($mask as $bitfield_type); } } - ).unwrap(); + ) + .unwrap(); let items = match item.unwrap().node { ast::ItemKind::Impl(_, _, _, _, _, items) => items, @@ -639,6 +646,7 @@ impl CodeGenerator for CompInfo { }; // Generate the vtable from the method list if appropriate. + // // TODO: I don't know how this could play with virtual methods that are // not in the list of methods found by us, we'll see. Also, could the // order of the vtable pointers vary? @@ -677,8 +685,9 @@ impl CodeGenerator for CompInfo { continue; } - for (i, ty) in applicable_template_args.iter().enumerate() { - if base_ty.signature_contains_named_type(ctx, ctx.resolve_type(*ty)) { + for (i, ty_id) in applicable_template_args.iter().enumerate() { + let template_arg_ty = ctx.resolve_type(*ty_id); + if base_ty.signature_contains_named_type(ctx, template_arg_ty) { template_args_used[i] = true; } } @@ -758,8 +767,9 @@ impl CodeGenerator for CompInfo { continue; } - for (i, ty) in applicable_template_args.iter().enumerate() { - if field_ty.signature_contains_named_type(ctx, ctx.resolve_type(*ty)) { + for (i, ty_id) in applicable_template_args.iter().enumerate() { + let template_arg = ctx.resolve_type(*ty_id); + if field_ty.signature_contains_named_type(ctx, template_arg) { template_args_used[i] = true; } } @@ -841,7 +851,8 @@ impl CodeGenerator for CompInfo { } #[inline] - pub unsafe fn $mutable_getter_name(&mut self) -> &mut $ty { + pub unsafe fn $mutable_getter_name(&mut self) + -> &mut $ty { &mut self.$field_name } } @@ -931,9 +942,12 @@ impl CodeGenerator for CompInfo { if !template_args_used[i] { let name = ctx.resolve_type(*ty).name().unwrap(); let ident = ctx.rust_ident(name); + let phantom = quote_ty!(ctx.ext_cx(), + ::std::marker::PhantomData<$ident>); let field = - StructFieldBuilder::named(format!("_phantom_{}", i)).pub_() - .build_ty(quote_ty!(ctx.ext_cx(), ::std::marker::PhantomData<$ident>)); + StructFieldBuilder::named(format!("_phantom_{}", i)) + .pub_() + .build_ty(phantom); fields.push(field) } } @@ -972,16 +986,18 @@ impl CodeGenerator for CompInfo { // affect layout, so we're bad and pray to the gods for avoid sending // all the tests to shit when parsing things like max_align_t. if self.found_unknown_attr() { - warn!("Type {} has an unkown attribute that may affect layout", canonical_name); + warn!("Type {} has an unkown attribute that may affect layout", + canonical_name); } + if applicable_template_args.is_empty() && !self.found_unknown_attr() { for var in self.inner_vars() { ctx.resolve_item(*var).codegen(ctx, result, &()); } if let Some(layout) = layout { - let fn_name = - ctx.rust_ident_raw(&format!("bindgen_test_layout_{}", canonical_name)); + let fn_name = format!("bindgen_test_layout_{}", canonical_name); + let fn_name = ctx.rust_ident_raw(&fn_name); let ident = ctx.rust_ident_raw(&canonical_name); let size_of_expr = quote_expr!(ctx.ext_cx(), ::std::mem::size_of::<$ident>()); @@ -1107,6 +1123,7 @@ impl MethodCodegen for Method { }; assert!(!fndecl.inputs.is_empty()); + // FIXME: use aster here. fndecl.inputs[0] = ast::Arg { ty: P(ast::Ty { @@ -1123,9 +1140,11 @@ impl MethodCodegen for Method { }), pat: P(ast::Pat { id: ast::DUMMY_NODE_ID, - node: ast::PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Immutable), - respan(ctx.span(), ctx.ext_cx().ident_of("self")), - None), + node: ast::PatKind::Ident( + ast::BindingMode::ByValue(ast::Mutability::Immutable), + respan(ctx.span(), ctx.ext_cx().ident_of("self")), + None + ), span: ctx.span(), }), id: ast::DUMMY_NODE_ID, @@ -1223,7 +1242,8 @@ impl CodeGenerator for Enum { } } None => { - warn!("Guessing type of enum! Forward declarations of enums shouldn't be legal!"); + warn!("Guessing type of enum! Forward declarations of enums \ + shouldn't be legal!"); IntKind::Int } }; @@ -1272,8 +1292,7 @@ impl CodeGenerator for Enum { // Only to avoid recomputing every time. enum_canonical_name: &str, // May be the same as "variant" if it's because the - // enum - // is unnamed and we still haven't seen the value. + // enum is unnamed and we still haven't seen the value. variant_name: &str, referenced_name: &str, enum_rust_ty: P<ast::Ty>, @@ -1342,9 +1361,11 @@ impl CodeGenerator for Enum { .canonical_name(ctx)); } + let parent_name = parent_canonical_name.as_ref() + .unwrap(); + Cow::Owned( - format!("{}_{}", parent_canonical_name.as_ref().unwrap(), - variant_name)) + format!("{}_{}", parent_name, variant_name)) }; add_constant(enum_ty, @@ -1464,13 +1485,15 @@ impl ToRustTy for Type { let mut inner_ty = inner.to_rust_ty(ctx).unwrap(); if let ast::TyKind::Path(_, ref mut path) = inner_ty.node { + let template_args = template_args.iter() + .map(|arg| arg.to_rust_ty(ctx)) + .collect(); + path.segments.last_mut().unwrap().parameters = ast::PathParameters::AngleBracketed( ast::AngleBracketedParameterData { lifetimes: vec![], - types: P::from_vec(template_args.iter().map(|arg| { - arg.to_rust_ty(ctx) - }).collect()), + types: P::from_vec(template_args), bindings: P::from_vec(vec![]), } ); @@ -1498,7 +1521,8 @@ impl ToRustTy for Type { Some(layout) => BlobTyBuilder::new(layout).build(), None => { warn!("Couldn't compute layout for a type with non \ - type template params or opaque, expect dragons!"); + type template params or opaque, expect \ + dragons!"); aster::AstBuilder::new().ty().unit() } }; @@ -1558,11 +1582,14 @@ impl ToRustTy for FunctionSig { let arg_item = ctx.resolve_item(ty); let arg_ty = arg_item.kind().expect_type(); - // From the C90 standard (http://c0x.coding-guidelines.com/6.7.5.3.html) - // 1598 - A declaration of a parameter as “array of type” shall be - // adjusted to “qualified pointer to type”, where the type qualifiers - // (if any) are those specified within the [ and ] of the array type - // derivation. + // From the C90 standard[1]: + // + // A declaration of a parameter as "array of type" shall be + // adjusted to "qualified pointer to type", where the type + // qualifiers (if any) are those specified within the [ and ] of + // the array type derivation. + // + // [1]: http://c0x.coding-guidelines.com/6.7.5.3.html let arg_ty = if let TypeKind::Array(t, _) = *arg_ty.kind() { t.to_rust_ty(ctx).to_ptr(arg_ty.is_const(), ctx.span()) } else { @@ -1678,8 +1705,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { context.options().whitelisted_vars.is_empty() { for (_item_id, item) in context.items() { // Non-toplevel item parents are the responsible one for - // generating - // them. + // generating them. if item.is_toplevel(context) { item.codegen(context, &mut result, &()); } diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 27094003..d55c24ca 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -275,22 +275,20 @@ impl CompInfo { self.detect_derive_debug_cycle.set(true); - let can_derive_debug = self.base_members.iter().all(|ty| { - ctx.resolve_type(*ty) - .can_derive_debug(ctx) - }) && - self.template_args.iter().all(|ty| { - ctx.resolve_type(*ty) - .can_derive_debug(ctx) - }) && - self.fields.iter().all(|field| { - ctx.resolve_type(field.ty) - .can_derive_debug(ctx) - }) && - self.ref_template.map_or(true, |template| { - ctx.resolve_type(template) - .can_derive_debug(ctx) - }); + let can_derive_debug = { + self.base_members + .iter() + .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) && + self.template_args + .iter() + .all(|ty| ctx.resolve_type(*ty).can_derive_debug(ctx)) && + self.fields + .iter() + .all(|f| ctx.resolve_type(f.ty).can_derive_debug(ctx)) && + self.ref_template.map_or(true, |template| { + ctx.resolve_type(template).can_derive_debug(ctx) + }) + }; self.detect_derive_debug_cycle.set(false); @@ -301,9 +299,7 @@ impl CompInfo { pub fn is_unsized(&self, ctx: &BindgenContext) -> bool { !self.has_vtable(ctx) && self.fields.is_empty() && self.base_members.iter().all(|base| { - ctx.resolve_type(*base) - .canonical_type(ctx) - .is_unsized(ctx) + ctx.resolve_type(*base).canonical_type(ctx).is_unsized(ctx) }) && self.ref_template .map_or(true, |template| ctx.resolve_type(template).is_unsized(ctx)) @@ -521,7 +517,7 @@ impl CompInfo { let mut maybe_anonymous_struct_field = None; cursor.visit(|cur, _other| { if cur.kind() != CXCursor_FieldDecl { - if let Some((ty, ref _clang_ty)) = maybe_anonymous_struct_field { + if let Some((ty, _)) = maybe_anonymous_struct_field { let field = Field::new(None, ty, None, None, None, false); ci.fields.push(field); } @@ -540,16 +536,24 @@ impl CompInfo { CXChildVisit_Continue }); if !used { - let field = Field::new(None, ty, None, None, None, false); + let field = Field::new(None, + ty, + None, + None, + None, + false); ci.fields.push(field); } - }, + } None => {} } let bit_width = cur.bit_width(); - let field_type = - Item::from_ty_or_ref(cur.cur_type(), Some(*cur), Some(potential_id), ctx); + let field_type = Item::from_ty_or_ref(cur.cur_type(), + Some(*cur), + Some(potential_id), + ctx); + let comment = cur.raw_comment(); let annotations = Annotations::new(cur); let name = cur.spelling(); @@ -562,8 +566,12 @@ impl CompInfo { let name = if name.is_empty() { None } else { Some(name) }; - let field = Field::new(name, field_type, comment, - annotations, bit_width, is_mutable); + let field = Field::new(name, + field_type, + comment, + annotations, + bit_width, + is_mutable); ci.fields.push(field); // No we look for things like attributes and stuff. @@ -586,14 +594,16 @@ impl CompInfo { CXCursor_ClassTemplate | CXCursor_ClassDecl => { let inner = Item::parse(*cur, Some(potential_id), ctx) - .expect("Inner ClassDecl"); + .expect("Inner ClassDecl"); if !ci.inner_types.contains(&inner) { ci.inner_types.push(inner); } // A declaration of an union or a struct without name could // also be an unnamed field, unfortunately. - if cur.spelling().is_empty() && cur.kind() != CXCursor_EnumDecl { - maybe_anonymous_struct_field = Some((inner, cur.cur_type())); + if cur.spelling().is_empty() && + cur.kind() != CXCursor_EnumDecl { + let ty = cur.cur_type(); + maybe_anonymous_struct_field = Some((inner, ty)); } } CXCursor_PackedAttr => { @@ -608,18 +618,24 @@ impl CompInfo { return CXChildVisit_Continue; } - let default_type = - Item::from_ty(&cur.cur_type(), Some(*cur), Some(potential_id), ctx).ok(); - let param = Item::named_type(cur.spelling(), default_type, - potential_id, ctx); + let default_type = Item::from_ty(&cur.cur_type(), + Some(*cur), + Some(potential_id), + ctx) + .ok(); + let param = Item::named_type(cur.spelling(), + default_type, + potential_id, + ctx); ci.template_args.push(param); } CXCursor_CXXBaseSpecifier => { if !ci.has_vtable { ci.has_vtable = cur.is_virtual_base(); } - let type_id = Item::from_ty(&cur.cur_type(), None, None, ctx) - .expect("BaseSpecifier"); + let type_id = + Item::from_ty(&cur.cur_type(), None, None, ctx) + .expect("BaseSpecifier"); ci.base_members.push(type_id); } CXCursor_CXXMethod => { @@ -668,9 +684,12 @@ impl CompInfo { return CXChildVisit_Continue; } - // NB: This gets us an owned `Function`, not a `FunctionSig`. - let method_signature = Item::parse(*cur, Some(potential_id), ctx) - .expect("CXXMethod"); + // NB: This gets us an owned `Function`, not a + // `FunctionSig`. + let method_signature = + Item::parse(*cur, Some(potential_id), ctx) + .expect("CXXMethod"); + let is_const = cur.method_is_const(); let method_kind = if is_static { MethodKind::Static @@ -679,7 +698,11 @@ impl CompInfo { } else { MethodKind::Normal }; - ci.methods.push(Method::new(method_kind, method_signature, is_const)); + + let method = + Method::new(method_kind, method_signature, is_const); + + ci.methods.push(method); } CXCursor_Destructor => { if cur.method_is_virtual() { @@ -693,7 +716,8 @@ impl CompInfo { } CXCursor_VarDecl => { let linkage = cur.linkage(); - if linkage != CXLinkage_External && linkage != CXLinkage_UniqueExternal { + if linkage != CXLinkage_External && + linkage != CXLinkage_UniqueExternal { return CXChildVisit_Continue; } @@ -703,7 +727,7 @@ impl CompInfo { } let item = Item::parse(*cur, Some(potential_id), ctx) - .expect("VarDecl"); + .expect("VarDecl"); ci.inner_vars.push(item); } // Intentionally not handled @@ -713,8 +737,10 @@ impl CompInfo { CXCursor_FunctionTemplate | CXCursor_ConversionFunction => {} _ => { - warn!("unhandled composite member `{}` (kind {}) in `{}` ({})", - cur.spelling(), cur.kind(), cursor.spelling(), + warn!("unhandled comp member `{}` (kind {}) in `{}` ({})", + cur.spelling(), + cur.kind(), + cursor.spelling(), cur.location()); } } diff --git a/src/ir/context.rs b/src/ir/context.rs index 5e29e0c9..273dc3e3 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -105,10 +105,15 @@ impl<'ctx> BindgenContext<'ctx> { let index = clang::Index::new(false, true); + let parse_options = + clangll::CXTranslationUnit_DetailedPreprocessingRecord; let translation_unit = - clang::TranslationUnit::parse(&index, "", &options.clang_args, &[], - clangll::CXTranslationUnit_DetailedPreprocessingRecord) - .expect("null TranslationUnit received from `clang::TranslationUnit::parse`"); + clang::TranslationUnit::parse(&index, + "", + &options.clang_args, + &[], + parse_options) + .expect("TranslationUnit::parse"); let root_module = Self::build_root_module(); let mut me = BindgenContext { @@ -531,7 +536,8 @@ impl<'ctx> BindgenContext<'ctx> { // That being said, this is not so common, so just error! and hope // for the best, returning the previous type, who knows. if old_args.len() != args.len() { - error!("Found partial template specialization, expect dragons!"); + error!("Found partial template specialization, \ + expect dragons!"); return wrapping; } diff --git a/src/ir/item.rs b/src/ir/item.rs index 6857bc70..4e893e35 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -80,10 +80,10 @@ impl TypeCollector for ItemId { type Extra = (); fn collect_types(&self, - context: &BindgenContext, + ctx: &BindgenContext, types: &mut ItemSet, extra: &()) { - context.resolve_item(*self).collect_types(context, types, extra); + ctx.resolve_item(*self).collect_types(ctx, types, extra); } } @@ -91,18 +91,18 @@ impl TypeCollector for Item { type Extra = (); fn collect_types(&self, - context: &BindgenContext, + ctx: &BindgenContext, types: &mut ItemSet, _extra: &()) { - if self.is_hidden(context) || types.contains(&self.id()) { + if self.is_hidden(ctx) || 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); + if !self.is_opaque(ctx) { + ty.collect_types(ctx, types, self); } } _ => {} // FIXME. @@ -329,8 +329,7 @@ impl Item { /// Normally we could do this check just in the `Type` kind, but we also /// need to check the `applicable_template_args` more generally, since we /// could need a type transitively from our parent, see the test added in - /// <https://github. - /// com/servo/rust-bindgen/pull/85/commits/2a3f93074dd2898669dbbce6e97e5cc4405d7cb1> + /// commit 2a3f93074dd2898669dbbce6e97e5cc4405d7cb1. /// /// It's kind of unfortunate (in the sense that it's a sort of complex /// process), but I think it should get all the cases. @@ -498,9 +497,12 @@ impl Item { let base_name = match *self.kind() { ItemKind::Type(ref ty) => { match *ty.kind() { - // If we're a template specialization, our name is our parent's - TypeKind::Comp(ref ci) if ci.is_template_specialization() => { - return ci.specialized_template().unwrap().canonical_name(ctx); + // If we're a template specialization, our name is our + // parent's. + TypeKind::Comp(ref ci) + if ci.is_template_specialization() => { + return ci.specialized_template().unwrap() + .canonical_name(ctx); }, // Same as above TypeKind::ResolvedTypeRef(inner) | @@ -524,7 +526,10 @@ impl Item { // would be needed. TypeKind::TemplateAlias(inner, _) => { if for_name_checking { - return ctx.resolve_item(inner).real_canonical_name(ctx, count_namespaces, false); + return ctx.resolve_item(inner) + .real_canonical_name(ctx, + count_namespaces, + false); } Some("") } @@ -608,8 +613,11 @@ impl Item { ctx: &BindgenContext) -> String { lazy_static! { - 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(); + 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() { @@ -687,7 +695,7 @@ impl ClangItemParser for Item { fn parse(cursor: clang::Cursor, parent_id: Option<ItemId>, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> Result<ItemId, ParseError> { use ir::function::Function; use ir::module::Module; @@ -701,15 +709,18 @@ impl ClangItemParser for Item { let comment = cursor.raw_comment(); let annotations = Annotations::new(&cursor); - let current_module = context.current_module(); + let current_module = ctx.current_module(); + let relevant_parent_id = parent_id.unwrap_or(current_module); + macro_rules! try_parse { ($what:ident) => { - match $what::parse(cursor, context) { + match $what::parse(cursor, ctx) { Ok(ParseResult::New(item, declaration)) => { let id = ItemId::next(); - context.add_item(Item::new(id, comment, annotations, - parent_id.unwrap_or(current_module), - ItemKind::$what(item)), + + ctx.add_item(Item::new(id, comment, annotations, + relevant_parent_id, + ItemKind::$what(item)), declaration, Some(cursor)); return Ok(id); @@ -747,7 +758,7 @@ impl ClangItemParser for Item { match Self::from_ty(&applicable_cursor.cur_type(), Some(applicable_cursor), parent_id, - context) { + ctx) { Ok(ty) => return Ok(ty), Err(ParseError::Recurse) => return Err(ParseError::Recurse), Err(ParseError::Continue) => {} @@ -781,13 +792,13 @@ impl ClangItemParser for Item { fn from_ty_or_ref(ty: clang::Type, location: Option<clang::Cursor>, parent_id: Option<ItemId>, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> ItemId { Self::from_ty_or_ref_with_id(ItemId::next(), ty, location, parent_id, - context) + ctx) } /// Parse a C++ type. If we find a reference to a type that has not been @@ -804,7 +815,7 @@ impl ClangItemParser for Item { ty: clang::Type, location: Option<clang::Cursor>, parent_id: Option<ItemId>, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> ItemId { debug!("from_ty_or_ref_with_id: {:?} {:?}, {:?}, {:?}", potential_id, @@ -812,19 +823,19 @@ impl ClangItemParser for Item { location, parent_id); - if context.collected_typerefs() { + if ctx.collected_typerefs() { debug!("refs already collected, resolving directly"); return Self::from_ty_with_id(potential_id, &ty, location, parent_id, - context) + ctx) .expect("Unable to resolve type"); } - if let Some(ty) = context.builtin_or_resolved_ty(potential_id, - parent_id, &ty, - location) { + if let Some(ty) = ctx.builtin_or_resolved_ty(potential_id, + parent_id, &ty, + location) { debug!("{:?} already resolved: {:?}", ty, location); return ty; } @@ -833,17 +844,17 @@ impl ClangItemParser for Item { let is_const = ty.is_const(); let kind = TypeKind::UnresolvedTypeRef(ty, location, parent_id); - let current_module = context.current_module(); - context.add_item(Item::new(potential_id, - None, - None, - parent_id.unwrap_or(current_module), - ItemKind::Type(Type::new(None, - None, - kind, - is_const))), - Some(clang::Cursor::null()), - None); + let current_module = ctx.current_module(); + ctx.add_item(Item::new(potential_id, + None, + None, + parent_id.unwrap_or(current_module), + ItemKind::Type(Type::new(None, + None, + kind, + is_const))), + Some(clang::Cursor::null()), + None); potential_id } @@ -851,9 +862,9 @@ impl ClangItemParser for Item { fn from_ty(ty: &clang::Type, location: Option<clang::Cursor>, parent_id: Option<ItemId>, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> Result<ItemId, ParseError> { - Self::from_ty_with_id(ItemId::next(), ty, location, parent_id, context) + Self::from_ty_with_id(ItemId::next(), ty, location, parent_id, ctx) } /// This is one of the trickiest methods you'll find (probably along with @@ -868,7 +879,7 @@ impl ClangItemParser for Item { ty: &clang::Type, location: Option<clang::Cursor>, parent_id: Option<ItemId>, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> Result<ItemId, ParseError> { use clangll::*; @@ -887,13 +898,14 @@ impl ClangItemParser for Item { let annotations = Annotations::new(&decl) .or_else(|| location.as_ref().and_then(|l| Annotations::new(l))); - if let Some(ref replaced) = annotations.as_ref() - .and_then(|a| a.use_instead_of()) { - context.replace(replaced, id); + if let Some(ref annotations) = annotations { + if let Some(ref replaced) = annotations.use_instead_of() { + ctx.replace(replaced, id); + } } if let Some(ty) = - context.builtin_or_resolved_ty(id, parent_id, ty, location) { + ctx.builtin_or_resolved_ty(id, parent_id, ty, location) { return Ok(ty); } @@ -911,7 +923,7 @@ impl ClangItemParser for Item { }; if valid_decl { - if let Some(&(_, item_id)) = context.currently_parsed_types + if let Some(&(_, item_id)) = ctx.currently_parsed_types .iter() .find(|&&(d, _)| d == declaration_to_look_for) { debug!("Avoiding recursion parsing type: {:?}", ty); @@ -919,22 +931,23 @@ impl ClangItemParser for Item { } } - let current_module = context.current_module(); + let current_module = ctx.current_module(); if valid_decl { - context.currently_parsed_types.push((declaration_to_look_for, id)); + ctx.currently_parsed_types.push((declaration_to_look_for, id)); } - let result = Type::from_clang_ty(id, ty, location, parent_id, context); + let result = Type::from_clang_ty(id, ty, location, parent_id, ctx); + let relevant_parent_id = parent_id.unwrap_or(current_module); let ret = match result { Ok(ParseResult::AlreadyResolved(ty)) => Ok(ty), Ok(ParseResult::New(item, declaration)) => { - context.add_item(Item::new(id, - comment, - annotations, - parent_id.unwrap_or(current_module), - ItemKind::Type(item)), - declaration, - location); + ctx.add_item(Item::new(id, + comment, + annotations, + relevant_parent_id, + ItemKind::Type(item)), + declaration, + location); Ok(id) } Err(ParseError::Continue) => Err(ParseError::Continue), @@ -949,7 +962,7 @@ impl ClangItemParser for Item { // logic with ir::context, so we should refactor that. if valid_decl { let (popped_decl, _) = - context.currently_parsed_types.pop().unwrap(); + ctx.currently_parsed_types.pop().unwrap(); assert_eq!(popped_decl, declaration_to_look_for); } @@ -959,7 +972,7 @@ impl ClangItemParser for Item { ty, Some(*cur), parent_id, - context); + ctx); match result { Ok(..) => CXChildVisit_Break, Err(ParseError::Recurse) => CXChildVisit_Recurse, @@ -968,7 +981,7 @@ impl ClangItemParser for Item { }); if valid_decl { - context.currently_parsed_types + ctx.currently_parsed_types .push((declaration_to_look_for, id)); } } @@ -982,10 +995,11 @@ impl ClangItemParser for Item { // It's harmless, but if we restrict that, then // tests/headers/nsStyleAutoArray.hpp crashes. if let Err(ParseError::Recurse) = result { - Ok(Self::named_type_with_id(id, ty.spelling(), + Ok(Self::named_type_with_id(id, + ty.spelling(), None, - parent_id.unwrap_or(context.current_module()), - context)) + relevant_parent_id, + ctx)) } else { result } @@ -993,8 +1007,7 @@ impl ClangItemParser for Item { }; if valid_decl { - let (popped_decl, _) = - context.currently_parsed_types.pop().unwrap(); + let (popped_decl, _) = ctx.currently_parsed_types.pop().unwrap(); assert_eq!(popped_decl, declaration_to_look_for); } @@ -1012,7 +1025,7 @@ impl ClangItemParser for Item { name: S, default: Option<ItemId>, parent_id: ItemId, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> ItemId where S: Into<String>, { @@ -1020,13 +1033,13 @@ impl ClangItemParser for Item { // and tests/headers/variadic_tname.hpp let name = name.into().replace("const ", "").replace(".", ""); - context.add_item(Item::new(id, - None, - None, - parent_id, - ItemKind::Type(Type::named(name, default))), - None, - None); + ctx.add_item(Item::new(id, + None, + None, + parent_id, + ItemKind::Type(Type::named(name, default))), + None, + None); id } @@ -1034,15 +1047,11 @@ impl ClangItemParser for Item { fn named_type<S>(name: S, default: Option<ItemId>, parent_id: ItemId, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> ItemId where S: Into<String>, { - Self::named_type_with_id(ItemId::next(), - name, - default, - parent_id, - context) + Self::named_type_with_id(ItemId::next(), name, default, parent_id, ctx) } } diff --git a/src/ir/ty.rs b/src/ir/ty.rs index bab50024..4d26cdff 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -460,7 +460,7 @@ impl Type { TypeKind::Pointer(..) => false, TypeKind::UnresolvedTypeRef(..) => { - unreachable!("Should have been resolved after parsing!") + unreachable!("Should have been resolved after parsing!"); } } } @@ -477,17 +477,26 @@ impl Type { ctx: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> { use clangll::*; - if let Some(ty) = - ctx.builtin_or_resolved_ty(potential_id, parent_id, ty, location) { - debug!("{:?} already resolved: {:?}", ty, location); - return Ok(ParseResult::AlreadyResolved(ty)); + { + let already_resolved = + ctx.builtin_or_resolved_ty(potential_id, + parent_id, + ty, + location); + if let Some(ty) = already_resolved { + debug!("{:?} already resolved: {:?}", ty, location); + return Ok(ParseResult::AlreadyResolved(ty)); + } } let layout = ty.fallible_layout().ok(); let cursor = ty.declaration(); let mut name = cursor.spelling(); - debug!("from_clang_ty: {:?}, ty: {:?}, loc: {:?}", potential_id, ty, location); + debug!("from_clang_ty: {:?}, ty: {:?}, loc: {:?}", + potential_id, + ty, + location); debug!("currently_parsed_types: {:?}", ctx.currently_parsed_types); let canonical_ty = ty.canonical_type(); @@ -502,19 +511,17 @@ impl Type { ctx); } CXType_Unexposed | CXType_Invalid => { - // For some reason Clang doesn't give us any hint - // in some situations where we should generate a - // function pointer (see - // tests/headers/func_ptr_in_struct.h), so we do a - // guess here trying to see if it has a valid return - // type. + // For some reason Clang doesn't give us any hint in some + // situations where we should generate a function pointer (see + // tests/headers/func_ptr_in_struct.h), so we do a guess here + // trying to see if it has a valid return type. if ty.ret_type().is_some() { - let signature = - try!(FunctionSig::from_ty(ty, &location.unwrap_or(cursor), ctx)); + let signature = try!(FunctionSig::from_ty(ty, + &location.unwrap_or(cursor), + ctx)); TypeKind::Function(signature) // Same here, with template specialisations we can safely - // assume - // this is a Comp(..) + // assume this is a Comp(..) } else if ty.template_args().map_or(false, |x| x.len() > 0) { debug!("Template specialization: {:?}", ty); let complex = @@ -543,11 +550,13 @@ impl Type { location.visit(|cur, _| { match cur.kind() { CXCursor_TypeAliasDecl => { - debug_assert!(cur.cur_type().kind() == CXType_Typedef); - inner = Item::from_ty(&cur.cur_type(), - Some(*cur), - Some(potential_id), - ctx); + debug_assert!(cur.cur_type().kind() == + CXType_Typedef); + inner = + Item::from_ty(&cur.cur_type(), + Some(*cur), + Some(potential_id), + ctx); } CXCursor_TemplateTypeParameter => { // See the comment in src/ir/comp.rs @@ -560,11 +569,13 @@ impl Type { Item::from_ty(&cur.cur_type(), Some(*cur), Some(potential_id), - ctx).ok(); + ctx) + .ok(); let param = Item::named_type(cur.spelling(), default_type, - potential_id, ctx); + potential_id, + ctx); args.push(param); } _ => {} @@ -573,7 +584,8 @@ impl Type { }); if inner.is_err() { - error!("Failed to parse templated type alias {:?}", location); + error!("Failed to parse templated alias {:?}", + location); return Err(ParseError::Continue); } @@ -592,24 +604,37 @@ impl Type { } CXCursor_TemplateRef => { let referenced = location.referenced(); + let referenced_ty = referenced.cur_type(); + let referenced_declaration = + Some(referenced_ty.declaration()); + return Self::from_clang_ty(potential_id, - &referenced.cur_type(), - Some(referenced.cur_type().declaration()), + &referenced_ty, + referenced_declaration, parent_id, ctx); } CXCursor_TypeRef => { let referenced = location.referenced(); - return Ok(ParseResult::AlreadyResolved( - Item::from_ty_or_ref_with_id(potential_id, - referenced.cur_type(), - Some(referenced.cur_type().declaration()), - parent_id, - ctx))); + let referenced_ty = referenced.cur_type(); + let referenced_declaration = + Some(referenced_ty.declaration()); + + let item = + Item::from_ty_or_ref_with_id( + potential_id, + referenced_ty, + referenced_declaration, + parent_id, + ctx); + return Ok(ParseResult::AlreadyResolved(item)); } _ => { if ty.kind() == CXType_Unexposed { - warn!("Unexposed type {:?}, recursing inside, loc: {:?}", ty, location); + warn!("Unexposed type {:?}, recursing inside, \ + loc: {:?}", + ty, + location); return Err(ParseError::Recurse); } @@ -643,16 +668,12 @@ impl Type { return Err(ParseError::Continue); } } - // NOTE: We don't resolve pointers eagerly because the - // pointee type - // might not have been parsed, and if it contains templates - // or - // something else we might get confused, see the comment - // inside + // NOTE: We don't resolve pointers eagerly because the pointee type + // might not have been parsed, and if it contains templates or + // something else we might get confused, see the comment inside // TypeRef. // - // We might need to, though, if the context is already in - // the + // We might need to, though, if the context is already in the // process of resolving them. CXType_MemberPointer | CXType_Pointer => { @@ -663,8 +684,7 @@ impl Type { TypeKind::Pointer(inner) } CXType_BlockPointer => TypeKind::BlockPointer, - // XXX: RValueReference is most likely wrong, but I don't - // think we + // XXX: RValueReference is most likely wrong, but I don't think we // can even add bindings for that, so huh. CXType_RValueReference | CXType_LValueReference => { @@ -678,19 +698,18 @@ impl Type { CXType_VariableArray | CXType_DependentSizedArray | CXType_IncompleteArray => { - let inner = - Item::from_ty(ty.elem_type() - .as_ref() - .expect("Not an appropriate type?"), - location, - parent_id, - ctx) - .expect("Not able to resolve array element?"); + let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(), + location, + parent_id, + ctx) + .expect("Not able to resolve array element?"); TypeKind::Pointer(inner) } CXType_FunctionNoProto | CXType_FunctionProto => { - let signature = try!(FunctionSig::from_ty(ty, &location.unwrap_or(cursor), ctx)); + let signature = try!(FunctionSig::from_ty(ty, + &location.unwrap_or(cursor), + ctx)); TypeKind::Function(signature) } CXType_Typedef => { @@ -709,37 +728,29 @@ impl Type { .expect("Not a complex type?"); TypeKind::Comp(complex) } - // FIXME: We stub vectors as arrays since in 99% of the - // cases the - // layout is going to be correct, and there's no way we can - // generate + // FIXME: We stub vectors as arrays since in 99% of the cases the + // layout is going to be correct, and there's no way we can generate // vector types properly in Rust for now. // // That being said, that should be fixed eventually. CXType_Vector | CXType_ConstantArray => { - let inner = - Item::from_ty(ty.elem_type() - .as_ref() - .expect("Not an appropriate type?"), - location, - parent_id, - ctx) - .expect("Not able to resolve array element?"); + let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(), + location, + parent_id, + ctx) + .expect("Not able to resolve array element?"); TypeKind::Array(inner, ty.num_elements().unwrap()) } // A complex number is always a real and an imaginary part, // so // represent that as a two-item array. CXType_Complex => { - let inner = - Item::from_ty(ty.elem_type() - .as_ref() - .expect("Not an appropriate type?"), - location, - parent_id, - ctx) - .expect("Not able to resolve array element?"); + let inner = Item::from_ty(ty.elem_type().as_ref().unwrap(), + location, + parent_id, + ctx) + .expect("Not able to resolve array element?"); TypeKind::Array(inner, 2) } #[cfg(not(feature="llvm_stable"))] diff --git a/src/ir/var.rs b/src/ir/var.rs index 6d9b61e1..216d8185 100644 --- a/src/ir/var.rs +++ b/src/ir/var.rs @@ -70,14 +70,17 @@ impl Var { impl ClangSubItemParser for Var { fn parse(cursor: clang::Cursor, - context: &mut BindgenContext) + ctx: &mut BindgenContext) -> Result<ParseResult<Self>, ParseError> { use clangll::*; match cursor.kind() { CXCursor_MacroDefinition => { - let value = match parse_int_literal_tokens(&cursor, context.translation_unit()) { - None => return Err(ParseError::Continue), + let value = parse_int_literal_tokens(&cursor, + ctx.translation_unit()); + + let value = match value { Some(v) => v, + None => return Err(ParseError::Continue), }; let name = cursor.spelling(); @@ -86,24 +89,20 @@ impl ClangSubItemParser for Var { return Err(ParseError::Continue); } - if context.parsed_macro(&name) { + if ctx.parsed_macro(&name) { warn!("Duplicated macro definition: {}", name); return Err(ParseError::Continue); } - context.note_parsed_macro(name.clone()); + ctx.note_parsed_macro(name.clone()); let ty = if value < 0 { - Item::builtin_type(TypeKind::Int(IntKind::Int), - true, - context) + Item::builtin_type(TypeKind::Int(IntKind::Int), true, ctx) } else if value.abs() > u32::max_value() as i64 { Item::builtin_type(TypeKind::Int(IntKind::ULongLong), true, - context) + ctx) } else { - Item::builtin_type(TypeKind::Int(IntKind::UInt), - true, - context) + Item::builtin_type(TypeKind::Int(IntKind::UInt), true, ctx) }; Ok(ParseResult::New(Var::new(name, @@ -125,20 +124,19 @@ impl ClangSubItemParser for Var { // XXX this is redundant, remove! let is_const = ty.is_const(); - let ty = Item::from_ty(&ty, Some(cursor), None, context) + let ty = Item::from_ty(&ty, Some(cursor), None, ctx) .expect("Unable to resolve constant type?"); // Note: Ty might not be totally resolved yet, see // tests/headers/inner_const.hpp // // That's fine because in that case we know it's not a literal. - let value = context.safe_resolve_type(ty) - .and_then(|t| t.safe_canonical_type(context)).and_then(|t| { - if t.is_integer() { - get_integer_literal_from_cursor(&cursor, context.translation_unit()) - } else { - None - } + let value = ctx.safe_resolve_type(ty) + .and_then(|t| t.safe_canonical_type(ctx)) + .and_then(|t| if t.is_integer() { Some(t) } else { None }) + .and_then(|_| { + get_integer_literal_from_cursor(&cursor, + ctx.translation_unit()) }); let mangling = cursor_mangling(&cursor); |