Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
65 changes: 65 additions & 0 deletions bindgen-tests/tests/expectations/tests/allow-item-callback.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions bindgen-tests/tests/expectations/tests/block-item-callback.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions bindgen-tests/tests/headers/allow-item-callback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// bindgen-flags: --allowlist-item 'list_allowed_.*'
// bindgen-parse-callbacks: allow-item

struct allowed_my_struct {
int a;
};

union allowed_my_union {
int a;
double b;
};

enum allowed_my_enum {
ALLOWED_MY_ENUM_A,
ALLOWED_MY_ENUM_B,
};

static const int allowed_my_const = 10;

struct non_allowed_my_struct {
int a;
};

union non_allowed_my_union {
int a;
double b;
};

enum non_allowed_my_enum {
NON_ALLOWED_MY_ENUM_A,
NON_ALLOWED_MY_ENUM_B,
};

static const int non_allowed_my_const = 10;

struct list_allowed_my_struct {
int a;
};
38 changes: 38 additions & 0 deletions bindgen-tests/tests/headers/block-item-callback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// bindgen-flags: --blocklist-item 'list_blocked_.*'
// bindgen-parse-callbacks: block-item

struct blocked_my_struct {
int a;
};

union blocked_my_union {
int a;
double b;
};

enum blocked_my_enum {
BLOCKED_MY_ENUM_A,
BLOCKED_MY_ENUM_B,
};

static const int blocked_my_const = 10;

struct non_blocked_my_struct {
int a;
};

union non_blocked_my_union {
int a;
double b;
};

enum non_blocked_my_enum {
NON_BLOCKED_MY_ENUM_A,
NON_BLOCKED_MY_ENUM_B,
};

static const int non_blocked_my_const = 10;

struct list_blocked_my_struct {
int a;
};
28 changes: 28 additions & 0 deletions bindgen-tests/tests/parse_callbacks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,32 @@ impl ParseCallbacks for OperatorRename {
}
}

#[derive(Debug)]
struct AllowItem;

impl ParseCallbacks for AllowItem {
fn allow_or_block_item(&self, item: &ItemInfo) -> Option<AllowOrBlockItem> {
if item.name.starts_with("allowed_") {
Some(AllowOrBlockItem::Allow)
} else {
None
}
}
}

#[derive(Debug)]
struct BlockItem;

impl ParseCallbacks for BlockItem {
fn allow_or_block_item(&self, item: &ItemInfo) -> Option<AllowOrBlockItem> {
if item.name.starts_with("blocked_") {
Some(AllowOrBlockItem::Block)
} else {
None
}
}
}

pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
match cb {
"enum-variant-rename" => Box::new(EnumVariantRename),
Expand All @@ -169,6 +195,8 @@ pub fn lookup(cb: &str) -> Box<dyn ParseCallbacks> {
"wrap-as-variadic-fn" => Box::new(WrapAsVariadicFn),
"type-visibility" => Box::new(TypeVisibility),
"operator-rename" => Box::new(OperatorRename),
"allow-item" => Box::new(AllowItem),
"block-item" => Box::new(BlockItem),
call_back => {
if let Some(prefix) =
call_back.strip_prefix("remove-function-prefix-")
Expand Down
30 changes: 30 additions & 0 deletions bindgen/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ pub enum MacroParsingBehavior {
Default,
}

/// Enum to indicate if the bindings for a given should be generated or blocked.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum AllowOrBlockItem {
/// Generate the bindings for the given item.
Allow,

/// Block bindings for the given item.
Block,
}

/// A trait to allow configuring different kinds of types in different
/// situations.
pub trait ParseCallbacks: fmt::Debug {
Expand Down Expand Up @@ -206,6 +216,26 @@ pub trait ParseCallbacks: fmt::Debug {
) {
}

/// Generate or block the bindings for the given item.
///
/// This method takes precedences over the `allowlist_*` options.
///
/// If at least one of the parse callbacks returns `Block`, the generation of the bindings
/// for the item is blocked.
///
/// If all the parse callbacks that don't return `None` return `Allow`, the bindings
/// for the item are generated.
///
/// If all the parse callbacks return `None` (the default implementation), the `allowlist_*`
/// options are used instead.
///
fn allow_or_block_item(
&self,
_item: &ItemInfo,
) -> Option<AllowOrBlockItem> {
None
}

// TODO add callback for ResolvedTypeRef
}

Expand Down
35 changes: 30 additions & 5 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use super::BindgenOptions;

use crate::callbacks::{
AttributeInfo, DeriveInfo, DiscoveredItem, DiscoveredItemId,
FieldAttributeInfo, FieldInfo, TypeKind as DeriveTypeKind,
FieldAttributeInfo, FieldInfo, ItemInfo, ItemKind as CallbackItemKind,
TypeKind as DeriveTypeKind,
};
use crate::codegen::error::Error;
use crate::ir::analysis::{HasVtable, Sizedness};
Expand Down Expand Up @@ -5008,7 +5009,18 @@ fn objc_method_codegen(
// Item::process_before_codegen; however, ObjC methods are not currently
// made into function items.
let name = format!("{rust_class_name}::{prefix}{}", method.rust_name());
if ctx.options().blocklisted_items.matches(name) {

let item_info = ItemInfo {
name: &name,
kind: CallbackItemKind::Function,
};

if ctx
.options()
.cb_item_is_blocked(&item_info)
.unwrap_or_else(|| ctx.options().blocklisted_items.matches(&name))
{
// Item is blocked through the parse callbacks or `blocklisted_items`.
return;
}

Expand Down Expand Up @@ -5325,7 +5337,9 @@ pub(crate) mod utils {
use super::helpers::BITFIELD_UNIT;
use super::serialize::CSerialize;
use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque};
use crate::callbacks::DiscoveredItemId;
use crate::callbacks::{
DiscoveredItemId, ItemInfo, ItemKind as CallbackItemKind,
};
use crate::ir::context::BindgenContext;
use crate::ir::context::TypeId;
use crate::ir::function::{Abi, ClangAbi, FunctionSig};
Expand Down Expand Up @@ -5456,9 +5470,20 @@ pub(crate) mod utils {
ctx: &BindgenContext,
result: &mut Vec<proc_macro2::TokenStream>,
) {
if ctx.options().blocklisted_items.matches(BITFIELD_UNIT) ||
ctx.options().blocklisted_types.matches(BITFIELD_UNIT)
let item_info = ItemInfo {
name: BITFIELD_UNIT,
kind: CallbackItemKind::Type,
};

if ctx
.options()
.cb_item_is_blocked(&item_info)
.unwrap_or_else(|| {
ctx.options().blocklisted_items.matches(BITFIELD_UNIT) ||
ctx.options().blocklisted_types.matches(BITFIELD_UNIT)
})
{
// Item is blocked through the parse callbacks or blocklists.
return;
}

Expand Down
13 changes: 13 additions & 0 deletions bindgen/ir/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use super::traversal::{self, Edge, ItemTraversal};
use super::ty::{FloatKind, Type, TypeKind};
use crate::clang::{self, ABIKind, Cursor};
use crate::codegen::CodegenError;
use crate::ir::item::ItemCanonicalName;
use crate::BindgenOptions;
use crate::{Entry, HashMap, HashSet};

Expand Down Expand Up @@ -2406,6 +2407,18 @@ If you encounter an error missing from this list, please file an issue or a PR!"
// Only consider roots that are enabled for codegen.
.filter(|&(_, item)| item.is_enabled_for_codegen(self))
.filter(|&(_, item)| {
let item_info = crate::callbacks::ItemInfo {
name: &item.canonical_name(self),
kind: item.callback_item_kind(),
};

if let Some(is_cb_allow) =
self.options().cb_item_is_allowed(&item_info)
{
// Item is allowed or not with the parse callbacks.
return is_cb_allow;
}

// If nothing is explicitly allowlisted, then everything is fair
// game.
if self.options().allowlisted_types.is_empty() &&
Expand Down
Loading
Loading