Skip to content

Commit 8c9bc80

Browse files
committed
add --unsafe-blocks option
1 parent 9c32b46 commit 8c9bc80

File tree

6 files changed

+171
-2
lines changed

6 files changed

+171
-2
lines changed

bindgen-cli/options.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,9 @@ where
574574
.value_name("override")
575575
.multiple_occurrences(true)
576576
.number_of_values(1),
577+
Arg::new("unsafe-blocks")
578+
.long("unsafe-blocks")
579+
.help("Wrap all the bodies of generated `unsafe` functions in `unsafe` blocks."),
577580
Arg::new("V")
578581
.long("version")
579582
.help("Prints the version, and exits"),
@@ -1106,5 +1109,9 @@ where
11061109
}
11071110
}
11081111

1112+
if matches.is_present("unsafe-blocks") {
1113+
builder = builder.unsafe_blocks(true);
1114+
}
1115+
11091116
Ok((builder, output, verbose))
11101117
}

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

bindgen/lib.rs

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

627+
if self.options.unsafe_blocks {
628+
output_vector.push("--unsafe-blocks".into());
629+
}
630+
627631
// Add clang arguments
628632

629633
output_vector.push("--".into());
@@ -1566,6 +1570,12 @@ impl Builder {
15661570
self
15671571
}
15681572

1573+
/// If true, wraps all the bodies of generated `unsafe` functions in `unsafe` blocks.
1574+
pub fn unsafe_blocks(mut self, doit: bool) -> Self {
1575+
self.options.unsafe_blocks = doit;
1576+
self
1577+
}
1578+
15691579
/// Generate the Rust bindings using the options built up thus far.
15701580
pub fn generate(self) -> Result<Bindings, BindgenError> {
15711581
let mut options = self.options.clone();
@@ -2129,6 +2139,9 @@ struct BindgenOptions {
21292139
merge_extern_blocks: bool,
21302140

21312141
abi_overrides: HashMap<Abi, RegexSet>,
2142+
2143+
/// Wrap the bodies of `unsafe` functions in `unsafe` blocks
2144+
unsafe_blocks: bool,
21322145
}
21332146

21342147
impl BindgenOptions {
@@ -2301,6 +2314,7 @@ impl Default for BindgenOptions {
23012314
sort_semantically: false,
23022315
merge_extern_blocks: false,
23032316
abi_overrides: Default::default(),
2317+
unsafe_blocks: Default::default(),
23042318
}
23052319
}
23062320
}

0 commit comments

Comments
 (0)