Skip to content

Commit 20338d9

Browse files
authored
Move unique_ptr translation in rules (#543)
1 parent 05b75bf commit 20338d9

50 files changed

Lines changed: 1624 additions & 777 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎cpp2rust/converter/converter.cpp‎

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,6 @@ std::vector<std::string> Converter::global_inits_;
3434
Converter::RecordIndex Converter::record_decls_;
3535
std::map<std::string, Converter::DeferredBlock> Converter::virtual_methods_;
3636

37-
void Converter::ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr) {
38-
bool is_star = expr->getOperator() == clang::OverloadedOperatorKind::OO_Star;
39-
PushParen paren(*this, is_star);
40-
if (is_star) {
41-
StrCat(token::kStar);
42-
}
43-
if (expr->getArg(0)->IgnoreImplicit()->getType().isConstQualified()) {
44-
StrCat("(*(std::ptr::addr_of!(");
45-
Convert(expr->getArg(0));
46-
StrCat(").cast_mut())).as_deref_mut().unwrap()");
47-
} else {
48-
Convert(expr->getArg(0));
49-
StrCat(".as_deref_mut().unwrap()");
50-
}
51-
}
52-
5337
void Converter::EmitFilePreamble() {
5438
StrCat(R"(
5539
extern crate libc;
@@ -3345,9 +3329,7 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) {
33453329
break;
33463330
case clang::OverloadedOperatorKind::OO_Star:
33473331
case clang::OverloadedOperatorKind::OO_Arrow:
3348-
if (IsUniquePtr(expr->getArg(0)->getType())) {
3349-
ConvertUniquePtrDeref(expr);
3350-
} else if (expr->getOperator() == clang::OverloadedOperatorKind::OO_Star) {
3332+
if (expr->getOperator() == clang::OverloadedOperatorKind::OO_Star) {
33513333
PushParen paren(*this);
33523334
StrCat(token::kStar);
33533335
Convert(expr->getArg(0));
@@ -3372,8 +3354,7 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) {
33723354
} else {
33733355
base_vars = GetAllVars(base);
33743356
}
3375-
if (!IsUniquePtr(base->getType()) &&
3376-
std::ranges::any_of(GetAllVars(idx), [&](const clang::ValueDecl *var) {
3357+
if (std::ranges::any_of(GetAllVars(idx), [&](const clang::ValueDecl *var) {
33773358
return base_vars.contains(var);
33783359
})) {
33793360
std::string idx_str;
@@ -4539,8 +4520,7 @@ void Converter::ConvertUnsignedArithOperand(clang::Expr *expr,
45394520
void Converter::ConvertEqualsNullPtr(clang::Expr *expr) {
45404521
StrCat('(');
45414522
Convert(expr);
4542-
if (IsUniquePtr(expr->getType()) ||
4543-
expr->getType()->isFunctionPointerType()) {
4523+
if (expr->getType()->isFunctionPointerType()) {
45444524
StrCat(").is_none()");
45454525
} else {
45464526
StrCat(").is_null()");
@@ -4614,13 +4594,7 @@ void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx,
46144594
return;
46154595
}
46164596
}
4617-
if (IsUniquePtr(base->getType())) {
4618-
PushExplicitAutoref no_autoref(*this, std::nullopt);
4619-
Convert(base->IgnoreImplicit());
4620-
StrCat(".as_mut().unwrap()");
4621-
} else {
4622-
Convert(base->IgnoreImplicit());
4623-
}
4597+
Convert(base->IgnoreImplicit());
46244598
PushExplicitAutoref no_autoref(*this, std::nullopt);
46254599
PushBracket bracket(*this);
46264600
{

‎cpp2rust/converter/converter.h‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -753,8 +753,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
753753
virtual void ConvertLoopVariable(clang::VarDecl *decl,
754754
clang::Expr *range_init);
755755

756-
virtual void ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr);
757-
758756
virtual bool ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr);
759757

760758
std::string GetMappedAsString(clang::Expr *expr, clang::Expr **args = nullptr,

‎cpp2rust/converter/models/boxed_vars.cpp‎

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,19 +147,6 @@ class AddressTakenVisitor
147147
AddValueUse(expr->getArg(0), /*write=*/true);
148148
AddValueUse(IgnoreNoOpCasts(expr->getArg(1)));
149149
}
150-
// Dereferencing a unique_ptr reads the pointer it holds; the object it
151-
// points to is not stored in the unique_ptr.
152-
switch (expr->getOperator()) {
153-
case clang::OO_Subscript:
154-
case clang::OO_Star:
155-
case clang::OO_Arrow:
156-
if (IsUniquePtr(expr->getArg(0)->getType())) {
157-
AddValueUse(IgnoreNoOpCasts(expr->getArg(0)));
158-
}
159-
break;
160-
default:
161-
break;
162-
}
163150
return true;
164151
}
165152

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 6 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ static bool IsArrayFieldPtr(clang::ASTContext &ctx, const clang::Expr *expr) {
8989
// Whether `expr` is a field of an element of a std::vector, whose arrays and
9090
// vectors are accessed through the place of the element, which is never
9191
// reinterpreted memory.
92-
static bool IsFieldOfVectorElem(const clang::MemberExpr *expr) {
92+
static bool IsFieldOfVectorElem(clang::ASTContext &ctx,
93+
const clang::MemberExpr *expr) {
9394
auto *op = clang::dyn_cast<clang::CXXOperatorCallExpr>(
9495
expr->getBase()->IgnoreParenImpCasts());
9596
return !expr->isArrow() && op && op->getOperator() == clang::OO_Subscript &&
96-
!IsUniquePtr(op->getArg(0)->getType());
97+
!Mapper::Contains(ctx, op);
9798
}
9899

99100
static bool IsPointerType(clang::ASTContext &ctx, clang::QualType type) {
@@ -175,8 +176,7 @@ bool ConverterRefCount::IsUnboxedPlace(const clang::Expr *expr) const {
175176
}
176177
if (auto *op = clang::dyn_cast<clang::CXXOperatorCallExpr>(expr)) {
177178
return op->getOperator() == clang::OO_Subscript &&
178-
!IsUniquePtr(op->getArg(0)->getType()) &&
179-
IsUnboxedPlace(op->getArg(0));
179+
!Mapper::Contains(ctx_, op) && IsUnboxedPlace(op->getArg(0));
180180
}
181181
auto *ref = clang::dyn_cast<clang::DeclRefExpr>(expr);
182182
return ref && IsUnboxedVar(ref->getDecl());
@@ -2811,20 +2811,6 @@ void ConverterRefCount::ConvertGenericBinaryOperator(
28112811
computed_expr_type_ = ComputedExprType::FreshValue;
28122812
}
28132813

2814-
void ConverterRefCount::ConvertUniquePtrDeref(
2815-
clang::CXXOperatorCallExpr *expr) {
2816-
if (isAddrOf()) {
2817-
StrCat(ConvertRValue(expr->getArg(0)), ".as_pointer()");
2818-
computed_expr_type_ = ComputedExprType::FreshPointer;
2819-
} else {
2820-
// The object is modified through its own Value.
2821-
StrCat(std::format("(*{}.as_ref().unwrap().borrow{}())",
2822-
ConvertRValue(expr->getArg(0)),
2823-
isRValue() ? "" : "_mut"));
2824-
SetValueFreshness(expr->getType());
2825-
}
2826-
}
2827-
28282814
bool ConverterRefCount::ConvertCXXOperatorCallExpr(
28292815
clang::CXXOperatorCallExpr *expr) {
28302816
switch (expr->getOperator()) {
@@ -2834,11 +2820,6 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
28342820

28352821
case clang::OverloadedOperatorKind::OO_Arrow:
28362822
case clang::OverloadedOperatorKind::OO_Star:
2837-
if (IsUniquePtr(expr->getArg(0)->getType())) {
2838-
ConvertUniquePtrDeref(expr);
2839-
break;
2840-
}
2841-
28422823
if (isLValue()) {
28432824
auto ptr = ToString(expr->getArg(0));
28442825
pending_deref_.set(std::move(ptr), isFresh());
@@ -2860,24 +2841,6 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
28602841
break;
28612842

28622843
case clang::OverloadedOperatorKind::OO_Subscript: {
2863-
if (IsUniquePtr(expr->getArg(0)->getType())) {
2864-
StrCat(
2865-
std::format("{}.as_ref().unwrap()", ConvertRValue(expr->getArg(0))));
2866-
if (isAddrOf()) {
2867-
StrCat(std::format(".as_pointer().offset(({}))",
2868-
ConvertRValue(expr->getArg(1))));
2869-
} else {
2870-
if (isRValue()) {
2871-
StrCat(".borrow()");
2872-
} else {
2873-
StrCat(".borrow_mut()");
2874-
}
2875-
StrCat(std::format("[({}) as usize]", ConvertRValue(expr->getArg(1))));
2876-
}
2877-
SetValueFreshness(expr->getType());
2878-
break;
2879-
}
2880-
28812844
bool is_inner_boxed =
28822845
IsBoxedType(ctx_, expr->getType().getNonReferenceType()) &&
28832846
IsBoxedType(ctx_, expr->getArg(0)->getType().getNonReferenceType());
@@ -2995,7 +2958,7 @@ std::string ConverterRefCount::ConvertElemPlace(clang::Expr *container,
29952958
!IsUnboxedPlace(member) &&
29962959
Mapper::Map(ctx_, field->getType().getUnqualifiedType())
29972960
.starts_with("Vec<")) {
2998-
if (IsFieldOfVectorElem(member)) {
2961+
if (IsFieldOfVectorElem(ctx_, member)) {
29992962
return std::format("index!({}, {})", ConvertPlace(member),
30002963
ConvertSubscriptIndex(idx));
30012964
}
@@ -3136,7 +3099,7 @@ void ConverterRefCount::ConvertPointerElem(clang::Expr *base,
31363099
// An element of an array field is accessed in place, through the struct.
31373100
if (IsArrayFieldPtr(ctx_, base)) {
31383101
auto *member = clang::cast<clang::MemberExpr>(base->IgnoreParenImpCasts());
3139-
if (IsFieldOfVectorElem(member)) {
3102+
if (IsFieldOfVectorElem(ctx_, member)) {
31403103
StrCat(std::format("index!({}, {})", ConvertPlace(member),
31413104
ConvertRValue(idx)));
31423105
computed_expr_type_ = ComputedExprType::FreshPointer;

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,6 @@ class ConverterRefCount final : public Converter {
285285
void ConvertAssignment(clang::Expr *lhs, clang::Expr *rhs,
286286
std::string_view assign_operator) override;
287287

288-
void ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr) override;
289-
290288
bool ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) override;
291289

292290
void ConvertFunctionParameters(clang::FunctionDecl *decl) override;

‎rules/unique_ptr/src.cpp‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,21 @@ std::unique_ptr<T1[]> &f15(std::unique_ptr<T1[]> &dst,
6363
std::unique_ptr<T1[]> &&src) {
6464
return dst = std::move(src);
6565
}
66+
67+
template <typename T1> T1 &f17(const std::unique_ptr<T1> &o) { return *o; }
68+
69+
template <typename T1> T1 *f18(const std::unique_ptr<T1> &o) {
70+
return o.operator->();
71+
}
72+
73+
template <typename T1> T1 &f19(const std::unique_ptr<T1[]> &o, std::size_t i) {
74+
return o[i];
75+
}
76+
77+
template <typename T1> bool f20(const std::unique_ptr<T1> &o, std::nullptr_t) {
78+
return o == nullptr;
79+
}
80+
81+
template <typename T1> bool f21(const std::unique_ptr<T1> &o, std::nullptr_t) {
82+
return o != nullptr;
83+
}

‎rules/unique_ptr/tgt_refcount.rs‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,23 @@ fn f14<T1: ByteRepr>(a0: Ptr<Option<Value<T1>>>, a1: &mut Option<Value<T1>>) {
7979
fn f15<T1: ByteRepr>(a0: Ptr<Option<Value<Box<[T1]>>>>, a1: &mut Option<Value<Box<[T1]>>>) {
8080
a0.write(a1.take())
8181
}
82+
83+
fn f17<T1>(a0: Value<T1>) -> Ptr<T1> {
84+
a0.as_pointer()
85+
}
86+
87+
fn f18<T1>(a0: Value<T1>) -> Ptr<T1> {
88+
a0.as_pointer()
89+
}
90+
91+
fn f19<T1>(a0: Value<T1>, a1: usize) -> Ptr<T1> {
92+
(a0.as_pointer() as Ptr<T1>).offset(a1 as isize)
93+
}
94+
95+
fn f20<T1>(a0: Option<Value<T1>>) -> bool {
96+
a0.is_none()
97+
}
98+
99+
fn f21<T1>(a0: Option<Value<T1>>) -> bool {
100+
a0.is_some()
101+
}

‎rules/unique_ptr/tgt_unsafe.rs‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,27 @@ unsafe fn f14<T1>(a0: &mut Option<Box<T1>>, a1: &mut Option<Box<T1>>) {
7373
unsafe fn f15<T1>(a0: &mut Option<Box<[T1]>>, a1: &mut Option<Box<[T1]>>) {
7474
*a0 = a1.take()
7575
}
76+
77+
unsafe fn f17<T1>(a0: &mut Option<Box<T1>>) -> *mut T1 {
78+
a0.as_deref()
79+
.map_or(::std::ptr::null_mut(), |v| v as *const T1 as *mut T1)
80+
}
81+
82+
unsafe fn f18<T1>(a0: &mut Option<Box<T1>>) -> *mut T1 {
83+
a0.as_deref()
84+
.map_or(::std::ptr::null_mut(), |v| v as *const T1 as *mut T1)
85+
}
86+
87+
unsafe fn f19<T1>(a0: &mut Option<Box<[T1]>>, a1: usize) -> *mut T1 {
88+
a0.as_deref()
89+
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut T1)
90+
.add(a1)
91+
}
92+
93+
unsafe fn f20<T1>(a0: &mut Option<Box<T1>>) -> bool {
94+
a0.is_none()
95+
}
96+
97+
unsafe fn f21<T1>(a0: &mut Option<Box<T1>>) -> bool {
98+
a0.is_some()
99+
}

‎tests/ub/out/refcount/ub6.rs‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,22 @@ pub fn fill_1(arr: Ptr<Option<Value<Box<[Ptr<i32>]>>>>, n1: Ptr<i32>) {
3131
mkPair_0(_x1, _x2)
3232
}),
3333
));
34-
(*arr.upgrade().deref()).as_ref().unwrap().borrow_mut()[(0_usize) as usize] =
35-
({ (*pair.borrow()).x1.clone() }).clone();
36-
(*arr.upgrade().deref()).as_ref().unwrap().borrow_mut()[(1_usize) as usize] =
37-
({ (*pair.borrow()).x2.clone() }).clone();
34+
((*arr.upgrade().deref()).as_pointer() as Ptr<Ptr<i32>>)
35+
.offset(0_usize as isize)
36+
.write(({ (*pair.borrow()).x1.clone() }).clone());
37+
((*arr.upgrade().deref()).as_pointer() as Ptr<Ptr<i32>>)
38+
.offset(1_usize as isize)
39+
.write(({ (*pair.borrow()).x2.clone() }).clone());
3840
}
3941
pub fn any_2(arr: Ptr<Option<Value<Box<[Ptr<i32>]>>>>, n1: Ptr<i32>) -> bool {
4042
let mut out: bool = false;
4143
let mut i: i32 = 0;
4244
'loop_: while ({ i } < { (n1.read()) }) {
4345
let __rhs = (out)
44-
|| (((*arr.upgrade().deref()).as_ref().unwrap().borrow()[(i as usize) as usize]
46+
|| (((((*arr.upgrade().deref()).as_pointer() as Ptr<Ptr<i32>>)
47+
.offset((i as usize) as isize)
4548
.read())
49+
.read())
4650
== 0);
4751
out = __rhs;
4852
i.prefix_inc();

‎tests/ub/out/unsafe/ub6.rs‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,25 @@ pub unsafe fn fill_1(arr: *mut Option<Box<[*mut i32]>>, n1: *mut i32) {
2222
let _x2: *mut i32 = &mut n2;
2323
mkPair_0(_x1, _x2)
2424
});
25-
(*arr).as_mut().unwrap()[(0_usize)] = (pair.x1);
26-
(*arr).as_mut().unwrap()[(1_usize)] = (pair.x2);
25+
(*(*arr)
26+
.as_deref()
27+
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut *mut i32)
28+
.add(0_usize)) = (pair.x1);
29+
(*(*arr)
30+
.as_deref()
31+
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut *mut i32)
32+
.add(1_usize)) = (pair.x2);
2733
}
2834
pub unsafe fn any_2(arr: *mut Option<Box<[*mut i32]>>, n1: *mut i32) -> bool {
2935
let mut out: bool = false;
3036
let mut i: i32 = 0;
3137
'loop_: while ((i) < (*n1)) {
32-
out = (out) || ((*(*arr).as_mut().unwrap()[(i as usize)]) == (0));
38+
out = (out)
39+
|| ((*(*(*arr)
40+
.as_deref()
41+
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut *mut i32)
42+
.add((i as usize))))
43+
== (0));
3344
i.prefix_inc();
3445
}
3546
return out;

0 commit comments

Comments
 (0)