@@ -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 {}
20312044impl 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 ( ) ) ;
0 commit comments