@@ -51,11 +51,20 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
5151 // This will filter to functions with `extern "C-unwind"` ABIs, for
5252 // example.
5353 for block in body. basic_blocks . as_mut ( ) {
54+ let Some ( terminator) = & mut block. terminator else { continue } ;
55+ let span = terminator. source_info . span ;
56+
57+ // If we see an `UnwindResume` terminator inside a function that cannot unwind, we need
58+ // to replace it with `UnwindTerminate`.
59+ if let TerminatorKind :: UnwindResume = & terminator. kind
60+ && !body_can_unwind
61+ {
62+ terminator. kind = TerminatorKind :: UnwindTerminate ( UnwindTerminateReason :: Abi ) ;
63+ }
64+
5465 if block. is_cleanup {
5566 continue ;
5667 }
57- let Some ( terminator) = & block. terminator else { continue } ;
58- let span = terminator. source_info . span ;
5968
6069 let call_can_unwind = match & terminator. kind {
6170 TerminatorKind :: Call { func, .. } => {
@@ -87,14 +96,18 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
8796 if !call_can_unwind {
8897 // If this function call can't unwind, then there's no need for it
8998 // to have a landing pad. This means that we can remove any cleanup
90- // registered for it.
99+ // registered for it (and turn it into `UnwindAction::Unreachable`) .
91100 let cleanup = block. terminator_mut ( ) . unwind_mut ( ) . unwrap ( ) ;
92101 * cleanup = UnwindAction :: Unreachable ;
93- } else if !body_can_unwind {
102+ } else if !body_can_unwind
103+ && matches ! ( terminator. unwind( ) , Some ( UnwindAction :: Continue ) )
104+ {
94105 // Otherwise if this function can unwind, then if the outer function
95106 // can also unwind there's nothing to do. If the outer function
96- // can't unwind, however, we need to change the landing pad for this
97- // function call to one that aborts.
107+ // can't unwind, however, we need to ensure that any `UnwindAction::Continue`
108+ // is replaced with terminate. For those with `UnwindAction::Cleanup`,
109+ // cleanup will still happen, and terminate will happen afterwards handled by
110+ // the `UnwindResume` -> `UnwindTerminate` terminator replacement.
98111 let cleanup = block. terminator_mut ( ) . unwind_mut ( ) . unwrap ( ) ;
99112 * cleanup = UnwindAction :: Terminate ( UnwindTerminateReason :: Abi ) ;
100113 }
0 commit comments