Skip to content

Commit 7160f2e

Browse files
committed
add --unsafe-blocks option
1 parent b5ec18e commit 7160f2e

File tree

7 files changed

+168
-2
lines changed

7 files changed

+168
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ lazycell = "1"
5757
lazy_static = "1"
5858
peeking_take_while = "0.1.2"
5959
quote = { version = "1", default-features = false }
60-
syn = { version = "1.0.99", features = ["full", "extra-traits"]}
60+
syn = { version = "1.0.99", features = ["full", "extra-traits", "visit-mut"]}
6161
regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
6262
which = { version = "4.2.1", optional = true, default-features = false }
6363
shlex = "1"

src/codegen/postprocessing/mod.rs

Lines changed: 3 additions & 1 deletion
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,
@@ -27,7 +29,7 @@ macro_rules! pass {
2729
}
2830

2931
const PASSES: &[PostProcessingPass] =
30-
&[pass!(merge_extern_blocks), pass!(sort_semantically)];
32+
&[pass!(merge_extern_blocks), pass!(sort_semantically), pass!(unsafe_blocks)];
3133

3234
pub(crate) fn postprocessing(
3335
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, 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_some() {
20+
let inner_block = std::mem::replace(
21+
block,
22+
syn::Block {
23+
brace_token: Default::default(),
24+
stmts: Default::default(),
25+
},
26+
);
27+
28+
block.stmts.push(Stmt::Expr(
29+
ExprUnsafe {
30+
attrs: Default::default(),
31+
block: inner_block,
32+
unsafe_token: Default::default(),
33+
}
34+
.into(),
35+
));
36+
}
37+
}
38+
}
39+
40+
impl VisitMut for Visitor {
41+
fn visit_item_fn_mut(&mut self, item: &mut ItemFn) {
42+
self.add_unsafe_block(&item.sig, &mut item.block);
43+
44+
visit_item_fn_mut(self, item)
45+
}
46+
47+
fn visit_impl_item_method_mut(&mut self, item: &mut ImplItemMethod) {
48+
self.add_unsafe_block(&item.sig, &mut item.block);
49+
50+
visit_impl_item_method_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+
}

src/lib.rs

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

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

623627
output_vector.push("--".into());
@@ -1559,6 +1563,12 @@ impl Builder {
15591563
self
15601564
}
15611565

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

21102120
/// Deduplicate `extern` blocks.
21112121
merge_extern_blocks: bool,
2122+
2123+
/// Wrap the bodies of `unsafe` functions in `unsafe` blocks
2124+
unsafe_blocks: bool,
21122125
}
21132126

21142127
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2266,6 +2279,7 @@ impl Default for BindgenOptions {
22662279
vtable_generation: false,
22672280
sort_semantically: false,
22682281
merge_extern_blocks: false,
2282+
unsafe_blocks: Default::default(),
22692283
}
22702284
}
22712285
}

src/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
}

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.

tests/headers/unsafe_blocks.h

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();

0 commit comments

Comments
 (0)