diff options
Diffstat (limited to 'src/ir/item.rs')
-rw-r--r-- | src/ir/item.rs | 135 |
1 files changed, 89 insertions, 46 deletions
diff --git a/src/ir/item.rs b/src/ir/item.rs index 4541504..8692575 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -4,7 +4,7 @@ use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME}; use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult}; use super::annotations::Annotations; use super::comment; -use super::comp::MethodKind; +use super::comp::{CompKind, MethodKind}; use super::context::{BindgenContext, ItemId, PartialType, TypeId}; use super::derive::{ CanDeriveCopy, CanDeriveDebug, CanDeriveDefault, CanDeriveEq, @@ -417,6 +417,8 @@ pub struct Item { parent_id: ItemId, /// The item kind. kind: ItemKind, + /// The source location of the item. + location: Option<clang::SourceLocation>, } impl AsRef<ItemId> for Item { @@ -433,18 +435,20 @@ impl Item { annotations: Option<Annotations>, parent_id: ItemId, kind: ItemKind, + location: Option<clang::SourceLocation>, ) -> Self { debug_assert!(id != parent_id || kind.is_module()); Item { - id: id, + id, local_id: LazyCell::new(), next_child_local_id: Cell::new(1), canonical_name: LazyCell::new(), path_for_allowlisting: LazyCell::new(), - parent_id: parent_id, - comment: comment, + parent_id, + comment, annotations: annotations.unwrap_or_default(), - kind: kind, + kind, + location, } } @@ -454,10 +458,15 @@ impl Item { ty: &clang::Type, ctx: &mut BindgenContext, ) -> TypeId { + let location = ty.declaration().location(); let ty = Opaque::from_clang_ty(ty, ctx); let kind = ItemKind::Type(ty); let parent = ctx.root_module().into(); - ctx.add_item(Item::new(with_id, None, None, parent, kind), None, None); + ctx.add_item( + Item::new(with_id, None, None, parent, kind, Some(location)), + None, + None, + ); with_id.as_type_id_unchecked() } @@ -612,10 +621,7 @@ impl Item { /// Is this item a module? pub fn is_module(&self) -> bool { - match self.kind { - ItemKind::Module(..) => true, - _ => false, - } + matches!(self.kind, ItemKind::Module(..)) } /// Get this item's annotations. @@ -635,13 +641,24 @@ impl Item { return true; } + if !ctx.options().blocklisted_files.is_empty() { + if let Some(location) = &self.location { + let (file, _, _, _) = location.location(); + if let Some(filename) = file.name() { + if ctx.options().blocklisted_files.matches(&filename) { + return true; + } + } + } + } + let path = self.path_for_allowlisting(ctx); let name = path[1..].join("::"); ctx.options().blocklisted_items.matches(&name) || match self.kind { ItemKind::Type(..) => { ctx.options().blocklisted_types.matches(&name) || - ctx.is_replaced_type(&path, self.id) + ctx.is_replaced_type(path, self.id) } ItemKind::Function(..) => { ctx.options().blocklisted_functions.matches(&name) @@ -658,10 +675,7 @@ impl Item { /// Is this item a var type? pub fn is_var(&self) -> bool { - match *self.kind() { - ItemKind::Var(..) => true, - _ => false, - } + matches!(*self.kind(), ItemKind::Var(..)) } /// Take out item NameOptions @@ -722,7 +736,7 @@ impl Item { .through_type_refs() .resolve(ctx) .push_disambiguated_name(ctx, to, level + 1); - to.push_str("_"); + to.push('_'); } to.push_str(&format!("close{}", level)); } @@ -835,7 +849,7 @@ impl Item { if ctx.options().enable_cxx_namespaces { return path.last().unwrap().clone(); } - return path.join("_").to_owned(); + return path.join("_"); } let base_name = target.base_name(ctx); @@ -873,7 +887,7 @@ impl Item { // If target is anonymous we need find its first named ancestor. if target.is_anon() { - while let Some(id) = ids_iter.next() { + for id in ids_iter.by_ref() { ids.push(id); if !ctx.resolve_item(id).is_anon() { @@ -904,6 +918,12 @@ impl Item { names.push(base_name); } + if ctx.options().c_naming { + if let Some(prefix) = self.c_naming_prefix() { + names.insert(0, prefix.to_string()); + } + } + let name = names.join("_"); let name = if opt.user_mangled == UserMangled::Yes { @@ -1054,6 +1074,23 @@ impl Item { path.reverse(); path } + + /// Returns a prefix for the canonical name when C naming is enabled. + fn c_naming_prefix(&self) -> Option<&str> { + let ty = match self.kind { + ItemKind::Type(ref ty) => ty, + _ => return None, + }; + + Some(match ty.kind() { + TypeKind::Comp(ref ci) => match ci.kind() { + CompKind::Struct => "struct", + CompKind::Union => "union", + }, + TypeKind::Enum(..) => "enum", + _ => return None, + }) + } } impl<T> IsOpaque for T @@ -1081,7 +1118,7 @@ impl IsOpaque for Item { ); self.annotations.opaque() || self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) || - ctx.opaque_by_name(&self.path_for_allowlisting(ctx)) + ctx.opaque_by_name(self.path_for_allowlisting(ctx)) } } @@ -1091,20 +1128,16 @@ where { fn has_vtable(&self, ctx: &BindgenContext) -> bool { let id: ItemId = (*self).into(); - id.as_type_id(ctx) - .map_or(false, |id| match ctx.lookup_has_vtable(id) { - HasVtableResult::No => false, - _ => true, - }) + id.as_type_id(ctx).map_or(false, |id| { + !matches!(ctx.lookup_has_vtable(id), HasVtableResult::No) + }) } fn has_vtable_ptr(&self, ctx: &BindgenContext) -> bool { let id: ItemId = (*self).into(); - id.as_type_id(ctx) - .map_or(false, |id| match ctx.lookup_has_vtable(id) { - HasVtableResult::SelfHasVtable => true, - _ => false, - }) + id.as_type_id(ctx).map_or(false, |id| { + matches!(ctx.lookup_has_vtable(id), HasVtableResult::SelfHasVtable) + }) } } @@ -1284,7 +1317,7 @@ impl ClangItemParser for Item { let id = ctx.next_item_id(); let module = ctx.root_module().into(); ctx.add_item( - Item::new(id, None, None, module, ItemKind::Type(ty)), + Item::new(id, None, None, module, ItemKind::Type(ty), None), None, None, ); @@ -1322,6 +1355,7 @@ impl ClangItemParser for Item { annotations, relevant_parent_id, ItemKind::$what(item), + Some(cursor.location()), ), declaration, Some(cursor), @@ -1369,7 +1403,7 @@ impl ClangItemParser for Item { } ctx.known_semantic_parent(definition) .or(parent_id) - .unwrap_or(ctx.current_module().into()) + .unwrap_or_else(|| ctx.current_module().into()) } None => relevant_parent_id, }; @@ -1415,9 +1449,7 @@ impl ClangItemParser for Item { ); } Some(filename) => { - if let Some(cb) = ctx.parse_callbacks() { - cb.include_file(&filename) - } + ctx.include_file(filename); } } } @@ -1503,8 +1535,9 @@ impl ClangItemParser for Item { potential_id, None, None, - parent_id.unwrap_or(current_module.into()), + parent_id.unwrap_or_else(|| current_module.into()), ItemKind::Type(Type::new(None, None, kind, is_const)), + Some(location.location()), ), None, None, @@ -1560,9 +1593,21 @@ impl ClangItemParser for Item { } } + // Treat all types that are declared inside functions as opaque. The Rust binding + // won't be able to do anything with them anyway. + // + // (If we don't do this check here, we can have subtle logic bugs because we generally + // ignore function bodies. See issue #2036.) + if let Some(ref parent) = ty.declaration().fallible_semantic_parent() { + if FunctionKind::from_cursor(parent).is_some() { + debug!("Skipping type declared inside function: {:?}", ty); + return Ok(Item::new_opaque_type(id, ty, ctx)); + } + } + let decl = { - let decl = ty.declaration(); - decl.definition().unwrap_or(decl) + let canonical_def = ty.canonical_type().declaration().definition(); + canonical_def.unwrap_or_else(|| ty.declaration()) }; let comment = decl.raw_comment().or_else(|| location.raw_comment()); @@ -1570,7 +1615,7 @@ impl ClangItemParser for Item { Annotations::new(&decl).or_else(|| Annotations::new(&location)); if let Some(ref annotations) = annotations { - if let Some(ref replaced) = annotations.use_instead_of() { + if let Some(replaced) = annotations.use_instead_of() { ctx.replace(replaced, id); } } @@ -1624,6 +1669,7 @@ impl ClangItemParser for Item { annotations, relevant_parent_id, ItemKind::Type(item), + Some(location.location()), ), declaration, Some(location), @@ -1818,11 +1864,7 @@ impl ClangItemParser for Item { clang_sys::CXChildVisit_Continue }); - if let Some(def) = definition { - def - } else { - return None; - } + definition? }; assert!(is_template_with_spelling(&definition, &ty_spelling)); @@ -1856,6 +1898,7 @@ impl ClangItemParser for Item { None, parent, ItemKind::Type(Type::named(name)), + Some(location.location()), ); ctx.add_type_param(item, definition); Some(id.as_type_id_unchecked()) @@ -1906,7 +1949,7 @@ impl ItemCanonicalPath for Item { path.push(CONSTIFIED_ENUM_MODULE_REPR_NAME.into()); } - return path; + path } fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> { @@ -1939,8 +1982,8 @@ impl<'a> NameOptions<'a> { /// Construct a new `NameOptions` pub fn new(item: &'a Item, ctx: &'a BindgenContext) -> Self { NameOptions { - item: item, - ctx: ctx, + item, + ctx, within_namespaces: false, user_mangled: UserMangled::Yes, } |