diff options
-rw-r--r-- | libbindgen/src/codegen/mod.rs | 77 | ||||
-rw-r--r-- | libbindgen/src/ir/context.rs | 35 | ||||
-rw-r--r-- | libbindgen/src/ir/item.rs | 19 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/maddness-is-avoidable.rs | 20 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/module-whitelisted.rs | 23 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/namespace.rs | 12 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/replace_use.rs | 28 | ||||
-rw-r--r-- | libbindgen/tests/expectations/tests/whitelist_fix.rs | 10 | ||||
-rw-r--r-- | libbindgen/tests/headers/maddness-is-avoidable.hpp | 9 | ||||
-rw-r--r-- | libbindgen/tests/headers/module-whitelisted.hpp | 2 | ||||
-rw-r--r-- | libbindgen/tests/headers/replace_use.hpp | 15 | ||||
-rw-r--r-- | libbindgen/tests/headers/whitelist-namespaces-basic.hpp | 2 | ||||
-rw-r--r-- | libbindgen/tests/headers/whitelist_fix.hpp | 4 |
13 files changed, 169 insertions, 87 deletions
diff --git a/libbindgen/src/codegen/mod.rs b/libbindgen/src/codegen/mod.rs index a3fefcc7..0469a5be 100644 --- a/libbindgen/src/codegen/mod.rs +++ b/libbindgen/src/codegen/mod.rs @@ -242,11 +242,6 @@ impl CodeGenerator for Item { match *self.kind() { ItemKind::Module(ref module) => { - if !ctx.options().enable_cxx_namespaces && - self.id() == ctx.root_module() { - return; - } - module.codegen(ctx, result, whitelisted_items, self); } ItemKind::Function(ref fun) => { @@ -274,22 +269,28 @@ impl CodeGenerator for Module { item: &Item) { debug!("<Module as CodeGenerator>::codegen: item = {:?}", item); - if !ctx.options().enable_cxx_namespaces { - for child in self.children() { - ctx.resolve_item(*child) - .codegen(ctx, result, whitelisted_items, &()); + let codegen_self = |result: &mut CodegenResult| { + // FIXME: This could be less expensive, I guess. + for &whitelisted_item in whitelisted_items { + if whitelisted_item == item.id() { + continue; + } + + let child = ctx.resolve_item(whitelisted_item); + if child.parent_id() == item.id() { + child.codegen(ctx, result, whitelisted_items, &()); + } } + }; + + if !ctx.options().enable_cxx_namespaces { + codegen_self(result); return; } let inner_items = result.inner(|result| { result.push(root_import(ctx)); - for child in self.children() { - if whitelisted_items.contains(child) { - ctx.resolve_item(*child) - .codegen(ctx, result, whitelisted_items, &()); - } - } + codegen_self(result); }); let module = ast::ItemKind::Mod(ast::Mod { @@ -428,13 +429,12 @@ 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 + // applicable_template_args. TypeKind::TemplateAlias(inner, _) => { - // NB: The inner Alias will pick the correct - // applicable_template_args. - let inner_item = ctx.resolve_item(inner); - inner_item.expect_type() - .codegen(ctx, result, whitelisted_items, inner_item); - } + ctx.resolve_item(inner) + .codegen(ctx, result, whitelisted_items, &()) + }, TypeKind::Alias(ref spelling, inner) => { let inner_item = ctx.resolve_item(inner); let name = item.canonical_name(ctx); @@ -1964,27 +1964,6 @@ impl CodeGenerator for Function { } } -// Return true if any of the ancestors of `id` are in the whitelisted items set, -// false otherwise. -fn ancestor_is_whitelisted(ctx: &BindgenContext, - whitelisted_items: &ItemSet, - id: ItemId) - -> bool { - let item = ctx.resolve_item(id); - let mut last = id; - let mut current = item.parent_id(); - - while last != current { - if whitelisted_items.contains(¤t) { - return true; - } - last = current; - current = ctx.resolve_item(current).parent_id(); - } - - false -} - pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { context.gen(|context| { let mut result = CodegenResult::new(); @@ -2000,18 +1979,8 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> { } } - for &id in whitelisted_items.iter() { - let item = context.resolve_item(id); - - // Non-toplevel items' parents are responsible one for generating - // their children. However, if we find an orphaned reference to a - // non-toplevel item whose parent is not in our whitelisted set, we - // need to take responsibility for generating it. - if item.is_toplevel(context) || - !ancestor_is_whitelisted(context, &whitelisted_items, id) { - item.codegen(context, &mut result, &whitelisted_items, &()); - } - } + context.resolve_item(context.root_module()) + .codegen(context, &mut result, &whitelisted_items, &()); let saw_union = result.saw_union; let mut result = result.items; diff --git a/libbindgen/src/ir/context.rs b/libbindgen/src/ir/context.rs index 76e27841..e599160e 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, ItemCanonicalName}; +use super::item::Item; use super::item_kind::ItemKind; use super::module::Module; use super::ty::{FloatKind, Type, TypeKind}; @@ -938,11 +938,9 @@ impl<'ctx> BindgenContext<'ctx> { return true; } - let name = item.canonical_name(self); + let name = item.real_canonical_name(self, false, true); match *item.kind() { - ItemKind::Module(..) => { - self.options().enable_cxx_namespaces - } + ItemKind::Module(..) => true, ItemKind::Function(_) => { self.options().whitelisted_functions.matches(&name) } @@ -954,18 +952,21 @@ impl<'ctx> BindgenContext<'ctx> { return true; } - // Unnamed top-level enums are special and we whitelist - // them via the `whitelisted_vars` filter, since they're - // effectively top-level constants, and there's no way - // for them to be referenced consistently. - if let TypeKind::Enum(ref enum_) = *ty.kind() { - if ty.name().is_none() && - enum_.variants().iter().any(|variant| { - self.options() - .whitelisted_vars - .matches(&variant.name()) - }) { - return true; + if self.resolve_item(item.parent_id()).is_module() { + // Unnamed top-level enums are special and we + // whitelist them via the `whitelisted_vars` filter, + // since they're effectively top-level constants, + // and there's no way for them to be referenced + // consistently. + if let TypeKind::Enum(ref enum_) = *ty.kind() { + if ty.name().is_none() && + enum_.variants().iter().any(|variant| { + self.options() + .whitelisted_vars + .matches(&variant.name()) + }) { + return true; + } } } diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs index b857acf9..1f15ff0f 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -532,6 +532,14 @@ impl Item { self.as_type().map_or(false, |ty| ty.is_type_ref()) } + /// Is this item a var type? + pub fn is_var(&self) -> bool { + match *self.kind() { + ItemKind::Var(..) => true, + _ => false, + } + } + /// Get the target item id for name generation. fn name_target(&self, ctx: &BindgenContext, @@ -664,6 +672,14 @@ impl Item { for_name_checking: bool) -> String { let target = ctx.resolve_item(self.name_target(ctx, for_name_checking)); + + // Short-circuit if the target has an override, and just use that. + if !for_name_checking { + if let Some(other) = target.annotations.use_instead_of() { + return other.to_owned(); + } + } + let base_name = target.base_name(ctx, for_name_checking); // Named template type arguments are never namespaced, and never @@ -1135,9 +1151,6 @@ impl ItemCanonicalName for Item { fn canonical_name(&self, ctx: &BindgenContext) -> String { debug_assert!(ctx.in_codegen_phase(), "You're not supposed to call this yet"); - if let Some(other_canon_type) = self.annotations.use_instead_of() { - return other_canon_type.to_owned(); - } if self.canonical_name_cache.borrow().is_none() { *self.canonical_name_cache.borrow_mut() = Some(self.real_canonical_name(ctx, diff --git a/libbindgen/tests/expectations/tests/maddness-is-avoidable.rs b/libbindgen/tests/expectations/tests/maddness-is-avoidable.rs new file mode 100644 index 00000000..d31345ba --- /dev/null +++ b/libbindgen/tests/expectations/tests/maddness-is-avoidable.rs @@ -0,0 +1,20 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RefPtr<T> { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData<T>, +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct RefPtr_Proxy<T, R, Args> { + pub _address: u8, + pub _phantom_0: ::std::marker::PhantomData<T>, + pub _phantom_1: ::std::marker::PhantomData<R>, + pub _phantom_2: ::std::marker::PhantomData<Args>, +} diff --git a/libbindgen/tests/expectations/tests/module-whitelisted.rs b/libbindgen/tests/expectations/tests/module-whitelisted.rs new file mode 100644 index 00000000..7e63c8c8 --- /dev/null +++ b/libbindgen/tests/expectations/tests/module-whitelisted.rs @@ -0,0 +1,23 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +pub mod root { + #[allow(unused_imports)] + use root; + #[repr(C)] + #[derive(Debug, Copy)] + pub struct Test { + pub _address: u8, + } + #[test] + fn bindgen_test_layout_Test() { + assert_eq!(::std::mem::size_of::<Test>() , 1usize); + assert_eq!(::std::mem::align_of::<Test>() , 1usize); + } + impl Clone for Test { + fn clone(&self) -> Self { *self } + } +} diff --git a/libbindgen/tests/expectations/tests/namespace.rs b/libbindgen/tests/expectations/tests/namespace.rs index abb48204..54bc08dc 100644 --- a/libbindgen/tests/expectations/tests/namespace.rs +++ b/libbindgen/tests/expectations/tests/namespace.rs @@ -76,15 +76,3 @@ pub mod root { } } } -extern "C" { - #[link_name = "_Z9top_levelv"] - pub fn top_level(); -} -#[repr(C)] -#[derive(Debug)] -pub struct C<T> { - pub _base: root::_bindgen_mod_id_13::A, - pub m_c: T, - pub m_c_ptr: *mut T, - pub m_c_arr: [T; 10usize], -} diff --git a/libbindgen/tests/expectations/tests/replace_use.rs b/libbindgen/tests/expectations/tests/replace_use.rs new file mode 100644 index 00000000..f4fee442 --- /dev/null +++ b/libbindgen/tests/expectations/tests/replace_use.rs @@ -0,0 +1,28 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + + +/** + * <div rustbindgen replaces="nsTArray"></div> + */ +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct nsTArray<T> { + pub y: ::std::os::raw::c_uint, + pub _phantom_0: ::std::marker::PhantomData<T>, +} +#[repr(C)] +#[derive(Debug, Copy)] +pub struct Test { + pub a: nsTArray<::std::os::raw::c_long>, +} +#[test] +fn bindgen_test_layout_Test() { + assert_eq!(::std::mem::size_of::<Test>() , 4usize); + assert_eq!(::std::mem::align_of::<Test>() , 4usize); +} +impl Clone for Test { + fn clone(&self) -> Self { *self } +} diff --git a/libbindgen/tests/expectations/tests/whitelist_fix.rs b/libbindgen/tests/expectations/tests/whitelist_fix.rs new file mode 100644 index 00000000..9e26e1be --- /dev/null +++ b/libbindgen/tests/expectations/tests/whitelist_fix.rs @@ -0,0 +1,10 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(non_snake_case)] + +pub enum Test {} + +extern "C" { + pub fn Servo_Test(a: *mut Test); +} diff --git a/libbindgen/tests/headers/maddness-is-avoidable.hpp b/libbindgen/tests/headers/maddness-is-avoidable.hpp new file mode 100644 index 00000000..46d7495e --- /dev/null +++ b/libbindgen/tests/headers/maddness-is-avoidable.hpp @@ -0,0 +1,9 @@ +// bindgen-flags: --blacklist-type RefPtr_Proxy_member_function + +template<typename T> +class RefPtr { + template<typename R, typename... Args> + class Proxy { + typedef R (T::*member_function)(Args...); + }; +}; diff --git a/libbindgen/tests/headers/module-whitelisted.hpp b/libbindgen/tests/headers/module-whitelisted.hpp new file mode 100644 index 00000000..f41e874e --- /dev/null +++ b/libbindgen/tests/headers/module-whitelisted.hpp @@ -0,0 +1,2 @@ +// bindgen-flags: --enable-cxx-namespaces +struct Test {}; diff --git a/libbindgen/tests/headers/replace_use.hpp b/libbindgen/tests/headers/replace_use.hpp new file mode 100644 index 00000000..de44eb19 --- /dev/null +++ b/libbindgen/tests/headers/replace_use.hpp @@ -0,0 +1,15 @@ +template<typename T> +struct nsTArray { + int x; +}; +/** + * <div rustbindgen replaces="nsTArray"></div> + */ +template<typename T> +struct nsTArray_Simple { + unsigned int y; +}; + +struct Test { + nsTArray<long> a; +}; diff --git a/libbindgen/tests/headers/whitelist-namespaces-basic.hpp b/libbindgen/tests/headers/whitelist-namespaces-basic.hpp index b631d290..abe9dc11 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 '.*Helper' +// bindgen-flags: --enable-cxx-namespaces --whitelist-type outer_inner_Helper namespace outer { namespace inner { diff --git a/libbindgen/tests/headers/whitelist_fix.hpp b/libbindgen/tests/headers/whitelist_fix.hpp new file mode 100644 index 00000000..d0abda54 --- /dev/null +++ b/libbindgen/tests/headers/whitelist_fix.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: --whitelist-function 'Servo_.*' --blacklist-type Test --raw-line "pub enum Test {}" + +struct Test {}; +extern "C" void Servo_Test(Test* a); |