Skip to content

Commit

Permalink
add --unsafe-blocks option
Browse files Browse the repository at this point in the history
  • Loading branch information
pvdrz committed Oct 5, 2022
1 parent 73ce4bc commit e2d471f
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 3 deletions.
7 changes: 7 additions & 0 deletions bindgen-cli/options.rs
Expand Up @@ -568,6 +568,9 @@ where
Arg::new("merge-extern-blocks")
.long("merge-extern-blocks")
.help("Deduplicates extern blocks."),
Arg::new("unsafe-blocks")
.long("unsafe-blocks")
.help("Wrap all the bodies of generated `unsafe` functions in `unsafe` blocks."),
Arg::new("V")
.long("version")
.help("Prints the version, and exits"),
Expand Down Expand Up @@ -1088,5 +1091,9 @@ where
builder = builder.merge_extern_blocks(true);
}

if matches.is_present("unsafe-blocks") {
builder = builder.unsafe_blocks(true);
}

Ok((builder, output, verbose))
}
78 changes: 78 additions & 0 deletions bindgen-tests/tests/expectations/tests/unsafe_blocks.rs

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

5 changes: 5 additions & 0 deletions bindgen-tests/tests/headers/unsafe_blocks.h
@@ -0,0 +1,5 @@
// bindgen-flags: --dynamic-loading TestLib --unsafe-blocks

int foo(int x, int y);
int bar(void *x);
int baz();
2 changes: 1 addition & 1 deletion bindgen/Cargo.toml
Expand Up @@ -45,7 +45,7 @@ lazycell = "1"
lazy_static = "1"
peeking_take_while = "0.1.2"
quote = { version = "1", default-features = false }
syn = { version = "1.0.99", features = ["full", "extra-traits"]}
syn = { version = "1.0.99", features = ["full", "extra-traits", "visit-mut"]}
regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
which = { version = "4.2.1", optional = true, default-features = false }
shlex = "1"
Expand Down
9 changes: 7 additions & 2 deletions bindgen/codegen/postprocessing/mod.rs
Expand Up @@ -6,9 +6,11 @@ use crate::BindgenOptions;

mod merge_extern_blocks;
mod sort_semantically;
mod unsafe_blocks;

use merge_extern_blocks::merge_extern_blocks;
use sort_semantically::sort_semantically;
use unsafe_blocks::unsafe_blocks;

struct PostProcessingPass {
should_run: fn(&BindgenOptions) -> bool,
Expand All @@ -26,8 +28,11 @@ macro_rules! pass {
};
}

const PASSES: &[PostProcessingPass] =
&[pass!(merge_extern_blocks), pass!(sort_semantically)];
const PASSES: &[PostProcessingPass] = &[
pass!(merge_extern_blocks),
pass!(sort_semantically),
pass!(unsafe_blocks),
];

pub(crate) fn postprocessing(
items: Vec<TokenStream>,
Expand Down
62 changes: 62 additions & 0 deletions bindgen/codegen/postprocessing/unsafe_blocks.rs
@@ -0,0 +1,62 @@
use syn::{
visit_mut::{
visit_impl_item_method_mut, visit_item_fn_mut,
visit_trait_item_method_mut, VisitMut,
},
ExprUnsafe, ImplItemMethod, Item, ItemFn, Stmt, TraitItemMethod,
};

pub(crate) fn unsafe_blocks(items: &mut Vec<Item>) {
for item in items {
syn::visit_mut::visit_item_mut(&mut Visitor, item);
}
}

struct Visitor;

impl Visitor {
fn add_unsafe_block(&self, sig: &syn::Signature, block: &mut syn::Block) {
if sig.unsafety.is_none() {
return;
}

let inner_block = std::mem::replace(
block,
syn::Block {
brace_token: Default::default(),
stmts: Default::default(),
},
);

block.stmts.push(Stmt::Expr(
ExprUnsafe {
attrs: Default::default(),
block: inner_block,
unsafe_token: Default::default(),
}
.into(),
));
}
}

impl VisitMut for Visitor {
fn visit_impl_item_method_mut(&mut self, item: &mut ImplItemMethod) {
self.add_unsafe_block(&item.sig, &mut item.block);

visit_impl_item_method_mut(self, item)
}

fn visit_item_fn_mut(&mut self, item: &mut ItemFn) {
self.add_unsafe_block(&item.sig, &mut item.block);

visit_item_fn_mut(self, item)
}

fn visit_trait_item_method_mut(&mut self, item: &mut TraitItemMethod) {
if let Some(ref mut block) = item.default {
self.add_unsafe_block(&item.sig, block);
}

visit_trait_item_method_mut(self, item)
}
}
14 changes: 14 additions & 0 deletions bindgen/lib.rs
Expand Up @@ -619,6 +619,10 @@ impl Builder {
output_vector.push("--merge-extern-blocks".into());
}

if self.options.unsafe_blocks {
output_vector.push("--unsafe-blocks".into());
}

// Add clang arguments

output_vector.push("--".into());
Expand Down Expand Up @@ -1560,6 +1564,12 @@ impl Builder {
self
}

/// If true, wraps all the bodies of generated `unsafe` functions in `unsafe` blocks.
pub fn unsafe_blocks(mut self, doit: bool) -> Self {
self.options.unsafe_blocks = doit;
self
}

/// Generate the Rust bindings using the options built up thus far.
pub fn generate(mut self) -> Result<Bindings, BindgenError> {
// Add any extra arguments from the environment to the clang command line.
Expand Down Expand Up @@ -2105,6 +2115,9 @@ struct BindgenOptions {

/// Deduplicate `extern` blocks.
merge_extern_blocks: bool,

/// Wrap the bodies of `unsafe` functions in `unsafe` blocks
unsafe_blocks: bool,
}

/// TODO(emilio): This is sort of a lie (see the error message that results from
Expand Down Expand Up @@ -2261,6 +2274,7 @@ impl Default for BindgenOptions {
vtable_generation: false,
sort_semantically: false,
merge_extern_blocks: false,
unsafe_blocks: Default::default(),
}
}
}
Expand Down

0 comments on commit e2d471f

Please sign in to comment.