Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 4 additions & 30 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,6 @@ std::vector<std::string> Converter::global_inits_;
Converter::RecordIndex Converter::record_decls_;
std::map<std::string, Converter::DeferredBlock> Converter::virtual_methods_;

void Converter::ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr) {
bool is_star = expr->getOperator() == clang::OverloadedOperatorKind::OO_Star;
PushParen paren(*this, is_star);
if (is_star) {
StrCat(token::kStar);
}
if (expr->getArg(0)->IgnoreImplicit()->getType().isConstQualified()) {
StrCat("(*(std::ptr::addr_of!(");
Convert(expr->getArg(0));
StrCat(").cast_mut())).as_deref_mut().unwrap()");
} else {
Convert(expr->getArg(0));
StrCat(".as_deref_mut().unwrap()");
}
}

void Converter::EmitFilePreamble() {
StrCat(R"(
extern crate libc;
Expand Down Expand Up @@ -3345,9 +3329,7 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) {
break;
case clang::OverloadedOperatorKind::OO_Star:
case clang::OverloadedOperatorKind::OO_Arrow:
if (IsUniquePtr(expr->getArg(0)->getType())) {
ConvertUniquePtrDeref(expr);
} else if (expr->getOperator() == clang::OverloadedOperatorKind::OO_Star) {
if (expr->getOperator() == clang::OverloadedOperatorKind::OO_Star) {
PushParen paren(*this);
StrCat(token::kStar);
Convert(expr->getArg(0));
Expand All @@ -3372,8 +3354,7 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) {
} else {
base_vars = GetAllVars(base);
}
if (!IsUniquePtr(base->getType()) &&
std::ranges::any_of(GetAllVars(idx), [&](const clang::ValueDecl *var) {
if (std::ranges::any_of(GetAllVars(idx), [&](const clang::ValueDecl *var) {
return base_vars.contains(var);
})) {
std::string idx_str;
Expand Down Expand Up @@ -4539,8 +4520,7 @@ void Converter::ConvertUnsignedArithOperand(clang::Expr *expr,
void Converter::ConvertEqualsNullPtr(clang::Expr *expr) {
StrCat('(');
Convert(expr);
if (IsUniquePtr(expr->getType()) ||
expr->getType()->isFunctionPointerType()) {
if (expr->getType()->isFunctionPointerType()) {
StrCat(").is_none()");
} else {
StrCat(").is_null()");
Expand Down Expand Up @@ -4614,13 +4594,7 @@ void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx,
return;
}
}
if (IsUniquePtr(base->getType())) {
PushExplicitAutoref no_autoref(*this, std::nullopt);
Convert(base->IgnoreImplicit());
StrCat(".as_mut().unwrap()");
} else {
Convert(base->IgnoreImplicit());
}
Convert(base->IgnoreImplicit());
PushExplicitAutoref no_autoref(*this, std::nullopt);
PushBracket bracket(*this);
{
Expand Down
2 changes: 0 additions & 2 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,6 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
virtual void ConvertLoopVariable(clang::VarDecl *decl,
clang::Expr *range_init);

virtual void ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr);

virtual bool ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr);

std::string GetMappedAsString(clang::Expr *expr, clang::Expr **args = nullptr,
Expand Down
13 changes: 0 additions & 13 deletions cpp2rust/converter/models/boxed_vars.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,6 @@ class AddressTakenVisitor
AddValueUse(expr->getArg(0), /*write=*/true);
AddValueUse(IgnoreNoOpCasts(expr->getArg(1)));
}
// Dereferencing a unique_ptr reads the pointer it holds; the object it
// points to is not stored in the unique_ptr.
switch (expr->getOperator()) {
case clang::OO_Subscript:
case clang::OO_Star:
case clang::OO_Arrow:
if (IsUniquePtr(expr->getArg(0)->getType())) {
AddValueUse(IgnoreNoOpCasts(expr->getArg(0)));
}
break;
default:
break;
}
return true;
}

Expand Down
49 changes: 6 additions & 43 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,12 @@ static bool IsArrayFieldPtr(clang::ASTContext &ctx, const clang::Expr *expr) {
// Whether `expr` is a field of an element of a std::vector, whose arrays and
// vectors are accessed through the place of the element, which is never
// reinterpreted memory.
static bool IsFieldOfVectorElem(const clang::MemberExpr *expr) {
static bool IsFieldOfVectorElem(clang::ASTContext &ctx,
const clang::MemberExpr *expr) {
auto *op = clang::dyn_cast<clang::CXXOperatorCallExpr>(
expr->getBase()->IgnoreParenImpCasts());
return !expr->isArrow() && op && op->getOperator() == clang::OO_Subscript &&
!IsUniquePtr(op->getArg(0)->getType());
!Mapper::Contains(ctx, op);
}

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

void ConverterRefCount::ConvertUniquePtrDeref(
clang::CXXOperatorCallExpr *expr) {
if (isAddrOf()) {
StrCat(ConvertRValue(expr->getArg(0)), ".as_pointer()");
computed_expr_type_ = ComputedExprType::FreshPointer;
} else {
// The object is modified through its own Value.
StrCat(std::format("(*{}.as_ref().unwrap().borrow{}())",
ConvertRValue(expr->getArg(0)),
isRValue() ? "" : "_mut"));
SetValueFreshness(expr->getType());
}
}

bool ConverterRefCount::ConvertCXXOperatorCallExpr(
clang::CXXOperatorCallExpr *expr) {
switch (expr->getOperator()) {
Expand All @@ -2834,11 +2820,6 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(

case clang::OverloadedOperatorKind::OO_Arrow:
case clang::OverloadedOperatorKind::OO_Star:
if (IsUniquePtr(expr->getArg(0)->getType())) {
ConvertUniquePtrDeref(expr);
break;
}

if (isLValue()) {
auto ptr = ToString(expr->getArg(0));
pending_deref_.set(std::move(ptr), isFresh());
Expand All @@ -2860,24 +2841,6 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
break;

case clang::OverloadedOperatorKind::OO_Subscript: {
if (IsUniquePtr(expr->getArg(0)->getType())) {
StrCat(
std::format("{}.as_ref().unwrap()", ConvertRValue(expr->getArg(0))));
if (isAddrOf()) {
StrCat(std::format(".as_pointer().offset(({}))",
ConvertRValue(expr->getArg(1))));
} else {
if (isRValue()) {
StrCat(".borrow()");
} else {
StrCat(".borrow_mut()");
}
StrCat(std::format("[({}) as usize]", ConvertRValue(expr->getArg(1))));
}
SetValueFreshness(expr->getType());
break;
}

bool is_inner_boxed =
IsBoxedType(ctx_, expr->getType().getNonReferenceType()) &&
IsBoxedType(ctx_, expr->getArg(0)->getType().getNonReferenceType());
Expand Down Expand Up @@ -2995,7 +2958,7 @@ std::string ConverterRefCount::ConvertElemPlace(clang::Expr *container,
!IsUnboxedPlace(member) &&
Mapper::Map(ctx_, field->getType().getUnqualifiedType())
.starts_with("Vec<")) {
if (IsFieldOfVectorElem(member)) {
if (IsFieldOfVectorElem(ctx_, member)) {
return std::format("index!({}, {})", ConvertPlace(member),
ConvertSubscriptIndex(idx));
}
Expand Down Expand Up @@ -3136,7 +3099,7 @@ void ConverterRefCount::ConvertPointerElem(clang::Expr *base,
// An element of an array field is accessed in place, through the struct.
if (IsArrayFieldPtr(ctx_, base)) {
auto *member = clang::cast<clang::MemberExpr>(base->IgnoreParenImpCasts());
if (IsFieldOfVectorElem(member)) {
if (IsFieldOfVectorElem(ctx_, member)) {
StrCat(std::format("index!({}, {})", ConvertPlace(member),
ConvertRValue(idx)));
computed_expr_type_ = ComputedExprType::FreshPointer;
Expand Down
2 changes: 0 additions & 2 deletions cpp2rust/converter/models/converter_refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,6 @@ class ConverterRefCount final : public Converter {
void ConvertAssignment(clang::Expr *lhs, clang::Expr *rhs,
std::string_view assign_operator) override;

void ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr) override;

bool ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) override;

void ConvertFunctionParameters(clang::FunctionDecl *decl) override;
Expand Down
18 changes: 18 additions & 0 deletions rules/unique_ptr/src.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,21 @@ std::unique_ptr<T1[]> &f15(std::unique_ptr<T1[]> &dst,
std::unique_ptr<T1[]> &&src) {
return dst = std::move(src);
}

template <typename T1> T1 &f17(const std::unique_ptr<T1> &o) { return *o; }

template <typename T1> T1 *f18(const std::unique_ptr<T1> &o) {
return o.operator->();
}

template <typename T1> T1 &f19(const std::unique_ptr<T1[]> &o, std::size_t i) {
return o[i];
}

template <typename T1> bool f20(const std::unique_ptr<T1> &o, std::nullptr_t) {
return o == nullptr;
}

template <typename T1> bool f21(const std::unique_ptr<T1> &o, std::nullptr_t) {
return o != nullptr;
}
20 changes: 20 additions & 0 deletions rules/unique_ptr/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,23 @@ fn f14<T1: ByteRepr>(a0: Ptr<Option<Value<T1>>>, a1: &mut Option<Value<T1>>) {
fn f15<T1: ByteRepr>(a0: Ptr<Option<Value<Box<[T1]>>>>, a1: &mut Option<Value<Box<[T1]>>>) {
a0.write(a1.take())
}

fn f17<T1>(a0: Value<T1>) -> Ptr<T1> {
a0.as_pointer()
}

fn f18<T1>(a0: Value<T1>) -> Ptr<T1> {
a0.as_pointer()
}

fn f19<T1>(a0: Value<T1>, a1: usize) -> Ptr<T1> {
(a0.as_pointer() as Ptr<T1>).offset(a1 as isize)
}

fn f20<T1>(a0: Option<Value<T1>>) -> bool {
a0.is_none()
}

fn f21<T1>(a0: Option<Value<T1>>) -> bool {
a0.is_some()
}
24 changes: 24 additions & 0 deletions rules/unique_ptr/tgt_unsafe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,27 @@ unsafe fn f14<T1>(a0: &mut Option<Box<T1>>, a1: &mut Option<Box<T1>>) {
unsafe fn f15<T1>(a0: &mut Option<Box<[T1]>>, a1: &mut Option<Box<[T1]>>) {
*a0 = a1.take()
}

unsafe fn f17<T1>(a0: &mut Option<Box<T1>>) -> *mut T1 {
a0.as_deref()
.map_or(::std::ptr::null_mut(), |v| v as *const T1 as *mut T1)
}

unsafe fn f18<T1>(a0: &mut Option<Box<T1>>) -> *mut T1 {
a0.as_deref()
.map_or(::std::ptr::null_mut(), |v| v as *const T1 as *mut T1)
}

unsafe fn f19<T1>(a0: &mut Option<Box<[T1]>>, a1: usize) -> *mut T1 {
a0.as_deref()
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut T1)
.add(a1)
}

unsafe fn f20<T1>(a0: &mut Option<Box<T1>>) -> bool {
a0.is_none()
}

unsafe fn f21<T1>(a0: &mut Option<Box<T1>>) -> bool {
a0.is_some()
}
14 changes: 9 additions & 5 deletions tests/ub/out/refcount/ub6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,22 @@ pub fn fill_1(arr: Ptr<Option<Value<Box<[Ptr<i32>]>>>>, n1: Ptr<i32>) {
mkPair_0(_x1, _x2)
}),
));
(*arr.upgrade().deref()).as_ref().unwrap().borrow_mut()[(0_usize) as usize] =
({ (*pair.borrow()).x1.clone() }).clone();
(*arr.upgrade().deref()).as_ref().unwrap().borrow_mut()[(1_usize) as usize] =
({ (*pair.borrow()).x2.clone() }).clone();
((*arr.upgrade().deref()).as_pointer() as Ptr<Ptr<i32>>)
.offset(0_usize as isize)
.write(({ (*pair.borrow()).x1.clone() }).clone());
((*arr.upgrade().deref()).as_pointer() as Ptr<Ptr<i32>>)
.offset(1_usize as isize)
.write(({ (*pair.borrow()).x2.clone() }).clone());
}
pub fn any_2(arr: Ptr<Option<Value<Box<[Ptr<i32>]>>>>, n1: Ptr<i32>) -> bool {
let mut out: bool = false;
let mut i: i32 = 0;
'loop_: while ({ i } < { (n1.read()) }) {
let __rhs = (out)
|| (((*arr.upgrade().deref()).as_ref().unwrap().borrow()[(i as usize) as usize]
|| (((((*arr.upgrade().deref()).as_pointer() as Ptr<Ptr<i32>>)
.offset((i as usize) as isize)
.read())
.read())
== 0);
out = __rhs;
i.prefix_inc();
Expand Down
17 changes: 14 additions & 3 deletions tests/ub/out/unsafe/ub6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,25 @@ pub unsafe fn fill_1(arr: *mut Option<Box<[*mut i32]>>, n1: *mut i32) {
let _x2: *mut i32 = &mut n2;
mkPair_0(_x1, _x2)
});
(*arr).as_mut().unwrap()[(0_usize)] = (pair.x1);
(*arr).as_mut().unwrap()[(1_usize)] = (pair.x2);
(*(*arr)
.as_deref()
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut *mut i32)
.add(0_usize)) = (pair.x1);
(*(*arr)
.as_deref()
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut *mut i32)
.add(1_usize)) = (pair.x2);
}
pub unsafe fn any_2(arr: *mut Option<Box<[*mut i32]>>, n1: *mut i32) -> bool {
let mut out: bool = false;
let mut i: i32 = 0;
'loop_: while ((i) < (*n1)) {
out = (out) || ((*(*arr).as_mut().unwrap()[(i as usize)]) == (0));
out = (out)
|| ((*(*(*arr)
.as_deref()
.map_or(::std::ptr::null_mut(), |s| s.as_ptr() as *mut *mut i32)
.add((i as usize))))
== (0));
i.prefix_inc();
}
return out;
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/out/refcount/07_unique.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write};
use std::os::fd::AsFd;
use std::rc::{Rc, Weak};
pub fn fn_0(mut u: Option<Value<i32>>) -> Option<Value<i32>> {
(*u.as_ref().unwrap().borrow_mut()) = 10;
u.as_pointer().write(10);
return u.take();
}
pub fn main() {
Expand All @@ -16,14 +16,14 @@ pub fn main() {
}
fn main_0() -> i32 {
let f: Value<Option<Value<i32>>> = Rc::new(RefCell::new(Some(Rc::new(RefCell::new(8)))));
(*(*f.borrow()).as_ref().unwrap().borrow_mut()) = 9;
(*f.borrow()).as_pointer().write(9);
let mut f_ptr1: Ptr<i32> = (*f.borrow()).as_pointer();
f_ptr1.write(10);
let mut f_ptr2: Ptr<i32> = ((*f.borrow()).as_pointer());
f_ptr2.write(11);
(f.as_pointer() as Ptr<Option<Value<i32>>>).write(Some(Rc::new(RefCell::new(9))).take());
(f.as_pointer() as Ptr<Option<Value<i32>>>).write(({ fn_0((*f.borrow_mut()).take()) }).take());
assert!(((*(*f.borrow()).as_ref().unwrap().borrow()) == 10));
assert!((((*f.borrow()).as_pointer().read()) == 10));
return 0;
}
pub fn __cpp2rust_init_globals() {}
12 changes: 8 additions & 4 deletions tests/unit/out/refcount/08_unique_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@ fn main_0() -> i32 {
let mut g: Option<Value<Box<[i32]>>> = Some(Rc::new(RefCell::new(
(0..2_usize).map(|_| <i32>::default()).collect::<Box<[_]>>(),
)));
g.as_ref().unwrap().borrow_mut()[(0_usize) as usize] = 11;
g.as_ref().unwrap().borrow_mut()[(1_usize) as usize] = 12;
(g.as_pointer() as Ptr<i32>)
.offset(0_usize as isize)
.write(11);
(g.as_pointer() as Ptr<i32>)
.offset(1_usize as isize)
.write(12);
let mut g_ptr: Ptr<i32> = g.as_pointer();
elem!(g_ptr, 0).write(13);
elem!(g_ptr, 1).write(14);
assert!(
((g.as_ref().unwrap().borrow()[(0_usize) as usize]
+ g.as_ref().unwrap().borrow()[(1_usize) as usize])
((((g.as_pointer() as Ptr<i32>).offset(0_usize as isize).read())
+ ((g.as_pointer() as Ptr<i32>).offset(1_usize as isize).read()))
== 27)
);
return 0;
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/refcount/11_move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub fn main() {
fn main_0() -> i32 {
let n: Value<Option<Value<i32>>> = Rc::new(RefCell::new(Some(Rc::new(RefCell::new(10)))));
({ change_0(n.as_pointer()) });
assert!(((*(*n.borrow()).as_ref().unwrap().borrow()) == 20));
assert!((((*n.borrow()).as_pointer().read()) == 20));
return 0;
}
pub fn __cpp2rust_init_globals() {}
Loading
Loading