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
39 changes: 24 additions & 15 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3021,16 +3021,16 @@ bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) {
return false;
}

std::string Converter::ConvertDeclRefExpr(clang::DeclRefExpr *expr) {
std::string Converter::ConvertDeclRef(clang::Expr *expr,
clang::ValueDecl *decl) {
if (isAddrOf()) {
clang::Expr *addrof_op = ToAddrOf(ctx_, expr);
if (auto str = GetMappedAsString(addrof_op); !str.empty()) {
return str;
}
}

auto *decl = expr->getDecl();
if (ShouldReplaceWithMappedBody(expr)) {
if (ShouldReplaceWithMappedBody(decl)) {
if (auto str = GetMappedAsString(expr); !str.empty()) {
return str;
}
Expand All @@ -3053,7 +3053,8 @@ std::string Converter::ConvertDeclRefExpr(clang::DeclRefExpr *expr) {
return name;
}

if (IsGlobalVar(expr)) {
if (auto *var = clang::dyn_cast<clang::VarDecl>(decl);
var && IsGlobalVar(var)) {
if (LazyStaticInit()) {
return std::format("(*std::cell::LazyCell::force_mut(&mut *&raw mut {}))",
GetNamedDeclAsString(decl));
Expand All @@ -3065,24 +3066,28 @@ std::string Converter::ConvertDeclRefExpr(clang::DeclRefExpr *expr) {
}

bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
auto str = ConvertDeclRefExpr(expr);
auto decl = expr->getDecl();
ConvertDeclRefValue(expr, expr->getDecl());
return false;
}

void Converter::ConvertDeclRefValue(clang::Expr *expr, clang::ValueDecl *decl) {
auto str = ConvertDeclRef(expr, decl);

if (decl->getType()->getAs<clang::ReferenceType>() && !isAddrOf() &&
!map_iter_decls_.contains(clang::dyn_cast<clang::VarDecl>(decl))) {
EmitDeref(std::move(str), decl->getType().getNonReferenceType());
SetValueFreshness(expr->getType());
return false;
return;
}

if (auto *fn_decl = clang::dyn_cast<clang::FunctionDecl>(decl)) {
if (isAddrOf()) {
ConvertFunctionToFunctionPointer(fn_decl);
return false;
return;
}
StrCat(str);
SetFreshType(expr->getType());
return false;
return;
}

if (auto var_decl = clang::dyn_cast<clang::VarDecl>(decl)) {
Expand All @@ -3093,7 +3098,7 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
PushParen paren(*this);
VisitLambdaExpr(lambda);
computed_expr_type_ = ComputedExprType::FreshValue;
return false;
return;
}
}
}
Expand All @@ -3103,16 +3108,15 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
StrCat(token::kRef, decl->getType().isConstQualified() ? "" : keyword_mut_,
str);
computed_expr_type_ = ComputedExprType::FreshPointer;
return false;
return;
}

StrCat(str);
if (clang::isa<clang::EnumConstantDecl>(decl)) {
computed_expr_type_ = ComputedExprType::FreshValue;
return false;
return;
}
SetValueFreshness(expr->getType());
return false;
}

bool Converter::VisitParenExpr(clang::ParenExpr *expr) {
Expand Down Expand Up @@ -3196,6 +3200,10 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) {

bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
auto *member = expr->getMemberDecl();
if (!member->isCXXInstanceMember()) {
ConvertDeclRefValue(expr, member);
return false;
}
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member);
method && IsMethodOnPtr(method) && !Mapper::Contains(expr)) {
SetUFCSReceiver(expr->getBase(), expr->isArrow(), method);
Expand Down Expand Up @@ -5169,8 +5177,9 @@ bool Converter::isCallee() const {
return !curr_expr_kind_.empty() && curr_expr_kind_.back() == ExprKind::Callee;
}

bool Converter::ShouldReplaceWithMappedBody(clang::DeclRefExpr *expr) const {
if (clang::isa<clang::FunctionDecl>(expr->getDecl()) && isAddrOf()) {
bool Converter::ShouldReplaceWithMappedBody(
const clang::ValueDecl *decl) const {
if (clang::isa<clang::FunctionDecl>(decl) && isAddrOf()) {
return false;
}
return true;
Expand Down
7 changes: 5 additions & 2 deletions cpp2rust/converter/converter.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,10 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
virtual bool VisitConditionalOperator(clang::ConditionalOperator *expr);

virtual bool VisitDeclRefExpr(clang::DeclRefExpr *expr);
std::string ConvertDeclRefExpr(clang::DeclRefExpr *expr);

virtual void ConvertDeclRefValue(clang::Expr *expr, clang::ValueDecl *decl);

std::string ConvertDeclRef(clang::Expr *expr, clang::ValueDecl *decl);

virtual bool VisitParenExpr(clang::ParenExpr *expr);

Expand Down Expand Up @@ -730,7 +733,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {

bool RecordHasCopyableFields(const clang::RecordDecl *decl);

bool ShouldReplaceWithMappedBody(clang::DeclRefExpr *expr) const;
bool ShouldReplaceWithMappedBody(const clang::ValueDecl *decl) const;

std::string *rs_code_;
clang::ASTContext &ctx_;
Expand Down
45 changes: 25 additions & 20 deletions cpp2rust/converter/models/converter_refcount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,26 +818,26 @@ bool ConverterRefCount::VisitConditionalOperator(
return false;
}

bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
void ConverterRefCount::ConvertDeclRefValue(clang::Expr *expr,
clang::ValueDecl *decl) {
if (isAddrOf()) {
clang::Expr *addrof_op = ToAddrOf(ctx_, expr);
if (auto str = GetMappedAsString(addrof_op); !str.empty()) {
StrCat(str);
SetFreshType(expr->getType());
return false;
return;
}
}

if (ShouldReplaceWithMappedBody(expr)) {
if (ShouldReplaceWithMappedBody(decl)) {
if (auto str = GetMappedAsString(expr); !str.empty()) {
StrCat(str);
SetFreshType(expr->getType());
return false;
return;
}
}

auto str = ConvertDeclRefExpr(expr);
auto decl = expr->getDecl();
auto str = ConvertDeclRef(expr, decl);

if (auto fn_decl = clang::dyn_cast<clang::FunctionDecl>(decl)) {
if (isAddrOf()) {
Expand All @@ -846,18 +846,19 @@ bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
StrCat(str);
SetFreshType(expr->getType());
}
return false;
return;
}

if (clang::isa<clang::EnumConstantDecl>(decl)) {
StrCat(str);
computed_expr_type_ = ComputedExprType::FreshValue;
return false;
return;
}

const auto decl_t = decl->getType();
bool is_global_value = false, is_global_ptr = false;
if (IsGlobalVar(expr)) {
if (auto *var = clang::dyn_cast<clang::VarDecl>(decl);
var && IsGlobalVar(var)) {
if (decl_t->isReferenceType()) {
str += ".with(Ptr::clone)";
is_global_ptr = true;
Expand All @@ -870,15 +871,15 @@ bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
if (map_iter_decls_.contains(clang::dyn_cast<clang::VarDecl>(decl))) {
StrCat(str);
SetValueFreshness(expr->getType());
return false;
return;
}

if (auto pointee = ref->getPointeeType();
isObject() && WantsElementPtr() && IsBoxedType(pointee)) {
StrCat(std::format("Ptr::<{}>::decay(&({}))", ToString(pointee),
std::move(str)));
computed_expr_type_ = ComputedExprType::FreshPointer;
return false;
return;
}

// references are not boxed
Expand All @@ -891,13 +892,13 @@ bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
} else {
if (isLValue()) {
pending_deref_.set(str, /*fresh=*/false);
return false;
return;
}
StrCat(DerefPtrExpr(str, ref->getPointeeType()));
}
SetValueFreshness(expr->getType());
}
return false;
return;
}

if (isAddrOf()) {
Expand All @@ -909,7 +910,7 @@ bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
StrCat(str, ".as_pointer()");
}
computed_expr_type_ = ComputedExprType::FreshPointer;
return false;
return;
}

bool fresh = false;
Expand All @@ -934,18 +935,17 @@ bool ConverterRefCount::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
StrCat(std::format("(*{}.borrow_mut())", std::move(str)));
}

if (auto *decl = clang::dyn_cast<clang::VarDecl>(expr->getDecl())) {
if (decl->getType()->isPointerType()) {
if (auto *var = clang::dyn_cast<clang::VarDecl>(decl)) {
if (var->getType()->isPointerType()) {
computed_expr_type_ = ComputedExprType::Pointer;
return false;
return;
}
}
if (fresh) {
SetFreshType(expr->getType());
} else {
SetValueFreshness(expr->getType());
}
return false;
}

static std::vector<const char *> printf2fmt(std::string &format) {
Expand Down Expand Up @@ -1727,6 +1727,10 @@ void ConverterRefCount::ConvertUnionMemberAccessor(clang::MemberExpr *expr) {

bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) {
auto *member = expr->getMemberDecl();
if (!member->isCXXInstanceMember()) {
ConvertDeclRefValue(expr, member);
return false;
}
bool known = Mapper::Contains(expr);

if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member);
Expand Down Expand Up @@ -2511,7 +2515,8 @@ clang::DeclRefExpr *ConverterRefCount::GetGlobalArrayRValue(clang::Expr *base) {
auto *ref = clang::dyn_cast<clang::DeclRefExpr>(base->IgnoreImplicit());
if (!isRValue() || !ref || !IsGlobalVar(ref) ||
ref->getDecl()->getType()->isReferenceType() ||
(ShouldReplaceWithMappedBody(ref) && !GetMappedAsString(ref).empty())) {
(ShouldReplaceWithMappedBody(ref->getDecl()) &&
!GetMappedAsString(ref).empty())) {
return nullptr;
}
auto *arr_ty = ctx_.getAsArrayType(ref->getType());
Expand Down Expand Up @@ -2567,7 +2572,7 @@ void ConverterRefCount::ConvertArraySubscript(clang::Expr *base,
// The index is evaluated first, as it may itself access the global.
StrCat(std::format(
"({{ let __idx = ({}) as usize; {}.with(|rc| rc.borrow()[__idx]{}) }})",
ConvertRValue(idx), ConvertDeclRefExpr(global),
ConvertRValue(idx), ConvertDeclRef(global, global->getDecl()),
TypeIsCopyable(type) ? "" : ".clone()"));
SetFreshType(type);
} else {
Expand Down
2 changes: 1 addition & 1 deletion cpp2rust/converter/models/converter_refcount.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class ConverterRefCount final : public Converter {

bool ConvertLambdaVarDecl(clang::VarDecl *decl) override;

bool VisitDeclRefExpr(clang::DeclRefExpr *expr) override;
void ConvertDeclRefValue(clang::Expr *expr, clang::ValueDecl *decl) override;

bool ConvertIncAndDec(clang::UnaryOperator *expr) override;

Expand Down
24 changes: 24 additions & 0 deletions tests/unit/out/refcount/static_var_in_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,18 @@ pub struct C {}
thread_local!(
pub static inner_const_1: Value<i32> = Rc::new(RefCell::new(2));
);
pub type anon_3 = u32;
pub const anon_3_kValue: anon_3 = 3;
#[derive(Clone, ByteRepr, Default)]
pub struct S {}
impl S {
pub fn f() -> i32 {
return counter_2.with(|rc| *rc.borrow());
}
}
thread_local!(
pub static counter_2: Value<i32> = Rc::new(RefCell::new(10));
);
pub fn main() {
__cpp2rust_init_globals();
std::process::exit(main_0());
Expand All @@ -24,6 +34,19 @@ fn main_0() -> i32 {
let c: Value<C> = Rc::new(RefCell::new(<C>::default()));
assert!((({ CImpl::get(&c.as_pointer(),) }) == 1));
assert!((inner_const_1.with(|rc| *rc.borrow()) == 2));
let s: Value<S> = Rc::new(RefCell::new(<S>::default()));
let p: Value<Ptr<S>> = Rc::new(RefCell::new((s.as_pointer())));
assert!((inner_const_1.with(|rc| *rc.borrow()) == 2));
assert!((inner_const_1.with(|rc| *rc.borrow()) == 2));
assert!(((anon_3_kValue as i32) == 3));
assert!(((anon_3_kValue as i32) == 3));
(*counter_2.with(Value::clone).borrow_mut()) = 20;
assert!((counter_2.with(|rc| *rc.borrow()) == 20));
(*counter_2.with(Value::clone).borrow_mut()) += 5;
assert!((counter_2.with(|rc| *rc.borrow()) == 25));
assert!((counter_2.with(|rc| *rc.borrow()) == 25));
assert!((({ S::f() }) == 25));
assert!((({ S::f() }) == 25));
return 0;
}
pub trait CImpl {
Expand All @@ -37,4 +60,5 @@ impl CImpl for Ptr<C> {
pub fn __cpp2rust_init_globals() {
let _ = inner_const_0.with(|_| ());
let _ = inner_const_1.with(|_| ());
let _ = counter_2.with(|_| ());
}
22 changes: 22 additions & 0 deletions tests/unit/out/unsafe/static_var_in_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ impl C {
}
}
pub static mut inner_const_1: std::cell::LazyCell<i32> = std::cell::LazyCell::new(|| unsafe { 2 });
pub type anon_3 = u32;
pub const anon_3_kValue: anon_3 = 3;
#[repr(C)]
#[derive(Copy, Clone, Default)]
pub struct S {}
impl S {
pub unsafe fn f() -> i32 {
return (*std::cell::LazyCell::force_mut(&mut *&raw mut counter_2));
}
}
pub static mut counter_2: std::cell::LazyCell<i32> = std::cell::LazyCell::new(|| unsafe { 10 });
pub fn main() {
unsafe {
__cpp2rust_init_globals();
Expand All @@ -29,9 +37,23 @@ unsafe fn main_0() -> i32 {
let mut c: C = <C>::default();
assert!(((unsafe { C::get(&mut c,) }) == (1)));
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut inner_const_1)) == (2)));
let mut s: S = <S>::default();
let mut p: *mut S = (&mut s as *mut S);
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut inner_const_1)) == (2)));
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut inner_const_1)) == (2)));
assert!(((anon_3_kValue as i32) == (3)));
assert!(((anon_3_kValue as i32) == (3)));
(*std::cell::LazyCell::force_mut(&mut *&raw mut counter_2)) = 20;
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut counter_2)) == (20)));
(*std::cell::LazyCell::force_mut(&mut *&raw mut counter_2)) += 5;
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut counter_2)) == (25)));
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut counter_2)) == (25)));
assert!(((unsafe { S::f() }) == (25)));
assert!(((unsafe { S::f() }) == (25)));
return 0;
}
pub unsafe fn __cpp2rust_init_globals() {
std::cell::LazyCell::force(&*&raw const inner_const_0);
std::cell::LazyCell::force(&*&raw const inner_const_1);
std::cell::LazyCell::force(&*&raw const counter_2);
}
Loading
Loading