@@ -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); }
22182221bool 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
32013218void 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+
35123551void 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 }
0 commit comments