Skip to content

Commit db51120

Browse files
committed
add --unsafe-blocks option
1 parent 6de2d3d commit db51120

File tree

5 files changed

+171
-2
lines changed

5 files changed

+171
-2
lines changed

Cargo.toml

+1-1
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/lib.rs

+80-1
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.
@@ -2110,6 +2120,9 @@ struct BindgenOptions {
21102120

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

21152128
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2120,7 +2133,7 @@ impl ::std::panic::UnwindSafe for BindgenOptions {}
21202133
impl BindgenOptions {
21212134
/// Whether any of the enabled options requires `syn`.
21222135
fn require_syn(&self) -> bool {
2123-
self.sort_semantically || self.merge_extern_blocks
2136+
self.sort_semantically || self.merge_extern_blocks || self.unsafe_blocks
21242137
}
21252138

21262139
fn build(&mut self) {
@@ -2272,6 +2285,7 @@ impl Default for BindgenOptions {
22722285
vtable_generation: false,
22732286
sort_semantically: false,
22742287
merge_extern_blocks: false,
2288+
unsafe_blocks: Default::default(),
22752289
}
22762290
}
22772291
}
@@ -2653,6 +2667,71 @@ impl Bindings {
26532667
});
26542668
}
26552669

2670+
if options.unsafe_blocks {
2671+
struct UnsafeBlocksVisitor;
2672+
2673+
impl UnsafeBlocksVisitor {
2674+
fn add_unsafe_block(
2675+
&self,
2676+
sig: &syn::Signature,
2677+
block: &mut syn::Block,
2678+
) {
2679+
if sig.unsafety.is_some() {
2680+
let inner_block = std::mem::replace(
2681+
block,
2682+
syn::Block {
2683+
brace_token: Default::default(),
2684+
stmts: Default::default(),
2685+
},
2686+
);
2687+
2688+
block.stmts.push(syn::Stmt::Expr(
2689+
syn::Expr::Unsafe(syn::ExprUnsafe {
2690+
attrs: Default::default(),
2691+
block: inner_block,
2692+
unsafe_token: Default::default(),
2693+
}),
2694+
));
2695+
}
2696+
}
2697+
}
2698+
2699+
impl syn::visit_mut::VisitMut for UnsafeBlocksVisitor {
2700+
fn visit_item_fn_mut(&mut self, item: &mut syn::ItemFn) {
2701+
self.add_unsafe_block(&item.sig, &mut item.block);
2702+
2703+
syn::visit_mut::visit_item_fn_mut(self, item)
2704+
}
2705+
2706+
fn visit_impl_item_method_mut(
2707+
&mut self,
2708+
item: &mut syn::ImplItemMethod,
2709+
) {
2710+
self.add_unsafe_block(&item.sig, &mut item.block);
2711+
2712+
syn::visit_mut::visit_impl_item_method_mut(self, item)
2713+
}
2714+
2715+
fn visit_trait_item_method_mut(
2716+
&mut self,
2717+
item: &mut syn::TraitItemMethod,
2718+
) {
2719+
if let Some(ref mut block) = item.default {
2720+
self.add_unsafe_block(&item.sig, block);
2721+
}
2722+
2723+
syn::visit_mut::visit_trait_item_method_mut(self, item)
2724+
}
2725+
}
2726+
2727+
for item in &mut syn_parsed_items {
2728+
syn::visit_mut::visit_item_mut(
2729+
&mut UnsafeBlocksVisitor,
2730+
item,
2731+
);
2732+
}
2733+
}
2734+
26562735
let synful_items = syn_parsed_items
26572736
.into_iter()
26582737
.map(|item| item.into_token_stream());

src/options.rs

+7
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,9 @@ where
563563
Arg::new("merge-extern-blocks")
564564
.long("merge-extern-blocks")
565565
.help("Deduplicates extern blocks."),
566+
Arg::new("unsafe-blocks")
567+
.long("unsafe-blocks")
568+
.help("Wrap all the bodies of generated `unsafe` functions in `unsafe` blocks."),
566569
Arg::new("V")
567570
.long("version")
568571
.help("Prints the version, and exits"),
@@ -1083,5 +1086,9 @@ where
10831086
builder = builder.merge_extern_blocks(true);
10841087
}
10851088

1089+
if matches.is_present("unsafe-blocks") {
1090+
builder = builder.unsafe_blocks(true);
1091+
}
1092+
10861093
Ok((builder, output, verbose))
10871094
}

tests/expectations/tests/unsafe_blocks.rs

+78
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/headers/unsafe_blocks.h

+5
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)