summaryrefslogtreecommitdiff
path: root/libbindgen
diff options
context:
space:
mode:
Diffstat (limited to 'libbindgen')
-rw-r--r--libbindgen/src/codegen/mod.rs13
-rw-r--r--libbindgen/src/ir/annotations.rs15
-rw-r--r--libbindgen/src/ir/context.rs100
-rw-r--r--libbindgen/src/ir/item.rs104
-rw-r--r--libbindgen/src/ir/ty.rs95
-rw-r--r--libbindgen/tests/expectations/tests/reparented_replacement.rs29
-rw-r--r--libbindgen/tests/expectations/tests/replace_template_alias.rs8
-rw-r--r--libbindgen/tests/expectations/tests/type_alias_template_specialized.rs2
-rw-r--r--libbindgen/tests/headers/reparented_replacement.hpp16
-rw-r--r--libbindgen/tests/headers/replace_template_alias.hpp2
-rw-r--r--libbindgen/tests/headers/whitelist-namespaces-basic.hpp2
11 files changed, 253 insertions, 133 deletions
diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs
index d2e2b96c..95a6f611 100644
--- a/libbindgen/src/codegen/mod.rs
+++ b/libbindgen/src/codegen/mod.rs
@@ -467,12 +467,9 @@ impl CodeGenerator for Type {
TypeKind::Comp(ref ci) => {
ci.codegen(ctx, result, whitelisted_items, item)
}
- // NB: The inner Alias will be generated and pick the correct
+ // NB: The code below will pick the correct
// applicable_template_args.
- TypeKind::TemplateAlias(inner, _) => {
- ctx.resolve_item(inner)
- .codegen(ctx, result, whitelisted_items, &())
- },
+ TypeKind::TemplateAlias(ref spelling, inner, _) |
TypeKind::Alias(ref spelling, inner) => {
let inner_item = ctx.resolve_item(inner);
let name = item.canonical_name(ctx);
@@ -1777,10 +1774,9 @@ impl ToRustTy for Type {
aster::ty::TyBuilder::new().array(len).build(inner)
}
TypeKind::Enum(..) => {
- let path = item.canonical_path(ctx);
+ let path = item.namespace_aware_canonical_path(ctx);
aster::AstBuilder::new().ty().path().ids(path).build()
}
- TypeKind::TemplateAlias(inner, ref template_args) |
TypeKind::TemplateRef(inner, ref template_args) => {
// PS: Sorry for the duplication here.
let mut inner_ty = inner.to_rust_ty(ctx).unwrap();
@@ -1803,6 +1799,7 @@ impl ToRustTy for Type {
P(inner_ty)
}
TypeKind::ResolvedTypeRef(inner) => inner.to_rust_ty(ctx),
+ TypeKind::TemplateAlias(ref spelling, inner, _) |
TypeKind::Alias(ref spelling, inner) => {
if item.is_opaque(ctx) {
// Pray if there's no available layout.
@@ -2141,7 +2138,7 @@ mod utils {
ctx: &BindgenContext,
only_named: bool)
-> P<ast::Ty> {
- let path = item.canonical_path(ctx);
+ let path = item.namespace_aware_canonical_path(ctx);
let builder = aster::AstBuilder::new().ty().path();
let template_args = if only_named {
diff --git a/libbindgen/src/ir/annotations.rs b/libbindgen/src/ir/annotations.rs
index 58308d6d..948dbc96 100644
--- a/libbindgen/src/ir/annotations.rs
+++ b/libbindgen/src/ir/annotations.rs
@@ -27,9 +27,9 @@ pub struct Annotations {
/// Whether this item should be hidden from the output. Only applies to
/// types.
hide: bool,
- /// Whether this type should be replaced by another. The name must be the
- /// canonical name that that type would get.
- use_instead_of: Option<String>,
+ /// Whether this type should be replaced by another. The name is a
+ /// namespace-aware path.
+ use_instead_of: Option<Vec<String>>,
/// Manually disable deriving copy/clone on this type. Only applies to
/// struct or union types.
disallow_copy: bool,
@@ -106,7 +106,7 @@ impl Annotations {
/// ```
///
/// That is, code for `Foo` is used to generate `Bar`.
- pub fn use_instead_of(&self) -> Option<&str> {
+ pub fn use_instead_of(&self) -> Option<&[String]> {
self.use_instead_of.as_ref().map(|s| &**s)
}
@@ -138,7 +138,12 @@ impl Annotations {
"opaque" => self.opaque = true,
"hide" => self.hide = true,
"nocopy" => self.disallow_copy = true,
- "replaces" => self.use_instead_of = Some(attr.value),
+ "replaces" => {
+ self.use_instead_of =
+ Some(attr.value.split("::")
+ .map(Into::into)
+ .collect())
+ },
"private" => {
self.private_fields = Some(attr.value != "false")
}
diff --git a/libbindgen/src/ir/context.rs b/libbindgen/src/ir/context.rs
index f832a5d2..1d658e7d 100644
--- a/libbindgen/src/ir/context.rs
+++ b/libbindgen/src/ir/context.rs
@@ -10,7 +10,7 @@ use std::collections::{HashMap, hash_map};
use std::collections::btree_map::{self, BTreeMap};
use std::fmt;
use super::int::IntKind;
-use super::item::Item;
+use super::item::{Item, ItemCanonicalPath};
use super::item_kind::ItemKind;
use super::module::Module;
use super::ty::{FloatKind, Type, TypeKind};
@@ -100,7 +100,7 @@ pub struct BindgenContext<'ctx> {
parsed_macros: HashMap<Vec<u8>, cexpr::expr::EvalResult>,
/// The active replacements collected from replaces="xxx" annotations.
- replacements: HashMap<String, ItemId>,
+ replacements: HashMap<Vec<String>, ItemId>,
collected_typerefs: bool,
@@ -172,7 +172,8 @@ impl<'ctx> BindgenContext<'ctx> {
declaration: Option<Cursor>,
location: Option<Cursor>) {
use clangll::{CXCursor_ClassTemplate,
- CXCursor_ClassTemplatePartialSpecialization};
+ CXCursor_ClassTemplatePartialSpecialization,
+ CXCursor_TypeAliasTemplateDecl};
debug!("BindgenContext::add_item({:?}, declaration: {:?}, loc: {:?}",
item,
declaration,
@@ -207,7 +208,8 @@ impl<'ctx> BindgenContext<'ctx> {
if let Some(location) = location {
if location.kind() == CXCursor_ClassTemplate ||
location.kind() ==
- CXCursor_ClassTemplatePartialSpecialization {
+ CXCursor_ClassTemplatePartialSpecialization ||
+ location.kind() == CXCursor_TypeAliasTemplateDecl {
declaration = location;
}
}
@@ -353,6 +355,10 @@ impl<'ctx> BindgenContext<'ctx> {
let mut replacements = vec![];
for (id, item) in self.items.iter() {
+ if item.annotations().use_instead_of().is_some() {
+ continue;
+ }
+
// Calls to `canonical_name` are expensive, so eagerly filter out
// items that cannot be replaced.
let ty = match item.kind().as_type() {
@@ -362,23 +368,13 @@ impl<'ctx> BindgenContext<'ctx> {
match *ty.kind() {
TypeKind::Comp(ref ci) if !ci.is_template_specialization() => {}
- TypeKind::TemplateAlias(_, _) |
- TypeKind::Alias(_, _) => {}
+ TypeKind::TemplateAlias(..) |
+ TypeKind::Alias(..) => {}
_ => continue,
}
- let in_namespace = self.options().enable_cxx_namespaces;
-
- let name = if in_namespace {
- item.name(self)
- .within_namespaces()
- .get()
- } else {
- item.name(self)
- .for_name_checking()
- .get()
- };
- let replacement = self.replacements.get(&name);
+ let path = item.canonical_path(self);
+ let replacement = self.replacements.get(&path[1..]);
if let Some(replacement) = replacement {
if replacement != id {
@@ -394,9 +390,33 @@ impl<'ctx> BindgenContext<'ctx> {
for (id, replacement) in replacements {
debug!("Replacing {:?} with {:?}", id, replacement);
- let mut item = self.items.get_mut(&id).unwrap();
- *item.kind_mut().as_type_mut().unwrap().kind_mut() =
- TypeKind::ResolvedTypeRef(replacement);
+ let new_parent = {
+ let mut item = self.items.get_mut(&id).unwrap();
+ *item.kind_mut().as_type_mut().unwrap().kind_mut() =
+ TypeKind::ResolvedTypeRef(replacement);
+ item.parent_id()
+ };
+
+
+ // Reparent the item.
+ let old_parent = self.resolve_item(replacement).parent_id();
+
+ if new_parent == old_parent {
+ continue;
+ }
+
+ if let Some(mut module) = self.items.get_mut(&old_parent).unwrap().as_module_mut() {
+ // Deparent the replacement.
+ let position = module.children().iter().position(|id| *id == replacement).unwrap();
+ module.children_mut().remove(position);
+ }
+
+ if let Some(mut module) = self.items.get_mut(&new_parent).unwrap().as_module_mut() {
+ module.children_mut().push(replacement);
+ }
+
+ self.items.get_mut(&replacement).unwrap().set_parent_for_replacement(new_parent);
+ self.items.get_mut(&id).unwrap().set_parent_for_replacement(old_parent);
}
}
@@ -637,7 +657,8 @@ impl<'ctx> BindgenContext<'ctx> {
if let Some(location) = location {
if location.kind() == CXCursor_ClassTemplate ||
location.kind() ==
- CXCursor_ClassTemplatePartialSpecialization {
+ CXCursor_ClassTemplatePartialSpecialization ||
+ location.kind() == CXCursor_TypeAliasTemplateDecl {
declaration = location;
}
}
@@ -827,17 +848,17 @@ impl<'ctx> BindgenContext<'ctx> {
///
/// Replacement types are declared using the `replaces="xxx"` annotation,
/// and implies that the original type is hidden.
- pub fn replace(&mut self, name: &str, potential_ty: ItemId) {
+ pub fn replace(&mut self, name: &[String], potential_ty: ItemId) {
match self.replacements.entry(name.into()) {
hash_map::Entry::Vacant(entry) => {
- debug!("Defining replacement for {} as {:?}",
+ debug!("Defining replacement for {:?} as {:?}",
name,
potential_ty);
entry.insert(potential_ty);
}
hash_map::Entry::Occupied(occupied) => {
- warn!("Replacement for {} already defined as {:?}; \
- ignoring duplicate replacement definition as {:?}}}",
+ warn!("Replacement for {:?} already defined as {:?}; \
+ ignoring duplicate replacement definition as {:?}",
name,
occupied.get(),
potential_ty);
@@ -847,27 +868,27 @@ impl<'ctx> BindgenContext<'ctx> {
/// Is the item with the given `name` hidden? Or is the item with the given
/// `name` and `id` replaced by another type, and effectively hidden?
- pub fn hidden_by_name(&self, name: &str, id: ItemId) -> bool {
+ pub fn hidden_by_name(&self, path: &[String], id: ItemId) -> bool {
debug_assert!(self.in_codegen_phase(),
"You're not supposed to call this yet");
- self.options.hidden_types.contains(name) ||
- self.is_replaced_type(name, id)
+ self.options.hidden_types.contains(&path[1..].join("::")) ||
+ self.is_replaced_type(path, id)
}
/// Has the item with the given `name` and `id` been replaced by another
/// type?
- pub fn is_replaced_type(&self, name: &str, id: ItemId) -> bool {
- match self.replacements.get(name) {
+ pub fn is_replaced_type(&self, path: &[String], id: ItemId) -> bool {
+ match self.replacements.get(path) {
Some(replaced_by) if *replaced_by != id => true,
_ => false,
}
}
/// Is the type with the given `name` marked as opaque?
- pub fn opaque_by_name(&self, name: &str) -> bool {
+ pub fn opaque_by_name(&self, path: &[String]) -> bool {
debug_assert!(self.in_codegen_phase(),
"You're not supposed to call this yet");
- self.options.opaque_types.contains(name)
+ self.options.opaque_types.contains(&path[1..].join("::"))
}
/// Get the options used to configure this bindgen context.
@@ -953,7 +974,8 @@ impl<'ctx> BindgenContext<'ctx> {
return true;
}
- let name = item.name(self).for_name_checking().get();
+ let name = item.canonical_path(self)[1..].join("::");
+ debug!("whitelisted_items: testing {:?}", name);
match *item.kind() {
ItemKind::Module(..) => true,
ItemKind::Function(_) => {
@@ -967,7 +989,10 @@ impl<'ctx> BindgenContext<'ctx> {
return true;
}
- if self.resolve_item(item.parent_id()).is_module() {
+ let parent = self.resolve_item(item.parent_id());
+ if parent.is_module() {
+ let mut prefix_path = parent.canonical_path(self);
+
// Unnamed top-level enums are special and we
// whitelist them via the `whitelisted_vars` filter,
// since they're effectively top-level constants,
@@ -976,9 +1001,12 @@ impl<'ctx> BindgenContext<'ctx> {
if let TypeKind::Enum(ref enum_) = *ty.kind() {
if ty.name().is_none() &&
enum_.variants().iter().any(|variant| {
+ prefix_path.push(variant.name().into());
+ let name = prefix_path[1..].join("::");
+ prefix_path.pop().unwrap();
self.options()
.whitelisted_vars
- .matches(&variant.name())
+ .matches(&name)
}) {
return true;
}
diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs
index f12e4b54..79aca5af 100644
--- a/libbindgen/src/ir/item.rs
+++ b/libbindgen/src/ir/item.rs
@@ -42,6 +42,12 @@ pub trait ItemCanonicalName {
/// For bar, the canonical path is `vec!["foo", "BAR"]`, while the canonical
/// name is just `"BAR"`.
pub trait ItemCanonicalPath {
+ /// Get the namespace-aware canonical path for this item. This means that if
+ /// namespaces are disabled, you'll
+ fn namespace_aware_canonical_path(&self,
+ ctx: &BindgenContext)
+ -> Vec<String>;
+
/// Get the canonical path for this item.
fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String>;
}
@@ -127,6 +133,14 @@ impl ItemCanonicalName for ItemId {
}
impl ItemCanonicalPath for ItemId {
+ fn namespace_aware_canonical_path(&self,
+ ctx: &BindgenContext)
+ -> Vec<String> {
+ debug_assert!(ctx.in_codegen_phase(),
+ "You're not supposed to call this yet");
+ ctx.resolve_item(*self).namespace_aware_canonical_path(ctx)
+ }
+
fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
debug_assert!(ctx.in_codegen_phase(),
"You're not supposed to call this yet");
@@ -276,6 +290,13 @@ impl Item {
self.parent_id
}
+ /// Set this item's parent id.
+ ///
+ /// This is only used so replacements get generated in the proper module.
+ pub fn set_parent_for_replacement(&mut self, id: ItemId) {
+ self.parent_id = id;
+ }
+
/// Get this `Item`'s comment, if it has any.
pub fn comment(&self) -> Option<&str> {
self.comment.as_ref().map(|c| &**c)
@@ -509,7 +530,7 @@ impl Item {
}
// XXX Is this completely correct? Partial template specialization
// is hard anyways, sigh...
- TypeKind::TemplateAlias(_, ref args) |
+ TypeKind::TemplateAlias(_, _, ref args) |
TypeKind::TemplateRef(_, ref args) => args.clone(),
// In a template specialization we've got all we want.
TypeKind::Comp(ref ci) if ci.is_template_specialization() => {
@@ -552,7 +573,7 @@ impl Item {
debug_assert!(ctx.in_codegen_phase(),
"You're not supposed to call this yet");
self.annotations.hide() ||
- ctx.hidden_by_name(&self.name(ctx).for_name_checking().get(), self.id)
+ ctx.hidden_by_name(&self.canonical_path(ctx), self.id)
}
/// Is this item opaque?
@@ -560,7 +581,7 @@ impl Item {
debug_assert!(ctx.in_codegen_phase(),
"You're not supposed to call this yet");
self.annotations.opaque() ||
- ctx.opaque_by_name(&self.name(ctx).for_name_checking().get())
+ ctx.opaque_by_name(&self.canonical_path(ctx))
}
/// Is this a reference to another type?
@@ -585,8 +606,7 @@ impl Item {
/// Get the target item id for name generation.
fn name_target(&self,
- ctx: &BindgenContext,
- for_name_checking: bool)
+ ctx: &BindgenContext)
-> ItemId {
let mut targets_seen = DebugOnlyItemSet::new();
let mut item = self;
@@ -595,6 +615,10 @@ impl Item {
debug_assert!(!targets_seen.contains(&item.id()));
targets_seen.insert(item.id());
+ if self.annotations().use_instead_of().is_some() {
+ return self.id();
+ }
+
match *item.kind() {
ItemKind::Type(ref ty) => {
match *ty.kind() {
@@ -611,13 +635,6 @@ impl Item {
TypeKind::TemplateRef(inner, _) => {
item = ctx.resolve_item(inner);
}
- // Template aliases use their inner alias type's name if
- // we are checking names for
- // whitelisting/replacement/etc.
- TypeKind::TemplateAlias(inner, _)
- if for_name_checking => {
- item = ctx.resolve_item(inner);
- }
_ => return item.id(),
}
}
@@ -657,14 +674,13 @@ impl Item {
}
/// Get this item's base name (aka non-namespaced name).
- ///
- /// The `for_name_checking` boolean parameter informs us whether we are
- /// asking for the name in order to do a whitelisting/replacement/etc check
- /// or if we are instead using it for code generation.
fn base_name(&self,
- ctx: &BindgenContext,
- for_name_checking: bool)
+ ctx: &BindgenContext)
-> String {
+ if let Some(path) = self.annotations().use_instead_of() {
+ return path.last().unwrap().clone();
+ }
+
match *self.kind() {
ItemKind::Var(ref var) => var.name().to_owned(),
ItemKind::Module(ref module) => {
@@ -677,9 +693,6 @@ impl Item {
ItemKind::Type(ref ty) => {
let name = match *ty.kind() {
TypeKind::ResolvedTypeRef(..) => panic!("should have resolved this in name_target()"),
- TypeKind::TemplateAlias(..) => {
- if for_name_checking { None } else { Some("") }
- }
_ => ty.name(),
};
name.map(ToOwned::to_owned)
@@ -717,16 +730,17 @@ impl Item {
opt: &NameOptions)
-> String {
let target =
- ctx.resolve_item(self.name_target(ctx, opt.for_name_checking));
+ ctx.resolve_item(self.name_target(ctx));
// Short-circuit if the target has an override, and just use that.
- if !opt.for_name_checking {
- if let Some(other) = target.annotations.use_instead_of() {
- return other.to_owned();
+ if let Some(path) = target.annotations.use_instead_of() {
+ if ctx.options().enable_cxx_namespaces {
+ return path.last().unwrap().clone();
}
+ return path.join("_").to_owned();
}
- let base_name = target.base_name(ctx, opt.for_name_checking);
+ let base_name = target.base_name(ctx);
// Named template type arguments are never namespaced, and never
// mangled.
@@ -744,8 +758,8 @@ impl Item {
})
.map(|id| {
let item = ctx.resolve_item(id);
- let target = ctx.resolve_item(item.name_target(ctx, false));
- target.base_name(ctx, false)
+ let target = ctx.resolve_item(item.name_target(ctx));
+ target.base_name(ctx)
})
.filter(|name| !name.is_empty())
.collect();
@@ -1217,17 +1231,34 @@ impl ItemCanonicalName for Item {
}
impl ItemCanonicalPath for Item {
+ fn namespace_aware_canonical_path(&self,
+ ctx: &BindgenContext)
+ -> Vec<String> {
+ if ctx.options().enable_cxx_namespaces {
+ return self.canonical_path(ctx);
+ }
+ return vec![self.canonical_path(ctx)[1..].join("_")];
+ }
+
fn canonical_path(&self, ctx: &BindgenContext) -> Vec<String> {
- if !ctx.options().enable_cxx_namespaces {
- return vec![self.canonical_name(ctx)];
+ if let Some(path) = self.annotations().use_instead_of() {
+ let mut ret =
+ vec![ctx.resolve_item(ctx.root_module()).name(ctx).get()];
+ ret.extend_from_slice(path);
+ return ret;
}
- let target = ctx.resolve_item(self.name_target(ctx, false));
+ let target = ctx.resolve_item(self.name_target(ctx));
let mut path: Vec<_> = target.ancestors(ctx)
.chain(iter::once(ctx.root_module()))
.map(|id| ctx.resolve_item(id))
.filter(|item| item.is_module() || item.id() == target.id())
- .map(|item| item.name(ctx).within_namespaces().get())
+ .map(|item| {
+ ctx.resolve_item(item.name_target(ctx))
+ .name(ctx)
+ .within_namespaces()
+ .get()
+ })
.collect();
path.reverse();
path
@@ -1242,7 +1273,6 @@ pub struct NameOptions<'item, 'ctx>
{
item: &'item Item,
ctx: &'item BindgenContext<'ctx>,
- for_name_checking: bool,
within_namespaces: bool,
}
@@ -1252,18 +1282,10 @@ impl<'item, 'ctx> NameOptions<'item, 'ctx> {
NameOptions {
item: item,
ctx: ctx,
- for_name_checking: false,
within_namespaces: false,
}
}
- /// Construct a name that is suitable for replacements/whitelisting/opaque-
- /// ness look ups.
- pub fn for_name_checking(&mut self) -> &mut Self {
- self.for_name_checking = true;
- self
- }
-
/// Construct the name without the item's containing C++ namespaces mangled
/// into it. In other words, the item's name within the item's namespace.
pub fn within_namespaces(&mut self) -> &mut Self {
diff --git a/libbindgen/src/ir/ty.rs b/libbindgen/src/ir/ty.rs
index 33e20861..8b0116df 100644
--- a/libbindgen/src/ir/ty.rs
+++ b/libbindgen/src/ir/ty.rs
@@ -64,6 +64,22 @@ impl Type {
&self.kind
}
+ /// Overrides the kind of the item. This is mostly a template alias
+ /// implementation detail, and debug assertions guard it like so.
+ pub fn set_kind(&mut self, kind: TypeKind) {
+ if cfg!(debug_assertions) {
+ match (&self.kind, &kind) {
+ (&TypeKind::Alias(ref alias_name, alias_inner),
+ &TypeKind::TemplateAlias(ref name, inner, _)) => {
+ assert_eq!(alias_name, name);
+ assert_eq!(alias_inner, inner);
+ }
+ _ => panic!("Unexpected kind in `set_kind`!"),
+ };
+ }
+ self.kind = kind;
+ }
+
/// Get a mutable reference to this type's kind.
pub fn kind_mut(&mut self) -> &mut TypeKind {
&mut self.kind
@@ -90,6 +106,14 @@ impl Type {
}
}
+ /// Is this a template alias type?
+ pub fn is_template_alias(&self) -> bool {
+ match self.kind {
+ TypeKind::TemplateAlias(..) => true,
+ _ => false,
+ }
+ }
+
/// Is this a function type?
pub fn is_function(&self) -> bool {
match self.kind {
@@ -195,7 +219,7 @@ impl Type {
ctx.resolve_type(t).can_derive_debug(ctx)
}
TypeKind::ResolvedTypeRef(t) |
- TypeKind::TemplateAlias(t, _) |
+ TypeKind::TemplateAlias(_, t, _) |
TypeKind::Alias(_, t) => ctx.resolve_type(t).can_derive_debug(ctx),
TypeKind::Comp(ref info) => {
info.can_derive_debug(ctx, self.layout(ctx))
@@ -232,7 +256,7 @@ impl Type {
-> bool {
match self.kind {
TypeKind::ResolvedTypeRef(t) |
- TypeKind::TemplateAlias(t, _) |
+ TypeKind::TemplateAlias(_, t, _) |
TypeKind::Alias(_, t) |
TypeKind::Array(t, _) => {
ctx.resolve_item(t)
@@ -252,7 +276,7 @@ impl Type {
ctx.resolve_item(t).can_derive_copy_in_array(ctx)
}
TypeKind::ResolvedTypeRef(t) |
- TypeKind::TemplateAlias(t, _) |
+ TypeKind::TemplateAlias(_, t, _) |
TypeKind::TemplateRef(t, _) |
TypeKind::Alias(_, t) => ctx.resolve_item(t).can_derive_copy(ctx),
TypeKind::Comp(ref info) => info.can_derive_copy(ctx, item),
@@ -265,7 +289,7 @@ impl Type {
// FIXME: Can we do something about template parameters? Huh...
match self.kind {
TypeKind::TemplateRef(t, _) |
- TypeKind::TemplateAlias(t, _) |
+ TypeKind::TemplateAlias(_, t, _) |
TypeKind::Alias(_, t) |
TypeKind::ResolvedTypeRef(t) => ctx.resolve_type(t).has_vtable(ctx),
TypeKind::Comp(ref info) => info.has_vtable(ctx),
@@ -278,7 +302,7 @@ impl Type {
pub fn has_destructor(&self, ctx: &BindgenContext) -> bool {
match self.kind {
TypeKind::TemplateRef(t, _) |
- TypeKind::TemplateAlias(t, _) |
+ TypeKind::TemplateAlias(_, t, _) |
TypeKind::Alias(_, t) |
TypeKind::ResolvedTypeRef(t) => {
ctx.resolve_type(t).has_destructor(ctx)
@@ -293,10 +317,9 @@ impl Type {
ctx: &BindgenContext,
ty: &Type)
-> bool {
- debug_assert!(ty.is_named());
let name = match *ty.kind() {
TypeKind::Named(ref name, _) => name,
- _ => unreachable!(),
+ ref other @ _ => unreachable!("Not a named type: {:?}", other),
};
match self.kind {
@@ -316,7 +339,7 @@ impl Type {
ctx.resolve_type(sig.return_type())
.signature_contains_named_type(ctx, ty)
}
- TypeKind::TemplateAlias(_, ref template_args) |
+ TypeKind::TemplateAlias(_, _, ref template_args) |
TypeKind::TemplateRef(_, ref template_args) => {
template_args.iter().any(|arg| {
ctx.resolve_type(*arg)
@@ -361,7 +384,7 @@ impl Type {
TypeKind::ResolvedTypeRef(inner) |
TypeKind::Alias(_, inner) |
- TypeKind::TemplateAlias(inner, _) |
+ TypeKind::TemplateAlias(_, inner, _) |
TypeKind::TemplateRef(inner, _) => {
ctx.resolve_type(inner).safe_canonical_type(ctx)
}
@@ -409,9 +432,9 @@ pub enum TypeKind {
/// A type alias, with a name, that points to another type.
Alias(String, ItemId),
- /// A templated alias, pointing to an inner `Alias` type, with template
- /// parameters.
- TemplateAlias(ItemId, Vec<ItemId>),
+ /// A templated alias, pointing to an inner type, just as `Alias`, but with
+ /// template parameters.
+ TemplateAlias(String, ItemId, Vec<ItemId>),
/// An array of a type and a lenght.
Array(ItemId, usize),
@@ -476,7 +499,7 @@ impl Type {
}
TypeKind::ResolvedTypeRef(inner) |
TypeKind::Alias(_, inner) |
- TypeKind::TemplateAlias(inner, _) |
+ TypeKind::TemplateAlias(_, inner, _) |
TypeKind::TemplateRef(inner, _) => {
ctx.resolve_type(inner).is_unsized(ctx)
}
@@ -630,13 +653,19 @@ impl Type {
location.visit(|cur| {
match cur.kind() {
CXCursor_TypeAliasDecl => {
- debug_assert!(cur.cur_type().kind() ==
+ let current = cur.cur_type();
+
+ debug_assert!(current.kind() ==
CXType_Typedef);
- inner =
- Item::from_ty(&cur.cur_type(),
- Some(cur),
- Some(potential_id),
- ctx);
+
+ name = current.spelling();
+
+ let inner_ty = cur.typedef_type();
+ inner = Item::from_ty(
+ &inner_ty,
+ Some(cur),
+ Some(potential_id),
+ ctx);
}
CXCursor_TemplateTypeParameter => {
// See the comment in src/ir/comp.rs
@@ -663,24 +692,16 @@ impl Type {
CXChildVisit_Continue
});
- if inner.is_err() {
- error!("Failed to parse templated alias {:?}",
- location);
- return Err(ParseError::Continue);
- }
+ let inner_type = match inner {
+ Ok(inner) => inner,
+ Err(..) => {
+ error!("Failed to parse template alias {:?}",
+ location);
+ return Err(ParseError::Continue);
+ }
+ };
- // NB: `args` may be empty here (if for example the
- // template parameters are constants).
- //
- // We can't reject it here then because inner points
- // to `potential_id` now, so either we remove
- // `inner` and return an error, or carry on.
- //
- // In this case, we just carry on, since it seems
- // easier if than removing every possible reference
- // to `item` from `ctx`, and it doesn't give any
- // problems that we didn't have anyway.
- TypeKind::TemplateAlias(inner.unwrap(), args)
+ TypeKind::TemplateAlias(name.clone(), inner_type, args)
}
CXCursor_TemplateRef => {
let referenced = location.referenced().unwrap();
@@ -870,13 +891,13 @@ impl TypeCollector for Type {
TypeKind::Pointer(inner) |
TypeKind::Reference(inner) |
TypeKind::Array(inner, _) |
- TypeKind::TemplateAlias(inner, _) |
TypeKind::Alias(_, inner) |
TypeKind::Named(_, Some(inner)) |
TypeKind::ResolvedTypeRef(inner) => {
types.insert(inner);
}
+ TypeKind::TemplateAlias(_, inner, ref template_args) |
TypeKind::TemplateRef(inner, ref template_args) => {
types.insert(inner);
for &item in template_args {
diff --git a/libbindgen/tests/expectations/tests/reparented_replacement.rs b/libbindgen/tests/expectations/tests/reparented_replacement.rs
new file mode 100644
index 00000000..74ee229c
--- /dev/null
+++ b/libbindgen/tests/expectations/tests/reparented_replacement.rs
@@ -0,0 +1,29 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+pub mod root {
+ #[allow(unused_imports)]
+ use self::super::root;
+ pub mod foo {
+ #[allow(unused_imports)]
+ use self::super::super::root;
+ /// <div rustbindgen replaces="foo::Bar"></div>
+ #[repr(C)]
+ #[derive(Debug, Copy)]
+ pub struct Bar {
+ pub bazz: ::std::os::raw::c_int,
+ }
+ #[test]
+ fn bindgen_test_layout_Bar() {
+ assert_eq!(::std::mem::size_of::<Bar>() , 4usize);
+ assert_eq!(::std::mem::align_of::<Bar>() , 4usize);
+ }
+ impl Clone for Bar {
+ fn clone(&self) -> Self { *self }
+ }
+ }
+ pub type ReferencesBar = root::foo::Bar;
+}
diff --git a/libbindgen/tests/expectations/tests/replace_template_alias.rs b/libbindgen/tests/expectations/tests/replace_template_alias.rs
index b9a0d0c9..f922ac77 100644
--- a/libbindgen/tests/expectations/tests/replace_template_alias.rs
+++ b/libbindgen/tests/expectations/tests/replace_template_alias.rs
@@ -4,12 +4,12 @@
#![allow(non_snake_case)]
+/// But the replacement type does use T!
+///
+/// <div rustbindgen replaces="JS::detail::MaybeWrapped" />
+pub type JS_detail_MaybeWrapped<T> = T;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct JS_Rooted<T> {
pub ptr: JS_detail_MaybeWrapped<T>,
}
-/// But the replacement type does use T!
-///
-/// <div rustbindgen replaces="JS_detail_MaybeWrapped" />
-pub type JS_detail_MaybeWrapped<T> = T;
diff --git a/libbindgen/tests/expectations/tests/type_alias_template_specialized.rs b/libbindgen/tests/expectations/tests/type_alias_template_specialized.rs
index 989f2015..11813bc6 100644
--- a/libbindgen/tests/expectations/tests/type_alias_template_specialized.rs
+++ b/libbindgen/tests/expectations/tests/type_alias_template_specialized.rs
@@ -17,3 +17,5 @@ fn bindgen_test_layout_Rooted() {
impl Clone for Rooted {
fn clone(&self) -> Self { *self }
}
+/// <div rustbindgen replaces="MaybeWrapped"></div>
+pub type MaybeWrapped<a> = a;
diff --git a/libbindgen/tests/headers/reparented_replacement.hpp b/libbindgen/tests/headers/reparented_replacement.hpp
new file mode 100644
index 00000000..4ac2bf03
--- /dev/null
+++ b/libbindgen/tests/headers/reparented_replacement.hpp
@@ -0,0 +1,16 @@
+// bindgen-flags: --enable-cxx-namespaces
+
+namespace foo {
+ struct Bar {
+ int baz;
+ };
+}
+
+namespace bar {
+ /// <div rustbindgen replaces="foo::Bar"></div>
+ struct Bar_Replacement {
+ int bazz;
+ };
+};
+
+typedef foo::Bar ReferencesBar;
diff --git a/libbindgen/tests/headers/replace_template_alias.hpp b/libbindgen/tests/headers/replace_template_alias.hpp
index b0648994..c325b5a3 100644
--- a/libbindgen/tests/headers/replace_template_alias.hpp
+++ b/libbindgen/tests/headers/replace_template_alias.hpp
@@ -18,6 +18,6 @@ class Rooted {
/// But the replacement type does use T!
///
-/// <div rustbindgen replaces="JS_detail_MaybeWrapped" />
+/// <div rustbindgen replaces="JS::detail::MaybeWrapped" />
template <typename T>
using replaces_MaybeWrapped = T;
diff --git a/libbindgen/tests/headers/whitelist-namespaces-basic.hpp b/libbindgen/tests/headers/whitelist-namespaces-basic.hpp
index abe9dc11..2eaa8740 100644
--- a/libbindgen/tests/headers/whitelist-namespaces-basic.hpp
+++ b/libbindgen/tests/headers/whitelist-namespaces-basic.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --enable-cxx-namespaces --whitelist-type outer_inner_Helper
+// bindgen-flags: --enable-cxx-namespaces --whitelist-type outer::inner::Helper
namespace outer {
namespace inner {