Skip to content

Commit c966e63

Browse files
committed
Add explicit reference for pointer dereferences that do autoreference
1 parent 39b1133 commit c966e63

2 files changed

Lines changed: 72 additions & 15 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,7 +1059,10 @@ void Converter::ConvertLoopVariable(clang::VarDecl *decl,
10591059
StrCat(std::format(".as_mut_ptr().add({})", loop_var_name));
10601060
}
10611061
} else {
1062-
Convert(range_init);
1062+
{
1063+
PushAutorefReceiver autoref(*this, /*is_mut=*/false);
1064+
Convert(range_init);
1065+
}
10631066
StrCat(std::format("[{}]", loop_var_name));
10641067
StrCat(".clone()");
10651068
}
@@ -2218,18 +2221,22 @@ void Converter::EmitStmtExprTail(clang::Expr *tail) { Convert(tail); }
22182221
bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) {
22192222
StrCat(keyword::kIf);
22202223
ConvertCondition(expr->getCond());
2224+
bool branch_is_addr =
2225+
expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType();
22212226
{
22222227
PushBrace then_brace(*this);
2223-
if (expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType()) {
2228+
if (branch_is_addr) {
22242229
StrCat(token::kRef, keyword_mut_);
2230+
autoref_receiver_ = false;
22252231
}
22262232
Convert(expr->getTrueExpr());
22272233
}
22282234
StrCat(keyword::kElse);
22292235
{
22302236
PushBrace else_brace(*this);
2231-
if (expr->isLValue() && !isRValue() && !expr->getType()->isFunctionType()) {
2237+
if (branch_is_addr) {
22322238
StrCat(token::kRef, keyword_mut_);
2239+
autoref_receiver_ = false;
22332240
}
22342241
Convert(expr->getFalseExpr());
22352242
}
@@ -2285,11 +2292,8 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) {
22852292

22862293
if (decl->getType()->getAs<clang::ReferenceType>() && !isAddrOf() &&
22872294
!map_iter_decls_.contains(clang::dyn_cast<clang::VarDecl>(decl))) {
2288-
{
2289-
PushParen paren(*this);
2290-
StrCat(GetPointerDerefPrefix(decl->getType().getNonReferenceType()),
2291-
std::move(str));
2292-
}
2295+
EmitMaybeWrappedDeref(std::move(str),
2296+
decl->getType().getNonReferenceType());
22932297
SetValueFreshness(expr->getType());
22942298
return false;
22952299
}
@@ -2362,9 +2366,17 @@ bool Converter::ConvertCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr) {
23622366
Convert(expr->getArg(0));
23632367
}
23642368
break;
2365-
case clang::OverloadedOperatorKind::OO_Subscript:
2369+
case clang::OverloadedOperatorKind::OO_Subscript: {
2370+
bool is_mut = true;
2371+
if (auto *callee = expr->getDirectCallee()) {
2372+
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(callee)) {
2373+
is_mut = !method->isConst();
2374+
}
2375+
}
2376+
PushAutorefReceiver autoref(*this, is_mut);
23662377
ConvertArraySubscript(expr->getArg(0), expr->getArg(1), expr->getType());
23672378
break;
2379+
}
23682380
case clang::OverloadedOperatorKind::OO_LessLess:
23692381
if (IsCallToOstream(expr)) {
23702382
ConvertCallToOstream(expr);
@@ -2430,8 +2442,8 @@ bool Converter::VisitMemberExpr(clang::MemberExpr *expr) {
24302442
}
24312443

24322444
if (!isAddrOf() && member->getType()->isReferenceType()) {
2433-
PushParen paren(*this);
2434-
StrCat(GetPointerDerefPrefix(member->getType().getNonReferenceType()), str);
2445+
EmitMaybeWrappedDeref(std::move(str),
2446+
member->getType().getNonReferenceType());
24352447
return false;
24362448
}
24372449

@@ -2459,6 +2471,11 @@ void Converter::ConvertMemberExpr(clang::MemberExpr *expr) {
24592471
auto *base = expr->getBase();
24602472
bool base_is_this = clang::isa<clang::CXXThisExpr>(base->IgnoreCasts());
24612473
PushExprKind push(*this, isLValue() ? ExprKind::LValue : ExprKind::RValue);
2474+
std::optional<PushAutorefReceiver> autoref;
2475+
if (auto *method = clang::dyn_cast<clang::CXXMethodDecl>(member);
2476+
method && !method->isStatic() && isCallee() && !base_is_this) {
2477+
autoref.emplace(*this, !method->isConst());
2478+
}
24622479
if (expr->isArrow() && !base_is_this) {
24632480
ConvertArrow(base);
24642481
} else {
@@ -3200,10 +3217,15 @@ void Converter::ConvertPointerOffset(clang::Expr *base, clang::Expr *idx,
32003217

32013218
void Converter::ConvertArraySubscript(clang::Expr *base, clang::Expr *idx,
32023219
clang::QualType type) {
3220+
bool is_unique_ptr = IsUniquePtr(base->getType());
3221+
if (is_unique_ptr) {
3222+
autoref_receiver_ = false;
3223+
}
32033224
Convert(base->IgnoreImplicit());
3204-
if (IsUniquePtr(base->getType())) {
3225+
if (is_unique_ptr) {
32053226
StrCat(".as_mut().unwrap()");
32063227
}
3228+
autoref_receiver_ = false;
32073229
PushBracket bracket(*this);
32083230
{
32093231
PushParen paren(*this);
@@ -3509,11 +3531,26 @@ void Converter::ConvertAddrOf(clang::Expr *expr, clang::QualType pointer_type) {
35093531
}
35103532
}
35113533

3534+
void Converter::EmitMaybeWrappedDeref(std::string inner,
3535+
clang::QualType pointee_type) {
3536+
bool wrap = autoref_receiver_;
3537+
bool wrap_mut = autoref_receiver_mut_;
3538+
autoref_receiver_ = false;
3539+
if (wrap) {
3540+
StrCat("(", wrap_mut ? "&mut " : "&");
3541+
}
3542+
{
3543+
PushParen paren(*this);
3544+
StrCat(GetPointerDerefPrefix(pointee_type), std::move(inner));
3545+
}
3546+
if (wrap) {
3547+
StrCat(")");
3548+
}
3549+
}
3550+
35123551
void Converter::ConvertDeref(clang::Expr *expr) {
35133552
if (!isAddrOf()) {
3514-
PushParen paren(*this);
3515-
StrCat(GetPointerDerefPrefix(expr->getType()->getPointeeType()),
3516-
ToString(expr));
3553+
EmitMaybeWrappedDeref(ToString(expr), expr->getType()->getPointeeType());
35173554
} else {
35183555
Convert(expr);
35193556
}

cpp2rust/converter/converter.h

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

475475
virtual void ConvertDeref(clang::Expr *expr);
476476

477+
void EmitMaybeWrappedDeref(std::string inner, clang::QualType pointee_type);
478+
477479
virtual void ConvertArrow(clang::Expr *expr);
478480

479481
virtual void ConvertCast(clang::QualType qual_type);
@@ -515,6 +517,24 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
515517
clang::ASTContext &ctx_;
516518
clang::FunctionDecl *curr_function_ = nullptr;
517519
bool in_function_formals_ = false;
520+
bool autoref_receiver_ = false;
521+
bool autoref_receiver_mut_ = false;
522+
523+
struct PushAutorefReceiver {
524+
Converter &c;
525+
bool prev_active;
526+
bool prev_mut;
527+
PushAutorefReceiver(Converter &c, bool is_mut)
528+
: c(c), prev_active(c.autoref_receiver_),
529+
prev_mut(c.autoref_receiver_mut_) {
530+
c.autoref_receiver_ = true;
531+
c.autoref_receiver_mut_ = is_mut;
532+
}
533+
~PushAutorefReceiver() {
534+
c.autoref_receiver_ = prev_active;
535+
c.autoref_receiver_mut_ = prev_mut;
536+
}
537+
};
518538
std::stack<clang::Expr *> curr_for_inc_;
519539
std::stack<clang::QualType> curr_init_type_;
520540

0 commit comments

Comments
 (0)