aboutsummaryrefslogtreecommitdiff
path: root/src/ir/item.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/item.rs')
-rw-r--r--src/ir/item.rs135
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,
}