@@ -51,11 +51,20 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
51
51
// This will filter to functions with `extern "C-unwind"` ABIs, for
52
52
// example.
53
53
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
+
54
65
if block. is_cleanup {
55
66
continue ;
56
67
}
57
- let Some ( terminator) = & block. terminator else { continue } ;
58
- let span = terminator. source_info . span ;
59
68
60
69
let call_can_unwind = match & terminator. kind {
61
70
TerminatorKind :: Call { func, .. } => {
@@ -87,14 +96,18 @@ impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
87
96
if !call_can_unwind {
88
97
// If this function call can't unwind, then there's no need for it
89
98
// 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`) .
91
100
let cleanup = block. terminator_mut ( ) . unwind_mut ( ) . unwrap ( ) ;
92
101
* cleanup = UnwindAction :: Unreachable ;
93
- } else if !body_can_unwind {
102
+ } else if !body_can_unwind
103
+ && matches ! ( terminator. unwind( ) , Some ( UnwindAction :: Continue ) )
104
+ {
94
105
// Otherwise if this function can unwind, then if the outer function
95
106
// 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.
98
111
let cleanup = block. terminator_mut ( ) . unwind_mut ( ) . unwrap ( ) ;
99
112
* cleanup = UnwindAction :: Terminate ( UnwindTerminateReason :: Abi ) ;
100
113
}
0 commit comments