Skip to content

Commit d4ba612

Browse files
committed
add --unsafe-blocks option
1 parent 8b29355 commit d4ba612

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
@@ -592,6 +592,10 @@ impl Builder {
592592
output_vector.push("--sort-semantically".into());
593593
}
594594

595+
if self.options.unsafe_blocks {
596+
output_vector.push("--unsafe-blocks".into());
597+
}
598+
595599
// Add clang arguments
596600

597601
output_vector.push("--".into());
@@ -1489,6 +1493,12 @@ impl Builder {
14891493
self
14901494
}
14911495

1496+
/// If true, wraps all the bodies of generated `unsafe` functions in `unsafe` blocks.
1497+
pub fn unsafe_blocks(mut self, doit: bool) -> Self {
1498+
self.options.unsafe_blocks = doit;
1499+
self
1500+
}
1501+
14921502
/// Generate the Rust bindings using the options built up thus far.
14931503
pub fn generate(mut self) -> Result<Bindings, BindgenError> {
14941504
// Add any extra arguments from the environment to the clang command line.
@@ -2021,6 +2031,9 @@ struct BindgenOptions {
20212031

20222032
/// Sort the code generation
20232033
sort_semantically: bool,
2034+
2035+
/// Wrap the bodies of `unsafe` functions in `unsafe` blocks
2036+
unsafe_blocks: bool,
20242037
}
20252038

20262039
/// TODO(emilio): This is sort of a lie (see the error message that results from
@@ -2031,7 +2044,7 @@ impl ::std::panic::UnwindSafe for BindgenOptions {}
20312044
impl BindgenOptions {
20322045
/// Whether any of the enabled options requires `syn`.
20332046
fn require_syn(&self) -> bool {
2034-
self.sort_semantically
2047+
self.sort_semantically || self.unsafe_blocks
20352048
}
20362049

20372050
fn build(&mut self) {
@@ -2175,6 +2188,7 @@ impl Default for BindgenOptions {
21752188
force_explicit_padding: false,
21762189
vtable_generation: false,
21772190
sort_semantically: false,
2191+
unsafe_blocks: Default::default(),
21782192
}
21792193
}
21802194
}
@@ -2503,6 +2517,71 @@ impl Bindings {
25032517
});
25042518
}
25052519

2520+
if options.unsafe_blocks {
2521+
struct UnsafeBlocksVisitor;
2522+
2523+
impl UnsafeBlocksVisitor {
2524+
fn add_unsafe_block(
2525+
&self,
2526+
sig: &syn::Signature,
2527+
block: &mut syn::Block,
2528+
) {
2529+
if sig.unsafety.is_some() {
2530+
let inner_block = std::mem::replace(
2531+
block,
2532+
syn::Block {
2533+
brace_token: Default::default(),
2534+
stmts: Default::default(),
2535+
},
2536+
);
2537+
2538+
block.stmts.push(syn::Stmt::Expr(
2539+
syn::Expr::Unsafe(syn::ExprUnsafe {
2540+
attrs: Default::default(),
2541+
block: inner_block,
2542+
unsafe_token: Default::default(),
2543+
}),
2544+
));
2545+
}
2546+
}
2547+
}
2548+
2549+
impl syn::visit_mut::VisitMut for UnsafeBlocksVisitor {
2550+
fn visit_item_fn_mut(&mut self, item: &mut syn::ItemFn) {
2551+
self.add_unsafe_block(&item.sig, &mut item.block);
2552+
2553+
syn::visit_mut::visit_item_fn_mut(self, item)
2554+
}
2555+
2556+
fn visit_impl_item_method_mut(
2557+
&mut self,
2558+
item: &mut syn::ImplItemMethod,
2559+
) {
2560+
self.add_unsafe_block(&item.sig, &mut item.block);
2561+
2562+
syn::visit_mut::visit_impl_item_method_mut(self, item)
2563+
}
2564+
2565+
fn visit_trait_item_method_mut(
2566+
&mut self,
2567+
item: &mut syn::TraitItemMethod,
2568+
) {
2569+
if let Some(ref mut block) = item.default {
2570+
self.add_unsafe_block(&item.sig, block);
2571+
}
2572+
2573+
syn::visit_mut::visit_trait_item_method_mut(self, item)
2574+
}
2575+
}
2576+
2577+
for item in &mut syn_parsed_items {
2578+
syn::visit_mut::visit_item_mut(
2579+
&mut UnsafeBlocksVisitor,
2580+
item,
2581+
);
2582+
}
2583+
}
2584+
25062585
let synful_items = syn_parsed_items
25072586
.into_iter()
25082587
.map(|item| item.into_token_stream());

src/options.rs

+7
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,9 @@ where
518518
Arg::new("sort-semantically")
519519
.long("sort-semantically")
520520
.help("Enables sorting of code generation in a predefined manner."),
521+
Arg::new("unsafe-blocks")
522+
.long("unsafe-blocks")
523+
.help("Wrap all the bodies of generated `unsafe` functions in `unsafe` blocks."),
521524
Arg::new("V")
522525
.long("version")
523526
.help("Prints the version, and exits"),
@@ -1007,5 +1010,9 @@ where
10071010
builder = builder.sort_semantically(true);
10081011
}
10091012

1013+
if matches.is_present("unsafe-blocks") {
1014+
builder = builder.unsafe_blocks(true);
1015+
}
1016+
10101017
Ok((builder, output, verbose))
10111018
}

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)