Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@
* Regex inputs are sanitized so alternation (`a|b`) is handled correctly but
wildcard patterns (`*`) are now considered invalid.
* the `ParseCallbacks`trait does not require to implement `UnwindSafe`.
* the `Builder::parse_callbacks` method no longer overwrites previously added
callbacks and composes them in a last-to-first manner.

## Removed

Expand Down
21 changes: 9 additions & 12 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2112,12 +2112,11 @@ impl CodeGenerator for CompInfo {

// The custom derives callback may return a list of derive attributes;
// add them to the end of the list.
let custom_derives;
if let Some(cb) = &ctx.options().parse_callbacks {
custom_derives = cb.add_derives(&canonical_name);
// In most cases this will be a no-op, since custom_derives will be empty.
derives.extend(custom_derives.iter().map(|s| s.as_str()));
};
let custom_derives = ctx
.options()
.all_callbacks(|cb| cb.add_derives(&canonical_name));
// In most cases this will be a no-op, since custom_derives will be empty.
derives.extend(custom_derives.iter().map(|s| s.as_str()));

if !derives.is_empty() {
attributes.push(attributes::derives(&derives))
Expand Down Expand Up @@ -3152,12 +3151,10 @@ impl CodeGenerator for Enum {

// The custom derives callback may return a list of derive attributes;
// add them to the end of the list.
let custom_derives;
if let Some(cb) = &ctx.options().parse_callbacks {
custom_derives = cb.add_derives(&name);
// In most cases this will be a no-op, since custom_derives will be empty.
derives.extend(custom_derives.iter().map(|s| s.as_str()));
};
let custom_derives =
ctx.options().all_callbacks(|cb| cb.add_derives(&name));
// In most cases this will be a no-op, since custom_derives will be empty.
derives.extend(custom_derives.iter().map(|s| s.as_str()));

attrs.push(attributes::derives(&derives));
}
Expand Down
39 changes: 19 additions & 20 deletions bindgen/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use super::module::{Module, ModuleKind};
use super::template::{TemplateInstantiation, TemplateParameters};
use super::traversal::{self, Edge, ItemTraversal};
use super::ty::{FloatKind, Type, TypeKind};
use crate::callbacks::ParseCallbacks;
use crate::clang::{self, Cursor};
use crate::parse::ClangItemParser;
use crate::BindgenOptions;
Expand Down Expand Up @@ -619,15 +618,10 @@ If you encounter an error missing from this list, please file an issue or a PR!"
)
}

/// Get the user-provided callbacks by reference, if any.
pub fn parse_callbacks(&self) -> Option<&dyn ParseCallbacks> {
self.options().parse_callbacks.as_deref()
}

/// Add another path to the set of included files.
pub fn include_file(&mut self, filename: String) {
if let Some(cbs) = self.parse_callbacks() {
cbs.include_file(&filename);
for cb in &self.options().parse_callbacks {
cb.include_file(&filename);
}
self.deps.insert(filename);
}
Expand Down Expand Up @@ -2240,19 +2234,24 @@ If you encounter an error missing from this list, please file an issue or a PR!"
.or_insert_with(|| {
item.expect_type()
.name()
.and_then(|name| match self.options.parse_callbacks {
Some(ref cb) => cb.blocklisted_type_implements_trait(
name,
derive_trait,
),
// Sized integer types from <stdint.h> get mapped to Rust primitive
// types regardless of whether they are blocklisted, so ensure that
// standard traits are considered derivable for them too.
None => Some(if self.is_stdint_type(name) {
CanDerive::Yes
.and_then(|name| {
if self.options.parse_callbacks.is_empty() {
// Sized integer types from <stdint.h> get mapped to Rust primitive
// types regardless of whether they are blocklisted, so ensure that
// standard traits are considered derivable for them too.
if self.is_stdint_type(name) {
Some(CanDerive::Yes)
} else {
Some(CanDerive::No)
}
} else {
CanDerive::No
}),
self.options.last_callback(|cb| {
cb.blocklisted_type_implements_trait(
name,
derive_trait,
)
})
}
})
.unwrap_or(CanDerive::No)
})
Expand Down
8 changes: 4 additions & 4 deletions bindgen/ir/enum_ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ impl Enum {
let name = cursor.spelling();
let annotations = Annotations::new(&cursor);
let custom_behavior = ctx
.parse_callbacks()
.and_then(|callbacks| {
.options()
.last_callback(|callbacks| {
callbacks
.enum_variant_behavior(type_name, &name, val)
})
Expand All @@ -119,8 +119,8 @@ impl Enum {
});

let new_name = ctx
.parse_callbacks()
.and_then(|callbacks| {
.options()
.last_callback(|callbacks| {
callbacks.enum_variant_name(type_name, &name, val)
})
.or_else(|| {
Expand Down
9 changes: 5 additions & 4 deletions bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -664,10 +664,11 @@ impl ClangSubItemParser for Function {
// but seems easy enough to handle it here.
name.push_str("_destructor");
}
if let Some(callbacks) = context.parse_callbacks() {
if let Some(nm) = callbacks.generated_name_override(&name) {
name = nm;
}
if let Some(nm) = context
.options()
.last_callback(|callbacks| callbacks.generated_name_override(&name))
{
name = nm;
}
assert!(!name.is_empty(), "Empty function name.");

Expand Down
4 changes: 2 additions & 2 deletions bindgen/ir/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -932,8 +932,8 @@ impl Item {
let name = names.join("_");

let name = if opt.user_mangled == UserMangled::Yes {
ctx.parse_callbacks()
.and_then(|callbacks| callbacks.item_name(&name))
ctx.options()
.last_callback(|callbacks| callbacks.item_name(&name))
.unwrap_or(name)
} else {
name
Expand Down
10 changes: 5 additions & 5 deletions bindgen/ir/var.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl ClangSubItemParser for Var {
use clang_sys::*;
match cursor.kind() {
CXCursor_MacroDefinition => {
if let Some(callbacks) = ctx.parse_callbacks() {
for callbacks in &ctx.options().parse_callbacks {
match callbacks.will_parse_macro(&cursor.spelling()) {
MacroParsingBehavior::Ignore => {
return Err(ParseError::Continue);
Expand All @@ -191,7 +191,7 @@ impl ClangSubItemParser for Var {
}

if cursor.is_macro_function_like() {
handle_function_macro(&cursor, callbacks);
handle_function_macro(&cursor, callbacks.as_ref());
// We handled the macro, skip macro processing below.
return Err(ParseError::Continue);
}
Expand Down Expand Up @@ -249,15 +249,15 @@ impl ClangSubItemParser for Var {
true,
ctx,
);
if let Some(callbacks) = ctx.parse_callbacks() {
for callbacks in &ctx.options().parse_callbacks {
callbacks.str_macro(&name, &val);
}
(TypeKind::Pointer(char_ty), VarType::String(val))
}
EvalResult::Int(Wrapping(value)) => {
let kind = ctx
.parse_callbacks()
.and_then(|c| c.int_macro(&name, value))
.options()
.last_callback(|c| c.int_macro(&name, value))
.unwrap_or_else(|| {
default_macro_constant_type(ctx, value)
});
Expand Down
26 changes: 23 additions & 3 deletions bindgen/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,7 @@ impl Builder {
mut self,
cb: Box<dyn callbacks::ParseCallbacks>,
) -> Self {
self.options.parse_callbacks = Some(Rc::from(cb));
self.options.parse_callbacks.push(Rc::from(cb));
self
}

Expand Down Expand Up @@ -1982,7 +1982,7 @@ struct BindgenOptions {

/// A user-provided visitor to allow customizing different kinds of
/// situations.
parse_callbacks: Option<Rc<dyn callbacks::ParseCallbacks>>,
parse_callbacks: Vec<Rc<dyn callbacks::ParseCallbacks>>,

/// Which kind of items should we generate? By default, we'll generate all
/// of them.
Expand Down Expand Up @@ -2160,6 +2160,26 @@ impl BindgenOptions {
pub fn rust_features(&self) -> RustFeatures {
self.rust_features
}

fn last_callback<T>(
&self,
f: impl Fn(&dyn crate::callbacks::ParseCallbacks) -> Option<T>,
) -> Option<T> {
self.parse_callbacks
.iter()
.filter_map(|cb| f(cb.as_ref()))
.last()
}

fn all_callbacks<T>(
&self,
f: impl Fn(&dyn crate::callbacks::ParseCallbacks) -> Vec<T>,
) -> Vec<T> {
self.parse_callbacks
.iter()
.flat_map(|cb| f(cb.as_ref()))
.collect()
}
}

impl Default for BindgenOptions {
Expand Down Expand Up @@ -2225,7 +2245,7 @@ impl Default for BindgenOptions {
clang_args: vec![],
input_headers: vec![],
input_header_contents: Default::default(),
parse_callbacks: None,
parse_callbacks: Default::default(),
codegen_config: CodegenConfig::all(),
conservative_inline_namespaces: false,
generate_comments: true,
Expand Down