@@ -201,14 +201,19 @@ bool ConverterRefCount::IsUnboxedPlace(const clang::Expr *expr) const {
201201 expr = expr->IgnoreParenImpCasts ();
202202 // Fields of unions and references are accessed through pointers.
203203 if (auto *member = clang::dyn_cast<clang::MemberExpr>(expr)) {
204- return !member->isArrow () && !member->getBase ()->getType ()->isUnionType () &&
205- !member->getMemberDecl ()->getType ()->isReferenceType () &&
206- IsUnboxedPlace (member->getBase ());
204+ return !member->getMemberDecl ()->getType ()->isReferenceType () &&
205+ IsFieldOfUnboxedPlace (member);
207206 }
208207 auto *ref = clang::dyn_cast<clang::DeclRefExpr>(expr);
209208 return ref && IsUnboxedVar (ref->getDecl ());
210209}
211210
211+ bool ConverterRefCount::IsFieldOfUnboxedPlace (
212+ const clang::MemberExpr *expr) const {
213+ return !expr->isArrow () && !expr->getBase ()->getType ()->isUnionType () &&
214+ IsUnboxedPlace (expr->getBase ());
215+ }
216+
212217ConverterRefCount::ConversionKind
213218ConverterRefCount::VarConversionKind (const clang::VarDecl *decl) const {
214219 if (in_function_formals_) {
@@ -527,7 +532,7 @@ bool ConverterRefCount::VisitArraySubscriptExpr(
527532 StrCat (GetPointerDerefPrefix (expr->getType ()));
528533 ConvertArraySubscript (base, expr->getIdx (), expr->getType ());
529534 StrCat (GetPointerDerefSuffix (expr->getType ()));
530- SetValueFreshness (expr->getType ());
535+ SetDerefFreshness (expr->getType ());
531536 } else {
532537 ConvertArraySubscript (base, expr->getIdx (), expr->getType ());
533538 }
@@ -996,6 +1001,8 @@ void ConverterRefCount::ConvertDeclRefValue(clang::Expr *expr,
9961001 return ;
9971002 }
9981003 StrCat (DerefPtrExpr (str, ref->getPointeeType ()));
1004+ SetDerefFreshness (ref->getPointeeType ());
1005+ return ;
9991006 }
10001007 SetValueFreshness (expr->getType ());
10011008 }
@@ -1005,7 +1012,10 @@ void ConverterRefCount::ConvertDeclRefValue(clang::Expr *expr,
10051012 if (IsUnboxedVar (decl)) {
10061013 assert (!isAddrOf () && " pointer to an unboxed variable" );
10071014 StrCat (str);
1008- if (decl_t ->isPointerType ()) {
1015+ if (isRValue () &&
1016+ moved_reads_.contains (clang::dyn_cast<clang::DeclRefExpr>(expr))) {
1017+ SetFreshType (expr->getType ());
1018+ } else if (decl_t ->isPointerType ()) {
10091019 computed_expr_type_ = ComputedExprType::Pointer;
10101020 } else {
10111021 SetValueFreshness (expr->getType ());
@@ -1277,7 +1287,7 @@ bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
12771287 str = std::format (" {{ {} {} }}" , ctx->temporary_bindings , str);
12781288 }
12791289 StrCat (str);
1280- SetValueFreshness (ref->getPointeeType ());
1290+ SetDerefFreshness (ref->getPointeeType ());
12811291 return false ;
12821292 }
12831293
@@ -1361,7 +1371,9 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
13611371
13621372 if (expr->isXValue () && sub_expr->isLValue ()) {
13631373 Convert (sub_expr);
1364- computed_expr_type_ = ComputedExprType::Value;
1374+ if (!isFresh ()) {
1375+ computed_expr_type_ = ComputedExprType::Value;
1376+ }
13651377 return false ;
13661378 }
13671379
@@ -1667,6 +1679,16 @@ bool ConverterRefCount::VisitUnaryExprOrTypeTraitExpr(
16671679 return Converter::VisitUnaryExprOrTypeTraitExpr (expr);
16681680}
16691681
1682+ bool ConverterRefCount::VisitReturnStmt (clang::ReturnStmt *stmt) {
1683+ auto *value = stmt->getRetValue ();
1684+ auto moved_reads =
1685+ std::exchange (moved_reads_, value ? FindMovableReads (ctx_, value)
1686+ : decltype (moved_reads_){});
1687+ Converter::VisitReturnStmt (stmt);
1688+ moved_reads_ = std::move (moved_reads);
1689+ return false ;
1690+ }
1691+
16701692bool ConverterRefCount::VisitStmtExpr (clang::StmtExpr *expr) {
16711693 PushConversionKind push (*this , ConversionKind::FullRefCount);
16721694 Converter::VisitStmtExpr (expr);
@@ -1879,7 +1901,7 @@ void ConverterRefCount::ConvertUnionMemberAccessor(clang::MemberExpr *expr) {
18791901 return ;
18801902 }
18811903 StrCat (DerefPtrExpr (str, member->getType ()));
1882- SetValueFreshness (member->getType ());
1904+ SetDerefFreshness (member->getType ());
18831905}
18841906
18851907bool ConverterRefCount::VisitMemberExpr (clang::MemberExpr *expr) {
@@ -1941,8 +1963,11 @@ bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) {
19411963 if (known) {
19421964 str = GetMappedAsString (expr);
19431965 } else if (clang::isa<clang::FieldDecl>(member)) {
1944- // The Value or the pointer that the field holds.
1945- str = ReadField (expr, value_field_ptr ? " .as_pointer()" : " .clone()" );
1966+ // The Value or the pointer that the field holds, which is used in place
1967+ // in an unboxed struct.
1968+ str = ReadField (expr, value_field_ptr ? " .as_pointer()"
1969+ : IsFieldOfUnboxedPlace (expr) ? " "
1970+ : " .clone()" );
19461971 } else {
19471972 Buffer buf (*this );
19481973 PushExprKind push (*this , ExprKind::RValue);
@@ -1967,7 +1992,10 @@ bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) {
19671992 return false ;
19681993 }
19691994 StrCat (DerefPtrExpr (str, member->getType ().getNonReferenceType ()));
1970- } else if (isRValue ()) {
1995+ SetDerefFreshness (member->getType ().getNonReferenceType ());
1996+ return false ;
1997+ }
1998+ if (isRValue ()) {
19711999 StrCat (std::format (" (*{}.borrow())" , std::move (str)));
19722000 } else {
19732001 StrCat (std::format (" (*{}.borrow_mut())" , std::move (str)));
@@ -2053,7 +2081,7 @@ std::string ConverterRefCount::ReadField(clang::MemberExpr *expr,
20532081 if (!TypeIsCopyable (expr->getMemberDecl ()->getType ())) {
20542082 str += copy;
20552083 }
2056- if (IsUnboxedPlace (expr)) {
2084+ if (IsFieldOfUnboxedPlace (expr)) {
20572085 return str;
20582086 }
20592087 return ptr.empty () ? std::format (" {{ {} }}" , str)
@@ -2710,7 +2738,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
27102738 Convert (expr->getArg (0 ));
27112739 if (deref) {
27122740 StrCat (GetPointerDerefSuffix (expr->getType ()));
2713- SetValueFreshness (expr->getType ());
2741+ SetDerefFreshness (expr->getType ());
27142742 }
27152743 }
27162744 break ;
@@ -2779,7 +2807,7 @@ bool ConverterRefCount::ConvertCXXOperatorCallExpr(
27792807 computed_expr_type_ = ComputedExprType::FreshPointer;
27802808 } else {
27812809 StrCat (GetPointerDerefSuffix (expr->getType ()));
2782- SetValueFreshness (expr->getType ());
2810+ SetDerefFreshness (expr->getType ());
27832811 }
27842812 }
27852813 break ;
@@ -2922,7 +2950,7 @@ void ConverterRefCount::ConvertPointerSubscript(
29222950 }
29232951 if (deref) {
29242952 StrCat (GetPointerDerefSuffix (expr->getType ()));
2925- SetValueFreshness (expr->getType ());
2953+ SetDerefFreshness (expr->getType ());
29262954 }
29272955}
29282956
@@ -2986,7 +3014,7 @@ void ConverterRefCount::ConvertDeref(clang::Expr *expr) {
29863014 Convert (expr);
29873015 if (deref) {
29883016 StrCat (GetPointerDerefSuffix (pointee_type));
2989- SetValueFreshness (pointee_type);
3017+ SetDerefFreshness (pointee_type);
29903018 }
29913019 }
29923020 str = std::move (buf).str ();
@@ -3022,7 +3050,7 @@ void ConverterRefCount::ConvertArrow(clang::Expr *expr) {
30223050 }
30233051 auto ptr = ToString (expr);
30243052 StrCat (DerefPtrExpr (ptr, pointee_type));
3025- SetValueFreshness (pointee_type);
3053+ SetDerefFreshness (pointee_type);
30263054 return ;
30273055 }
30283056
@@ -3060,12 +3088,21 @@ void ConverterRefCount::ConvertConstructedValue(clang::QualType type,
30603088 ConvertVarInit (type, ctor);
30613089}
30623090
3091+ bool ConverterRefCount::DerefReadsValue (clang::QualType pointee_type) {
3092+ return pointee_type.isPODType (ctx_) && !pointee_type->isRecordType ();
3093+ }
3094+
30633095const char *
30643096ConverterRefCount::GetPointerDerefSuffix (clang::QualType pointee_type) {
3065- if (pointee_type.isPODType (ctx_) && !pointee_type->isRecordType ()) {
3066- return " .read()" ;
3097+ return DerefReadsValue (pointee_type) ? " .read()" : " .upgrade().deref()" ;
3098+ }
3099+
3100+ void ConverterRefCount::SetDerefFreshness (clang::QualType pointee_type) {
3101+ if (DerefReadsValue (pointee_type)) {
3102+ SetFreshType (pointee_type);
3103+ } else {
3104+ SetValueFreshness (pointee_type);
30673105 }
3068- return " .upgrade().deref()" ;
30693106}
30703107
30713108const char *
0 commit comments