Skip to content

Commit bd01426

Browse files
eefriedmanbrson
authored andcommitted
Clear cached landing pads before generating a call.
Using the wrong landing pad has obvious bad effects, like dropping a value twice. Testcase written by Alex Crichton. Fixes #25089.
1 parent 7991c0d commit bd01426

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

src/librustc_trans/trans/cleanup.rs

+7
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,15 @@ impl<'blk, 'tcx> CleanupScope<'blk, 'tcx> {
954954
}
955955
}
956956

957+
/// Manipulate cleanup scope for call arguments. Conceptually, each
958+
/// argument to a call is an lvalue, and performing the call moves each
959+
/// of the arguments into a new rvalue (which gets cleaned up by the
960+
/// callee). As an optimization, instead of actually performing all of
961+
/// those moves, trans just manipulates the cleanup scope to obtain the
962+
/// same effect.
957963
pub fn drop_non_lifetime_clean(&mut self) {
958964
self.cleanups.retain(|c| c.is_lifetime_end());
965+
self.clear_cached_exits();
959966
}
960967
}
961968

src/test/run-pass/issue-25089.rs

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::thread;
12+
13+
struct Foo(i32);
14+
15+
impl Drop for Foo {
16+
fn drop(&mut self) {
17+
static mut DROPPED: bool = false;
18+
unsafe {
19+
assert!(!DROPPED);
20+
DROPPED = true;
21+
}
22+
}
23+
}
24+
25+
struct Empty;
26+
27+
fn empty() -> Empty { Empty }
28+
29+
fn should_panic(_: Foo, _: Empty) {
30+
panic!("test panic");
31+
}
32+
33+
fn test() {
34+
should_panic(Foo(1), empty());
35+
}
36+
37+
fn main() {
38+
let ret = thread::spawn(test).join();
39+
assert!(ret.is_err());
40+
}

0 commit comments

Comments
 (0)