Skip to content

Commit e2d471f

Browse files
committed
add --unsafe-blocks option
1 parent 73ce4bc commit e2d471f

File tree

7 files changed

+174
-3
lines changed

7 files changed

+174
-3
lines changed

bindgen-cli/options.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,9 @@ where
568568
Arg::new("merge-extern-blocks")
569569
.long("merge-extern-blocks")
570570
.help("Deduplicates extern blocks."),
571+
Arg::new("unsafe-blocks")
572+
.long("unsafe-blocks")
573+
.help("Wrap all the bodies of generated `unsafe` functions in `unsafe` blocks."),
571574
Arg::new("V")
572575
.long("version")
573576
.help("Prints the version, and exits"),
@@ -1088,5 +1091,9 @@ where
10881091
builder = builder.merge_extern_blocks(true);
10891092
}
10901093

1094+
if matches.is_present("unsafe-blocks") {
1095+
builder = builder.unsafe_blocks(true);
1096+
}
1097+
10911098
Ok((builder, output, verbose))
10921099
}

bindgen-tests/tests/expectations/tests/unsafe_blocks.rs

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// bindgen-flags: --dynamic-loading TestLib --unsafe-blocks
2+
3+
int foo(int x, int y);
4+
int bar(void *x);
5+
int baz();

bindgen/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ lazycell = "1"
4545
lazy_static = "1"
4646
peeking_take_while = "0.1.2"
4747
quote = { version = "1", default-features = false }
48-
syn = { version = "1.0.99", features = ["full", "extra-traits"]}
48+
syn = { version = "1.0.99", features = ["full", "extra-traits", "visit-mut"]}
4949
regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
5050
which = { version = "4.2.1", optional = true, default-features = false }
5151
shlex = "1"

bindgen/codegen/postprocessing/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ use crate::BindgenOptions;
66

77
mod merge_extern_blocks;
88
mod sort_semantically;
9+
mod unsafe_blocks;
910

1011
use merge_extern_blocks::merge_extern_blocks;
1112
use sort_semantically::sort_semantically;
13+
use unsafe_blocks::unsafe_blocks;
1214

1315
struct PostProcessingPass {
1416
should_run: fn(&BindgenOptions) -> bool,
@@ -26,8 +28,11 @@ macro_rules! pass {
2628
};
2729
}
2830

29-
const PASSES: &[PostProcessingPass] =
30-
&[pass!(merge_extern_blocks), pass!(sort_semantically)];
31+
const PASSES: &[PostProcessingPass] = &[
32+
pass!(merge_extern_blocks),
33+
pass!(sort_semantically),
34+
pass!(unsafe_blocks),
35+
];
3136

3237
pub(crate) fn postprocessing(
3338
items: Vec<TokenStream>,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use syn::{
2+
visit_mut::{
3+
visit_impl_item_method_mut, visit_item_fn_mut,
4+
visit_trait_item_method_mut, VisitMut,
5+
},
6+
ExprUnsafe, ImplItemMethod, Item, ItemFn, Stmt, TraitItemMethod,
7+
};
8+
9+
pub(crate) fn unsafe_blocks(items: &mut Vec<Item>) {
10+
for item in items {
11+
syn::visit_mut::visit_item_mut(&mut Visitor, item);
12+
}
13+
}
14+
15+
struct Visitor;
16+
17+
impl Visitor {
18+
fn add_unsafe_block(&self, sig: &syn::Signature, block: &mut syn::Block) {
19+
if sig.unsafety.is_none() {
20+
return;
21+
}
22+
23+
let inner_block = std::mem::replace(
24+
block,
25+
syn::Block {
26+
brace_token: Default::default(),
27+
stmts: Default::default(),
28+
},
29+
);
30+
31+
block.stmts.push(Stmt::Expr(
32+
ExprUnsafe {
33+
attrs: Default::default(),
34+
block: inner_block,
35+
unsafe_token: Default::default(),
36+
}
37+
.into(),
38+
));
39+
}
40+
}
41+
42+
impl VisitMut for Visitor {
43+
fn visit_impl_item_method_mut(&mut self, item: &mut ImplItemMethod) {
44+
self.add_unsafe_block(&item.sig, &mut item.block);
45+
46+
visit_impl_item_method_mut(self, item)
47+
}
48+
49+
fn visit_item_fn_mut(&mut self, item: &mut ItemFn) {
50+
self.add_unsafe_block(&item.sig, &mut item.block);
51+
52+
visit_item_fn_mut(self, item)
53+
}
54+
55+
fn visit_trait_item_method_mut(&mut self, item: &mut TraitItemMethod) {
56+
if let Some(ref mut block) = item.default {
57+
self.add_unsafe_block(&item.sig, block);
58+
}
59+
60+
visit_trait_item_method_mut(self, item)
61+
}
62+
}

bindgen/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,10 @@ impl Builder {
619619
output_vector.push("--merge-extern-blocks".into());
620620
}
621621

622+
if self.options.unsafe_blocks {
623+
output_vector.push("--unsafe-blocks".into());
624+
}
625+
622626
// Add clang arguments
623627

624628
output_vector.push("--".into());
@@ -1560,6 +1564,12 @@ impl Builder {
15601564
self
15611565
}
15621566

1567+
/// If true, wraps all the bodies of generated `unsafe` functions in `unsafe` blocks.
1568+
pub fn unsafe_blocks(mut self, doit: bool) -> Self {
1569+
self.options.unsafe_blocks = doit;
1570+
self
1571+
}
1572+
15631573
/// Generate the Rust bindings using the options built up thus far.
15641574
pub fn generate(mut self) -> Result<Bindings, BindgenError> {
15651575
// Add any extra arguments from the environment to the clang command line.
@@ -2105,6 +2115,9 @@ struct BindgenOptions {
21052115

21062116
/// Deduplicate `extern` blocks.
21072117
merge_extern_blocks: bool,
2118+
2119+
/// Wrap the bodies of `unsafe` functions in `unsafe` blocks
2120+
unsafe_blocks: bool,
21082121
}
21092122

21102123
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2261,6 +2274,7 @@ impl Default for BindgenOptions {
22612274
vtable_generation: false,
22622275
sort_semantically: false,
22632276
merge_extern_blocks: false,
2277+
unsafe_blocks: Default::default(),
22642278
}
22652279
}
22662280
}

0 commit comments

Comments
 (0)