@@ -619,6 +619,10 @@ impl Builder {
619
619
output_vector. push ( "--merge-extern-blocks" . into ( ) ) ;
620
620
}
621
621
622
+ if self . options . unsafe_blocks {
623
+ output_vector. push ( "--unsafe-blocks" . into ( ) ) ;
624
+ }
625
+
622
626
// Add clang arguments
623
627
624
628
output_vector. push ( "--" . into ( ) ) ;
@@ -1560,6 +1564,12 @@ impl Builder {
1560
1564
self
1561
1565
}
1562
1566
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
+
1563
1573
/// Generate the Rust bindings using the options built up thus far.
1564
1574
pub fn generate ( mut self ) -> Result < Bindings , BindgenError > {
1565
1575
// Add any extra arguments from the environment to the clang command line.
@@ -2110,6 +2120,9 @@ struct BindgenOptions {
2110
2120
2111
2121
/// Deduplicate `extern` blocks.
2112
2122
merge_extern_blocks : bool ,
2123
+
2124
+ /// Wrap the bodies of `unsafe` functions in `unsafe` blocks
2125
+ unsafe_blocks : bool ,
2113
2126
}
2114
2127
2115
2128
/// 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 {}
2120
2133
impl BindgenOptions {
2121
2134
/// Whether any of the enabled options requires `syn`.
2122
2135
fn require_syn ( & self ) -> bool {
2123
- self . sort_semantically || self . merge_extern_blocks
2136
+ self . sort_semantically || self . merge_extern_blocks || self . unsafe_blocks
2124
2137
}
2125
2138
2126
2139
fn build ( & mut self ) {
@@ -2272,6 +2285,7 @@ impl Default for BindgenOptions {
2272
2285
vtable_generation : false ,
2273
2286
sort_semantically : false ,
2274
2287
merge_extern_blocks : false ,
2288
+ unsafe_blocks : Default :: default ( ) ,
2275
2289
}
2276
2290
}
2277
2291
}
@@ -2653,6 +2667,71 @@ impl Bindings {
2653
2667
} ) ;
2654
2668
}
2655
2669
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
+
2656
2735
let synful_items = syn_parsed_items
2657
2736
. into_iter ( )
2658
2737
. map ( |item| item. into_token_stream ( ) ) ;
0 commit comments