Skip to content

Commit b4c051e

Browse files
authored
Make const variables that need destruction mut in unsafe (#515)
1 parent 6e5caf5 commit b4c051e

5 files changed

Lines changed: 38 additions & 6 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,7 @@ bool Converter::NeedsMut(const clang::VarDecl *decl, clang::QualType type,
480480
auto *method_or_null =
481481
curr_function_ ? clang::dyn_cast<clang::CXXMethodDecl>(curr_function_)
482482
: nullptr;
483-
return ((hoisted_decls_.contains(decl) ||
483+
return ((hoisted_decls_.contains(decl) || NeedsScopedDestructor(decl) ||
484484
(!type.isConstQualified() && !type->isReferenceType())) &&
485485
((method_or_null == nullptr) || !method_or_null->isVirtual()) &&
486486
!IsGlobalVar(decl) && name != "_");
@@ -627,8 +627,21 @@ bool Converter::VisitVarDecl(clang::VarDecl *decl) {
627627
return false;
628628
}
629629

630-
void Converter::EmitScopedDestructor(const clang::VarDecl *decl) {
630+
bool Converter::NeedsScopedDestructor(const clang::VarDecl *decl) const {
631631
if (in_function_formals_ || !decl->isLocalVarDecl() || IsGlobalVar(decl)) {
632+
return false;
633+
}
634+
auto type = decl->getType();
635+
if (auto lambda = AsLambdaClass(type);
636+
lambda && LambdaNeedsDestruction(lambda)) {
637+
return true;
638+
}
639+
return !type->isReferenceType() && !type->isArrayType() &&
640+
TypeNeedsDestruction(type);
641+
}
642+
643+
void Converter::EmitScopedDestructor(const clang::VarDecl *decl) {
644+
if (!NeedsScopedDestructor(decl)) {
632645
return;
633646
}
634647
auto type = decl->getType();
@@ -640,10 +653,6 @@ void Converter::EmitScopedDestructor(const clang::VarDecl *decl) {
640653
GetNamedDeclAsString(decl)));
641654
return;
642655
}
643-
if (type->isReferenceType() || type->isArrayType() ||
644-
!TypeNeedsDestruction(type)) {
645-
return;
646-
}
647656
auto name = GetNamedDeclAsString(decl);
648657
StrCat(token::kSemiColon,
649658
std::format("let _dtor_{0} = ScopedDestructorUnsafe::new(&raw mut "

‎cpp2rust/converter/converter.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
150150

151151
virtual std::string DestroyMembers(const clang::CXXRecordDecl *decl);
152152

153+
bool NeedsScopedDestructor(const clang::VarDecl *decl) const;
154+
153155
virtual void EmitScopedDestructor(const clang::VarDecl *decl);
154156

155157
void EmitDeallocation(clang::CXXDeleteExpr *expr,

‎tests/unit/destructor.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,12 @@ int main() {
106106
assert(order[1] == 2);
107107
assert(order[2] == 1);
108108

109+
int before = global;
110+
{
111+
const S cs;
112+
(void)cs;
113+
}
114+
assert(global == before + 1);
115+
109116
return 0;
110117
}

‎tests/unit/out/refcount/destructor.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,13 @@ fn main_0() -> i32 {
183183
order_1.with(|rc| rc.borrow()[__idx])
184184
}) == 1)
185185
);
186+
let mut before: i32 = global_0.with(|rc| *rc.borrow());
187+
{
188+
let cs: Value<S> = Rc::new(RefCell::new(<S>::default()));
189+
let _dtor_cs = ScopedDestructor::new(&cs, |__p| __p.destructor());
190+
&(*cs.borrow_mut());
191+
}
192+
assert!((global_0.with(|rc| *rc.borrow()) == (before + 1)));
186193
return 0;
187194
}
188195
pub trait ArrayMemberImpl {

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ unsafe fn main_0() -> i32 {
198198
assert!((((*std::cell::LazyCell::force_mut(&mut *&raw mut order_1))[(0) as usize]) == (3)));
199199
assert!((((*std::cell::LazyCell::force_mut(&mut *&raw mut order_1))[(1) as usize]) == (2)));
200200
assert!((((*std::cell::LazyCell::force_mut(&mut *&raw mut order_1))[(2) as usize]) == (1)));
201+
let mut before: i32 = (*std::cell::LazyCell::force_mut(&mut *&raw mut global_0));
202+
{
203+
let mut cs: S = <S>::default();
204+
let _dtor_cs = ScopedDestructorUnsafe::new(&raw mut cs, S::destructor);
205+
&(cs);
206+
}
207+
assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut global_0)) == ((before) + (1))));
201208
return 0;
202209
}
203210
pub unsafe fn __cpp2rust_init_globals() {

0 commit comments

Comments
 (0)