Skip to content

Commit 1598aa4

Browse files
committed
Make destructors on extern "C" frames to be executed
1 parent a3f76a2 commit 1598aa4

File tree

1 file changed

+19
-6
lines changed

1 file changed

+19
-6
lines changed

compiler/rustc_mir_transform/src/abort_unwinding_calls.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)