Skip to content

Commit ed68c58

Browse files
committed
In unsafe, const variables that need destruction need to be mut
1 parent 2bb3063 commit ed68c58

3 files changed

Lines changed: 24 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
}

0 commit comments

Comments
 (0)