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 Sep 10, 2022
1 parent 8b29355 commit d4ba612
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -57,7 +57,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
81 changes: 80 additions & 1 deletion src/lib.rs
Expand Up @@ -592,6 +592,10 @@ impl Builder {
output_vector.push("--sort-semantically".into());
}

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

// Add clang arguments

output_vector.push("--".into());
Expand Down Expand Up @@ -1489,6 +1493,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 @@ -2021,6 +2031,9 @@ struct BindgenOptions {

/// Sort the code generation
sort_semantically: 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 All @@ -2031,7 +2044,7 @@ impl ::std::panic::UnwindSafe for BindgenOptions {}
impl BindgenOptions {
/// Whether any of the enabled options requires `syn`.
fn require_syn(&self) -> bool {
self.sort_semantically
self.sort_semantically || self.unsafe_blocks
}

fn build(&mut self) {
Expand Down Expand Up @@ -2175,6 +2188,7 @@ impl Default for BindgenOptions {
force_explicit_padding: false,
vtable_generation: false,
sort_semantically: false,
unsafe_blocks: Default::default(),
}
}
}
Expand Down Expand Up @@ -2503,6 +2517,71 @@ impl Bindings {
});
}

if options.unsafe_blocks {
struct UnsafeBlocksVisitor;

impl UnsafeBlocksVisitor {
fn add_unsafe_block(
&self,
sig: &syn::Signature,
block: &mut syn::Block,
) {
if sig.unsafety.is_some() {
let inner_block = std::mem::replace(
block,
syn::Block {
brace_token: Default::default(),
stmts: Default::default(),
},
);

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

impl syn::visit_mut::VisitMut for UnsafeBlocksVisitor {
fn visit_item_fn_mut(&mut self, item: &mut syn::ItemFn) {
self.add_unsafe_block(&item.sig, &mut item.block);

syn::visit_mut::visit_item_fn_mut(self, item)
}

fn visit_impl_item_method_mut(
&mut self,
item: &mut syn::ImplItemMethod,
) {
self.add_unsafe_block(&item.sig, &mut item.block);

syn::visit_mut::visit_impl_item_method_mut(self, item)
}

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

syn::visit_mut::visit_trait_item_method_mut(self, item)
}
}

for item in &mut syn_parsed_items {
syn::visit_mut::visit_item_mut(
&mut UnsafeBlocksVisitor,
item,
);
}
}

let synful_items = syn_parsed_items
.into_iter()
.map(|item| item.into_token_stream());
Expand Down
7 changes: 7 additions & 0 deletions src/options.rs
Expand Up @@ -518,6 +518,9 @@ where
Arg::new("sort-semantically")
.long("sort-semantically")
.help("Enables sorting of code generation in a predefined manner."),
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 @@ -1007,5 +1010,9 @@ where
builder = builder.sort_semantically(true);
}

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

Ok((builder, output, verbose))
}
78 changes: 78 additions & 0 deletions 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 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();

0 comments on commit d4ba612

Please sign in to comment.