diff options
Diffstat (limited to 'libbindgen/src')
-rw-r--r-- | libbindgen/src/clang.rs | 13 | ||||
-rw-r--r-- | libbindgen/src/ir/comp.rs | 18 | ||||
-rw-r--r-- | libbindgen/src/ir/context.rs | 6 | ||||
-rw-r--r-- | libbindgen/src/ir/item.rs | 23 | ||||
-rw-r--r-- | libbindgen/src/ir/ty.rs | 2 | ||||
-rw-r--r-- | libbindgen/src/lib.rs | 23 |
6 files changed, 68 insertions, 17 deletions
diff --git a/libbindgen/src/clang.rs b/libbindgen/src/clang.rs index 72069644..7c6d3199 100644 --- a/libbindgen/src/clang.rs +++ b/libbindgen/src/clang.rs @@ -760,6 +760,19 @@ impl Type { pub fn is_valid_and_exposed(&self) -> bool { self.is_valid() && self.kind() != CXType_Unexposed } + + /// Is this type a fully specialized template? + pub fn is_fully_specialized_template(&self) -> bool { + // Yep, the spelling of this containing type-parameter is extremely + // nasty... But can happen in <type_traits>. Unfortunately I couldn't + // reduce it enough :( + !self.spelling().contains("type-parameter") && + self.template_args() + .map_or(false, |mut args| { + args.len() > 0 && + !args.any(|t| t.spelling().contains("type-parameter")) + }) + } } /// An iterator for a type's template arguments. diff --git a/libbindgen/src/ir/comp.rs b/libbindgen/src/ir/comp.rs index d19d1209..d2ace023 100644 --- a/libbindgen/src/ir/comp.rs +++ b/libbindgen/src/ir/comp.rs @@ -498,17 +498,29 @@ impl CompInfo { None => vec![], Some(arg_types) => { let num_arg_types = arg_types.len(); + let mut specialization = true; let args = arg_types.filter(|t| t.kind() != CXType_Invalid) - .map(|t| Item::from_ty_or_ref(t, None, None, ctx)) + .filter_map(|t| { + if t.spelling().starts_with("type-parameter") { + specialization = false; + None + } else { + Some(Item::from_ty_or_ref(t, None, None, ctx)) + } + }) .collect::<Vec<_>>(); - if args.len() != num_arg_types { + if specialization && args.len() != num_arg_types { ci.has_non_type_template_params = true; warn!("warning: Template parameter is not a type"); } - args + if specialization { + args + } else { + vec![] + } } }; diff --git a/libbindgen/src/ir/context.rs b/libbindgen/src/ir/context.rs index 67db2a59..a0e57610 100644 --- a/libbindgen/src/ir/context.rs +++ b/libbindgen/src/ir/context.rs @@ -367,10 +367,8 @@ impl<'ctx> BindgenContext<'ctx> { _ => continue, } - let name = item.real_canonical_name(self, - self.options() - .enable_cxx_namespaces, - true); + let in_namespace = self.options().enable_cxx_namespaces; + let name = item.real_canonical_name(self, in_namespace, true); let replacement = self.replacements.get(&name); if let Some(replacement) = replacement { diff --git a/libbindgen/src/ir/item.rs b/libbindgen/src/ir/item.rs index 1f15ff0f..1d643a45 100644 --- a/libbindgen/src/ir/item.rs +++ b/libbindgen/src/ir/item.rs @@ -688,14 +688,14 @@ impl Item { return base_name; } - if within_namespace { - return ctx.rust_mangle(&base_name).into_owned(); - } - // Concatenate this item's ancestors' names together. let mut names: Vec<_> = target.parent_id() .ancestors(ctx) .filter(|id| *id != ctx.root_module()) + .take_while(|id| { + // Stop iterating ancestors once we reach a namespace. + !within_namespace || !ctx.resolve_item(*id).is_module() + }) .map(|id| { let item = ctx.resolve_item(id); let target = ctx.resolve_item(item.name_target(ctx, false)); @@ -703,8 +703,13 @@ impl Item { }) .filter(|name| !name.is_empty()) .collect(); + names.reverse(); - names.push(base_name); + + if !base_name.is_empty() { + names.push(base_name); + } + let name = names.join("_"); ctx.rust_mangle(&name).into_owned() @@ -1152,11 +1157,11 @@ impl ItemCanonicalName for Item { debug_assert!(ctx.in_codegen_phase(), "You're not supposed to call this yet"); if self.canonical_name_cache.borrow().is_none() { + let in_namespace = ctx.options().enable_cxx_namespaces || + ctx.options().disable_name_namespacing; + *self.canonical_name_cache.borrow_mut() = - Some(self.real_canonical_name(ctx, - ctx.options() - .enable_cxx_namespaces, - false)); + Some(self.real_canonical_name(ctx, in_namespace, false)); } return self.canonical_name_cache.borrow().as_ref().unwrap().clone(); } diff --git a/libbindgen/src/ir/ty.rs b/libbindgen/src/ir/ty.rs index 7f01e388..33e20861 100644 --- a/libbindgen/src/ir/ty.rs +++ b/libbindgen/src/ir/ty.rs @@ -554,7 +554,7 @@ impl Type { TypeKind::Function(signature) // Same here, with template specialisations we can safely // assume this is a Comp(..) - } else if ty.template_args().map_or(false, |x| x.len() > 0) { + } else if ty.is_fully_specialized_template() { debug!("Template specialization: {:?}", ty); let complex = CompInfo::from_ty(potential_id, ty, location, ctx) diff --git a/libbindgen/src/lib.rs b/libbindgen/src/lib.rs index 10961e36..f25c6cdf 100644 --- a/libbindgen/src/lib.rs +++ b/libbindgen/src/lib.rs @@ -243,6 +243,25 @@ impl Builder { self } + /// Disable auto-namespacing of names if namespaces are disabled. + /// + /// By default, if namespaces are disabled, bindgen tries to mangle the + /// names to from `foo::bar::Baz` to look like `foo_bar_Baz`, instead of + /// just `Baz`. + /// + /// This option disables that behavior. + /// + /// Note that this intentionally doesn't change the names using for + /// whitelisting and blacklisting, that should still be mangled with the + /// namespaces. + /// + /// Note, also, that using this option may cause duplicated names to be + /// generated. + pub fn disable_name_namespacing(mut self) -> Builder { + self.options.disable_name_namespacing = true; + self + } + /// Ignore functions. pub fn ignore_functions(mut self) -> Builder { self.options.ignore_functions = true; @@ -341,6 +360,9 @@ pub struct BindgenOptions { /// generated bindings. pub enable_cxx_namespaces: bool, + /// True if we should avoid mangling names with namespaces. + pub disable_name_namespacing: bool, + /// True if we shold derive Debug trait implementations for C/C++ structures /// and types. pub derive_debug: bool, @@ -400,6 +422,7 @@ impl Default for BindgenOptions { ignore_methods: false, derive_debug: true, enable_cxx_namespaces: false, + disable_name_namespacing: false, unstable_rust: true, use_core: false, ctypes_prefix: None, |