Skip to content

Commit d16fb00

Browse files
authored
Call take on unique_ptr in unsafe (#339)
After a `std::move` from a `std::unique_ptr`, C++ nulls the unique_ptr. Refcount already did that, unsafe did not. Also call `take()` in unsafe to null the pointer.
1 parent 6930ba5 commit d16fb00

11 files changed

Lines changed: 27 additions & 21 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,11 @@ bool Converter::VisitCallExpr(clang::CallExpr *expr) {
17181718
}
17191719

17201720
if (expr->isCallToStdMove()) {
1721+
if (IsUniquePtr(expr->getArg(0)->getType())) {
1722+
StrCat(std::format("{}.take()", ConvertLValue(expr->getArg(0))));
1723+
computed_expr_type_ = ComputedExprType::FreshValue;
1724+
return false;
1725+
}
17211726
StrCat(std::format("{}", ToString(expr->getArg(0))));
17221727
computed_expr_type_ = ComputedExprType::FreshValue;
17231728
return false;

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,13 +1030,7 @@ bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
10301030
}
10311031

10321032
if (expr->isCallToStdMove()) {
1033-
if (IsUniquePtr(expr->getArg(0)->getType())) {
1034-
StrCat(std::format("{}.take()", ConvertLValue(expr->getArg(0))));
1035-
} else {
1036-
Convert(expr->getArg(0));
1037-
}
1038-
computed_expr_type_ = ComputedExprType::FreshValue;
1039-
return false;
1033+
return Converter::VisitCallExpr(expr);
10401034
}
10411035

10421036
if (auto *opcall = clang::dyn_cast<clang::CXXOperatorCallExpr>(expr);

‎tests/unit/11_move.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
void change(std::unique_ptr<int> &n) {
88
std::unique_ptr<int> m = std::make_unique<int>(20);
99
n = std::move(m);
10+
assert(m.get() == nullptr);
1011
}
1112

1213
int main() {

‎tests/unit/out/refcount/11_move.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub fn change_0(n: Ptr<Option<Value<i32>>>) {
1010
let m: Value<Option<Value<i32>>> = Rc::new(RefCell::new(Some(Rc::new(RefCell::new(20)))));
1111
let __rhs = (*m.borrow_mut()).take();
1212
n.write(__rhs);
13+
assert!(((*m.borrow()).as_pointer()).is_null());
1314
}
1415
pub fn main() {
1516
std::process::exit(main_0());

‎tests/unit/out/unsafe/07_unique.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ unsafe fn main_0() -> i32 {
2525
let mut f_ptr2: *mut i32 = (&mut (*f.as_deref_mut().unwrap()) as *mut i32);
2626
(*f_ptr2) = 11;
2727
f = Some(Box::new(9));
28-
f = (unsafe { fn_0(f) });
28+
f = (unsafe { fn_0(f.take()) });
2929
assert!(((*f.as_deref_mut().unwrap()) == (10)));
3030
return 0;
3131
}

‎tests/unit/out/unsafe/11_move.rs‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
88
use std::rc::Rc;
99
pub unsafe fn change_0(n: *mut Option<Box<i32>>) {
1010
let mut m: Option<Box<i32>> = Some(Box::new(20));
11-
(*n) = m;
11+
(*n) = m.take();
12+
assert!(
13+
(m.as_deref_mut()
14+
.map_or(::std::ptr::null_mut(), |v| v as *mut i32))
15+
.is_null()
16+
);
1217
}
1318
pub fn main() {
1419
unsafe {

‎tests/unit/out/unsafe/alloc_array.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub unsafe fn All_0(arr: *mut Option<Box<[i32]>>, mut N: i32, mut element: i32)
1717
all.as_mut().unwrap()[(i as usize)] = element;
1818
i.prefix_inc();
1919
}
20-
(*arr) = all;
20+
(*arr) = all.take();
2121
}
2222
pub unsafe fn Consume_1(mut arr: Option<Box<[i32]>>, mut N: i32) -> i32 {
2323
let mut sum: i32 = 0;
@@ -40,6 +40,6 @@ unsafe fn main_0() -> i32 {
4040
.collect::<Box<[_]>>(),
4141
);
4242
(unsafe { All_0(&mut arr as *mut Option<Box<[i32]>>, N, 1) });
43-
assert!(((unsafe { Consume_1(arr, N,) }) == (10)));
43+
assert!(((unsafe { Consume_1(arr.take(), N,) }) == (10)));
4444
return 0;
4545
}

‎tests/unit/out/unsafe/matmul.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ unsafe fn main_0() -> i32 {
6666
let mut m1: Option<Box<[Option<Box<[i32]>>]>> = (unsafe { matalloc_0(n, p, 1) });
6767
let mut m2: Option<Box<[Option<Box<[i32]>>]>> = (unsafe { matalloc_0(p, n, 2) });
6868
let mut m3: Option<Box<[Option<Box<[i32]>>]>> = (unsafe {
69-
let _m1: Option<Box<[Option<Box<[i32]>>]>> = m1;
69+
let _m1: Option<Box<[Option<Box<[i32]>>]>> = m1.take();
7070
let _n1: i32 = n;
7171
let _p1: i32 = p;
72-
let _m2: Option<Box<[Option<Box<[i32]>>]>> = m2;
72+
let _m2: Option<Box<[Option<Box<[i32]>>]>> = m2.take();
7373
let _n2: i32 = p;
7474
let _p2: i32 = n;
7575
matmul_1(_m1, _n1, _p1, _m2, _n2, _p2)

‎tests/unit/out/unsafe/references2.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
88
use std::rc::Rc;
99
pub unsafe fn change_0(p: *mut Option<Box<i32>>) {
1010
let mut q: Option<Box<i32>> = Some(Box::new(7));
11-
(*p) = q;
11+
(*p) = q.take();
1212
}
1313
pub fn main() {
1414
unsafe {

‎tests/unit/out/unsafe/unique_ptr.rs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ pub unsafe fn DoStuffWithSafePointer_0(safe_ptr: *mut Option<Box<SafePointer>>)
3232
let mut x1: Option<Box<i32>> = Some(Box::new(0));
3333
let mut x2: Option<Box<i32>> = Some(Box::new(0));
3434
(*x2.as_deref_mut().unwrap()) = 1;
35-
x1 = x2;
35+
x1 = x2.take();
3636
let mut raw_ptr1: *mut i32 = (&mut (*x1.as_deref_mut().unwrap()) as *mut i32);
3737
(*raw_ptr1).prefix_inc();
38-
(*(*safe_ptr).as_deref_mut().unwrap()).ptr = x1;
38+
(*(*safe_ptr).as_deref_mut().unwrap()).ptr = x1.take();
3939
(unsafe { SafePointer::inc(&mut (*(*safe_ptr).as_deref_mut().unwrap())) });
4040
(unsafe { SafePointer::inc(&mut (*(*safe_ptr).as_deref_mut().unwrap())) });
4141
let mut x3: Option<Box<i32>> = Some(Box::new(10));
4242
let mut x4: Option<Box<i32>> = Some(Box::new(20));
4343
(*x3.as_deref_mut().unwrap()) = ((*x3.as_deref_mut().unwrap()) + (*x4.as_deref_mut().unwrap()));
44-
x4 = x3;
44+
x4 = x3.take();
4545
let mut raw_ptr2: *mut i32 = (&mut (*x4.as_deref_mut().unwrap()) as *mut i32);
4646
(*raw_ptr2) += 1;
4747
let mut pair: Option<Box<Pair>> = Some(Box::new(Pair {
@@ -60,7 +60,7 @@ pub unsafe fn DoStuffWithSafePointer_0(safe_ptr: *mut Option<Box<SafePointer>>)
6060
+ ((*pair.as_deref_mut().unwrap()).y));
6161
}
6262
pub unsafe fn Consume_1(mut safe_ptr: Option<Box<SafePointer>>) -> i32 {
63-
let mut x: Option<Box<SafePointer>> = safe_ptr;
63+
let mut x: Option<Box<SafePointer>> = safe_ptr.take();
6464
let mut p: Option<Box<Pair>> = Some(Box::from_raw(
6565
(Box::leak(Box::new(<Pair>::default())) as *mut Pair),
6666
));
@@ -149,8 +149,8 @@ pub fn main() {
149149
}
150150
unsafe fn main_0() -> i32 {
151151
let mut x: Option<Box<i32>> = Some(Box::new(0));
152-
let mut safe_ptr: Option<Box<SafePointer>> = Some(Box::new(SafePointer { ptr: x }));
152+
let mut safe_ptr: Option<Box<SafePointer>> = Some(Box::new(SafePointer { ptr: x.take() }));
153153
(unsafe { DoStuffWithSafePointer_0(&mut safe_ptr as *mut Option<Box<SafePointer>>) });
154-
assert!(((unsafe { Consume_1(safe_ptr,) }) == (60)));
154+
assert!(((unsafe { Consume_1(safe_ptr.take(),) }) == (60)));
155155
return 0;
156156
}

0 commit comments

Comments
 (0)